接口(interface)
定义:接口是一种特殊的抽象类。Java中的接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
作用:Java只支持单继承,要想实现多继承,运用接口。
实例理解:1)接口感觉就是一些类似的事物共有的域或方法,就像有一个接口animal,里面有个方法eat,然后你每一个动物的类,都去实现这个接口,因为每个动物都有各自的饮食方法,这样就增加了代码的复用性,不要再每一动物类里都要重新想一个名字来定义eat。
2)我们有鸭子和鸡这两个类,鸭子有家鸭和野鸭,有吃与叫的方法,鸡有家鸡和野鸡,也有吃与叫的方法。但是野鸭和野鸡都有飞的方法,所以家鸭与野鸭继承鸭子这个类,家鸡与野鸡继承鸡这个类,我们还要定义一个能飞的接口,然后让野鸭和野鸡实现这个接口。
因此,我们可以大致这样讲:相同类的共同方法和属性,提炼到父类(抽象类),不同类的公共方法,提炼到接口
深入理解:
接口实际上相当于一个父类,实现了一个接口就证明这个类肯定会有某些行为。这样我只要知道这个类实现了某个接口,却不用关心这个类如何实现,也不用关心这个类还实现了其他什么功能。
例如:
接口A 包含方法public void print1(){};和public void print(){};
接口B 包含方法public void print2(){};和public void print(){};
我有个类C实现了A和B
那么 我用 A去声明C的时候
A a = new C();
我们不必关心C能做什么,却能保证可以调用
a.print();
a.print1();
同理
B b = new C();
b.print();
b.print2();
这往往在模块化开发中,例如3个人每人负责一个模块,模块互相调用的都是接口。那么一个模块完全不用关心其他模块的接口是如何实现的,只需要专注自己的代码即可。现代的测试环境可以为接口模拟返回值,使模块开发更方便,更不依赖于其他模块。
注意:
1、 接口的地位(层级结构)等同于class,接口中的所有方法都是抽象方法,并且方法都是public的。Public interface MyInterface{ },
2、 在声明接口方法的时候,可以使用abstract关键字,也可以省略掉abstract关键字。
Eg:Public (abstract) void output();
3、 接口可以看成是一种特殊的抽象类,这种抽象类中只包含常量和抽象方法的定义,而没有变量和方法的实现。(抽象类中可以有具体的方法,也可以有抽象的方法,而接口里只能有抽象方法,实现时必须被重写)。所以属性都是final变量,不能改变。
Eg:public interface Runner{
public static final int id=10;
public void start();
public void run();
public void stop();
}
4、 类可以实现接口,实现使用关键字implements,代表某个类实现了某个接口。
5、 如果某个类实现了一个接口,并且这个类不是抽象类,那么这个类必须实现这个接口中所有的方法(接口里都是抽象方法)。如果这个类是抽象类,那么就无需实现接口中的方法了。
6、 Java是单继承的,也就是说一个某一个类只能有唯一的一个父类。但一个类可以实现多个接口,多个接口间使用逗号分隔。
Eg :Class A implementsB1,B2{ }
7、 某一个类可以同时继承一个类和实现多个接口(多重实现),多个无关的类可以实现同一个接口。接口和实现类之间存在多态性
Eg:Class A extends B implements C1,C2
8、 接口中所声明的方法都是抽象方法,接口中的方法都是public的。
9、 接口中也可以定义声明属性,但是必须初始化。接口中的属性都是也只能是public、final、static的。都是常量(避免实现的多个接口之间的相同成员变量)
例如:class interface Interface{
public final static int=3;
}
10、 不能通过new来生成接口的对象的实例。
11、 接口还可以继承其他的接口,并添加新的属性和抽象方法。
12、 类和类之间、接口和接口之间可以互相继承,而类和接口之间只能实现。
13、 接口可以多重继承:即
interface A{
public void printA();
}
interface B{
public void printB();
}
interface C extends A,B{
public void printC();
}
例如:
public interface Singer
{
public void sing();//定义一个唱歌的方法,能唱歌的东西,具体怎么唱不知道,人有人的唱法,动物有动物的唱法。
public void sleeping();
}
class Student implements Singer{
//实现接口,必须实现其中所有的方法。
public void sing()
{
}
public void sleeping()
{
}
}
代码详解:
public classimplementszzj {
/**
* 接口的定义:由于c++有多继承,java只能单继承, 所以增加了接口来实现多继承 接口是一种特殊的抽象类, 也就是final类。
* 这种抽象类中,只包含常量,也就是final定义的静态static变量和方法定义,
* 也就是只有定义函数,不在里面写实现的内容在抽象类中定义常量的好处是, 由于该量只能存放到data segment静态字符常量保存地方,
* 不放在变量栈内存和类方法的堆内存中,所以,避免了c++中, 多继承的时候, 定义的变量名一样,导致调用困难。data segment好处,
* 也就是不管多少个相同的定义名,在里面都默认为一个。 好了复习下四大存放区域: heap 定义new方法的资料存放地 stack 局部变量
* 主函数变量存放地 data segment 静态变量字符常量存放地code segment 代码存放
*
*@param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
s1 ss1 = new set1("set1的名字");
ss1.ss1();
ss1.ss2(); // 注意,接口类只能调用自己的接口方法
s2 ss2 = new set2(12);
ss2.sss1();
ss2.sss2();
// //
// 由于set包含了set1和set2。所以s1只能访问s1,s2只能访问s2;
// 表明每一个接口对应自己的方法。所以用什么接口在set3上,就调用该接口方法
// s1 ss3=new set3();
s2 ss3 = new set3();
ss3.sss1();
}
}
// 定义了s1的接口以及方法
interface s1 {
public void ss1();
public void ss2();
}
// 定义了接口的实现过程,注意,定义接口必须要对应实现过程
class set1implements s1 {
private String name;
set1(final String name) {
this.name = name;
System.out.println("定义构造方法来传递姓名");
}
public void sett1() {
System.out.println("这个是自己定义 的方法");
}
public void ss1() {
//TODO Auto-generated method stub
System.out.println("这个是接口ss1的实现过程");
}
public void ss2() {
// TODO Auto-generated method stub
System.out.println("这个是接口ss2的实现过程");
}
}
// 定义了s2的接口以及方法
interface s2 {
public void sss1();
public void sss2();
}
// 定义了接口的实现过程,注意,定义接口必须要对应实现过程
class set2implements s2 {
private int age;
set2(final int age) {
this.age = age;
System.out.println("定义构造方法来传递年龄");
}
public void sss1() {
// TODO Auto-generated method stub
System.out.println("这个是接口sss1的实现过程");
}
public void sss2() {
// TODO Auto-generated method stub
System.out.println("这个是接口sss2的实现过程");
}
}
// 定义了多个接口的实现过程,注意,定义接口必须要对应实现过程
class set3 implements s1, s2 {
public void ss1() {
// TODO Auto-generated method stub
System.out.println("这个是接口ss1的实现过程");
}
public void ss2() {
// TODO Auto-generated method stub
System.out.println("这个是接口ss2的实现过程");
}
public void sss1() {
// TODO Auto-generated method stub
System.out.println("这个是接口sss1的实现过程");
}
public void sss2() {
// TODO Auto-generated method stub
System.out.println("这个是接口sss2的实现过程");
}
}
//定义一个类并且 定义了一个方法并实现
class set4 {
void sett() {
System.out.println("这个是set4的方法");
}
}
//定义一个类并且继承了 set4的类和 继承了 s1 s2的接口
class set5 extendsset4 implements s1, s2 {
//定义接口必须要对应实现过程
public void ss1() {
// TODO Auto-generated method stub
}
public void ss2() {
// TODO Auto-generated method stub
}
public void sss1() {
// TODO Auto-generated method stub
}
public void sss2() {
// TODO Auto-generated method stub
}
}
//定义了一个类,继承了set2的类,由于里面有自己定义的构造方法,所以
//继承下来必须也重写自己的构造方法并且通过super方法来传递给父类set2
class set6 extendsset2
{
set6(int age) {
super(age);
// TODO Auto-generated constructorstub
}
}
class set7 extendsset1
{
set7(String name) {
super(name);
// TODO Auto-generated constructorstub
}
}
转载于:https://blog.51cto.com/8786457/1390081