一、概述:
接口是多个类的公共规范
接口是引用数据类型,其中最突出的特点就是包含:抽象方法
接口不能像class类进行new关键字实例化,要实现它的属性和方法必须让一个类来实现它,再实例化该类,才能调用接口的方法
二、什么是抽象方法/类?
我们都知道,在Java的继承关系当中,父类是将多个子类所共同拥有的属性和方法、行为特征进行抽取,这些属性和方法中,有的是已经明确实现了的,有的还无法确定,那么我们就可以将其定义成抽象,当具体子类使用该类时才进行具体属性、方法、行为特征的定义,进行具体化。
用abstract关键字来修饰类:public abstract class/abstract class
用abstract来修饰方法:修饰符 abstract 返回值 方法名(参数类型)
举个例子:动物都有相同的行为动作,吃食和栖息在不同地方的行为,狗狗爱吃骨肉,栖息在狗窝,猫咪爱吃鱼儿,栖息在猫窝,那它们都有相同的行为动作,即吃食和栖息
的行为,但行为动作不一样,那我们就可以把两个不同的行为定义在抽象类中,并定义成抽象方法
package daily; abstract class abstract_exp { //吃食行为 public abstract void eat();//抽象方法所在的类必须是抽象类,但抽象类可以定义非抽象方法 //栖息行为 public abstract void sleep(); } class dog extends abstract_exp{//一个类实现抽象类、必须重写抽象类中所有的抽象方法 @Override public void eat() { System.out.println("我是狗狗,我爱吃骨头!"); } @Override public void sleep() { System.out.println("我是狗狗,我的住在狗窝"); } } class cat extends abstract_exp{//一个类实现抽象类、必须重写抽象类中所有的抽象方法 @Override public void eat() { System.out.println("我是猫咪,我爱吃鱼儿!"); } @Override public void sleep() { System.out.println("我是猫咪,我的住在猫圈"); } } class abstract_main{ public static void main(String[] args) { cat c = new cat(); dog d = new dog(); c.eat(); c.sleep(); d.eat(); d.sleep(); } } 运行结果: 我是猫咪,我爱吃鱼儿! 我是猫咪,我的住在猫圈 我是狗狗,我爱吃骨头! 我是狗狗,我的住在狗窝
二、接口的定义
2.1格式:
public interface 接口名称
{
//接口内容
}
备注:由类class换成接口interfa后编译生成的仍然是.java文件,即 .class-->.java
2.2在不同的jdk版本中,接口所能包含的内容:
(1)如果在jdk1.7: 只包含常量、抽象方法
(2)如果在jdk1.8:还能包含静态、默认方法(默认方法原则上只能在接口中被调用)
(3)如果在jdk1.9:还能包含私有方法
即在任何的jdk版本中,都能在接口中定义抽象(Abstract)方法,接口不包含构造方法、静态代码块、构造代码块
2.3接口中方法的定义:
(1)定义原则:
a.接口中定义的抽象方法,必须由public 和 abstract 同时修饰
b.如果不添加,则java会给你自动添加这两个关键字
(2)方法定义格式:
public interface 接口名称
{
返回值 方法名(参数类型); //默认抽象方法像这样定义
public abstract 返回值 方法名(参数类型);//实际上是和第一种定义方式一样。系统会自动添加public abstract,无需添加
public static 返回值 方法名(参数类型){ };/静态方法的定义,/必须有方法体
private default 返回值 方法值(参数类型){ };//默认方法的定义,必须有方法体,一般只允许在接口内部使用
}
三、使用接口的时候,需要注意事项:
(1)接口是没有静态代码块或者构造方法的
(2)一个类只能直接继承一个父类,但能同时实现多个接口,格式:
public class 类名称/class 类名称 implements 接口A,..,接口N
(3)一个类实现接口,如果该类不是抽象类的话(抽象类不允许实例化),必须重写接口中所有的抽象方法
(4)如果一个类在实现的多个接口的时候,存在重复的抽象方法,那么只需要重写一次即可
(5)如果一个类在实现的多个接口的时候,存在重复的默认方法,那么实现类一定要对冲突进行处理,对默认方法进行重写
(6)若一个接口中定义了默认方法,而另外一个父类又定义了一个同名的方法时,那么接口中具有相同名称的方法会被忽略
定义一个接口inter:
package daily; public interface inter { //接口中定义的属性必须初始化 int i=0; String name="ibear"; char a = 'A'; //定义接口中的静态方法,不允许子类重写,一般要private修饰,因为类可以实现多个接口,当多个接口有相同的方法的话,继承的类会不知道调用哪个方法的 private static void inter_static_method() { System.out.println("我是接口中的静态方法!"); } //定义接口中的默认方法,原则上该方法只能在该接口中内部使用 default void d(){ System.out.println("我是接口中的默认方法!"); } //定义抽象方法1 public abstract void method_1(); //定义抽象方法2、系统默认支持这种会自动添加public 和 abstract void method_2(); default void nomal_method() { System.out.println("我是接口中的普通方法!"); } }
定义一个classimpint类来实现inter接口:
package daily; public class classimpint implements inter { //实现一个接口必须重写接口的所有抽象方法,除非这个类是抽象类,但抽象类不允许实例化 @Override public void method_1() { System.out.println("我是继承的子类,我已经重写了inter接口的method_1方法"); } @Override public void method_2() { System.out.println("我是继承的子类,我已经重写了inter接口的method_2方法"); } //当一个子类实现的多个接口,多个接口中有相同的默认方法名称时,必须解决冲突,重写该默认方法,且修饰符要为public @Override public void d(){ System.out.println("我是子类中的默认方法!"); } }
主方法:
package daily; public class date5_10 { public static void main(String[] args) { //调用接口中的属性,方式:接口名称.属性名称 System.out.println("我是inter接口中的字符属性:"+inter.a); System.out.println("我是inter接口中的数字属性:"+inter.i); System.out.println("我是inter接口中的字符串属性:"+inter.name); //调用接口中的方法,通过子类来实现 classimpint subclass = new classimpint(); subclass.nomal_method(); //调用实现类中的方法 subclass.method_1(); } } 运行结果: 我是inter接口中的字符属性:A 我是inter接口中的数字属性:0 我是inter接口中的字符串属性:ibear 我是接口中的普通方法! 我是继承的子类,我已经重写了inter接口的method_1方法
}
}