目录
在面向对象语言中,所有对象都是用类来描述,但并不是所有对象都是用类来描述的,如果一个类没有包含足够的信息去描述一个对象,这就是抽象类。
接口是对一些共有的行为的一种规范,类只需要实现一些接口就可以实现属于自己的行为。
语法规则
abstract class A { abstract public void fun(); int a; public void fun2() { System.out.println("bbbbb"); } } class B extends A { public void fun() { System.out.println("aaaaa"); } }abstract修饰抽象类
注意:抽象类是没有足够的信息来描述一个对象,因此抽象类是不能实例化对象,最大的作用就是被类所继承。一般类继承抽象类是必须重写抽象类中抽象方法,除非是抽象类继承抽象类,但最终被一般类继承后还是得重写抽象类方法。由于抽象方法要被重写,所以不能被private,final,static修饰。抽象类也是类,所以它包含一般类应有的特性,比如也存在构造方法等等。
语法规则
interface A { void fun(); public abstract void fun2(); int a = 0; public static final int a2 = 0; } class B implements A { public void fun() { System.out.println("aaaaa"); } public void fun2() { System.out.println("bbbbb"); } }interface声明接口,implements实现接口
注意:
🎈接口就是规范行为,用来被实现的,所以不能实例化对象。接口中只能包含抽象方法和常量,就算方法或者变量前什么都不写,默认被public abstract和public static final修饰。由于接口不是类,其中不能包含静态代码块,和构造方法。
🎈在java中不支持多继承,但是一个类可以同时实现多个接口,对所有接口中抽象方法必须重写,否则就用抽象类实现。接口和接口之间是可以继承的,使用extends关键字,接口之间支持多继承。
class Person0 implements Cloneable{ int age; String name; public void fun() { System.out.println("aaaaa"); } public Person0(int age, String name){ this.age = age; this.name = name; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "Person0{" + "age=" + age + ", name='" + name + '\'' + '}'; } } public class Test13 { public static void main(String[] args) throws CloneNotSupportedException{ Person0 stu = new Person0(21,"www"); Person0 stu2 = (Person0)stu.clone(); System.out.println(stu); System.out.println(stu2); } }
🤨所有没有继承类的类默认都继承了Object类。
🤨原码中Cloneable是一个空接口,其中没有任何的抽象方法,是由于在Object类中有clone方法,Cloneable的存在就是让我们清楚看见这个类实例化的对象是支持克隆的。所以我们只需要重写clone方法,然后去调用父类Object中clone方法。
import java.util.Arrays; class Person0 implements Comparable{ int age; String name; public void fun() { System.out.println("aaaaa"); } public Person0(int age, String name) { this.age = age; this.name = name; } @Override public String toString() { return "Person0{" + "age=" + age + ", name='" + name + '\'' + '}'; } @Override public int compareTo(Person0 o) { return this.age - o.age; } } public class Test13 { public static void main(String[] args) throws CloneNotSupportedException { Person0[] stu = {new Person0(21,"www"), new Person0(18,"qqq"),new Person0(25,"eee")}; Arrays.sort(stu); System.out.println(Arrays.toString(stu)); } }🪖实现Comparable接口,重写comeTo方法,调用Arrays类下的sort方法就可以对stu数组指定排序。由于sort方法中原码,是把传过去的对象强转成Comparable,然后调用comparTo方法。这就是接口和多态的强大。
浅拷贝
class Money{ int m = 100; } class Person5 implements Cloneable{ Money money = new Money(); @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } public class Test14 { public static void main(String[] args) throws CloneNotSupportedException{ Person5 stu = new Person5(); Person5 stu1 = (Person5)stu.clone(); stu1.money.m = 200; System.out.println(stu.money.m); System.out.println(stu1.money.m); } }
🎄可以清楚看见stu1里money对象的m修改后,stu里面money对象的m也被修改了。这是因为stu和stu1所指向对象里money的地址是相同的,意味着指向的是同一个m。
深拷贝
class Money implements Cloneable{ int m = 100; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } class Person5 implements Cloneable{ Money money = new Money(); @Override protected Object clone() throws CloneNotSupportedException { Person5 tmp = (Person5)super.clone(); tmp.money = (Money)this.money.clone(); return tmp; } } public class Test14 { public static void main(String[] args) throws CloneNotSupportedException{ Person5 stu = new Person5(); Person5 stu1 = (Person5)stu.clone(); stu1.money.m = 200; System.out.println(stu.money.m); System.out.println(stu1.money.m); } }
🧢 可以清楚看见改变stu1引用对象里money的m后,stu引用对象里money的m没有改变。这是由于拷贝时,改变了stu1引用对象里money的指向,意味着指向的m是不同的。
🐵一些不懂的地方,可以尝试看看原码,会提升自己对代码逻辑的理解,坚持就会有不一样的收获。