接口
什么是接口
在Java中,接口可以看成是:多个类的公共规范,接口是一种引用数据类型。
接口的特点
1、使用interface来修饰接口
2、接口的成员变量默认都是public static final修饰的,因为有final,所以要进行初始化赋值
3、接口的成员方法默认都是抽象方法【以后的类要进行重写抽象方法】,由public abstract 修饰
4、接口的普通成员方法一般是不能有具体的实现的,但是在前面加上default就可以加上具体实现【JDK8以后才有的】
5、接口中可以有静态的成员方法,但是不管是default还是静态的方法,都是public的
6、接口也不能进行实例化
7、类与接口之间使用implements关联,接口可以引用具体的实现类,也能实现向上转型
8、接口里面不能有代码块或者构造方法(都不能实例化,要构造方法干什么呢)
9、抽象类实现一个接口,可以在在前面加上abstract,就不用重写接口中的抽象方法,但是下面还是要写别的类,还是要重写抽象方法【重写抽象方法是逃不掉的】
interface IShape{
int COUNT=12;//接口的成员变量默认是public static final修饰的
void func();//接口的成员方法默认是public abstract修饰的
void func1();//接口的成员方法一般不具体实现
default void func2() {
System.out.println("haha");
}
static void func3() {
System.out.println("heihei");
}
}
public class Test {
//IShape iShape=new IShape(); err,接口也是不能实例化的
}
复制代码
接口的具体应用
interface IShape{ //interface修饰接口
void draw();
}
class Rect implements IShape { //使用implements来连接接口与具体的类,叫做实现
@Override //对抽象方法重写
public void draw() { //上面的draw方法是public,所以这里要想访问draw就必须要使用public(大于等于接口的访问修饰限定符)
System.out.println("矩形");
}
}
class Circle implements IShape {
@Override
public void draw() {
System.out.println("圆");
}
}
public class Test {
public static void drawMap(IShape shape){
shape.draw();//动态绑定
}
public static void main(String[] args) {
//IShape iShape=new IShape();//err,接口不能实例化
IShape rect= new Rect();//向上转型
drawMap(rect);
IShape circle = new Circle();
drawMap(circle);
//不进行实例化
/* drawMap(new Rect());
drawMap(new Circle());*/
}
}
复制代码
多个接口的具体使用
abstract class Animal{
String name;
int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public abstract void eat();//吃
}
//如何实现跑的动作?
//首先,不是所有的动物都能跑,所以跑这个动作不能放在Animal里面,其次,要是再写一个跑的类,但是Java是不允许多继承的(一个子类继承两个父类)
//所以为了实现这样的灵活调用,就要用到多个接口
interface IRUNNING{ //跑步的接口
void run();
}
interface IFLYING{ //飞的接口
void fly();
}
class Dog extends Animal implements IRUNNING { //Dog这个类继承了Animal类并且实现了IRUNNING接口
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(this.name + "正在吃狗粮");
}
@Override
public void run() {
System.out.println(this.name+"正在四处跑");
}
}
class Bird extends Animal implements IRUNNING,IFLYING{ //Bird类继承了Animal类并且实现了IRUNNING,IFLYING多个接口,而狗就没有飞这个功能/接口,所以使用接口十分灵活
public Bird(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(this.name+"正在吃鸟粮");
}
@Override
public void run() {
System.out.println(this.name+"正在用细细的腿跳着跑");
}
@Override
public void fly() {
System.out.println(this.name+"准备起飞");
}
}
public class test {
public static void Run(IRUNNING irunning) { //传过来的都已经实现了接口,所以可以成功
irunning.run();
}
public static void main(String[] args) {
Run(new Dog("旺财", 2));
Run(new Bird("小鸟", 3));
}
//以下是多态的使用,可以对比一下
public static void func(Animal animal) {
animal.eat();
public static void main1(String[] args) {
func(new Dog("旺财", 2));
func(new Bird("小鸟", 3));
}
}
}
复制代码
继承是is-a的关系(子类父类包含关系),接口是XXX特性,十分灵活
接口的继承
接口可以继承别的接口,也是使用extends,实现代码的复用
interface IA{
void func1();
}
interface IB{
void func2();
}
//接口的继承---接口功能的拓展
//IC拥有IA和IB的功能
interface IC extends IA, IB{
void func3();
}
class A implements IC{
@Override
public void func1() {
}
@Override
public void func2() {
}
@Override
public void func3() {
}
}
public class test {
}
复制代码
几种常用的接口
1、比较自定义类型的大小 / 排序(Comparable接口)
注意:实现接口后面还要加上<自定义类名>
//比较大小
class Student implements Comparable{ //此时会报错,直接alt+enter,就可以重写compareTo方法
String name;
int age;
double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
@Override
public int compareTo(Student o) { //重写compareTo方法
/*if (this.age > o.age) {
return 1;
} else if (this.age == o.age) {
return 0;
} else {
return -1;
}
*/
return this.age-o.age;//o就是传的参数,谁调用compareTo谁就是this
//两种代码效果是一样的,按照年龄比较大小
}
}
public class test {
public static void main(String[] args) {
Student student1 = new Student("zhangsan", 32, 29.0);
Student student2 = new Student("lisi", 20, 1.2);
if (student1.compareTo(student2) > 0) {
System.out.println("student1>student2");
}
}
}
复制代码
//排序
import java.util.Arrays;
class Student implements Comparable{
String name;
int age;
double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
@Override
public int compareTo(Student o) { //重写
return this.age-o.age;//o就是传的参数,谁调用compareTo谁就是this
//要是想要改为降序就调换一下减的顺序
}
}
public class test {
public static void main(String[] args) {
Student[] student= new Student[3]; //定义Student类型的数组
student[0] = new Student("zhangsan", 32, 29.0);
student[1] = new Student("lisi", 20, 1.2);
student[2] = new Student("wangwu", 52, 89);
System.out.println("排序前"+Arrays.toString(student));
Arrays.sort(student);//要是不写Comparable接口就不知道是按照什么进行排序的
System.out.println("排序后"+Arrays.toString(student));//升序打印
}
}
复制代码
但是上面使用Comparable接口,就将比较/排序的规则定死了,已经加入到了Student类里面,后期就会不方便改
此时既可以使用Comparator接口
2、Comparator接口(比较器)
import java.util.Comparator;
//比较大小
class Student {
String name;
int age;
double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
class AgeComparator implements Comparator { //定义一个年龄比较器的类
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}
class ScoreComparator implements Comparator{ //定义一个分数比较器的类
@Override
public int compare(Student o1, Student o2) {
return (int )(o1.score - o2.score);
}
}
class NameComparator implements Comparator { //定义一个名字比较器的类
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);//compareTo的返回值是int
}
}
public class test {
public static void main(String[] args) {
Student student1 = new Student("zhangsan", 32, 29.0);
Student student2 = new Student("lisi", 20, 1.2);
AgeComparator ageComparator = new AgeComparator();//实例化年龄比较器
int ret=ageComparator.compare(student1, student2);
System.out.println(ret);
ScoreComparator scoreComparator = new ScoreComparator();//实例化分数比较器
int ret2 = scoreComparator.compare(student1, student2);
System.out.println(ret2);
NameComparator nameComparator = new NameComparator();//实例化名字比较器
int ret3 = nameComparator.compare(student1, student2);
System.out.println(ret3);
}
//年龄之差12
//分数之差是27
//名字的首字母相差14
复制代码
使用比较器对数组元素进行排序
import java.util.Arrays;
import java.util.Comparator;
class Student {
String name;
int age;
double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
class AgeComparator implements Comparator {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}
class ScoreComparator implements Comparator{
@Override
public int compare(Student o1, Student o2) {
return (int)(o1.score - o2.score);
}
}
class NameComparator implements Comparator {
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);//compareTo的返回值是int
}
}
public class test {
public static void main(String[] args) {
Student[] student= new Student[3];
student[0] = new Student("zhangsan", 32, 29.0);
student[1] = new Student("lisi", 20, 1.2);
student[2] = new Student("wangwu", 52, 89);
AgeComparator ageComparator = new AgeComparator();//实例化年龄比较器
Arrays.sort(student, ageComparator);//Arrays.sort是可以重载的(既可以只放一个数组名,还能再放一个比较器对象)
System.out.println(Arrays.toString(student));
ScoreComparator scoreComparator = new ScoreComparator();
Arrays.sort(student, scoreComparator);
System.out.println(Arrays.toString(student));
NameComparator nameComparator = new NameComparator();
Arrays.sort(student, nameComparator);
System.out.println(Arrays.toString(student));
}
//[Student{name='lisi', age=20, score=1.2}, Student{name='zhangsan', age=32, score=29.0}, Student{name='wangwu', age=52, score=89.0}]
//
//[Student{name='lisi', age=20, score=1.2}, Student{name='zhangsan', age=32, score=29.0}, Student{name='wangwu', age=52, score=89.0}]
//
//[Student{name='lisi', age=20, score=1.2}, Student{name='wangwu', age=52, score=89.0}, Student{name='zhangsan', age=32, score=29.0}]
复制代码
使用比较器不会涉及到自定义的类,想要按照什么比较就写一个专门的比较器,实例化 比较器来进行比较,所以写比较器是十分灵活的,十分好用
3、克隆当前对象(Cloneable接口)
class Person implements Cloneable{ //Cloneable里面没有任何东西,是一个空接口/标记接口:说明当前类可以被克隆
public int age;
public Person(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException { //正式实现克隆 alt+enter,选中clone即可
//重写的是Object里面的clone方法(由C/C++写的,所以看不见)
return super.clone();
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person(10);
Person person2= (Person) person.clone();//要将Object类型的强转为Person
System.out.println(person);
System.out.println(person2);
}
}