Java泛型的应用
Posted vkbwxdx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java泛型的应用相关的知识,希望对你有一定的参考价值。
---恢复内容开始---
在开发中,我们有时候会用到泛型来写工具类,为了使方法更通用,以前,没有完全弄懂,今天,就这个机会把泛形写一写
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。泛型的引入,让JAVA更安全。之前没有引入泛型,各种的类型转换错误。
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。
我们见不各种泛型的字母通配符T,E,K,V等等,还有?,其实这些字母只约定,实际中使用什么字母都可以,以下是约定:
- ? 表示不确定的java类型
- T (type) 表示具体的一个java类型
- K V (key value) 分别代表java键值中的Key Value
- E (element) 代表Element
import java.util.ArrayList;
public class Demo {
public static void main(String[] args) {
}
public <T> void aa(T t){
ArrayList<?> al=new ArrayList<T>();
}
}
这种方式 正确
ArrayList<?> al=new ArrayList<T>();
但是这样就不行了,后面只能是具体类型,不能是通配符,前边是可以的
ArrayList<?> al=new ArrayList<?>();
?和T都表示不确定的类型 ,但如果是T的话,函数里面可以对T进行操作,比方 T car = getCar(),而不能用? car = getCar()。
Class<T>在实例化的时候,T要替换成具体类
Class<?>它是个通配泛型,?可以代表任何类型,主要用于声明时的限制情况
public class Test {
public static <T> T createInstance(Class<T> clazz) throws IllegalAccessException, InstantiationException {
return clazz.newInstance();
}
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
Fruit fruit= createInstance(Fruit .class);
People people= createInstance(People.class);
}
}
class Fruit{
}
class People{
}
上面的类使用Class<T>泛型后,newInstance不用强转
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
//虽然Test<T1,T2>,但类名字仍为Test。T1,T2只是告诉我们new的时候要加入泛型,更方便通用
//T1,T2可以任意定义,比如改成K,V都可以
//他们不会关联到其他类,只是在本类中通用
public class Test<T1, T2> {
public static void main(String[] args) {
System.out.println(new Test().getT1());
System.out.println(new Test().getT2());
new Test<String, String>().getClassName("");//T1,T2在new的时候用到,这里都为String
new Test().getClassAndList(Integer.class);
//HashMap的括号里面不能是T,E,T1,T2等不确定的东西,但可以是?
HashMap<?, ?> map = new HashMap<Object, String>();
List<?> list = new ArrayList<String>();
}
public T1 getT1() {
//这里的“T1”替换成1或1.0都会报错
return (T1) "T1";
}
T2 getT2() {
//将自动转型为String
return (T2) "T2";
}
public <T> void getClassName(T x) {
//<T>必须放在void或者返回类型的前面
System.out.println(x.getClass().getName());
}
public <T> Class<?> getClassAndList(Class<?> a) {
//Class<T>前面缺少<T>必须定义,否则将出现编译错误
//T改成其他字母都可以,但一定要声明
// 返回类型和参数中的类型:Class<T>和Class<?>都可以。因为返回的a的类型为Class<T>,Class<?>可以通配
//当两个都是Class<?>,参数中的?自动通配成T
System.out.println(a.getClass().getName());//传入的a是一个类,Class类型
//参数里面的Class<T>最大的好处是如果方法里面定义了泛型,可以自动获取类型值,比如如下的List<T>可以自动获取到a的类型,不必强调死
List<?> aa = new ArrayList<T>();
//List<?> aa = new ArrayList<?>();会报错,以为ArrayList必须是一种类型,List<>起到通配的作用
//List<T> aa = new ArrayList<T>();当然正确
System.out.println(aa);
return a;
}
}
这个例子说明泛型可以是任何字母
public class GenericTest {
public static void main(String[] args) {
Box<String> name = new Box<String>("corn");
Box<Integer> age = new Box<Integer>(712);
Box<Number> number = new Box<Number>(314);
getData(name);
getData(age);
getData(number);
//getUpperNumberData(name); // 1
getUpperNumberData(age); // 2
getUpperNumberData(number); // 3
}
public static void getData(Box<?> data) {
System.out.println("data :" + data.getData());
}
public static void getUpperNumberData(Box<? extends Number> data){
System.out.println("data :" + data.getData());
}
}
class Box<T> {
private T data;
public Box() {
}
public Box(T data) {
setData(data);
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
Box<? extends Number> 问号也可以通过这种方式代表,传入的都是Nubmber的子类
以上是关于Java泛型的应用的主要内容,如果未能解决你的问题,请参考以下文章