1.子类继承了所有的属性和方法,但是私有属性和方法不能在子类直接访问,要通过公共的方法去访问。
package com.kxy.extend_;
public class Base {
public int n1=100;
protected int n2=200;
int n3=300;
private int n4=400;
}
package com.kxy.extend_;
public class Sub extends Base{
public Sub() {//子类的无参构造器
}
public void sayOk() {
//第一句话:非私有的属性和方法可以在子类访问,私有的属性和方法不能被子类访问
System.out.println(n1+" "+n2+" "+n3+" " ) ;
System.out.printLn(n4);//错误
}
}
怎么通过公共的方法去访问?我们在父类写上这个方法:
package com.kxy.extend_;
public class Base {
public int n1=100;
protected int n2=200;
int n3=300;
private int n4=400;
public int getN4() {//第二句话:通过公共的方法去访问子类原本不能访问的私有属性
return n4;
}
}
在子类方法里调用它就可以访问了。
package com.kxy.extend_;
public class Sub extends Base{
public Sub() {//子类的无参构造器
}
public void sayOk() {
//第一句话:非私有的属性和方法可以在子类访问,私有的属性和方法不能被子类访问
System.out.println(n1+" "+n2+" "+n3+" " ) ;
// System.out.printLn(n4);//错误
//但是我们可以通过公共的方法去访问
System.out.println("n4="+getN4());
}
}
我们在主类调用它:
package com.kxy.extend_;
public class ExtendsDetail {
public static void main(String[] args) {
Sub sub=new Sub();
sub.sayOk();
}
}
2.子类必须 调用父类的构造器,完成父类的初始化
package com.kxy.extend_;
public class Base {
public Base() {//父类的无参构造器
System.out.println("base()被调用了...");
}
}
package com.kxy.extend_;
public class Sub extends Base{
public Sub() {//子类的无参构造器
}
}
package com.kxy.extend_;
public class ExtendsDetail {
public static void main(String[] args) {
Sub sub=new Sub();
}
}
为什么创建子类的时候,子类一定会调用父类的构造器里的方法呢?
因为在子类的无参构造器里,系统默认添加了一行代码super();
package com.kxy.extend_;
public class Sub extends Base{
public Sub() {//子类的无参构造器
super();//程序默认调用父类无参构造器
}
}
即使你不写,它也会被立即执行。如果不懂super是什么可以去看作者的另一个博客,点击跳转:
super关键字什么时候使用?super的适用场景是?_❀༊烟花易冷ღ࿐❀的博客-CSDN博客
3.当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成父类的初始化操作,否则编译不会通过。
我们在子类原来基础上创建有参构造器
package com.kxy.extend_;
public class Sub extends Base{
public Sub() {//子类的无参构造器
// super();//程序默认调用父类无参构造器
System.out.println("Sub()被调用了...");
}
public Sub(String name) {
System.out.println("Sub(name)被调用了...");
}
}
当我们new一个有参的子类对象时
package com.kxy.extend_;
public class ExtendsDetail {
public static void main(String[] args) {
Sub sub=new Sub();
System.out.println("=========");
Sub sub2=new Sub("jack");//new一个有参子类对象
}
}
控制台输出,分割线上面是sub,下面是sub2
通过对比我们可以发现,当我们new一个指定参数的对象,就间接的调用了指定的构造方法。
如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成父类的初始化操作,否则编译不会通过。怎么理解?
像这样,我们把父类的无参构造器给注释掉了,此时有参构造器就会覆盖掉原有的无参构造器。
package com.kxy.extend_;
public class Base {
// public Base() {//父类的无参构造器
// System.out.println("base()被调用了...");
// }
public Base(String name,int age) {
System.out.println("base(name,age)被调用了...");
}
}
我们来看看子类的情况如何?
可以看到,此时子类不管是有参构造器还是无参构造器,都报了相同的错误:父类的无参构造器没有定义,必须选择其他的构造器。
那么解决方案是什么呢?
package com.kxy.extend_;
public class Sub extends Base{
public Sub() {//子类的无参构造器
// super();//程序默认调用父类无参构造
super("Tom",15);
System.out.println("Sub()被调用了...");
}
public Sub(String name) {
super("Jam",18);
System.out.println("Sub(name)被调用了...");
}
}
所以,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成父类的初始化操作。
同样,在子类的有参构造器也是如此。
通过对比上次的控制台输出,我们总结一个规律。
1.如果父类没有写无参构造器,那么系统默认给你调用无参构造器,只是里面没有任何方法。
2.如果父类写了无参构造器,那么子类必须调用父类无参构造器。
3.如果父类写了无参构造器,又写了有参构造器,那么可以通过super指定选择使用哪个构造器,但是每个构造方法里只能super一次。也可以不使用super,那么相当于所有的子类构造方法都写了一个隐形的super();也就是默认使用无参构造器。
4.如果父类没有写无参构造器,但写了有参构造器,那么有参覆盖无参,此时子类构造方法必须用super来完成初始化。
ps:注意:在构造方法里,super必须在方法体里最前面。否则会报错。
以下是关于本次博客的核心梳理:
1.子类继承了所有的属性和方法,但是私有属性和方法不能在子类直接访问,要通过公共的方法去访问。
2.子类必须 调用父类的构造器,完成父类的初始化
3.当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成父类的初始化操作,否则编译不会通过。