学习 Java 泛型 内容!
Java 泛型是 JDK 5 中引入的一个新特性,目的是用来弥补集合可以容纳各种类型数据导致的类型异常。
集合中可以存放字符串、整型数据等各种数据,对于集合而言,都将其统一当作是 object 类型(Java 中所有类的父类是 Object)。类比,集合是一个大房子,各种数据类比为人、狗、猫等具体的,对于房子而言都将其统一看作是活物。
存在问题:将所有类型数据都当作 object 类型存放,后续使用具体数据类型时需要强制类型转换,造成类型转换错误。
List list = new ArrayList ();
list.add("hello");
list.add(6);
for (object o : list) {
System.out.println((String) o); // 发生错误:Integer 不能转换成 String 类型
}
定义泛型时可以类比成增加了一个安检功能,使用时如果使用泛型(安检功能),则会对不符合限制(特定数据类型)的进行过滤,也可以不适用泛型(安检功能),不使用就没有过滤功能(默认就是 Object 类型)。
所谓的泛型就是参数化类型,即将要操作的类型作为一个参数。
参数化类型是什么?字面拆解。参数化:变成参数,类型:数据类型,例如,String、Interger,参数化类型:将类型当作参数。例如,将 String 直接变成参数。
public class Main {
public static void main(String[] args) {
List list = new ArrayList(); // 不使用泛型
// <String> 泛型表达:将 String 类型变成集合 List 的参数
List<String> list1 = new ArrayList<>();
}
// 该方法规定需要传入一个 String 类型的参数(具体的字符串)
public void Do(String s) {
System.out.println(s);
}
泛型的作用:给集合加上特定的限制,只能存储特定的类型数据。
对于方法,方法参数有形参和实参。对于泛型,参数化类型,就是将类型当作参数,类型参数就是 <> 内的东西。类型参数也分为类型实参和类型形参。
类型实参
List<String> list1 = new ArrayList<>();
<> 内的 String 就是类型实参,即实际的类型参数,这里的类型参数就是各个数据类型。
类型形参
public interface List<E> extends Collection<E> {
...
}
对于泛型就是使用一些大写的英文字母来作为类型形参,这列的 E 就是类型形参,代表通用型。例如,E:在集合框架中使用,K V:含有映射关系使用(Map),N:用于数字,T S U V:通用类型。
对于泛型,如果是使用泛型用类型实参,如果是定义泛型接口或泛型类用类型形参。
interface MyList<E> { // E 作为类型形参
// 打印泛型实际类型实参的类型名称
void showTypeName(E e)
}
// 通过 MyListImp 类实现一个泛型接口
public class MyListImp<E> implents MyList<E>{
public void showTypeName(E e) {
System.out.println(e.getClass().getName());
}
}
// 测试类
public class Main {
public static void main(String[] args) {
MyList<String> myList = new MyListImp<>();
myList.showTypeName("hello");
}
// 定义
// 给类增加泛型,相当于给类增加了过滤
public class FxClass<G> { // G 类型形参,定义时不能确定具体的类型,后面使用时传入类型实参确定 G 类型
private G g;
public G getG() {
return g;
}
public void setG(G g) {
this.g = g;
}
}
// 使用泛型类:使用时会根据泛型定义对操作进行可一些过滤
public class Main {
public static void main(String[] args) {
FxClass<String> fxClass = new FxClass<>();
fxClass.setG("自定义泛型类");
System.out.println(fxClass.getG());
Test test = new Test();
}
// 泛型类的继承
class Test extends FxClass<String> { // 继承泛型类的时候要指定具体的类型实参
}
// 原始类型
class Test extends FxClass { // 不写类型实参被称为原始类型等价于 class Test extends FxClass<object>
}
泛型类是不存在的,泛型类并不是一个新的种类
List list = new ArrayList(); // 没有使用泛型
List<String> stringlist = new ArrayList<>(); // 使用了泛型:没有生成新的 List 本质上还是上一个 List,只不过泛型做了规定只能装载特定的数据
使用通配符
public void doS(List<?> list) {
}
修饰符 <T,E, … 形参> 返回值类型 方法名称 (形参列表) {
方法体,具体的逻辑实现
}
public class Test {
public static void main(String[] args) {
// 普通方法
public void doS(String s) {
System.out.println(s.getClass().getName());
}
// 泛型方法
public <T> void doSS(T t) { // <T> T 形参
System.out.println(T.getClass().getName());
}
}