一、抽象类
1.抽象类的概念
在Java语言中,所有的对象都是通过类来描绘的,而抽象类则是一个没有足够的信息来描绘任何对象的类,例如动物、植物等。
2.抽象类语法
在Java中,抽象类需要用到abstract关键字,抽象类无法给出具体的实体。
public abstract class Animal{
//被abstract修饰的方法叫做抽象方法;
//抽象方法必须被重写且没有方法体
abstruct public void eat();
abstract String name;
}
//抽象类中也可以有非抽象方法
public void run(String name){
System.out.println(this.name+"正在奔跑");
}
注:抽象类也是类,可以包含普通方法和属性以及构造方法。
关于抽象类,有一些注意事项:
-
抽象类不能用private、final和static关键字修饰,因为抽象类需要子类继承以达到实现实体的目的;
-
抽象类不可以实例化对象;
-
抽象类必须被继承,子类要重写抽象类中的抽象方法,除非子类也是一个抽象类;
-
抽象类中不一定有抽象方法,但有抽象方法的类一定要是抽象类;
-
抽象类的作用相当于多了一重编译器的校验,例如本来需要重写的方法没有重写就会报错产生提示,这对以后编码工作很有帮助。
二、接口
1.接口的概念
接口可以看作一个抽象类,它也没有足够的信息实例化对象,只能依靠类来实现自己的功能,不过与类不同的是,一个类可以实现多个接口,其语法规则为:
public interface 接口名称{
//抽象方法和字段
public String id;
public abstract method();
}
2.接口的使用
比如:想要实现电脑使用USB鼠标、USB键盘。
- USB接口:包含打开设备、关闭设备功能;
- 笔记本类:包含开机、关机、使用USB设备功能;
- 鼠标类:实现USB接口,具备点击功能;
- 键盘类:实现USB接口,具备输入功能;
Computer类:
public class Computer{public void powerOn(){System.out.println("正在执行开机功能......");}public void UseIUSB(IUSB iusb){iusb.OpenDevice();//判断传参进的接口具体实现是哪个类//是哪个类就调用对应类的方法if(iusb instanceof Keyboard){((Keyboard) iusb).input();}else if(iusb instanceof Mouse){((Mouse) iusb).Click();}iusb.CloseDevice();}public void powerClose(){System.out.println("正在执行关机功能......");}
}
IUSB接口:
public interface IUSB {public void OpenDevice();public void CloseDevice();
}
Keyboard类:
public class Keyboard implements IUSB{@Overridepublic void OpenDevice() {System.out.println("正在打开键盘服务");}public void input(){System.out.println("正在从键盘上输入内容");}@Overridepublic void CloseDevice() {System.out.println("正在关闭键盘服务");}
}
Mouse类:
public class Mouse implements IUSB{@Overridepublic void OpenDevice() {System.out.println("正在打开鼠标服务");}public void Click(){System.out.println("正在使用鼠标点击功能");}@Overridepublic void CloseDevice() {System.out.println("正在关闭鼠标服务");}
}
测试:
public class Test {//接口小练习public static void main(String[] args) {Computer computer = new Computer();//调用电脑的开机功能computer.powerOn();computer.UseIUSB(new Keyboard());System.out.println("===========");computer.UseIUSB(new Mouse());computer.powerClose();}
}
3.接口的特性
接口类型是一种引用类型,它也有着一些规则。
- 接口不可以直接被用作new一个对象;
- 接口中的每个方法都是public的抽象方法,(default和static修饰除外)变量和方法默认指定为public abstract,其他修饰符会报错;
- 接口中的方法不能在接口中实现,需要在“实现类”中重写;
- 重写接口方法时不能用默认访问权限;
- 接口中不可以有静态代码块和构造方法;
- 接口编译后的字节码文件后缀也是.class;
4.接口的好处
在实际应用中,一个程序中可以有很多接口,它们每个接口都可以实现不同的功能,使用接口的好处就在于可以使程序员不再关注接口功能实现的对象是什么,比如run()跑这个方法,只要有这个功能都可以调用这个接口,无所谓机器还是动物。
5.接口的继承
接口与接口之间也可以继承,继承的形式为:
public interface A{
//接口A的方法
}
public interface B{
//接口B的方法
}
public interface C extends A,B{
//此时接口C的方法中包含A和B的方法,
//而且接口C中也可以有新的方法,相当于扩展
//不过接口的C实现类还要继续实现A和B中的方法
}
例如:给对象数组排序
按照姓名比较:
import java.util.Comparator;public class NameCompare implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.name.compareTo(o2.name);}
}
按照年龄比较:
import java.util.Comparator;public class AgeCompare implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.age - o2.age;}
}
按照成绩比较:
import java.util.Comparator;public class ScoreCompare implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.score-o2.score;}
}
Student类:
import java.util.Comparator;
//这里的comparable接口实现的方法是compareTo,这个可以提供一个默认比较方法
//而comparator可以提供多种比较方式
public class Student implements Comparator<Student> ,Comparable<Student>{public String name;public int age;public int score;public Student(String name, int age, int score) {this.name = name;this.age = age;this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}@Overridepublic int compare(Student o1, Student o2) {return 0;}@Overridepublic int compareTo(Student o) {return this.name.compareTo(o.name);}
}
测试1:
public class Test {public static void main(String[] args) {Student student1 = new Student("张三",18,56);Student student2 = new Student("李四",20,62);AgeCompare ageCompare = new AgeCompare();if(ageCompare.compare(student1,student2)>0){System.out.println("student1 > student2");} else{System.out.println("student1 < student2");}}
}
测试2:利用这个机制给一个学生数组排序
import java.util.Arrays;public class Test2 {public static void BubbleSort(Comparable[] comparables){
// NameCompare nameCompare = new NameCompare();
//可以直接利用nameCompare引用for (int i = 0; i < comparables.length - 1; i++) {for (int j = 0; j < comparables.length - i - 1; j++) {if(0 < comparables[j].compareTo(comparables[j + 1])){Comparable temp = comparables[j];comparables[j] = comparables[j+1];comparables[j+1] = temp;}}}}public static void main(String[] args) {Student[] students = new Student[4];students[0] = new Student("zhangsan",18,6);students[1] = new Student("lisi",17,15);students[2] = new Student("wangwu",20,25);students[3] = new Student("afei",23,11);BubbleSort(students);System.out.println(Arrays.toString(students));}
}
6.cloneable接口以及拷贝
cloneable接口可以克隆一个对象,它能够将一个对象以及这个对象的引用进行拷贝,拷贝也分为深拷贝和浅拷贝。
例如:要拷贝一个Person类
class Money implements Cloneable{double money = 15.8;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}public class Person implements Cloneable {String name;Money m;public Person(String name) {this.name = name;this.m = new Money();}@Overrideprotected Object clone() throws CloneNotSupportedException {//这里如果直接写return super.clone();//那么就会使得money类没有被拷贝,这也就是所谓的浅拷贝//改为以下代码就变成了深拷贝Person tmp = (Person) super.clone();this.m = (Money) this.m.clone();return tmp;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +'}';}
}
public class Test1 {public static void main(String[] args) throws CloneNotSupportedException {Person person1 = new Person("张三");Person person2 = (Person) person1.clone();person2.name = "李四";System.out.println(person1);System.out.println(person2);System.out.println("======================");person2.m.money = 98.2;System.out.println(person1.m.money);System.out.println(person2.m.money);}
}
7.object类
object类是所有类的父类,如果一个类没有父类,那么默认object是它的父类,所有的类都可以使用Object的引用进行接收。
equals比较对象和hashCode方法:
import java.util.Objects;public class Person {String name;public Person(String name) {this.name = name;}@Overridepublic boolean equals(Object o) {
// return (this == o);if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return Objects.equals(name, person.name);}@Overridepublic int hashCode() {return Objects.hash(name);}
}
public class Test2 {public static void main(String[] args) {Person person1 = new Person("1234");Person person2 = new Person("1234");System.out.println(person1.equals(person2));System.out.println(person1.hashCode());System.out.println(person2.hashCode());}
}
equals可以提供一个判断两个对象是否一致的方法,而hashCode的作用是如果两个对象的name一致,那么就会确定这两个对象处在同一片空间,返回同一个哈希值。