接口的特点
注意只针对JDK8之前的
-
接口中的方法可以有参数列表和返回类型, 所有方法都没有方法体。
-
接口没有构造方法。因为构造方法用于创建对象。
-
接口中所有 成员变量都默认是由 public static final 修饰的。
-
接口中的字段只是被存储在该接口的静态存储区域内,而不属于该接口。
-
接口中的方法可以被声明为 public 或不声明,但结果都会按照 public 类型处理。
-
接口中的 所有方法都默认是由 public abstract 修饰的。也可以使用 protected ,但不能用 private 。
-
当实现一个接口时,需要将被定义的方法声明为 public 类型的,否则为默认访问类型, Java 编译器不允许这种情况。
-
如果没有实现接口中所有方法,那么创建的仍然是一个接口。
-
扩展一个接口来生成新的接口应使用关键字 extends ,实现一个接口使用 implements 。
-
一个接口同时继承多个接口 (interface C extends A, B {}是可以的.)
-
接口中的方法是抽象方法(abstract),不能是静态方法(static).接口的所有方法都是抽象的,而抽象方法是没有static,有static的方法是不能override的,所以这样定义接口才有意义。
-
实现接口的类 必须提供接口中所有方法的具体实现内容。
Java(JDK)8接口
JDK8版本,接口中允许有以下三种方法:
- abstract修饰的抽象方法:public abstract 返回类型 方法名(参数);
- default修饰的默认方法:public default 返回类型 方法名(参数) {方法体};
- static修饰的静态方法:public static 返回类型 方法名(参数) {方法体};
Java(JDK)8接口新特性
- 接口中可以使用 default 关键字修饰的非抽象方法。即:默认方法(或扩展方法),实现类可重写或不重写,
- 接口里可以使用static关键字修饰接口的静态方法,实现类和子接口不可以重写接口静态方法,接口中定义的静态方法,只能通过接口来调用。
Java(JDK)8接口规则
public interface CompareA {
//静态方法
public static void method1(){
System.out.println("CompareA:北京");
}
//默认方法
public default void method2(){
System.out.println("CompareA:上海");
}
public default void method3(){
System.out.println("CompareA");
}
}
-
接口中定义的静态方法,只能通过接口来调用
public class SubClassTest { public static void main(String[] args) { SubClass s = new SubClass(); //s.method1(); 错误写法 CompareA.method1(); } } class SubClass implements CompareA{ }
-
通过实现类的对象,可以调用接口中的默认方法。
-
如果实现类重写了接口中的默认方法,调用时仍然调用的是重写以后的方法。
子接口和父接口的方法重写
接口静态方法是不能被实现类和子接口实现的
接口静态方法是不能被实现类和子接口重写
default(默认)方法是可以被实现类和子接口实现的
子接口继承父接口重写父接口的默认方法。
代码示例如下:
interface interfaceA{
default void defaultMethod(){
System.out.println("interfaceA defaultMethod 方法");
}
}
interface interfaceB extends interfaceA{
default void defaultMethod(){
//通过接口名.super.方法名来调用父类
interfaceA.super.defaultMethod();
System.out.println("interfaceB defaultMethod 方法");
}
}
interface interfaceC extends interfaceB{
default void defaultMethod(){
interfaceA.super.defaultMethod();
interfaceB.super.defaultMethod();
System.out.println("interfaceB defaultMethod 方法");
}
}
如果每个重写方法都调用其超级方法,则您会有一系列调用。一般情况,一个实现可以始终覆盖默认方法而无需调用super
。
接口中同名变量和方法
注意当前目录下是针对JDK8之前的。
1.父类与接口或接口之间出现同名变量
注意 接口中的同名变量属于常量( public static final 修饰),只能用
接口名.常量名
调用。
问题一: 在实现接口和继承父类都存在相同变量时,导致子类无法抉择。
解决方法:
在子类的方法中显示表明要输出的变量是父类还是接口的变量。(super/接口名.变量名
)。
代码示例如下:
interface interfaceA{
int value = 0;
}
class ClassA{
int value=10;
}
interface interface2{
int value = 100;
}
class Test extends ClassA implements interfaceA,interface2{
public int getValue(){
//return super.value; //父类中的i
//return A.value; //接口A中的i
return A2.value; //接口A2中的i
}
}
public class TestMain {
public static void main(String[] args) {
Test t = new Test();
System.out.println(t.printI());
}
}
2.父类与接口中存在同名方法
代码示例如下:
interface interfaceA{
public void methodA();
}
class ClassA{
public void methodA(){
System.out.println("ClassA中的methodA()方法");
};
}
class Test extends ClassA implements interfaceA{
//注意:这里子类不重写接口的方法,也不会报错
//子类直接继承父类和实现接口不实现接口方法不报错,说明这种情况下默认父类实现该方法
}
public class TestMain {
public static void main(String[] args) {
Test t = new Test();
t.methodA();
}
}
//打印日志
//我是Test类中的methodA()方法
-
若子类没有重写方法,则默认会优先调用父类中的方法,不会报错。
注意:这里父类已经有了接口中的方法,不重写接口的方法,也不会报错
子类直接继承父类和实现接口不实现接口方法不报错,说明这种情况下默认父类实现该方法 -
若子类重写了该方法,则相当于同时重写了父类以及接口中的方法。注意:调用的是子类重写后的方法。
class Test extends ClassA implements interfaceA{
@Override
public void methodA() {
System.out.println("Test中的methodA()方法");
}
}
public static void main(String[] args) {
Test t = new Test();
t.methodA();
}
//打印日志
//Test中的methodA()方法
- 若子类想用父类的方法,可以通过
super.方法名
class Test extends ClassA implements interfaceA{
@Override
public void methodA() {
super.methodA()
System.out.println("Test中的methodA()方法");
}
}
public static void main(String[] args) {
Test t = new Test();
t.methodA();
}
//打印日志
//ClassA中的methodA()方法
//Test中的methodA()方法
3.接口和接口之间存在同名方法
1.参数列表+返回值 都相同:实现类只要实现一次此方法即可
interface interfaceA{
public void methodA();
}
interface interface2{
public void methodA();
}
class Test implements interfaceA,interface2{
@Override
public void methodA(){
System.out.println("Test中的methodA()方法");
};
}
public class TestMain {
public static void main(String[] args) {
Test t = new Test();
t.methodA();
}
}
//打印日志
//Test中的methodA()方法
2.参数列表相同+返回值不同:实现类无法直接实现两个方法(IDE报错)。
interface interfaceA{
public void methodA();
}
interface interface2{
public int methodA();
}
class Test implements interfaceA,interface2{
//编译期就会直接报错
//英文:'methodA()' in 'Test' clashes with 'methodA()' in 'InterfaceB';
//attempting to use incompatible return type
//中文:'Test' 中的 'methodA()' 与 'InterfaceB' 中的 'methodA()' 冲突;
//尝试使用不兼容的返回类型
//无论重写哪一个接口中的方法都会报错,返回参数不同,定位不到哪个方法。
@Override
public void methodA(){
};
}
3.参数列表不相同:实现类可以分别实现两个方法
interface interfaceA{
public void methodA();
}
interface interfaceB{
public int methodA(String name);
}
class Test implements interfaceA,interfaceB{
//参数列表不相同,分别重写,构成Test类重载。
@Override
public void methodA(){
System.out.println("Test中的methodA()方法");
}
@Override
public void methodA(String name){
System.out.println("Test中的methodA(value="+name+")方法");
};
}
public class TestMain {
public static void main(String[] args) {
Test t = new Test();
t.methodA();
t.methodA("fry");
}
}
//打印日志
//Test中的methodA()方法
//Test中的methodA(value=fry)方法