- 一、Comparable接口
- 二、Comparator接口
- 三、Cloneable接口
接口不是类,而是对类的一组需求描述,这些类要遵从接口描述的统一格式进行定义。
Arrays类中的sort方法承诺可以对对象数组进行排序,但要求满足下列前提:对象所属的类必须实现了Comparabe接口
下面是Comparable接口代码
public interface Comparable{ public int compareTo(T o); }
该接口对实现它的每个类的对象强加一个整体排序。 这个排序被称为类的自然排序 ,类的compareto方法被称为其自然比较方法 。
Collections.sort (和Arrays.sort )可以自动对实现此接口的对象进行列表(和数组)排序。
在实现Comparable
public int compareTo(T o);
1、当没有实现Comparable接口时
class Student { private String name; private int age; private float score; public Student(String name, int age, float score) { this.name = name; this.age = age; this.score = score; } @Override public String toString() { return "Student{" + "name='" + name + ''' + ", age=" + age + ", score=" + score + '}'; } }
public class InterfaceTest { public static void main(String[] args) { Student[] students = new Student[3]; students[0] = new Student("小明", 20, 68); students[1] = new Student("小红", 21, 78); students[2] = new Student("小李", 20, 99); System.out.println(Arrays.toString(students)); Arrays.sort(students); System.out.println(Arrays.toString(students)); } }
上述代码会抛出异常
因为sort方法不知道依据哪个属性进行排序。所以,利用sort想要对象实现排序功能,就必须提供对象的比较方法,这个时候就需要使用Comparable和Comparator
2、当实现Comparable接口
class Student implements Comparable{ private String name; private int age; private float score; public Student(String name, int age, float 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 InterfaceTest { public static void main(String[] args) { Student[] students = new Student[3]; students[0] = new Student("小明", 20, 68); students[1] = new Student("小红", 21, 78); students[2] = new Student("小李", 20, 99); System.out.println(Arrays.toString(students)); Arrays.sort(students); System.out.println(Arrays.toString(students)); } }
这时Student实现了Comparable接口,并且重写了compareto方法,compareto方法表示当前对象与参数中的对象进行比较,返回值为你要比较的方式,如果比较两个对象的年龄,就让当前对象的年龄减去参数中对象的年龄。
最终sort方法就完成了对对象的排序。
Comparator是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足要求时,可写一个比较器来完成两个对象之间大小的比较。
class Person { private String name; private int age; private double rise; public Person(String name, int age, double rise) { this.name = name; this.age = age; this.rise = rise; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public double getRise() { return rise; } public void setRise(double rise) { this.rise = rise; } @Override public String toString() { return "person{" + "name='" + name + ''' + ", age=" + age + ", rise=" + rise + '}'; } } class NameComparator implements Comparator{ @Override public int compare(Person o1, Person o2) { return o1.getName().compareTo(o2.getName()); } } class AgeComparator implements Comparator { @Override public int compare(Person o1, Person o2) { return o1.getAge() - o2.getAge(); } } class RiseComparator implements Comparator { @Override public int compare(Person o1, Person o2) { return (int)(o1.getRise() - o2.getRise()); } }
public class InterfaceTest { public static void main(String[] args) { Person[] person = new Person[3]; person[0] = new Person("小明", 20, 168.2); person[1] = new Person("小红", 21, 178.4); person[2] = new Person("小李", 20, 199); NameComparator nameComparator = new NameComparator(); Arrays.sort(person, nameComparator); System.out.println(Arrays.toString(person)); AgeComparator ageComparator = new AgeComparator(); Arrays.sort(person, ageComparator); System.out.println(Arrays.toString(person)); RiseComparator riseComparator = new RiseComparator(); Arrays.sort(person, riseComparator); System.out.println(Arrays.toString(person)); } }
上述代码中,我们实现了三种比较器,每个比较器都是一个类,而且实现了Comparator接口,重写了compare方法。
public int compare(Person o1, Person o2) { return o1.getAge() - o2.getAge(); }
o1 - 要比较的第一个对象。
o2 - 要比较的第二个对象。
clone方法是在Object种定义的,而且是protected型的,只有实现了这个接口,才可以在该类的实例上调用clone方法,否则会抛出CloneNotSupportException。
public class CloneTest { public static void main(String[] args) throws CloneNotSupportedException { Animal animal = new Animal(); Animal animal1 = (Animal) animal.clone(); } } class Dog { public int rise = 80; } class Animal implements Cloneable { private String name; private int age; public Dog dog = new Dog(); public Animal(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void run() { System.out.println("Animal.run"); } @Override public String toString() { return "Animal{" + "name='" + name + ''' + ", age=" + age + '}'; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } }
需要注意的是:我们进入clone方法(下方代码段),该clone的类型为Object,所以调用clone方法的时候应该强制转换为Animal,而且当前的Animal对象必须是可以被clone的,所以Animal类要实现cloneable接口。而当我们使用clone方法的时候,需要重写clone方法,并且抛出一个异常
protected native Object clone() throws CloneNotSupportedException;
下面看animal和animal1的大致内存图。
Object中默认的实现是一个浅拷贝,也就是表面拷贝,如果需要实现深层次拷贝的话,必须对类中可变域生成新的实例。这个时候就体现了为什么要重写clone方法。
public class CloneTest { public static void main(String[] args) throws CloneNotSupportedException { Animal animal = new Animal("小明", 21); Animal animal1 = (Animal) animal.clone(); animal1.dog.rise = 10; System.out.println(animal.toString()); System.out.println(animal1.toString()); } } class Dog implements Cloneable { public int rise = 80; @Override public String toString() { return "Dog{" + "rise=" + rise + '}'; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } class Animal implements Cloneable { private String name; private int age; public Dog dog = new Dog(); public Animal(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Animal{" + "name='" + name + ''' + ", age=" + age + ", dog=" + dog + '}'; } @Override public Object clone() throws CloneNotSupportedException { Animal tmp = (Animal) super.clone(); tmp.dog = (Dog) tmp.dog.clone(); return tmp; } }
我们来对比重写clone的代码
对于当前代码浅拷贝实现方式
@Override public Object clone() throws CloneNotSupportedException { return super.clone(); }
对于当前代码深拷贝实现方式
@Override public Object clone() throws CloneNotSupportedException { Animal tmp = (Animal) super.clone(); tmp.dog = (Dog) tmp.dog.clone(); return tmp; }
对比之后发现,其实多了层对Dog类的克隆,当克隆完之后新的tmp对象与之前被克隆对象互不影响。从而达成深拷贝。最后返回新对象。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)