- A+
【前言】
extends和implements是JAVA里面非常重要的两个概念,发现百度里面搜的博客很多写的好差,特意回头再梳理一下。
extends
extends表示继承,无法继承声明为final或abstract的类,并且只能继承 一个父类(不像C语言可以继承多个),继承后可以使用父类的方法,也可以重写父类的方法、写自己的方法。
abstract抽象类可以继承其它类和实现其他接口,而且不需要实现或者重写其中的方法;抽象类不能实例化, 实例化的话只能使用匿名内部类 , 但是可以声明一个抽象类的引用;abstract不能与static、private、final一起修饰方法,因为这些方法不能被重写;abstract不能作用于final,因为final类不能被继承;如果一个子类没有实现父类所有的abstract方法,那么这个子类必须要定义为抽象类;当一个非抽象子类实现了其抽象父类所有abstract方法(包括父类的父类中的abstract方法, 父类实现的接口中的abstract方法), 这个子类就可以定义为普通类
代码实例:
下面的A叫父类,B,C继承了A,叫子类classA{inti;voidf(){
}
}classBextendsA{intj;voidf(){
System.out.println("我是B"); }//重写方法voidg(){}
}classCextendsA{intj;voidf(){
System.out.println("我是C"); }//重写方法voidg(){}
}
父类调用子类实例化的过程:
A a =newB();
如上代码,实际上有三个过程:
(1) A a;
将a声明为父类对象,只是一个引用,未分配空间。
(2) B temp = new B();
通过B类的构造函数建立了一个B类对象的实例,也就是初始化。
(3) a = (A)temp;
将子类对象temp转换为父类对象并赋给a,向上转型(upcast),是安全的。经过以上3个过程,a就彻底成为了一个A类的实例。
总结:
子类往往比父类有更多的属性和方法,上传只是舍弃,是安全的;而向下转型(downcast)有时会增加方法,通常是不安全的。这也是instanceof不能判断一个对象是否是真正的父类对象的原因。
继承导致的多态:
A a1 =newB();
A a2 =newC();
如上代码所示, 父类A调用了子类B、C,同时子类在继承之后的实现方式又不同,
a1,a2两个虽然都是父类对象,但各自的f()不同。这就是子类型多态的体现。
implements
implements表示实现,可以实现多个接口,通过重写他们的方法去实现各种功能。
说到这里,必须了解接口和类、接口与抽象类的区别。
接口与类的区别:
接口不能用于实例化对象。接口没有构造方法。接口中所有的方法必须是抽象方法,Java 8 之后 接口中可以使用 default 关键字修饰的非抽象方法。接口不能包含成员变量,除了 static 和 final 变量。接口不是被类继承了,而是要被类实现。接口支持多继承。
接口和抽象类:
接口可以继承接口,不能实现接口;抽象类不可以继承接口,但可以实现接口。抽象类可以继承实体类。抽象类可以实现(implements)接口,抽象类是否可继承实体类,取决于实体类必须是否有明确的构造函数。抽象类可以继承实体类,这是因为抽象类可继承性且有方法。一个接口可以继承多个接口,interface C extends A, B {}是可以的(Java类是单继承的,但接口是可以多继承的)。不允许类多重继承的主要原因是,如果A同时继承B和C,而B和C同时有一个D方法,A如何决定该继承那一个呢?但接口不存在这样的问题,接口全都是抽象方法继承谁都无所谓,所以接口可以继承多个接口。
抽象类和接口的区别:
抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。注:JDK1.8以后,
接口里可以有静态方法和方法体了。
接口允许包含具体实现的方法,该方法称为"默认方法",默认方法使用default关键字修饰。
注:JDK1.9以后,允许将方法定义为private,使得某些复用的代码不会把方法暴露出去。
代码实例:
//定义一个接口publicinterfaceInterA{voidshow();//抽象方法defaultvoidmethod(){//默认方法,必须写方法体System.out.println("默认方法被实现了"); }staticvoidtest(){//静态方法,必须写方法体System.out.println("静态方法被实现了"); }
}//定义接口的一个实现类publicclassInterlmplimplementsInterA{
@Overridepublicvoidshow(){
System.out.println("show方法"); }
}//定义测试类publicclassInterDemo{publicstaticvoidmain(String[] args){
InterA i =newInterlmpl();
i.show();//抽象方法强制重写i.method();//默认方法不强制重写,但可以被重写,重写时去掉default关键字Inter.test();//静态方法只能通过接口名调用,不能通过实现类名或者对象名调用}
}