目录
一、抽象类
1、介绍
抽象类只能被继承,使用abstract修饰,内部的成员方法没有具体实现,是抽象方法,抽象类被继承后,子类必须要重写父类的构造方法。
2、为什么要有抽象类
对代码多一层检验,提前发现错误。因为如果开发时本来不能使用父类,需要使用使用子类,但是不小心使用了父类,这就发生了错误,将父类设置为抽象类,由于抽象类不能直接使用,所以会提前提醒,尽早发现问题。
3、规则
基于上述抽象类的特性,所以会有以下几种规则:
- 抽象方法不能被private,static,final修饰,因为会使得不能被重写,方法默认为public。
- 抽象类中不规定必须要有抽象方法,但有抽象方法的类,一定是抽象类
二、接口
1、介绍
例:电脑的usb接口,只要一个产品符合相应的规范,就可以使用这个usb接口。
Java的接口与usb接口类似,只要一个类符合相应的规范,具有相关功能,就可以实现某个接口。
类之间的继承的关系是:is - a的关系,而接口之间是(xxxx具有xxxx)的功能。
例:猫是动物,具有跑的功能。
java
public class Cat extends Animal implements IRunning {
}
语法格式:class换成了interface。
java
public interface 接口名称 {
}
2、为什么要有接口
为了解决Java不能多继承的问题,一个类只能继承一个类,但是可以实现多个接口。
3、接口的应用
若有两个数据进行比较大小,如果是普通的数据类型可以直接比较,但是如果数据的类型是引用数据类型,那么不能直接进行比较,有两种方法,第一种方法 是使得数据的类实现Comparable接口,在类中重写接口的comparTo方法;第二种方法是不在类中写出比较的方法,直接创建新的类,这种类叫做比较器,让比较器实现Compartor接口,在比较器中重写接口中的compare方法。
第一种方法:
java
class Student implements Comparable<Student> {
private int age;
private String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
}
public class Test01 {
public static void main(String[] args) {
Student student1 = new Student(10,"xxp");
Student student2 = new Student(20,"zyt");
System.out.println(student1.compareTo(student2));
}
}
第二种方法:
java
import java.util.Comparator;
class Student implements Comparable<Student> {
public int age;
public String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
}
class AgeCompartor implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age-o2.age;
}
}
class NameCompartor implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
}
public class Test01 {
public static void main(String[] args) {
Student student1 = new Student(10,"xxp");
Student student2 = new Student(20,"zyt");
//System.out.println(student1.compareTo(student2));
AgeCompartor ageCompartor = new AgeCompartor();
NameCompartor nameCompartor = new NameCompartor();
ageCompartor.compare(student1,student2);
nameCompartor.compare(student1,student2);
}
}
这两种方法相比,第一种方法不如第二种灵活,因为第一种方法的只能比较一种,age或者name,不能兼得,第二种方法可以比较两种,灵活。
若给出一个数组,要将数组中的元素进行排序,而且里面的元素是引用数据类型,该如何比较呢?导入Arrays这个工具类,调用Arrays的sort方法,将数组作为参数传进去,由于传进去的是引用数据类型,所以sort方法会将数组的元素的类型强转为Comparable类,调用comparTo方法比较,所以数组的那些元素的类必须实现Comparable接口,否则无法强转。
java
import java.util.Arrays;
import java.util.Comparator;
class Student implements Comparable<Student> {
public int age;
public String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
}
public class Test01 {
public static void main(String[] args) {
Student student1 = new Student(10,"xxp");
Student student2 = new Student(20,"zyt");
Student[] stu = {student1,student2,new Student(30,"lll")};
Arrays.sort(stu);
}
}
也可以将数组和比较器一起作为参数传进去,sort方法会根据比较器的比较原则,对数组中的元素进行比较。
java
import java.util.Arrays;
import java.util.Comparator;
class Student implements Comparable<Student> {
public int age;
public String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
}
class AgeCompartor implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age-o2.age;
}
}
class NameCompartor implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.name.compareTo(o2.name);
}
}
public class Test01 {
public static void main(String[] args) {
Student student1 = new Student(10,"xxp");
Student student2 = new Student(20,"zyt");
Student[] stu = {student1,student2,new Student(30,"lll")};
AgeCompartor ageCompartor = new AgeCompartor();
Arrays.sort(stu,ageCompartor);
}
}
- 4、浅拷贝与深拷贝
拷贝就是拷贝一个对象,产生新的对象。深浅之别在于,如果要拷贝的对象中,某个成员变量是引用,那么引用的对象如果不拷贝,就是浅拷贝,对象也拷贝的话,就是深拷贝。
浅拷贝:
java
import java.util.Arrays;
import java.util.Comparator;
class Student implements Comparable<Student> ,Cloneable {
public int age;
public String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Test01 {
public static void main(String[] args) throws CloneNotSupportedException {
Student student1 = new Student(10,"xxp");
Student student2 = new Student(20,"zyt");
Student student3 = (Student)student1.clone();
}
}
深拷贝:
java
import java.util.Arrays;
import java.util.Comparator;
class Money {
public int m;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Student implements Comparable<Student> ,Cloneable {
public int age;
public Money money = new Money();
public String string;
public Student(int age, String string) {
this.age = age;
this.string = string;
}
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
//拷贝了普通数据
Student student = (Student)super.clone();
//拷贝对象
student.money = (Money) this.money.clone();
return student;
}
}
public class Test01 {
public static void main(String[] args) throws CloneNotSupportedException {
Student student1 = new Student(10,"xxp");
Student student2 = new Student(20,"zyt");
Student student3 = (Student)student1.clone();
}
}
- 5、抽象类与接口之间有什么区别
接口比抽象类更加抽象,接口里面不允许有普通的成员变量与普通的成员方法,抽象类不做要求。
接口里面的变量默认为public static final修饰,方法默认为public abstract。
三、内部类
当有需求,创建出一个对象只在一个类中使用时,那么可以将类创建在类里面,也就是内部类。
内部类分为4种:
1、实例内部类
由于内部类是类的成员,所以创建内部类对象时,要先创建出外部类的对象。
java
public class Date {
private int year;
private int month;
private int day;
class Type {
}
public void setDate(int year,int month,int day){
this.year = year;
this.month = month;
this.day = day;
}
public static void main(String[] args) {
Date date = new Date();
Date.Type type = date.new Type(); //通过外部类创建的对象date去.new Type(),因为内部类是外部类的成员。
}
注意:当内部类与外部类有同名的成员变量或者方法时,在内部类的方法中优先访问的是内部类中的变量和方法,如果非要访问外部类的,也可以,通过外部类名.this.可以完成访问。
2、静态内部类
java
public class Date {
private int year;
private int month;
private int day;
static class Type {
}
public void setDate(int year,int month,int day){
this.year = year;
this.month = month;
this.day = day;
}
public static void main(String[] args) {
Date date = new Date();
Date.Type type = new Date.Type(); //因为是静态的,所以通过外部类名.内部类名
}
}
3、局部内部类
这个用的很少,只能在方法体中使用。
4、匿名内部类
这个内部类没有名字。
java
IA ia = new Ia () {
}
//这是一个匿名内部类的对象,然后将对象赋值给了ia