Java 继承

继承理论说明:

  • 继承主要解决的问题就是:共性的抽取实现代码复用
  • Java中提供一个关键字extends,用这个关键字,我们可以让一个类和另一个类建立起父子关系


关于继承如下 3 点请记住:

  • 1、子类拥有父类对象所有的属性和方法(包括私有属性私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有。
  • 2、子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
  • 3、子类可以用自己的方式实现父类的方法。


Q&A
Q:子类是否可以继承父类的构造器?
A:不可以,子类有自己的构造器,父类构造器用于初始化父类对象。

Q:子类是否可以继承父类的私有成员?
A:可以,只是不能直接访问。

Q:子类是否可以继承父类的静态成员?
A:子类可以直接使用父类的静态成员,但是不能继承父类的静态成员(共享并不是继承)。

Q:Java中为什么不支持多重继承?
A:若子类继承的两个父类中有一个同名方法时,无法选择调用哪一个方法。

Q:Java中为什么支持多层继承(A继承B,B继承C)?
A:即使B和C中有同名方法,A可以通过就近原则来调用B的方法。

上实例:
父类
解释:父类中有构造方法、静态方法、实例方法

public class A {
    public A() {
        System.out.println("大家好,这是【父类-A】的【构造方法】");
    }

    // 父类A的静态类方法
    public static void sayHello() {
        System.out.println("大家好,这是【父类-A】的【静态】类方法");
    }

    // 父类A的实例方法
    public void sayHello2() {
        System.out.println("大家好,这是【父类-A】的【实例】方法");
    }
}

子类
解释:子类中有构造方法、与父类同名的静态方法、重写父类的方法

public class B extends A {
    public B() {
        System.out.println("大家好,这是【子类-B】的【构造方法】");
    }

    // 子类B静态类方法
    public static void sayHello() {
        System.out.println("大家好,这是【子类-B】的【静态方法】");
    }

    // 子类B的实例方法
    public void sayHello2() {
        System.out.println("大家好,这是【子类-B】的【实例方法】");
    }
}

测试
第一种情况:

public static void main(String[] args) {
        B b = new B();
        System.out.println("--------");
        A a = new B();
    }
执行结果:
	大家好,这是【父类-A】的【构造方法】
	大家好,这是【子类-B】的【构造方法】
	--------
	大家好,这是【父类-A】的【构造方法】
	大家好,这是【子类-B】的【构造方法】    

第二种情况:(静态方法)

public static void main(String[] args) {
        B b = new B();
        A a = b;
        System.out.println("----");
        A.sayHello();
        a.sayHello();
        System.out.println("======");
        B.sayHello();
        b.sayHello();
    }
执行结果:
	大家好,这是【父类-A】的【构造方法】
	大家好,这是【子类-B】的【构造方法】
	----
	大家好,这是【父类-A】的【静态】类方法
	大家好,这是【父类-A】的【静态】类方法
	======
	大家好,这是【子类-B】的【静态方法】
	大家好,这是【子类-B】的【静态方法】 
	
如果注掉子类B的静态方法(就是去掉),
  执行结果:
	大家好,这是【父类-A】的【构造方法】
	大家好,这是【子类-B】的【构造方法】
	----
	大家好,这是【父类-A】的【静态】类方法
	大家好,这是【父类-A】的【静态】类方法
	======
	大家好,这是【父类-A】的【静态】类方法
	大家好,这是【父类-A】的【静态】类方法	   

说明:
1、静态方法不能继承
2、如果父类中有静态方法,子类中没有,但是子类可以调用父类的静态方法
3、如果父类中有静态方法,子类中也有跟父类相同的静态方法,那么父类不管是 类名调用 还是 实例调用 都是调用的父类的静态方法
子类不管是 类名调用 还是 实例调用 都是调用子类的静态方法

第三种情况:(成员方法)

public static void main(String[] args) {
        A a = new B();  // 创建子类对象 指向 父类
        a.sayHello2();
        System.out.println("------");
        
        A a1 = new A(); // 创建父类对象
        a1.sayHello2();
        System.out.println("=======");
        
        B b = new B(); // 创建子类对象
        b.sayHello2();
    }
执行结果:
	大家好,这是【父类-A】的【构造方法】
	大家好,这是【子类-B】的【构造方法】
	大家好,这是【子类-B】的【实例方法】
	------
	大家好,这是【父类-A】的【构造方法】
	大家好,这是【父类-A】的【实例】方法
	=======
	大家好,这是【父类-A】的【构造方法】
	大家好,这是【子类-B】的【构造方法】
	大家好,这是【子类-B】的【实例方法】    

成员变量、成员方法的调用

在子类方法中访问成员(成员变量、成员方法)满足:就近原则

  • 先在子类局部范围找
  • 然后在子类成员范围找
  • 最后在父类成员范围找,如果父类范围还没有找到则报错
  • 如果子类和父类中有同名变量,根据就近原则访问的是子类的成员变量,另外也可以通过关键字来访问该成员变量(子类使用this.变量名,父类使用super.变量名

子类访问父类私有成员变量

上面说:子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有
那么我们怎么才能访问到父类的私有属性呢?

class A{                     //父类A
	private int value=10;    //声明一个私有变量value并赋值为10
	public int getvalue() {  //声明一个公有成员方法getvalue,返回value
		return value;
	}
}
class B extends A{           //A的子类B
}
public class myfirst {    
	public static void main(String[] args) {
	  B b=new B();           //创建子类B的一个实例对象
	  System.out.println("子类通过父类提供的公共接口访问A中的私有字段value:"+b.getvalue());
	}
}
执行结果:
	子类通过父类提供的公共接口访问A中的私有字段value:10
	

使用super关键字

  • 1、使用super调用父类中重写的方法、访问父类中被隐藏的字段

子类重写了父类中的某一个方法,隐藏父类中的字段,假如想在子类中访问到父类中被重写的方法和隐藏父类的字段,可以在子类中通过使用关键字super来调用父类中被重写的方法和访问父类中被隐藏的字段。例如:

package first;
class A{
    public String name="张飞";         //添加成员变量
	public void say() {                //添加成员方法say
		System.out.println("我是父类A成员方法say");
	}
}
class B extends A{
    public String name="关羽";         //与父类中同名的字段,隐藏父类
	public void say(){                 //重写方法say
		super.say();                   //使用super关键字调用父类中的方法
		System.out.println("我是子类B成员方法say");
        System.out.println("父类的name名字:"+super.name); //使用super关键字访问父类中的变量
	}
}
public class myfirst {
	public static void main(String[] args) {
	  B b=new B();                     //创建子类的一个实例对象
	  b.say();                         //调用子类中重写的方法
	  System.out.println("子类的name名字:"+b.name);   //调用子类中的name
	}
}

执行结果:
	我是父类A成员方法say
	我是子类B成员方法say
	父类的name名字:张飞
	子类的name名字:关羽
  • 2、使用super调用父类的无参数构造方法/有参数构造方法

子类不继承其父类的构造方法。

  • 当使用无参数的super()时,父类的无参数构造方法就会被调用;
  • 当使用带有参数的super()方法时,父类的有参数构造方法就会被调用。
class SuperClass {              //创建父类SuperClass
	  private int n;            //声明一个私有变量n
	  SuperClass(){             //父类无参数构造方法
	    System.out.println("这是父类SuperClass无参数构造方法");
	  }
	  SuperClass(int n) {       //父类有参数构造方法
	    System.out.println("这是父类SuperClass有参数构造方法");
	    this.n = n;
	  }
	}
	class SubClass extends SuperClass{     // SubClass类继承SuperClass类
	  private int n;                       //声明一个私有变量n
	  SubClass(){                          // 自动调用父类的无参数构造器
	    System.out.println("这是子类无参数构造方法");
	  }  
	  
	  public SubClass(int n){              //子类有参数构造方法
	    super(300);                        //调用父类中带有参数的构造器
	    System.out.println("这是子类有参数构造方法"+n);
	    this.n = n;
	  }
	}
public class myfirst {
	public static void main(String[] args) {
		    SubClass sc1 = new SubClass();      //创建子类SubClass实例对象,调用其无参数构造方法
		    SubClass sc2 = new SubClass(100);   //创建子类SubClass实例对象,调用其有参数构造方法
	}
}

执行结果:
	这是父类SuperClass无参数构造方法
	这是子类无参数构造方法
	这是父类SuperClass有参数构造方法
	这是子类有参数构造方法100

注意:

  • 如果要初始化父类中的字段,可以在子类的构造方法中通过关键字super调用父类的构造方法;
  • 对父类的构造放的调用必须放在子类构造方法的第一行;
  • 如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器;
  • 如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表;
  • 子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。

典型例题

	public class A {
			   public A() {
			       System.out.println("1.A类的构造方法");
			   }
			
			    {
			        System.out.println("2.A类的构造块");
			    }
			
			    static {
			        System.out.println("3.A类的静态方法");
			    } 		}
			 		public class B extends A {
			    public B() {
			        System.out.println("4.B类的构造方法");
			    }
			
			    {
			        System.out.println("5.B类的构造块");
			    }
			
			    static {
			        System.out.println("6.B类的静态方法");
			    } 		} 		public static void main(String[] args) {
			        System.out.println("7.start......");
			        new B();
			        new B();
			        System.out.println("8.end.....");
			    } 		
			执行结果:
			7.start......
			3.A类的静态方法
			6.B类的静态方法
			2.A类的构造块
			1.A类的构造方法
			5.B类的构造块
			4.B类的构造方法
			2.A类的构造块
			1.A类的构造方法
			5.B类的构造块
			4.B类的构造方法
			8.end.....

参考:

https://blog.csdn.net/weixin_52122271/article/details/114285424

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值