接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。
1.接口使用关键字interface来修饰。
2.接口当中的成员方法,只能是抽象方法。所有的方法默认都是public abstract。
3.接口当中的方法如果要实现,需要用default来修饰
4.接口当中的成员变量,默认都是public static final
5.接口当中的静态方法,可以有具体的实现
6.接口不能进行实例化。new接口
7.一个普通的类,可以用implements来实现接口
8.接口中不能有静态代码块和构造方法
9.接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是.class
10. 如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类
下面用一个简单的代码来介绍一下上方的重点
interface IShape{
//成员变量
//成员方法
void draw();
default void func1(){
System.out.println("默认方法");
}
public static void staticFunc(){
System.out.println("静态方法");
}
}
class A implements IShape {
@Override
public void draw() {
System.out.println("haha");
}
}
public class TestDemo {
public static void main(String[] args) {
IShape a=new A();
a.draw();
a.func1();
IShape.staticFunc();
}
}
11.一个类,可以继承抽象类,同时也可以实现多个接口。每个接口之间用逗号隔开。
下面我用一个实例来演示一下。
class Animals{
public int age;
public String name;
public Animals(String name) {
this.name = name;
}
public void eat() {
System.out.println(this.name + "在吃饭");
}
}
interface IRunning{
void run();
}
interface ISwimming{
void swim();
}
interface IFlying{
void fly();
}
class Dog extends Animals implements IRunning,ISwimming{
public Dog(String name) {
super(name);
}
@Override
public void run() {
System.out.println(this.name+"正在跑");
}
@Override
public void swim() {
System.out.println(this.name+"正在游泳");
}
}
public class TestDemo {
public static void main(String[] args) {
Dog dog=new Dog("小狗");
dog.run();
dog.swim();
}
}
这里可以看出,接口的出现解决了多继承的问题。
下面来简单的用代码讲讲这个方法的运用。
class Animals{
public int age;
public String name;
public Animals(String name) {
this.name = name;
}
public void eat() {
System.out.println(this.name + "在吃饭");
}
}
interface IRunning{
void run();
}
interface ISwimming{
void swim();
}
interface IFlying{
void fly();
}
class Dog extends Animals implements IRunning,ISwimming{
public Dog(String name) {
super(name);
}
@Override
public void run() {
System.out.println(this.name+"正在跑");
}
@Override
public void swim() {
System.out.println(this.name+"正在游泳");
}
}
class Robit implements ISwimming{
@Override
public void swim() {
System.out.println("我是机器人,我在跑");
}
}
public class TestDemo {
public static void walk(ISwimming swimming){
swimming.swim();
}
public static void main(String[] args) {
ISwimming cat=new Dog("mimi");
ISwimming dog=new Dog("nini2");
walk(dog);
walk(cat);
walk(new Robit());
}
public static void main1(String[] args) {
Dog dog=new Dog("小狗");
dog.run();
dog.swim();
}
}
运行结果如下
12.类和接口之间是implements,那接口和接口之间的关系是什么呢?extends
下面用代码来实现一下结果。
interface A{
void func();
}
interface B{
void func1();
}
interface C extends A,B{
void func2();
}
class D implements C{
@Override
public void func() {
}
@Override
public void func1() {
}
@Override
public void func2() {
}
}
由此可知,接口和接口之间可以用extends来关联,但是当你关联之后,有一个类用了一种一个接口的时候,需要把相关的接口里面的方法全部都重写。
讲三个重要的接口,以前我们排序的代码如下
int[] a={32,1,24,29,17};
Arrays.sort(a);
System.out.println(Arrays.toString(a));
那现在我们新建了一个类,来描绘数组学生,里面有学生的姓名,年龄,成绩,那么我们应该怎么排序呢?代码如下
class Student implements Comparable<Student>{
public String name;
public int age;
public 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;
}
}
public class Test {
public static void main(String[] args) {
Student[] students=new Student[3];
students[0]=new Student("zhangsan",26,79.0);
students[1]=new Student("lisi",36,89.0);
students[2]=new Student("abc",46,99.0);
Arrays.sort(students);
System.out.println(Arrays.toString(students));
}
}
这个代码就是以年龄来排序,如果用其他的应该怎么写呢?
我就直接展示compareTo里面的代码吧。
public int compareTo(Student o) {
//return this.age-o.age;
return this.name.compareTo(o.name);
}
但是这个方法其实也有他自己的缺陷,你写的是age的比较,但是当其他人用的时候,想用name来比较,还得继续改,就比较麻烦。下面我就用一个新的方法来说一下,名字叫比较器。代码如下
class Student {
public String name;
public int age;
public 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<Student>{
@Override
public int compare(Student o1, Student o2) {
return o1.age-o2.age;
}
}
class StringComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
}
class ScoreComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return (int)(o1.score-o2.score);
}
}
public class Test {
public static void main(String[] args) {
Student[] students=new Student[3];
students[0]=new Student("zhangsan",26,79.0);
students[1]=new Student("lisi",36,89.0);
students[2]=new Student("abc",46,99.0);
AgeComparator ageComparator=new AgeComparator();
StringComparator stringComparator=new StringComparator();
ScoreComparator scoreComparator=new ScoreComparator();
Arrays.sort(students,ageComparator);
System.out.println(Arrays.toString(students));
Arrays.sort(students,stringComparator);
System.out.println(Arrays.toString(students));
Arrays.sort(students,scoreComparator);
System.out.println(Arrays.toString(students));
}
下面就提一下一个Clonable接口还有深拷贝,比前面的有一点点绕,但是其实还好。
class Person implements Cloneable{
public int i=1234;
@Override
public String toString() {
return "Person{" +
"i=" + i +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1=new Person();
Person person2=(Person) person1.clone();
System.out.println(person2);
}
}
这样就可以克隆person1里面的信息了。
下面来用代码表示一下什么叫深拷贝
class Money implements Cloneable{
public double money=19.9;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable{
public int i=1234;
public Money m=new Money();
@Override
public String toString() {
return "Person{" +
"i=" + i +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person tmp=(Person) super.clone();
tmp.m=(Money) this.m.clone();
return tmp;
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1=new Person();
Person person2=(Person) person1.clone();
System.out.println(person2);
System.out.println(person1.m.money);
System.out.println(person2.m.money);
person2.m.money=99.9;
System.out.println("=================");
System.out.println(person1.m.money);
System.out.println(person2.m.money);
}
}
实现深拷贝,是代码层次上进行的,不是说,某个方法是深拷贝,是从代码的实现上来看的
抽象类和接口的区别
抽象类和接口都是 Java 中多态的常见使用方式. 都需要重点掌握. 同时又要认清两者的区别(重要!!! 常见面试题).
核心区别: 抽象类中可以包含普通方法和普通字段, 这样的普通方法和字段可以被子类直接使用(不必重写), 而接口中不能包含普通方法, 子类必须重写所有的抽象方法.
抽象类存在的意义是为了让编译器更好的校验, 像 Animal 这样的类我们并不会直接使用, 而是使用它的子类.万一不小心创建了 Animal 的实例, 编译器会及时提醒我们.