Java中的泛型详细解析
作者:咕咕猫_
引言
使用传统方法的问题分析
1.不能对加入到集合ArrayList中的数据类型进行约束(不安全)
2.遍历的时候需要进行类型转换,如果集合中的数据量较大,对效率有影响
泛型的好处
1.编译时会检查添加元素的类型,提高了安全性
2.减少了类型转换的次数,提高效率
3.不再提示编译警告
一、泛型介绍
泛(广泛)型(类型)
1.泛型又称参数化类型,是JDK5.0出现的新特性,解决了数据类型的安全型问题
2.在类声明或实例化时只要指定好需要的具体类型即可
3.Java泛型可以保证如果程序在编译时没用发出警告,运行时就不会产生ClassCastException异常。同时,代码更加简洁、健壮
4.泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型
二、泛型的语法
2.1 泛型的声明
- class 类<K,V> { }
- interface 接口<T> { }
说明:1.其中的K,V,T不代表值,而是表示类型; 2.任意字母都可以,常用T表示,是Type的缩写
2.2 泛型的实例化
要在类名后面指定类型参数的值(类型)
1. List<String> strList = new ArrayList<String>();
2. Iterator<Customer> iterator = customers.iterator();
三、泛型使用的注意事项和细节
1.给泛型指向数据类型时,要求是引用类型,不能是基本数据类型
2.在给泛型指定具体类型后,可以传入该类型或者其子类类型
3.泛型使用形式
①List <Integer> list1 = new ArrayList<Integer>();
②List <Integer> list2 = new ArrayList<>();
③如果这样写 List list3 = new ArrayList();默认给它的泛型是Object
四、自定义泛型
4.1 基本语法
class 类名<T,R...> { //...表示可以有多个泛型 成员 }
4.2 注意细节
1.普通成员可以使用泛型(属性、方法)
2.使用泛型的数组不能初始化
3.静态方法中不能使用类的泛型
4.泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)
5.如果在创建对象时没用指定类型,默认为Objcet
4.3 自定义泛型接口
4.3.1 基本语法
interface 接口名 <T,R...> { }
4.3.2 注意细节
1.接口中,静态成员也不能使用泛型()
2.泛型接口的类型,在继承接口或者实现接口时确定
3.没有指定类型,默认为Object
4.4 自定义泛型方法
4.4.1 基本语法
修饰符 <T,R...>返回类型 方法名(参数列表) { }
4.4.2 注意细节
1.泛型方法可以定义在普通类中,也可以定义在泛型类中
2.当泛型方法呗调用时,类型会确定
3.pulbic void ear(E e) {} ,修饰符后没有<T,R...>,eat方法不是泛型方法,而是使用了泛型
public class CustomMethodGeneric { public static void main(String[] args) { Car car = new Car(); car.fly("宝马",100);//当调用方法时传入参数,编译器就会确定类型 Fish<String, ArrayList> fish = new Fish<>(); fish.hello(new ArrayList<>(),1.1f); } } //泛型方法,可以定义在普通类中,也可以定义在泛型类中 class Car { //普通类 public void run() { //普通方法 } //说明,泛型方法 //1. <T,R>就是泛型 //2. 是提供给fly使用的 public <T,R> void fly(T t, R r) { //泛型方法 System.out.println(t.getClass()); //String System.out.println(r.getClass()); //Integer } } class Fish<T,R> { //泛型类 public void run() { //普通方法 } public<U,M> void eat(U u, M m) { //泛型方法 } //说明 //1.下面的hi方法不是泛型方法 //2.是hi方法使用了类声明的泛型 public void hi(T t){ } //泛型方法可以使用类声明的泛型,也可以使用自己声明泛型 public<K> void hello(R r,K k){ System.out.println(r.getClass()); System.out.println(k.getClass()); } }
五、泛型的继承和通配符
通配符:?
1. 泛型不具备继承性
2. <?> :支持任意泛型类型
泛型的上下限
3. <? extends A> :支持A类以及A类的子类,规定了泛型的上限
4. <? super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限
/** * @author 咕咕猫 * @version 1.0 * 泛型的继承与通配符 */ @SuppressWarnings({"all"}) public class GenericExtends { public static void main(String[] args) { Object o = new String("XXX"); //泛型没有继承性 //List<Object> list = new ArrayList<String>(); //举例说明下面三个方法的使用 List<Object> list1 = new ArrayList<>(); List<String> list2 = new ArrayList<>(); List<AA> list3 = new ArrayList<>(); List<BB> list4 = new ArrayList<>(); List<CC> list5 = new ArrayList<>(); //如果是 List<?> c ,可以接受任意的泛型类型 printCollection1(list1); printCollection1(list2); printCollection1(list3); printCollection1(list4); printCollection1(list5); //List<? extends AA> c: 表示 上限,可以接受 AA 或者 AA 子类 // printCollection2(list1);//× // printCollection2(list2);//× printCollection2(list3);//√ printCollection2(list4);//√ printCollection2(list5);//√ //List<? super AA> c: 支持 AA 类以及 AA 类的父类,不限于直接父类 printCollection3(list1);//√ //printCollection3(list2);//× printCollection3(list3);//√ //printCollection3(list4);//× //printCollection3(list5);//× } //说明: List<?> 表示 任意的泛型类型都可以接受 public static void printCollection1(List<?> c) { for (Object object : c) { // 通配符,取出时,就是 Object System.out.println(object); } } // ? extends AA 表示 上限,可以接受 AA 或者 AA 子类 public static void printCollection2(List<? extends AA> c) { for (Object object : c) { System.out.println(object); } } // ? super 子类类名 AA:支持 AA 类以及 AA 类的父类,不限于直接父类, //规定了泛型的下限 public static void printCollection3(List<? super AA> c) { for (Object object : c) { System.out.println(object); } } } class AA { } class BB extends AA { } class CC extends BB { }
六、JUnit
6.1 为什么需要JUnit
1.一个类有很多功能代码需要测试,为了测试,就需要写到main方法中
2.如果 有多个功能代码测试,就需要来回注销,切换很麻烦
6.2 基本介绍
1.JUnit是一个Java语言的单元测试框架
2.多数Java的开发环境都已经集成了JUnit作为单元测试的工具
使用:在需要测试的代码前加上@Test,按alt + enter选择版本即可
到此这篇关于Java中的泛型详细解析的文章就介绍到这了,更多相关Java泛型内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!