继承
什么是继承?继承财产!儿子继承父亲的财产。
- Java是单继承机制,即一个儿子类只能有一个父亲类。但是反过来,一个父亲类可以有很多个儿子。
class Dog{
String name;
void show() {
System.out.println("汪汪");
}
}
class Dog1{
String name;
void show(){
System.out.println("汪汪");
}
}
class son1 extends Dog{}//第一个儿子
class son2 extends Dog{}//第二个儿子
class son3 extends Dog1,Dog{}//错误
class son4 extends Dog1 extends Dog{}//错误
- 子类继承到父类的非私有属性,非私有方法。私有的儿子类是拿不到的。
class Dog{
String name;
private void show() {
System.out.println("父类私有你拿不到");
}
void show1() {
System.out.println("不是私有可以拿得到");
}
}
class son extends Dog{}
- 子类继承父类可以重写父类的public方法,这样创建的子类对象,调用与父类同名方法时优先调用的是子类方法。
class Dog{
String name;
void show() {
System.out.println("父类show");
}
}
class son extends Dog{
void show(){
System.out.println("子类show");
}
}
public class Test{
public static void main(String[] args) {
son s = new son();
s.show();//调用的是子类的show(),可简单理解为就近原则
}
}
- 子类继承父类调用父类的protected方法,但是不可以重写父类的protected方法,编译会报错。
class Fu{
protected void show(){
System.out.println("子类可以重写父类的protected方法吗");
}
}
class Zi extends Fu{
void show(){//这里会报错,编译不通过
System.out.println("不可以哦,会报错");
}
}
这里可以简单的理解为就近原则,子类重写父类方法。其本质是涉及对象空间对象调用方法的问题。
对象创建之后存在于堆中,对象调用方法时会现在对象空间寻找show方法,没找到才会往父类空间找。
- 鉴于构造函数的重要性,继承父类时,子类在调用自己构造函数之前会自动通过super()去调用父类的构造函数完成父类属性的初始化。super. 则调用父类的属性或者方法。
class Dog{
String name = "汪汪";
Dog(){
System.out.println("父类构造");
}
}
class son extends Dog{
son(){
//此处隐藏了一个:super();
System.out.println("子类构造");
System.out.println(super.name);//通过super.去调用父类属性,也可以是方法,但不包括构造方法。
}
}
public class Test{
public static void main(String[] args) {
son s = new son();
//先输出的是父类构造,后出来的是子类构造
}
}
也就是说,在调用子类构造函数的时候,子类中的构造函数会自动调用一个super()去调用父类的构造函数,先完成父类的属性初始化,这是因为子类很有可能需要用到父类的一些属性,所以调用父类构造为子类准备资源。
class Dog{
Dog(){
System.out.println("父类构造");
}
}
class son extends Dog{
son(){
this();//报错,有this()则不会有super(),而没有super()则无法调用父类构造函数
System.out.println("子类构造");
}
}
class son extends Dog{
son(){
System.out.println("子类构造");
super();//报错,super()未声明则默认放在第一句,声明了则必须放在第一句
}
}
class son extends Dog{
son(){
super();//正确,子类中可以有多个super()
System.out.println("子类构造");
}
son(String name){
super();
}
}
那super()究竟是什么?
拿Dog类来说,super()就可以看作是Dog(); 自然super("参数")就可以看成是 Dog("参数"); (同理其实this()也一样)
class Dog{
Dog(String name){
System.out.println("父类构造");
}
}
class son extends Dog{
son(){
super();//报错,这里相当于调用Dog(),但是父类的构造函数是Dog(String name);
//是有String类的参数的,所以调用错误!
System.out.println("子类构造");
}
}
这里可以对super()做一个总结:
- super()存在于继承中,具体存在于子类构造函数中。
- 可以自己给出,如不给出则系统默认给出。
- super() 等同于 父类名()
- super()可有参可无参,具体需要看父类,若是父类构造函数只有有参构造,则必须自己添加super(有参),父类有无参则可不添加super(),系统会自动给出。
- super()为的就是调用父类构造初始化,为子类可能要用到父类的属性提供初始化,即提供资源。
- super()默认在子类构造函数的第一句,不能放在其他位置,同样,不能与this()出现在同一个构造函数中,因为它们都放在第一句。
- super()至少有一个,有多个构造函数,自己可添加多个,否则系统默认一个,但默认的super()是调用父类的无参构造,必须满足上面的4.
- super. 则可以调用父类的属性或方法。
this()调用:
- this指的是当前类,通过 this. 可调用当前类的 属性,方法。
- 而this()是调用当前类的无参构造,同样this(参数)调用的是当前类的有参构造,也只存在于构造函数中。
- 并且也只能出现在构造函数的第一句。
- 这样的话就可以在构造函数中通过this()调用其他的构造函数,但是要注意,构造函数调用构造函数的时候,不能形成回调,也就是形成一个环形调用,这样会形成递归调用,导致栈溢出。
class son extends Dog{
int age = 19;
son(){
this("参数");//调用son(String name)这个有参构造。将“参数”传递给了son的有参构造的 name
System.out.println(this.age);//通过 this. 调用当前类属性
this.show();//通过 this. 来调用当前类方法
}
son(String name){
System.out.println(super.name);//通过super. 调用父类属性,也可以调用父类方法,但不包括构造方法。
System.out.println(name);//输出 参数
}
void show() {
System.out.println("通过this来调用我啊");
}
}
总结:
- 无论是this()调用还是super()调用,都是封装好的一种机制,都能减少代码冗余,增强代码封装性
- this()和super()有很多相似之处,this()侧重当前类的构造方法调用,super()是对父类构造方法的调用
- this. 是对当前类,也就是子类的属性方法的调用,super. 是对父类属性方法的调用。
- this()和super()都只能放在构造函数内的第一句,this()可以有多个(子类中) ,super()至少有一个,也可以有多个。
- this() super() 可以其实就相当于 类名()
- 万变不离其综,不变其魂。
本文深入解析Java中的继承机制,包括单继承特性、子类如何继承父类的非私有属性和方法,以及如何重写父类的public方法。同时,探讨了子类构造函数中super()和this()的使用规则及其在初始化过程中的作用。
753

被折叠的 条评论
为什么被折叠?



