接口
定义格式
- JDK7:包含抽象方法
- JDK8:增加了默认方法和静态方法
- JDK9:增加了私有方法
示例
interface Flyable{
//静态常量
long MAX_SPEED = 7900000;//这里单位是毫米/秒,7.9千米/秒,超过这个速度,就变成卫星
//抽象方法
void fly();
//默认方法
public default void start(){
System.out.println("开始");
}
public default void stop(){
System.out.println("结束");
}
//静态方法
public static void broken(){
System.out.println("飞行中遇到物体就坏了");
}
}
接口的实现
接口不能创建对象,但是可以被实现(implements)
class Bird implements Flyable{ //重写/实现接口的抽象方法,【必选】 public void fly() { System.out.println("展翅高飞"); } //重写接口的默认方法,【可选】 //重写默认方法时,default单词去掉 public void start(){ System.out.println("先扇两下翅膀,一蹬腿,开始飞"); } }
public class TestInteface { public static void main(String[] args) { //创建实现类对象 Bird b = new Bird(); //通过实现类对象调用重写的抽象方法,以及接口的默认方法,如果实现类重写了就执行重写的默认方法,如果没有重写,就执行接口中的默认方法 b.start(); b.fly(); b.stop(); //通过接口名调用接口的静态方法 Flyable.broken(); } }
接口的多实现
接口中有多个抽象方法时,实现类必须重写所有抽象方法
如果抽象方法有重名的,只需要重写一次
【修饰符】 class 实现类 implements 接口1,接口2,接口3。。。{ // 重写接口中所有抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写 // 重写接口中默认方法【可选】 } 【修饰符】 class 实现类 extends 父类 implements 接口1,接口2,接口3。。。{ // 重写接口中所有抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写 // 重写接口中默认方法【可选】 }
冲突问题
亲爹优先原则
- 当一个类,既继承一个父类,又实现若干个接口时,父类的成员方法与接口中的抽象方法重名,子类就近选择执行父类的成员方法
必须做出选择
一个类同时实现了多个接口,而多个接口中包含方法签名相同的默认方法时,必须保留一个,或者选择自己完全重写
interface A{ public default void d(){ System.out.println("今晚7点-8点陪我吃饭看电影"); } } interface B{ public default void d(){ System.out.println("今晚7点-8点陪我逛街吃饭"); } }
class C implements A,B{ @Override public void d() { A.super.d(); } }
class D implements A,B{ @Override public void d() { System.out.println("自己待着"); } }
接口的多继承
- 一个接口能继承另一个或者多个接口,接口的继承也使用extends关键字
- 子接口重写默认方法时,default关键字可以保留
- 子类重写默认方法时,default关键字不可以保留
其他特点
- 接口中无法定义成员变量,但是可以定义常量,其值不可以改变2,默认使用public static final修饰
- 接口中没有构造方法,不能创建对象
- 接口中没有静态代码块
接口与实现类对象的多态引用
public class TestInterface {
public static void main(String[] args) {
Flyable b = new Bird();
b.fly();
Flyable k = new Kite();
k.fly();
}
}
interface Flyable{
//抽象方法
void fly();
}
class Bird implements Flyable{
@Override
public void fly() {
System.out.println("展翅高飞");
}
}
class Kite implements Flyable{
@Override
public void fly() {
System.out.println("别拽我,我要飞");
}
}
经典接口介绍
java.lang.Comparable
public class TestComparable {
public static void main(String[] args) {
Student s1 = new Student(1,"张三",89);
Student s2 = new Student(2,"李四",89);
if(s1.compareTo(s2)>0){
System.out.println("s1>s2");
}else if(s1.compareTo(s2)<0){
System.out.println("s1<s2");
}else{
System.out.println("s1 = s2");
}
}
}
class Student implements Comparable{
private int id;
private String name;
private int score;
//省略了构造器、get/set、toString等方法
@Override
public int compareTo(Object o) {
//这些需要强制,将o对象向下转型为Student类型的变量,才能调用Student类中的属性
Student stu = (Student) o;
if(this.score != stu.score){
return this.score - stu.score;
}else{//成绩相同,按照学号比较大小
return this.id - stu.id;
}
}
}
java.util.Comparator
class StudentScoreCompare implements Comparator{
@Override
public int compare(Object o1, Object o2) {
Student s1 = (Student) o1;
Student s2 = (Student) o2;
return s1.getScore() - s2.getScore();
}
}
import java.util.Comparator;
public class TestComparator {
public static void main(String[] args) {
Student stu1 = new Student("张三",89);
Student stu2 = new Student("李四",78);
StudentScoreCompare ssc = new StudentScoreCompare();
if(ssc.compare(stu1, stu2)>0){
System.out.println(stu1 + ">" + stu2);
}else if(ssc.compare(stu1, stu2)<0){
System.out.println(stu1 + "<" + stu2);
}else{
System.out.println(stu1 + "=" + stu2);
}
}
}
匿名内部类的使用
方式一:匿名内部类的对象直接调用方法
interface A{
void a();
}
public class Test{
public static void main(String[] args){
new A(){
@Override
public void a() {
System.out.println("aaaa");
}
}.a();
}
}
方式二:通过父类或父接口的变量多态引用匿名内部类的对象
class B{
public void b(){
System.out.println("bbbb");
}
}
public class Test{
public static void main(String[] args){
B obj = new B(){
public void b(){
System.out.println("ccccc");
}
};
obj.b();
}
}
方式三:匿名内部类的对象作为实参
interface A{
void method();
}
public class Test{
public static void test(A a){
a.method();
}
public static void main(String[] args){
test(new A(){
@Override
public void method() {
System.out.println("aaaa");
}
});
}
}