Java中的继承的好处:
A:提高了代码的复用性
多个类相同的成员可以放在相同的一个类中
B:提高了代码的维护性
如果功能的代码需要修改,只需要修改一处即可
C:让类与类之间产生关系,是多态的前提
其实这也是继承的一个弊端:类的耦合性很强
Java中继承的特点:
A:Java只支持单继承,不支持多继承
一个只能有一个父类,不可以有多个父类
B:Java支持多层继承(继承体系)
以下举例说明:
//采用多层继承,
class TestA {
public void show1() {
System.out.println("我是A");
}
}
//TestB继承TestA
class TestB extends TestA{
public void show2() {
System.out.println("我是B");
}
}
//TestC承TestB,这里就采用了多层继承
class TestC extends TestB {}
class TestDemo {
public static void main(String[] args) {
//创建TestC的对象,再去调用TestA和TestB的方法
TestC c= new TestC();
c.show1();//输出结果为:我是A
c.show2();//输出结果为:我是B
}
}
Java中继承的注意事项
A:子类只能继承父类中所有非私有的成员(成员方法和成员变量)
代码举例:
class TestA {
private int number1 = 100;
public int number2 = 200;
public void show1() {
System.out.println(number1);
System.out.println(number2);
}
//定义静态私有方法show2()
private void show2() {
System.out.println(number1);
System.out.println(number2);
}
}
class TestB extends TestA {}
class TestDemo {
public static void main(String[] args) {
TestB b = new TestB();
b.show1();//结果正确
//b.show2();//由于方法show2()在被继承中是静态的,TestB无法继承
}
}
B:子类不能继承父类的构造方法,但是可以通过supe关键字去访问类的构造方法
代码举例:
class TestA {
int number = 10;
}
class TestB extends TestA{
int number = 20;
public void show() {
int number = 30;
//以下输出的变量名一样,但是根据关键字的修饰,所输出的结果如下
System.out.println(number);//输出本方法中的变量
System.out.println(this.number);//输出本类中的变量
System.out.println(super.number);//输出父类中的变量
}
}
class TestDemo {
public static void main(String[] args) {
TestB b = new TestB();
b.show();
}
}
``()
不要为了部分功能而去继承
代码简单举例说明:==错误示范==
==注意以下代码是错误的==
```java
class TestA {
public void show1() {}
public void show2() {}
}
class TestB {
public void show2() {}
public void show3() {}
}
//此时发现TestA和TestB中都有show2方法,就会想到用继承,注意是错的想法
//以下的继承情况是错误的
class TestB extends TestA { //错误示范
public void show3() {} //错误示范
} //错误示范
//这种方法所说继承了TestA的show2()方法,但是也伴随着继承了TestA的show1()方法
那么,我们到底什么时候考虑使用继承呢?
继承其实体现的是一种关系:“is a”的关系
例如:
(苹果,香蕉,西瓜) 他们都属于(水果)
(黄瓜,波菜,白菜) 他们都属于(蔬菜)
继承中成员变量的关系
A:子类中的成员变量和父类中的成员变量名称不一样,则在调用的时候按照正常程序走
B:子类中的成员变量和父类中的成员变量名称一样?
在子类方法中访问一个变量的查找顺序:
a:在子类方法的局部范围查找,有就使用
b:在子类的成员范围找,有就使用
c:在父类的成员范围找,有就是用
d:如果找不到,就报错
继承中构造方法的关系
子类所有的构造方法默认都会访问父类中空参数的构造方法
因为子类会继承父类的数据,可能还会使用父类的数据
所以子类初始化之前,一定要先完成父类数据的初始化
子类的每一个构造方法的第一条语句默认都是:super()
代码举例:
class TestA {
public TestA() {
System.out.println("这是父类的无参构造方法");
}
public TestA(String name) {
System.out.println("这是父类的有参构造方法");
}
}
class TestB extends TestA {
public TestB() {
//super();
System.out.println("这是子类的无参构造方法");
}
public TestB(String name) {
//super();
System.out.println("这是子类的有参构造方法");
}
}
class TestDemo{
public static void main(String[] args) {
//调用无参构造方法
System.out.println("调用无参构造方法");
TestB b = new TestB();
System.out.println("--------");
System.out.println("调用有参构造方法");
TestB c = new TestB("这个字符串只是代表一个实参字符串");
}
}
/*
编译执行后的结果:
调用无参构造方法
这是父类的无参构造方法
这是子类的无参构造方法
--------
调用有参构造方法
这是父类的无参构造方法
这是子类的有参构造方法
当在子列的每一个构造方法的第一条语句加上:super();的前后的结果是一样的,
说明当没有加super();语句的时候,其实就是默认的有super();
说明在每一次调用子类的构造方法时,无论调用的子类的构造方法是有参还是无参,都会调用父类的无参构造方法
*/
那么问题就来了
如果父类没有无参构造方法,那么子类会出现什么现象?有什么方案解决
如果父类没有无参构造方法,那么在调用子类的时候,就会出现报错的情况
解决方案为:
A:在父类中加上无参构造方法(在上边的代码就可以体现)
B:在子类中的每一个构造方法的第一条语句加上super(”实参“);
C:在子类中通过this(),调用本类的构造方法,而被调用方法需要使用super(“实参”);对父类进行初始化【子类中一定要有一个去访问父类中的构造方法,否则父类就没有被初始化】
举例方案B代码:
class TestA {
public TestA(String name) {
System.out.println("这是父类的有参构造方法");
}
}
class TestB extends TestA {
public TestB() {
super("字符串实参");
System.out.println("这是子类的无参构造方法");
}
public TestB(String name) {
super("字符串实参");
System.out.println("这是子类的有参构造方法");
}
}
class TestDemo {
public static void main(String[] args) {
TestB b = new TestB();
System.out.println("----------");
TestB bb = new TestB("字符串实参");
}
}
/*
编译执行后的结果:
这是父类的有参构造方法
这是子类的无参构造方法
----------
这是父类的有参构造方法
这是子类的有参构造方法
*/
举例方案C代码:
class TestA {
public TestA(String name) {
System.out.println("这是父类的有参构造方法");
}
}
class TestB extends TestA {
public TestB() {
super("字符串实参");//初始化父类
System.out.println("这是子类的无参构造方法")
}
public TestB(String name) {
this();//这是调用本类的无参构造方法,紧接着看本类中的无参构造的代码
System.out.println("这是子类的有参构造方法");
}
}
class TestDemo {
public static void main(String[] args) {
TestB b = new TestB();
System.out.println("--------");
Testb bb = new TestB("字符串实参");
}
}
/*
编译执行后的结果:
这是父类的有参构造方法
这是子类的无参构造方法
--------
这是父类的有参构造方法
这是子类的无参构造方法
这是子类的有参构造方法
*/
【注意】
this(…) 和 super(…) 必须放在第一条语句
如果没有将**super(…)**放在第一条语句,那么在构造方法中的第一条语句就会默认的有一个super();, 就会就进行多次初始化