抽象类
什么是抽象类
被abstract修饰的类就是抽象类。抽象类是类的进一步抽象,抽象类中的方法可以不做具体的实现(抽象方法,由abstract修饰)。抽象类中也可以有普通方法。
抽象方法不能由static和final修饰,因为抽象方法要被子类重写。
抽象类中不一定要有抽象方法,但是有抽象方法的类一定是抽象类。
抽象类不能实例化,但可以引用其子类对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 abstract class Animal { public String name; public Animal (String name) { this .name = name; } public abstract void eat () ; } class Dog extends Animal { public Dog (String name) { super (name); } @Override public void eat () { System.out.println(this .name+"正在吃狗粮" ); } } public class Demo1 { public static void main (String[] args) { Animal animal = new Dog("旺旺" ); animal.eat(); } }
执行结果:旺旺正在吃狗粮
为什么需要抽象类
抽象类中的方法可以不做具体实现,为了子类能够继承该抽象类。使用抽象类能够多一层编译器校验,增加了安全性。就像常量用final修饰,不小心修改时编译器会报错提醒。
像上面的代码main方法中new Dog改成new Animal,编译器就会报错:‘Animal’ is abstract; cannot be instantiated。
接口
什么是接口
接口是多个类的公共规范,是一种引用数据类型。接口可以理解为一种功能、特性,类实现某个接口,便可以具备某种功能。
接口中的方法默认是由public abstract修饰,接口中的属性默认是public final static。建议接口中的方法和属性不加任何修饰符号, 保持代码的简洁性.
接口不能实例化。
接口中不能有静态代码块和构造方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 interface Running { void run () ; } interface Flying { void fly () ; } abstract class Animal { public String name; public Animal (String name) { this .name = name; } public abstract void eat () ; } class Dog extends Animal implements Running { public Dog (String name) { super (name); } @Override public void eat () { System.out.println(this .name+"正在吃狗粮" ); } @Override public void run () { System.out.println(this .name+"正在扑向他的主人" ); } } class Bird extends Animal implements Flying { public Bird (String name) { super (name); } @Override public void eat () { System.out.println(this .name+"正在觅食" ); } @Override public void fly () { System.out.println(this .name+"正在天空中自由地翱翔" ); } } public class Demo1 { public static void main (String[] args) { Dog dog = new Dog("旺旺" ); dog.eat(); dog.run(); Bird bird = new Bird("飞儿" ); bird.eat(); bird.fly(); } }
执行结果:
旺旺正在吃狗粮
旺旺正在扑向他的主人
飞儿正在觅食
飞儿正在天空中自由地翱翔
为什么需要接口
Java不允许多重继承,通过接口可以提供多重继承的大部分好处,同时还能避免多重继承的复杂性和低效性。
接口的使用实例
Comparable接口
对数组元素按年龄排序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import java.util.Arrays;class Student implements Comparable <Student > { public String name; public int age; public Student (String name, int age) { this .name = name; this .age = age; } @Override public String toString () { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}' ; } @Override public int compareTo (Student o) { return this .age-o.age; } } public class Compare { public static void main (String[] args) { Student[] students = new Student[]{ new Student("panghu" ,20 ), new Student("xiaofu" ,18 ), new Student("daxiong" ,19 ), new Student("jingxiang" ,16 ) }; Arrays.sort(students); System.out.println(Arrays.toString(students)); } }
执行结果:
[Student{name=‘jingxiang’, age=16}, Student{name=‘xiaofu’, age=18}, Student{name=‘daxiong’, age=19}, Student{name=‘panghu’, age=20}]
上面代码有一个问题,只能按年龄排序,如果想按姓名排序就要修改compareTo方法,修改后又只能按姓名排序。有没有一种办法,可以实现按不同的属性进行排序。利用比较器可以实现该要求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 import java.util.Arrays;import java.util.Comparator;class Student1 { public String name; public int age; public Student1 (String name, int age) { this .name = name; this .age = age; } @Override public String toString () { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}' ; } } class AgeComparator implements Comparator <Student1 > { @Override public int compare (Student1 o1, Student1 o2) { return o1.age-o2.age; } } class NameComparator implements Comparator <Student1 > { @Override public int compare (Student1 o1, Student1 o2) { return o1.name.compareTo(o2.name); } } public class Compare1 { public static void main (String[] args) { Student1[] students = new Student1[]{ new Student1("panghu" ,20 ), new Student1("xiaofu" ,18 ), new Student1("daxiong" ,19 ), new Student1("jingxiang" ,16 ) }; AgeComparator ageComparator = new AgeComparator(); NameComparator nameComparator = new NameComparator(); Arrays.sort(students,ageComparator); System.out.println("按年龄" +Arrays.toString(students)); Arrays.sort(students,nameComparator); System.out.println("按姓名" +Arrays.toString(students)); } }
执行结果:
按年龄[Student{name=‘jingxiang’, age=16}, Student{name=‘xiaofu’, age=18}, Student{name=‘daxiong’, age=19}, Student{name=‘panghu’, age=20}]
按姓名[Student{name=‘daxiong’, age=19}, Student{name=‘jingxiang’, age=16}, Student{name=‘panghu’, age=20}, Student{name=‘xiaofu’, age=18}]
Clonable接口
实现Clonable接口需要重写Object类的clone()方法,在方法中使用super关键字调用Object类的clone()方法,然后调用该方法即可实现克隆。
浅拷贝:仅仅拷贝当前对象本身,不拷贝引用类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Phone { public String phone; } class Person implements Cloneable { public int age; Phone p = new Phone(); @Override protected Object clone () throws CloneNotSupportedException { return super .clone(); } @Override public String toString () { return "Person{" + "age=" + age + ", p.phone=" + p.phone + '}' ; } } public class Demo { public static void main (String[] args) throws CloneNotSupportedException { Person person = new Person(); person.age=20 ; person.p.phone="xiaomi" ; Person person2 = (Person)person.clone(); person2.age=10 ; person2.p.phone="iphone" ; System.out.println(person); System.out.println(person2); } }
深拷贝:不仅拷贝当前对象,还拷贝其引用类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class Phone implements Cloneable { public String phone; @Override protected Object clone () throws CloneNotSupportedException { return super .clone(); } } class Person implements Cloneable { public int age; Phone p = new Phone(); @Override protected Object clone () throws CloneNotSupportedException { Person tmp = (Person) super .clone(); tmp.p= (Phone) this .p.clone(); return tmp; } @Override public String toString () { return "Person{" + "age=" + age + ", p.phone=" + p.phone + '}' ; } } public class Demo1 { public static void main (String[] args) throws CloneNotSupportedException { Person person = new Person(); person.age=20 ; person.p.phone="xiaomi" ; Person person2 = (Person)person.clone(); person2.age=10 ; person2.p.phone="iphone" ; System.out.println(person); System.out.println(person2); } }