泛型
不使用泛型,使用集合时编程比较复杂
List list=new ArrayList();
list.add(123); //自动向上转型 int–>Integer–>Object
//获取数据还需要窄化操作
int kk=(Integer)list.get(0); //不进行类型判断,有可能出现 ClassCastException
使用泛型,可以将运行时的类型检查搬到编译期实现;同时获取数据时不需要再编码进行类型转换List list=new ArrayList<>(); //从 JDK1.7+支持泛型推导
list.add(123);
list.add(new Random());//编译报错
int kk=list.get(0); //不需要进行强制类型转
什么是泛型
泛型是 jdk5 引入的类型机制,就是将类型参数化,泛型作为一种安全机制而产生
泛型在本质上是指类型参数化。所谓类型参数化,是指用来声明数据的类型本身,也是可以改变的,它由实际参数来决定。在一般情况下,实际参数决定了形式参数的值。而类型参数化,则是实际参数的类型决定了形式参数的类型。
使用泛型的优势
1、可读性,从字面上就可以判断集合中的内容类型;
2 、类型检查,避免插入非法类型。
3 、获取数据时不在需要强制类型转换。
带两个类型参数的泛型类
如果引用多个类型,可以使用逗号分隔:<S, D>
类型参数名可以使用任意字符串,建议使用有代表意义的单个字符,以便于和普通类型名区分,如:T 代表 type,有源数据和目的数据就用 S/D,子元素类型用 E 等。当然,你也可以定义为 XYZ,甚至 xyZ。泛型中的类型参数严格说明集合中装载的数据类型是什么和可以加入什么类型的数据,记住:Collection 和 Collection 是两个没有转换关系的参数化的类型
带两个类型参数的泛型类
如果引用多个类型,可以使用逗号分隔:<S, D>
类型参数名可以使用任意字符串,建议使用有代表意义的单个字符,以便于和普通类型名区
分,如:T 代表 type,有源数据和目的数据就用 S/D,子元素类型用 E 等。当然,你也可
以定义为 XYZ,甚至 xyZ。泛型中的类型参数严格说明集合中装载的数据类型是什么和可以加入什么类型的数据,记
住:Collection 和 Collection 是两个没有转换关系的参数化的类型集合类中定义范型
有界类型
public class MyClass{ }表示允许传入给 T
的类型必须是 Number 类型的子类型或者 Number 类型MyClass mc=new MyClass(); 语法正确,因为 Integer 是Number 的子类型MyClass mc=new MyClass<>(); 语法错误,因为 String 不是 Number 类型
声明泛型可以给泛型添加约束
Java 提供了有界类型 bounded types。在指定一个类型参数时,可以指定一个上界,声明所有的实际类型都必须是这个超类的直接或间接子类。class classname
接口和类都可以用来做上界。
类充当上界 public class Oper
接口充当上界 class Stats这里需要注意:针对上界接口使用的关键字仍然是 extends 而非 implements
通配符参数
使用一般用于接收参数void doSomething(Stats<?> ob) 表示这个参数 ob 可以是任意的 Stats 类型。其中?表示一个不确定的类型,它的值会在调用时确定下来。 List<?> list = new ArrayList();
泛型方法
所谓泛型方法,就是带有类型参数的方法,它既可以定义在泛型类中(例如 public void show(T aa),在使用泛型上没有任何特殊语法要求),也可以定义在普通类中(需要自定义参数类型,那么把泛型参数放在方法上就可以了,就是放在返回值类型之前,例如 public void show(T aa)), 静态方法不能访问类的泛型,如果需要泛型只能在方法上使用泛型,例如 public static void show(T aa)
在泛型类中包含泛型的方法
Set接口的定义
Set接口是Collection接口的子接口
无序、不允许重复[重复元素的添加会产生覆盖]
没有新方法
boolean add(E e);向集合中追加元素e对象,如果出现重复则后盖前
问题:如何判断两个元素相等
首先比较两个对象的hashcode值是否相等,如果hashcode值不相等则不会调用equals,认为两个对象不相等
如果hashcode值相等才调用equals进行比较,否则不相等
潜规则【不是语法】:SUN要求当两个对象的equals为true时,hashcode值应该相等
实现类HashSet
类定义
数据的存储方式