继承的快速入门:
认识继承(extend):
Java中提供了一个关键字extends,用这个关键字,可以让一个类和另一个类建立起父子关系。
public class B extends A{
}
这里的B继承(extends)了A,被称为A的子类(派生类)。A被称为父类(基类)
继承的特点:子类能继承父类的非私有成员(成员变量、成员方法)。
继承后对象的创建:子类对象的创建是由子类、父类共同完成的。
继承的应用场景:
使用继承可以减少重复代码的编写。
如图,teacher类和consultant类存在大量重复代码,如何减少代码量?
解决思路:将重复的内容封装成一个people类,然后使teacher类和consultant类继承people类。
尽管teacher类和consultant类的代码看似不完整,但子类对象的创建是由子类、父类共同完成的。所以对对象并没有影响。
继承相关的注意事项:
1.权限修饰符
什么是权限修饰符?
就是是用来限制类中的成员(成员变量、成员方法、构造器、代码块…)能够被访问的范围。
权限修饰符有几种?各自的作用是什么?

2.单继承,Object
单继承:Java是单继承的,Java中的类不支持多继承,但是支持多层继承。
人话:每次只能继承一个类,但是可以重复继承:c继承b,b继承a。
Object类:是java所有类的祖宗类。我们写的任何一个类,其实都是object的子类或子孙类。
换句话说,创建的所有类都可以直接继承并调用Object类的变量与方法。
3.方法重写:
什么是方法重写?
- 当子类觉得父类中的某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写。
- 注意:重写后,方法的访问,Java会遵循就近原则。
方法重写的其它注意事项
- 使用@Override注解,他可以指定java编译器,检查我们方法重写的格式是否正确,代码可读性也会更好。
- 子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限( public > protected > 缺省 )。
- 重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。
- 私有方法、静态方法不能被重写,如果重写会报错的。
方法重写的实际应用:
重写toString方法:
子类重写Object类的toString()方法,以便返回对象的内容。
public String toString(){
return value;
}
4.子类中访问其他成员的特点:
在子类方法中访问其他成员(成员变量、成员方法),是依照就近原则的。
public class A {
String name="A变量";
}
class B extends A{
String name="B变量";
public void ShowName(){
String name="局部变量";
System.out.println(name);
}
}
//此时ShowName打印的是"局部变量"
要想访问B的name怎么办?
System.out.println(this.name);
//此时ShowName打印的是"B变量"
要想访问A的name怎么办?
使用“super”关键字
System.out.println(super.name);
//此时ShowName打印的是"A变量"
成员方法和成员变量同理,执行就近原则。
5.子类构造器的特点:
子类的全部构造器,都会先调用父类的构造器,再执行自己。
子类构造器是如何实现调用父类构造器的:
- 默认情况下,子类全部构造器的第一行代码都是 super() (写不写都有) ,它会调用父类的无参数构造器。
- 如果父类没有无参数构造器,则我们必须在子类构造器的第一行手写super(….),指定去调用父类的有参数构造器。
public class A {
A(){
System.out.println("==A的无参构造器被调用了==");
}
}
class B extends A{
B(){
System.out.println("==B的无参构造器被调用了==");
}
}
此时new一个B类的对象,会先打印“==A的无参构造器被调用了==”,再打印“==B的无参构造器被调用了==”。
同样,即使子类是有参数构造器,也会先调用父类的无参数构造器。
原因:子类的构造器中,第一行默认存在super()关键字,即自动调用父类无参构造器。
假设父类只有有参构造器而没有无参构造器呢?
此时必须手写出super(),指定调用父类的有参构造器。
比如:
public class A {
A(String name,int age){
System.out.println("==A的无参构造器被调用了==");
}
}
class B extends A{
B(){
super("kevin",19);
System.out.println("==B的无参构造器被调用了==");
}
}
//如果你希望子类创建有参数构造器,使创建对象的时候可以直接传参
class B extends A{
B(String name,int age){
super(name,age);
System.out.println("==B的无参构造器被调用了==");
}
}
为什么子类构造器里要调用父类构造器?
由于引入了继承的概念,导致创建对象的时候分为父类和子类。可能有些成员变量是父类的,有些成员变量是子类的。如果我们想写一个子类有参构造器,为对象直接传参时,我们不能直接指定那些父类的变量传参(this.xxx=xxx)(因为这些变量实质上不是子类的),所以引入super关键字,如上方代码。
补充:this()调用兄弟构造器:
任意类的构造器中,是可以通过this(…) 去调用该类的其他构造器的。
此时构成了构造器重载关系。
注意:this(…) 、super(…) 都只能放在构造器的第一行,因此,有了this(…)就不能写super(…)了,反之亦然。