接口
接口是一种约定规范,是多个抽象方法的集合,仅仅只是定义了有哪些功能,本身不实现功能。
作用:
为了制定规范,体现了规范和事项相分离的思想,也体现了组件之间低耦合的特点。
耦合:各个部分之间的距离
内聚:各个部分内部的凝聚度
注意:
- 接口可以被认为是一种特殊的类,定义类的时候使用class关键字,定义接口的时候使用的是interface关键字。接口名一般以I开头
语法:
public interface 接口名{
//抽象方法1
//抽象方法2
//抽象方法3
.....
}
- 接口中的方法都是公共的抽象方法从Java8开始, Java支持在接口中定义有实现的方法
public interface Iwalkable{
void walk();
}
//等价于
public interface Iwalkable{
public abstract void walk();
}
public interface IWalkable {
public abstract void walk();//抽象方法
default void defaultMethod(){
System.out.println("有默认实现的方法, 属于对象");
}
static void defaultMethod(){
System.out.println("有默认实现的方法, 属于类");
}
}
- 类可以继承,但是不能多继承。接口可以继承,而且可以继承多个接口,也就是说一个接口可以同时继承多个接口,
public interface IAmphibiable extends IWalkable,ISwimable{
}
接口实现类
和抽象对象一样,接口也是不能创建对象的,必须要定义一个类去实现接口,并覆盖这个方法,这个类称为实现类,类和接口之间的关系称为实现关系(implements)
public class 类名 implements 接口名{
//覆盖接口中的方法
}
根据方法覆盖原则:子类方法的访问修饰符必须大于等于父类方法的访问修饰符,接口中的方法都是public修饰的,所以实现类中的方法只能使用public修饰。
如果是创建实现类对象,此时要面对接口编程:
接口名 变量名 = new 实现类();
如果既有继承又要实现接口,应该把继承写在前面。
public class 类名 extends 父类 implements 接口名...{
}
多态
public class Animal{}
public class Dog extends Animal{}
public class Cat extends Animal{}
public static void main(String[] args){
Dog dog = new Dog();
dog.eat();
//多态的体现
//Animal:编译类型
//Dog:运行类型
Animal d = new Dog();
//编译时期看Animal中是否有调用的方法
//如果有,编译通过
//在运行时期,先找Dog中是否存在方法,有就执行,如果没有就去父类中找方法
d.eat();
}
当编译类型和运行类型不一致的时候,多态就产生了。
注意:编译类型必须是运行类型的父类或者接口
所谓多态,就是一个对象可以有多种形态:
Animal a = null;
a = new Dog(); // a此时表示Dog类型的形态
a = new Cat(); // a此时表示Cat类型的形态
操作继承关系
父类引用变量指向于子类对象,调用方法时实际调用的是子类的方法
接口 变量名 = new 实现类();
变量名.方法();
public class Animal{}
public class Dog extends Animal{}
public class Cat extends Animal{}
public class AnimalDemo {
public static void main(String[] args) {
// 创建Cat对象
Animal a = new Cat();
a.shout();
// 创建Dog对象
a = new Dog();
a.shout();
}
}
操作实现关系
接口 变量名 = new 实现类();
变量名.方法();
多态时方法调用的问题
可以看出,此时通过多态的方法不能访问到父类不存在但是子类存在的方法,那么就引出了下面的问题
类型转换和instanceof运算符
- 自动类型转换:把子类对象赋给父类变量
- 强制类型转换:把父类类型对象赋给子类类型变量(ClassCastException类型转换异常:当把一个对象转换一个类型不匹配的对象时)
public class Dog extends Animal{
public void eat(){
System.out.println("吃屎");
}
public void sleep(){
System.out.println("睡觉");
}
}
Animal a = new Dog();
a.eat();
//在这里我们需要访问子类中特有的方法
//需要将Animal类型的变量a转换成Cat类型的变量
Dog d1 =(Dog) a;
d1.sleep();
instanseof:
Cat c = (Cat)a;
//运行报错:ClassCastException 类型转换异常。
//当把一个对象转换成一个类型不匹配的对象的时候就会报错
//instanceof判断对象是否时某一个类的实例
//语法:对象A instanceof 类B;
// 判断 A对象是否是 B类的实例?如果是,返回true
System.out.println(a instanceof Dog); //true
System.out.println(a instanceof Animal);//true
System.out.println(a instanceof Object); //true
System.out.println(a instanceof Cat); //false
if(a instanceof Cat){
Cat c = (Cat)a;
}
多态的好处
把实现类对象赋给接口类型变量,屏蔽了不同实现类之间的实现差异,从而做到通用编程
小结
- 接口和抽象类的区别:
1.接口可以多实现,抽象类可以不能多继承
2.接口里边的方法都是抽象方法,抽象类中即可以有抽象方法也可以有普通方法 - 接口和抽象类的相同点
都可以实现约束规范 - 接口和接口实现类定义的语法
接口: public interface 接口名{}
一般来说,接口名以I开头
接口实现类:public class 类名 (extends 父类名) implements 接口名 (,接口名){} - 实现类在实现一个接口的时候需要注意的地方