接口
- 一.对学生进行排序
- 二.Clonable接口
- 三.抽象类和接口的区别
- 四.Object类
一.对学生进行排序
很明显我们直接对学生进行排序是会报错的,因为编译器也不知道你需要按照名字排还是分数排,我们点击报错位置进入sort内部。
在sort内部我们可以看到它把数组转换成立一个Comparable类型。而这个Comparable是一个接口型,而这个接口里有一个compareto方法,我们需要实现这个接口。
import java.util.Arrays;
class Student implements Comparable<Student>{
String name;
int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name=" + name +
", score=" + score +
'}';
}
@Override
public int compareTo(Student o) {
if(this.score<o.score) return 1;
else if(this.score>o.score) return -1;
else return 0;
}
}
public class sort {
public static void main(String[] args) {
Student[] st=new Student[3];
st[0]=new Student("张三",28);
st[1]=new Student("李四",100);
st[2]=new Student("王麻子",63);
Arrays.sort(st);//排序
System.out.println(Arrays.toString(st));//打印出来
}
}
但是这样写有一个很明显缺点,就是写死了。它这个类就只能按年龄比较,为了更加灵活,java又提供了另一个接口comparator。
import java.util.Arrays;
import java.util.Comparator;
class Student{
String name;
int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name=" + name +
", score=" + score +
'}';
}
}
//灵活方法
class Scompare implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
if(o1.score<o2.score) return 1;
else if(o1.score>o2.score) return -1;
else return 0;
}
}
public class sort {
public static void main(String[] args) {
Student[] st=new Student[3];
st[0]=new Student("张三",28);
st[1]=new Student("李四",100);
st[2]=new Student("王麻子",63);
//使用
Scompare s=new Scompare();
Arrays.sort(st,s);//排序
System.out.println(Arrays.toString(st));//打印出来
}
}
二.Clonable接口
Java 中内置了一些很有用的接口, Clonable 就是其中之一
Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对象的 “拷贝”。但是要想合法调用 clone 方法, 必须要先实现Clonable 接口, 否则就会抛出 CloneNotSupportedException 异常。object是所有类的父类(即使你没有写任何继承)。
import java.util.Arrays;
import java.util.Comparator;
class Student implements Cloneable{
String name;
int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name=" + name +
", score=" + score +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class sort {
//因为克隆会抛出一个异常,所以main函数也需要声明异常
public static void main(String[] args) throws CloneNotSupportedException{
Student A=new Student("张三",60);
//因为克隆方法是object里的,object是所有类的父类
//这里相当于向下转,所以需要强转转型
Student B=(Student) A.clone();
System.out.println(B);
}
}
上面我们仅仅是调用的object的克隆方法会问题,更改一下代码
这里出现了问题,我们只对A的money进行了修改,就跟B的money也发生了改变,不符合我们的预期。
因为我们仅仅将A里Money类的地址进行了拷贝,所以两者指向的Money对象自然是同一个,接下来实现一下让他们指向不同Money。
import java.util.Arrays;
import java.util.Comparator;
class Money implements Cloneable{
public double money=12.5;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Student implements Cloneable{
public String name;
public int score;
public Money m=new Money();
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name=" + name +
", score=" + score +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
//克隆了student对象
Student stu=(Student) super.clone();
//克隆了student里的money对象
stu.m=(Money) this.m.clone();
return stu;
}
}
public class sort {
//因为克隆会抛出一个异常,所以main函数也需要声明异常
public static void main(String[] args) throws CloneNotSupportedException{
Student A=new Student("张三",60);
//因为克隆方法是object里的,object是所有类的父类
//这里相当于向下转,所以需要强转转型
Student B=(Student) A.clone();
System.out.println(A.m.money);
System.out.println(B.m.money);
System.out.println("#########");
A.m.money=52.2;
System.out.println(A.m.money);
System.out.println(B.m.money);
}
}
三.抽象类和接口的区别
核心区别: 抽象类中可以包含普通方法和普通字段, 这样的普通方法和字段可以被子类直接使用(不必重写), 而接口中不能包含普通方法,子类必须重写所有的抽象方法。
四.Object类
Object是Java默认提供的一个类。Java里面除了Object类,所有的类都是存在继承关系的。默认会继承Object父类。即所有类的对象都可以使用Object的引用进行接收。
例如
所以在开发之中,Object类是参数的最高统一类型。但是Object类也存在有定义好的一些方法。如下:
例如为什么在写了toString后printlen就会自动调用toString呢
printlen实际上是用object类接收的,然后再调用了一个valueof。
而valueof也是用object类接收,它就会调用自己写的toString。