前言
子类可以继承父类(除私有化外)的全部属性和方法,当然父类的构造方法也不可以被继承,只能使用super来调用。对于父类的默认无参构造方法,子类会默认调用;但对于父类的有参构造,子类只能使用super来显示调用,且super调用的这行代码必须位于子类相应构造方法的第一行。
其实子类对象中也存在父类的私有化属性和方法,只不过子类无法直接访问这些私有属性和方法,需要通过父类的get、set方法等来调用。有人可能会问这不自相矛盾了吗,你上面不是才说了子类不可以继承父类的私有化属性和方法吗,其实啊,Java官方文档里是这样规定的:父类的私有变量和私有方法虽然存在于子类对象中,但是对于子类对象而言这些私有化属性和方法是不可见的,子类对象无法直接访问和调用,正由于这种虽存在但不可见的特性,所以官方规定其为不可以被继承,大家简单了解就好。
正文:
一、子类可以继承父类的哪些数据域和方法
1、普通属性
private修饰的普通属性不能被子类继承,但是子类可以调用父类提供的访问器和修改器进行访问和修改;
无修饰符的普通属性可以被子类继承;
protected修饰的普通属性可以被子类继承;
public修饰的普通属性可以被子类继承;

2、静态属性
private修饰的静态属性不能被子类继承,但是子类可以调用父类提供的访问器和修改器进行访问和修改;
无修饰符的静态属性可以被子类继承;
protected修饰的静态属性可以被子类继承;
public修饰的静态数属性可以被子类继承;

3、普通方法
private修饰的普通方法不能被子类继承;
无修饰符的普通方法可以被子类继承;
protected修饰的普通方法可以被子类继承;
public修饰的普通方法可以被子类继承;

4、静态方法
private修饰的静态方法不能被子类继承;
无修饰符的静态方可可以被子类继承;
protected修饰的静态方法可以被子类继承;
public修饰的静态方法可以被子类继承;

5、构造方法
父类的构造方法不会被子类继承,但是可以通过super关键字进行调用。

6、总结
除父类中private修饰的属性和方法以及构造方法外,子类都可以继承。

二、子类可以重写父类的哪些方法
1、普通方法
private修饰的普通方法不能被重写,如果子类中定义的方法在父类中是私有的,那么这两个方法完全没有关系;
无修饰符的普通方法可以被重写;
protected修饰的普通方法可以被重写;
public修饰的普通方法可以被重写;

2、静态方法
只要是静态方法就不能被重写,和访问修饰符无关。

三、父类引用指向子类对象时

1、若子类覆盖了某方法,则父类引用调用子类重新定义的新方法

2、若子类未覆盖某方法,则父类引用调用父类本身的旧方法

3、若子类覆盖了某属性,但父类引用仍调用父类本身的旧属性

4、若子类未覆盖某属性,则父类引用调用父类本身的旧属性

5、父类引用不能访问子类新定义的方法

四、子类引用指向自身对象时

1、若子类覆盖了某方法,则子类引用调用子类重新定义的新方法

2、若子类未覆盖某方法,则子类引用调用父类本身的旧方法

3、若子类覆盖了某属性,则子类引用调用子类重新定义的新属性

4、若子类未覆盖某属性,则子类引用调用父类本身的旧属性

5、子类引用可以访问子类新定义的方法

五、实例分析

public class Father {
 
	int a = 1;
	int b = 2;
 
	void f1() {
		System.out.println(" Father.f1()");
	}
 
	void f2() {
		System.out.println(" Father.f2()");
	}
 
}
public class Son extends Father {
 
	int a = 3;
 
	@Override
	void f1() {
		System.out.println("Son.f1()");
	}
 
	void f3() {
		System.out.println("Son.f3()");
	}
 
	public static void main(String[] args) {
 
		Father father= new Son();// 父类引用指向子类对象
		father.f1();// 子类覆盖了该方法,所以父类引用调用新方法
		father.f2();// 子类未覆盖该方法,所以父类引用调用旧方法
		// b.f3();此行去掉注释会报错,父类引用不能访问子类新定义方法
		System.out.println(father.a);// 子类覆盖了该属性,但父类引用仍旧访问旧属性
		System.out.println(father.b);// 子类未覆盖该属性,父类访问旧属性
 
		System.out.println();
 
		Son son = new Son();// 子类引用指向自身对象
		son.f1();// 子类覆盖了父类方法,所以调用新方法
		son.f2();// 子类未覆盖父类方法,所以调用旧方法
		son.f3();// 子类调用自己新定义的方法
		System.out.println(son.a);// 子类覆盖了该属性,所以访问新属性
		System.out.println(son.b);// 子类未覆盖该属性,所以访问旧属性
	}
}
Son.f1()
Father.f2()
1
2
 
Son.f1()
Father.f2()
Son.f3()
3
2