Java 接口
接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
接口实现和类继承的规则不同,为了数据的安全,继承时一个类只有一个直接父类,也就是单继承,但是一个类可以实现多个接口,接口弥补了类的不能多继承缺点,继承和接口的双重设计既保持了类的数据安全也变相实现了多继承。
Java接口本身没有任何实现,因为Java接口不涉及表象,而只描述public行为,所以Java接口比Java抽象类更抽象化。但是接口不是类,不能使用new 运算符实例化一个接口。如 x=new comparable(…);//这个是错误来的。但是可以声明接口变量Comparable x; //这是允许的。
Java接口的方法只能是抽象的和公开的,Java接口不能有构造器,Java接口可以有public、static和final属性。即接口中的属性可以定义为 public static final int value=5; [1]
接口把方法的特征和方法的实现分割开来。这种分割体现在接口常常代表一个角色,它包装与该角色相关的操作和属性,而实现这个接口的类便是扮演这个角色的演员。一个角色由不同的演员来演,而不同的演员之间除了扮演一个共同的角色之外,并不要求其它的共同之处。
定义接口格式:
[public]interface 接口名称 [extends父接口名列表]
{
//静态常量
[public] [static] [final] 数据类型变量名=常量值;
//抽象方法
[public] [abstract] [native] 返回值类型方法名(参数列表);
}
实现接口格式:
[修饰符] class 类名[extends 父类名] [implements 接口A,接口B,···]
{
类成员变量和成员方法;
为接口A中的所有方法编写方法体,实现接口A;
为接口B中的所有方法编写方法体,实现接口B;
}
接口的注意事项
- 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
- 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
- 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
- 一个接口可以有多个方法,接口文件保存在 .java 结尾的文件中,文件名使用接口名。
接口的字节码文件保存在 .class 结尾的文件中,接口相应的字节码文件必须在与包名称相匹配的目录结构中。 - 接口不能用于实例化对象,也不能有构造方法,接口里的方法必须为抽象方法,接口不能包含除了 static 和 final 变量以外的成员变量。
- 接口不是被类继承,而是被类实现,接口可以多继承,子接口可以对父接口的方法和常量进行重写
实现接口
求两个数的和与最大值
public interface jiekou{//定义一个接口
int summation(); // 完成两个数的相加
int compare(int one,int two); // 获取较大的数
}
public class shili implements jiekou
{
int one;
int two;
public shili(int one,int two){//构造方法
this.one=one;
this.two=two;
}
public int summation()//求和
{
return one+two;
}
public int compare(int one,int two)//最大值
{
if(one>two)
return one;
else
return two;
}
}
public class Test {
public static void main(String[] args) {
// 创建实现类的对象
shili a=new shili(111,222);
System.out.println("和:"+a.summation());
System.out.println("MAX:"+a.compare(111,222));
}
}
运行结果:
说明
在该程序中,首先定义了一个 jiekou 的接口,在该接口中只声明了两个未实现的方法,这两个方法需要在接口的实现类中实现。在实现类 shili 中定义了两个私有的属性,并赋予两个属性初始值,同时创建了该类的构造方法。因为该类实现了 shili 接口,因此必须实现接口中的方法。在最后的测试类中,需要创建实现类对象,然后通过实现类对象调用实现类中的方法。
default关键字
方法在使用关键字default后可以有方法体了。
interface bit
{
default void a_l()
{
System.out.println("111");
}
void eat();
}
class bitbit implements bit{
public void eat()
{
System.out.println("222");
}
}
public class Father1
{
public static void main(String [] args)
{
bit a=new bitbit();
a.eat();
a.a_l();
}
}
运行结果:
以上符合java多态的特性,default使方法有方法体,当一个类去实现这个接口时,可以不用再重写这个方法,若要重写则会覆盖default方法
总之,接口中默认为抽象方法,实现类必须重写所有抽象方法,defalut方法可以不重写。
接口的多继承
在Java中,类的多继承是不合法,但接口允许多继承。
在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口。 如下所示:
public interface Hockey extends Sports, Event
以上的程序片段是合法定义的子接口,与类不同的是,接口允许多继承,而 Sports及 Event 可以定义或是继承相同的方法
举个实例来演示一下接口的多继承:
interface Attack
{
void attack();
}
interface Medic
{
void medic();
}
class Shootting implements Attack
{
public void attack()
{
System.out.println("步兵可以攻击");
}
}
class Medicman implements Attack,Medic
{
public void attack()
{
System.out.println("医疗兵也可以射击");
}
public void medic()
{
System.out.println("医疗兵可以救人");
}
}
public class Test21
{
public static void main(String[] agrs)
{
Shootting shootting=new Shootting();
shootting.attack();
Medicman medicman=new Medicman();
medicman.medic();
medicman.attack();
}
}
运行结果:
步兵可以攻击
医疗兵可以救人
医疗兵也可以射击
如果多个接口有重名的方法
package multiex;
interface A {
void m();
}
//注意:方法返回值不一样
interface B {
int m();
}
class C implements A, B {
public void m() {
System.out.println("void m()");
}
public int m() {
System.out.println("int m()");
}
}
public class Test {
public static void main(String[] args) {
C c1 = new C();
c1.m();
}
}
编译将无法通过:
方法名+参数(不含返回值类型)唯一确定一个方法。
所以当返回值不同时,Java认为这还是同一个方法,会与其中一个接口的返回类型冲突。导致编译错误。
如果返回类型相同,那么就是一个方法,实现类实现这一个方法一次就好了。
同理,在继承中子类和父类的方法名和参数若相同,返回值也必须相同
方法的继承与属性的继承有很大的不同,属性任何继承方式均可,而方法则有各种限制,于是在这里做了一个简单的总结:
1、修饰符相同的方法覆盖,即只改内部,不改外部。
2、访问权限不同的方法覆盖,子类只能相对父类越来越宽松,例如父类是public,子类就不能是缺省或protect,private。
3、返回值的类型覆盖,只允许相容的返回类型,例如不能将返回值为int型改为double型,但是复合类型则例外。
4、final的方法覆盖,只能是父类无,子类有,而不能是父类有,子类无。
5、static(静态)的方法覆盖不能有任何变动,即父类有,子类必须有,父类无,子类也必须无。