java ------- 泛型
泛型 在 jdk 1.5 的时候增加,本质是参数化类型,也就是说操作的数据类型被执行为一个参数,使代码可以应用于多种类型。我的感觉让集合存储指定的类型,
好处:安全简单,所有强制转化都是自动和隐式进行的,提高了代码重用率。
定义:把对象类型作为参数,指定到其他类或者方法上,从而保证类型转换的安全性和稳定性。
本质:参数化类型
格式:
类1或接口 <类型实参> 对象 = new 类2 <类型实参> (); //注意: //类2 可以与类1相同,也可以是类1 的子类,或其接口的实现类 //类2 和 类1 的 类型实参必须相同
在集合中使用泛型
使用泛型后,原来通过get() 方法取出对象时,不用强转了,避免了容易出现的 ClassCastException, 但是,使用泛型后,不能再往该集合中存储与类型实参不同的类型数据
package com.obge.boge; import com.obge.model.Animal; import java.util.*; public class GenericityStu { public static void main(String[] args) { //弄个类 Animal dog1 = new Animal("小白",22,"雄"); Animal cat1 = new Animal("小橘",22,"雄"); //放在list 集合中 有序不唯一 List<Animal> alist = new ArrayList<Animal>(); alist.add(dog1); alist.add(cat1); //遍历出来 for(Animal animal:alist){ System.out.println("list 集合获取名字"+animal.getName()); } LinkedList<Animal> alinklist = new LinkedList<>(); alinklist.add(dog1); alinklist.addFirst(cat1); //遍历出来 for(Animal animal :alinklist){ System.out.println("list 集合下的LinkedList获取名字"+animal.getName()); } System.out.println("******** obge *************"); //放在Set 集合中 无序 唯一 HashSet<Animal> aset = new HashSet<Animal>(); aset.add(dog1); aset.add(cat1); //遍历出来 Iterator<Animal> iterator = aset.iterator(); while(iterator.hasNext()){ System.out.println("set 集合获取名字"+iterator.next().getName()); } System.out.println("**********obge*********"); //放在 Map 集合中 key 无序不重复 value 无序可重复 Map<String,Animal> amap = new HashMap<String, Animal>(); amap.put("小狗",dog1); amap.put("小猫",cat1); //遍历 key for(String key:amap.keySet()){ System.out.println("键来"+key); } //遍历 value for(Animal value : amap.values()){ System.out.println("值来"+value.getName()); } System.out.println("键名小狗相应的值的对象名为:"+amap.get("小狗").getName()); } }
存储数据是进行严格类型检查,确保只有何事类型的对象才能存储在集合中,遍历时免去了强制类型转换
在其他地方使用泛型
集合中使用泛型只是泛型多种类型的一种,在接口、类、方法等方面也有这广泛的有应用
参数化类型的重要性允许创建一些接口、类、方法,所操作的数据类型定义为参数,真正使用时指定具体类型
参数化类型:包含一个类或接口,以及实际的类型参数列表。
类型变量:一种非限定性标识符,用来指定类、接口或者方法的类型
1、定义泛型类、泛型接口和泛型方法
使用场景:对于一些常常处理不同类型的数据转换的接口或类,
泛型类:具有一个或多个类型参数的类
定义泛型类语法格式:
访问修饰符 calss 类名<TypeList>{
}
//TypeList 表示类型参数列表,每个类型变量之间使用 逗号分隔
实例化泛型类语法格式
new 类名 <TypeList>(argList); //TypeList 表示定义的类型列表,可以有多个 //argList 实际传递的类型参数列表,每个类型变量之间使用逗号分隔
一个小例子:
定义:
package com.obge.model; public class Department <Ty1> { private Ty1 name; public Ty1 getName() { return name; } public void setName(Ty1 name) { this.name = name; } public Department(Ty1 name) { this.name = name; } }
实例:
package com.obge.boge; import com.obge.model.Department; public class GenericityOtherUser { public static void main(String[] args) { //存放字符串类型 Department<String> departmentGenericity = new Department<String>("波哥"); System.out.println(departmentGenericity.getName()); //存放 整数类型 Department<Integer> departmentGenericity1 = new Department<Integer>(001); System.out.println(departmentGenericity1.getName()); } }
泛型接口:拥有一个或多个类型参数的接口
定义接口语法格式
访问修饰符 interface 接口名<TypeList>{ } //TypeList 表示类型参数列表,每个类型变量之间使用 逗号分隔
实现接口的语法格式:
访问修饰符 class 类名 <TypeList> implements interface 接口名<TypeList>{ } //TypeList 表示类型参数列表,每个类型变量之间使用 逗号分隔
一个小例子:
定义:
package com.obge.interface1; public interface GenericityInterfce <T>{ T add(); }
实现:
package com.obge.implements1; import com.obge.interface1.GenericityInterfce; //注意包名不要是关键字 public class GenericityImplmentsInterfaace<T> implements GenericityInterfce<T> { @Override public T add() { return null; } }
泛型方法:带有参数类型的方法
如果数据的类型不确定,可以通过泛型方法的方式,达到简化代码提高代码重用性的目的
不管在不在泛型类中都可以定义泛型方法
定义泛型方法语法格式:
访问修饰符 <类型参数> 返回值 方法名(类型参数列表)
定义:
package com.obge.boge; public class GenericMethod { public <Integer> void testGenericMethod(Integer o){ System.out.println(o.getClass().getName()); } }
调用:
package com.obge.boge; import com.obge.model.Department; public class GenericityOtherUser { public static void main(String[] args) { GenericMethod genericMethod = new GenericMethod(); genericMethod.testGenericMethod(1); } }
多个参数的泛型类
泛型类的类型参数可以有多个,如HashMap<K,V> 中就有两个指定的类型参数,
package com.obge.model; public class User<T,V> { private T username; private V type; public User(T username, V type) { this.username = username; this.type = type; } public void showType(){ System.out.println("username的类型是:"+username.getClass().getName()); System.out.println("username的类型是:"+type.getClass().getName()); } } //调用 public static void main(String[] args) { User<String,Integer> user = new User<String, Integer>("tom",001); user.showType(); }
定义时这两个类型变量的具体类型并不知道,实例化时就可以传入两个类型参数进行替换。
泛型类派生子类
面向队形的特性同样适用于泛型类,所以泛型类也可以继承,继承了泛型类的子类也是泛型类
继承泛型类格式:
访问修饰符 子类名 <T> extends 父类名<T>{}
package com.obge.boge; public class GenericityFather<T> { protected int homeArea = 0; public void printHomeArea(T area){ homeArea ++; } } //泛型类继承父类 public class GenericitySon<T> extends GenericityFather<T> { //重写父类方法 public void printHomeArea(List<T> list){ homeArea += list.size(); }