临近年关各种忙,
检查代码想撞墙,
年会聚餐怎么样,
我只关心年终奖。
------------------------------打油诗分割线---------------------------
泛型,java中的语法糖,为了代码优化,增强可读性及类型转换的方式。
泛型的主要使用:泛型类,接口,泛型方法。
想了解泛型,得先知道一个概念:
类型擦除:
Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉。这个去掉的过程就是类型擦除。
下面可以看一段代码:
public static void main(String[] args) {
ArrayList c1 = new ArrayList();
ArrayList c2 = new ArrayList();
}
在编译之后,得到的结果如下:
可以看出,编译器并没有记录具体类型,因为泛型在编译过程中,已经被编译器替换掉了。
这就带来了一些问题,如下代码所示:
public class Erased {
private static final int SIZE = 100;
public void f(Object arg) {
if(arg instanceof T) {} // Cannot perform instanceof check against type parameter T
T var = new T(); // Cannot create a generic array of T
T[] array = new T[SIZE]; //Cannot create a generic array of T
T[] array1 = (T[])new Object[SIZE]; //Type safety: Unchecked cast from Object[] to T[]
}
}
许多运行期才能知道确切类型的代码,都会编译不通过。
泛型修饰类:
如代码所示,定义一个泛型类,在创建实例时,会根据传入的具体类型创建对应的实例。
public class Generics {
private T arg;
public String f(T arg) {
return arg.toString();
}
public static void main(String[] args) {
Generics generics = new Generics();
String s = generics.f("111");
System.out.println(s);
}
}
泛型修饰方法:
如代码所示,返回值前的 不能省略,否则就编程了泛型类中的普通方法,而不省略,则是泛型方法。
泛型方法在方法调用时根据传入的参数类型确定类型。
//泛型类
public class Generics {
private T arg;
//泛型类的普通方法
public String f(T arg) {
return arg.toString();
}
//泛型方法
private static K genericsType(K t)
{
return t;
}
public static void main(String[] args) {
Generics generics = new Generics();
String s = generics.f("111");
System.out.println(s);
Generics.genericsType(new Integer(1));
}
}
通配符:
那么,还有剩下的问题,我想更方便的使用这个类,既要传入Integer,也要传入String,如何处理呢。
如下这样会报错:
public class Generics {
private T arg;
private ArrayList arraylist;
public String f(T arg) {
return arg.toString();
}
private static K genericsType(K t)
{
return t;
}
public static void main(String[] args) {
Generics generics = new Generics();
String s = generics.f("111");
System.out.println(s);
Generics.genericsType(new Integer(1));
generics.arraylist=new ArrayList();
//报错,因为已经匹配了String
generics.arraylist=new ArrayList();//Type mismatch: cannot convert from ArrayList to ArrayList
}
}
而使用通配符?后,就可以做到:
public class Generics {
private T arg;
//使用通配符?
private ArrayList> arraylist;
public String f(T arg) {
return arg.toString();
}
private static K genericsType(K t)
{
return t;
}
public static void main(String[] args) {
Generics generics = new Generics();
String s = generics.f("111");
System.out.println(s);
Generics.genericsType(new Integer(1));
generics.arraylist=new ArrayList();
generics.arraylist=new ArrayList();
}
}
通配符的上下界:
这个概念也很好理解,当使用通配符时, extends Generics> 表示某种特定类型 ( Generics或者其子类 ) 的泛型, super Generics>示某种特定类型 ( Generics或者其超类 ) 的泛型。因为泛型的擦除是有上界的,如果直接使用?,那么有些不关联的类,只能使用到Object的方法,因为编译器只能确定该类是Object的子类。
而使用了 extends Generics>之后,所有的Generics类的方法,这个泛型均能使用。 extends Generics>这种形式在很多场景中被广泛使用。