目录
比较器
用于在类当中去定义该类对象比较大小的规则。
如果不去做这件事情,那么Collections当中所有跟比较有关的行为根本没有办法实现。
Comparable接口 -- 内部比较器
被比较对象自己内部实现的比较规则。先人定义的常用类都已经实现了该接口。
内部比较接口应该实现在被比较对象本身身上实现,然后重写该接口提供的compareTo方法。
compareTo方法的内部实现,记住:
根据在规则下确立的对象位置,分别返回负数、0和整数。
当前对象的位置在传入对象的位置之前,返回“负数”;之后返回“正数”。
Comparator -- 外部比较器
在比较的时候,通过参数指定比较规则,这个规则与内部比较器如果同时存在,以外部为准。
单独书写一个比较器类去实现外部比较器,只需要重写compare --- 接口中的其他方法都是default的。
compare方法的内部实现与上面的内部比较器是一样的,相当于用“第一个参数”的位置 减去 “第二个参数”的位置,分别得到负数、0或正数。
泛型的基本语法
泛型其实早就在其他编程语言当中就已经出现了的,Java其实是比较晚去实现它的语法(JDK1.5之后)。
泛型 在编程语言中的意义 其实比大家想象得要大。我们用专业的方式来描述它的话,它应该叫做“数据类型的参数化”。
也就是说有时候我们在定义一个类或方法的时候,并不能确定我要操作的数据类型是哪一个,需要使用者后期在使用的过程中告之。那么这个时候,我们就可以使用 --- “泛型”的语法来进行设计。
泛型类
假如在一个类的内部,需要使用到某种不确定的类型元素,那么我们就可以在类的声明处通过"<>"来定义泛型。
public class 类名<T>{
}
T只是一个标识符,可以自定义,但通常都写为T、E、K、V。
然后,在我们的这个类内部,只要需要用到这个类型的时候,就都可以用这个标识符来表达了。可以用它来申明属性,可以用它来声明形参,也可以用它来做返回类型,甚至是局部变量的类型。
在定义类的内容时,T由于没有具体的类型(这个还不确定),所以在Java中默认它是一个Object类型,所以可以用T定义的变量访问来自于Object的方法,但是不能访问某个具体子类的具体行为。注意,T在外部确定的时候,不能是基本数据类型。
使用的时候:
MyClass<某个引用数据类型> mc = new MyClass<>();
mc对象中,所有用到T的地方,就都改变成了你在 "<>"内所规范的数据类型。
泛型接口
在接口中也可以定义泛型,定义语法与泛型类是一样的。
public interface MyInterface<T> {
public void add(T t);
public T delete();
}
它的实现类有三种情况:
1、实现类不做泛型设计,那么实现类中的T全部被“擦除”为Object
public class MyClass1 implements MyInterface{
public void add(Object o) {
System.out.println(o);
}
public Object delete() {
return null;
}
}
2、实现类根据接口指定的泛型类型
public class MyClass1 implements MyInterface<String>{
public void add(String o) {
System.out.println(o);
}
public String delete() {
return null;
}
}
3、实现类继续使用T,让它的调用者去确定T到底是谁?
public class MyClass1<T> implements MyInterface<T>{
public void add(T o) {
System.out.println(o);
}
public T delete() {
return null;
}
}
泛型方法
语法
public <T> 返回类型 方法名(T t){
}
在调用方法的时候,根据实际参数的类型确定T的类型。支持静态方法和非静态方法,以及多态参数。
Java的泛型的不足
Java的泛型和其他编程语言(特别是C#)语言的泛型比起来就是弟弟。
因为Java的泛型是假泛型。Java为了让它的JVM在运行的时候能够兼容之前的版本,所以Java泛型是不会在运行期做限制的,只是在编译期做了一个编译时的检查。
我们可以根据Java当中的“反射”技术,在运行期绕过它的泛型规范。