目录
- 1.什么是继承
- 2.父类成员访问
- 2.1 子类访问父类的成员变量
- 2.1.1 子类和父类不存在同名成员变量
- 2.1.2 子类和父类存在同名成员变量
- 2.2子类中访问父类的成员方法
- 2.2.1. 成员方法名字不同
- 2.2.22. 成员方法名字相同
- 3.super关键字
- 4.子类构造方法
- 5.super和this的异同点
- 6.代码块的顺序
- 6.继承方式
- 7.final关键字
1.什么是继承
继承是一种机制,是对代码复用的重要手段。
主要解决的问题是:共性的抽取,实现代码的复用。
我们使用继承的时候,使用extends关键字
A extends B 这个就是继承
A:称为子类/派生类
B:称为父类/超类/基类
class 子类 extends 父类 {
// …
}
因为姓名和年纪是公用的,所以我们将姓名和年纪放到父类中,我们的子类只需要继承就可以了
这个样子就避免了代码的冗余。
继承之后,子类可以复用父类中成员,子类在实现时只需关心自己新增加的成员即可。
class Animal{
public String name;
public int age;
}
class Dog extends Animal
{
}
class Cat extends Animal
{
}
public class Test {
public static void main(String[] args) {
Dog dog=new Dog();
Cat cat=new Cat();
}
}
2.父类成员访问
2.1 子类访问父类的成员变量
2.1.1 子类和父类不存在同名成员变量
当我们的子类和父类不存在同名的变量的时候,我们直接使用就可以了。
其中a,b是从父类继承下来的,c是子类自己的
class Base
{
public int a;
public int b;
}
class Derivce extends Base
{
public int c=9;
public void func()
{
System.out.println(a);
System.out.println(b);
System.out.println(c);//优先子类
}
}
public class Test2 {
public static void main(String[] args) {
Derivce derivce=new Derivce();
derivce.func();
}
}
2.1.2 子类和父类存在同名成员变量
当我们的子类和父类存在同名的变量的时候,如果子类中有这个变量,我们会优先值子类的,如果之类没有那就会向父类中查询,取到父类的。
其中a,b是从父类继承下来的,在子类中没有,所以取到的是父类的,c是优先子类自己的。
在子类方法中 或者 通过子类对象访问成员时:
如果访问的成员变量子类中有,优先访问自己的成员变量。
如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
如果访问的成员变量与父类中成员变量同名,则优先访问自己的
class Base
{
public int a;
public int b;
public int c=199;
}
class Derivce extends Base
{
public int c=9;
public void func()
{
System.out.println(a);
System.out.println(b);
System.out.println(c);//优先子类
}
}
public class Test2 {
public static void main(String[] args) {
Derivce derivce=new Derivce();
derivce.func();
}
}
2.2子类中访问父类的成员方法
2.2.1. 成员方法名字不同
class A
{
public void MethodA()
{
System.out.println("MethodA");
}
}
class B extends A
{
public void MethodB()
{
System.out.println("Method B");
}
public void show()
{
MethodB();
MethodA();
}
}
public class Test3 {
public static void main(String[] args) {
B b=new B();
b.show();
}
}
这时我们可以看出来,当我们访问方法的时候,如果子类有就优先子类的,子类没有就去父类里面找,如果父类也没有的话,就会报错。
2.2.22. 成员方法名字相同
class A
{
public void MethodA()
{
System.out.println("MethodA");
}
}
class B extends A
{
public void MethodB()
{
System.out.println("Method B");
}
public void MethodA()
{
System.out.println("Method and B");
}
public void show()
{
MethodB();
MethodA();
}
}
public class Test3 {
public static void main(String[] args) {
B b=new B();
b.show();
}
}
通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到
则访问,否则编译报错。
通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用
方法适传递的参数选择合适的方法访问,如果没有则报错;
3.super关键字
当我们子类和父类都有变量或者方法的时候,我们都知道会优先访问子类自己的变量或者方法,那么如果我们想要访问父类的变量或者方法,怎么办呢?
这个时候我们就要借助super’这个关键字。
Java提供了super关键字,该关键字主要作用:在子类方法中访问父类的成员
class Base
{
public int a;
public int b;
public int c=199;
}
class Derivce extends Base
{
public int c=9;
public void func()
{
System.out.println(a);
System.out.println(b);
System.out.println(c);//优先子类
System.out.println(super.c);//拿的是父类的
System.out.println(this.c);//自己的
}
}
public class Test2 {
public static void main(String[] args) {
Derivce derivce=new Derivce();
derivce.func();
}
}
【注意事项】
super只是一个关键字,最大作用就是在写代码的时候体现出更好的可读性
1. 只能在非静态方法中使用
2. 在子类方法中,访问父类的成员变量和方法。
super 只能代指直接的父类
super.属性 在子类中,访问父类的成员变量
super.方法() 在子类中,访问父类的成员方法
4.子类构造方法
在继承关系上,当我们在构造之类的时候,一定要先帮父类进行构造。
父子父子,先有父再有子,即:
子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法
当我们在子类构造一个方法的时候,我们就一定要先帮父类也构造一个方法。,当我们构造一个子类方法的时候,系统会默认帮我们在里面构造一个无参数的super。
class Animal{
public String name;
public int age;
public void eat(){
System.out.println(name + "正在吃饭");
}
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void sleep(){
System.out.println(name + "正在睡觉");
}
}
class Dog extends Animal
{
public Dog() {
}
//在构造子类的时候,一定要先构造父类
public Dog(String name, int age) {
//super一定要在第一行
super(name,age);//显示的调用父类的构造方法,帮助父类的成员实现初始化
}
public void speak(){
System.out.println(name + "在汪汪汪");
}
}
class Cat extends Animal
{
public Cat() {
super();
}
public Cat(String name, int age) {
super(name, age);
}
public void speak(){
System.out.println(name + "在喵喵喵");
}
}
public class Test {
public static void main(String[] args) {
//Animal animal=new Animal();
// Dog dog=new Dog("小狗",10);
Dog dog=new Dog();
dog.name="小狗";
dog.age=10;
dog.speak();
dog.eat();
System.out.println("===========");
Cat cat=new Cat("小猫",11);
// cat.name="小猫";
// cat.age=11;
cat.speak();
cat.eat();
}
}
在子类构造方法中,并没有写任何关于基类构造的代码,但是在构造子类对象时,先执行基类的构造方法,然后执
行子类的构造方法,因为:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子
肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整
,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整 。
注意:
- 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构
造方法 - 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
- 在子类构造方法中,super(…)调用父类构造时,必须是子类构造函数中第一条语句。4. 4. super(…)只能在子类构造方法中出现一次,并且不能和this同时出现
5.super和this的异同点
【相同点】
- 都是Java中的关键字
- 只能在类的非静态方法中使用,用来访问非静态成员方法和字段
- 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在【不同点】
【不同点】 - this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成
员的引用 - 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性
- 在构造方法中:this(…)用于调用本类构造方法,super(…)用于调用父类构造方法,两种调用不能同时在构造
方法中出现 - 构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有
6.代码块的顺序
我们可以看出来,显著性静态代码块,然后执行父类的代码块,最后执行之类的代码块,
这里需要注意:静态代码块只在第一次初始化的时候会执行一次,后面再创建对象的时候,不会执静态代码块。
class Animal{
public String name;
public int age;
static {
System.out.println("Animal Static");
}
{
System.out.println("Aninmal{}");
}
public void eat(){
System.out.println(name + "正在吃饭");
}
public Animal() {
System.out.println("Animal()");
}
}
class Dog extends Animal
{
static {
System.out.println("Dog Static");
}
{
System.out.println("Dog{}");
}
public Dog() {
System.out.println("Dog()");
}
}
class Cat extends Animal
{
public Cat() {
super();
}
public void speak(){
System.out.println(name + "在喵喵喵");
}
}
public class Test {
public static void main(String[] args) {
Dog dog=new Dog();
System.out.println("===========");
Dog dog1=new Dog();
}
}
通过分析执行结果,得出以下结论:
1、父类静态代码块优先于子类静态代码块执行,且是最早执行
2、父类实例代码块和父类构造方法紧接着执行
3、子类的实例代码块和子类构造方法紧接着再执行
4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行
6.继承方式
在我们的Java中有以下这几个继承方式
1.单继承
class A
{
}
class B extends A
{
}
2.多继承
class A
{
}
class B extends A
{
}
class C extends B{
}
3.不同类继承同一个类
class A
{
}
class B extends A
{
}
class C extends A{
}
7.final关键字
final关键字可以用来修饰变量,成员方法,以及类等等。
- 当final修饰变量的时候,表示常量,不能被改变
一旦被概念就会报错
2.修饰类的时候
当final修饰类的时候,不能被继承,否则会报错
3.修饰方法:表示该方法不能被重写
当final修饰方法的时候,方法不能被重写,会编译错误