接口
接口是抽象类的更进一步. 抽象类中还可以包含非抽象方法, 和字段. 而接口中包含的方法都是抽象方法, 字段只能包含静态常量.
语法规则
interface IShape {
int a=10;//实际a为public static final int变量
void draw();//补全省略的为public abstract void draw();
}
class Cycle implements IShape {
@Override
public void draw() {
System.out.println("○");
}
}
public class Test {
public static void main(String[] args) {
IShape shape = new Cycle ();
shape.draw();
}
}
- 使用 interface 定义一个接口
- 接口中所有的方法必须是抽象方法, 因此可以省略 abstract
- 接口中的方法一定是 public, 因此可以省略 public
- 接口中的变量会被隐式的指定为 public static final 变量
- Cycle 使用 implements 继承接口. 此时表达的含义不再是 “扩展”, 而是 “实现”
- 在调用的时候同样可以创建一个接口的引用, 对应到一个子类的实例.
扩展(extends) vs 实现(implements)
扩展指的是当前已经有一定的功能了, 进一步扩充功能.
实现指的是当前啥都没有, 需要从头构造出来.
接口的注意事项
- 接口不能单独被实例化
- 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法。
- 接口不能包含成员变量,除了 static 和 final 变量。
- 接口不是被类继承了,而是要被类实现。
- 接口支持多继承。
注意
- 我们创建接口的时候, 接口的命名一般以大写字母 I 开头.
- 接口的命名一般使用 “形容词” 词性的单词.
- 阿里编码规范中约定, 接口中的方法和属性不要加任何修饰符号, 保持代码的简洁性
实现多个接口
有的时候我们需要让一个类同时继承自多个父类. 这件事情在有些编程语言通过多继承的方式来实现的.
然而 Java 中只支持单继承, 一个类只能 extends 一个父类. 但是可以同时实现多个接口, 也能达到多继承类似的效果.
现在我们通过类来表示一组动物
public class fr {
static class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
}
interface IFlying {
void fly();
}
interface IRunning {
void run();
}
interface ISwimming {
void swim();
}
static class Frog extends Animal implements IRunning, ISwimming {
public Frog(String name) {
super(name);
}
public void run() {
System.out.println(this.name + "正在往前跳");
}
public void swim() {
System.out.println(this.name + "正在蹬腿游泳");
}
}
public static void main(String[] args) {
Frog r = new Frog("青蛙");
r.run();
r.swim();
}
}
一个类继承一个父类, 同时实现多种接口.
有了接口之后, 类的使用者就不必关注具体类型, 而只关注某个类是否具备某种能力
接口间的继承
- 使用 extends 关键字.
interface IRunning {
void run();
}
interface ISwimming {
void swim();
}
interface IAmphibious extends IRunning, ISwimming {
}//IAmphibious 代表两栖动物
static class Frog extends Animal implements IAmphibious {
public Frog(String name) {
super(name);
}
public void run() {
System.out.println(this.name + "正在往前跳");
}
public void swim() {
System.out.println(this.name + "正在蹬腿游泳");
}
}
接口间的继承相当于把多个接口合并在一起
也可以增加接口中的方法——对接口进行扩展
interface A{
void func1();
}
interface B extends A {
void func2();
}//此时B里面既有func1方法,又有func2方法,实现了 对A的扩展
Comparable接口——java中的接口
该接口对实现它的每个类的对象强加一个整体排序。 这个排序被称为类的自然排序 ,类的compareTo方法被称为其自然比较方法 。
import java.util.Arrays;
class Student implements Comparable<Student>{//实现接口
public int age;
public String name;
public int score;
public Student(int age,String name,int score){ //定义构造方法,初始变量
this.age = age;
this.name = name;
this.score = score;
}
@Override
public String toString() { //重写打印数组的方法
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", score=" + score +
'}';
}
public int compareTo(Student o) { //重写接口中的compareTo方法,按年龄进行排序
if (this.age < o.age){ //返回小于的数字
return -1;
}else if (this.age > o.age){
return 1;
}else{
return 0;
}
}
}
public class demo{
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student(10,"a",98);
students[1] = new Student(50,"b",98);
students[2] = new Student(20,"c",98);
Arrays.sort(students);//对students这个数组按年龄进行排序
System.out.println(Arrays.toString(students));
}
}
//结果为
[Student{age=10, name='a', score=98}, Student{age=20, name='c', score=98}, Student{age=50, name='b', score=98}]
- 注意:如果没有实现Comparable接口,重写compareTo方法,对自定义类型的数据进行排序,调用Arrays.sort()方法时,会出现ClassCastException 异常
Cloneable接口——Java中的接口
Cloneable接口是标记型接口,实现Cloneable 接口来表示该类可以被克隆,才可以调用Object.clone() 方法对该类的实例进行按字段复制。如果在没有实现Cloneable 接口的实例上调用Object.clone() 方法,则会抛出CloneNotSupportedException(克隆不被支持)的异常。
Object.clone() 方法:
protected Object clone() throws CloneNotSupportedException;//创建并返回此对象的副本。按照惯例,返回的对象应该通过调用super.clone获得。
import java.security.spec.RSAOtherPrimeInfo;
class Person implements Cloneable{
public String name = "a";
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class clone {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person p = (Person) person.clone(); //调用clone()方法的返回值为Object类型,需强制转换为Person类型
System.out.println(person);
System.out.println(p);
System.out.println("==========");
p.name = "b";
System.out.println(person);
System.out.println(p);
}
}
//结果为
Person{name='a'}
Person{name='a'}
==========
Person{name='a'}
Person{name='b'}
接口和抽象类的区别
1.抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。