JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

java语法糖之泛型

wys521 2024-12-11 12:13:07 精选教程 32 ℃ 0 评论

临近年关各种忙,

检查代码想撞墙,

年会聚餐怎么样,

我只关心年终奖。

------------------------------打油诗分割线---------------------------

泛型,java中的语法糖,为了代码优化,增强可读性及类型转换的方式。

泛型的主要使用:泛型类,接口,泛型方法。

想了解泛型,得先知道一个概念:

类型擦除:

Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉。这个去掉的过程就是类型擦除。

下面可以看一段代码:

public static void main(String[] args) {

ArrayList c1 = new ArrayList<String>();

ArrayList c2 = new ArrayList<Integer>();

}

在编译之后,得到的结果如下:


可以看出,编译器并没有记录具体类型,因为泛型在编译过程中,已经被编译器替换掉了。

这就带来了一些问题,如下代码所示:

public class Erased<T> {

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<T> {

private T arg;

public String f(T arg) {

return arg.toString();

}

public static void main(String[] args) {

Generics<String> generics = new Generics<String>();

String s = generics.f("111");

System.out.println(s);

}

}

泛型修饰方法:

如代码所示,返回值前的<K> 不能省略,否则就编程了泛型类中的普通方法,而不省略,则是泛型方法。

泛型方法在方法调用时根据传入的参数类型确定类型。

//泛型类

public class Generics<T> {

private T arg;

//泛型类的普通方法

public String f(T arg) {

return arg.toString();

}

//泛型方法

private static <K> K genericsType(K t)

{

return t;

}

public static void main(String[] args) {

Generics<String> generics = new Generics<String>();

String s = generics.f("111");

System.out.println(s);

Generics.genericsType(new Integer(1));

}

}

通配符:

那么,还有剩下的问题,我想更方便的使用这个类,既要传入Integer,也要传入String,如何处理呢。

如下这样会报错:

public class Generics<T> {

private T arg;

private ArrayList<T> arraylist;

public String f(T arg) {

return arg.toString();

}

private static <K> K genericsType(K t)

{

return t;

}

public static void main(String[] args) {

Generics<String> generics = new Generics<String>();

String s = generics.f("111");

System.out.println(s);

Generics.genericsType(new Integer(1));

generics.arraylist=new ArrayList<String>();

//报错,因为已经匹配了String

generics.arraylist=new ArrayList<Integer>();//Type mismatch: cannot convert from ArrayList<Integer> to ArrayList<String>

}

}

而使用通配符?后,就可以做到:

public class Generics<T> {

private T arg;

//使用通配符?

private ArrayList<?> arraylist;

public String f(T arg) {

return arg.toString();

}

private static <K> K genericsType(K t)

{

return t;

}

public static void main(String[] args) {

Generics<String> generics = new Generics<String>();

String s = generics.f("111");

System.out.println(s);

Generics.genericsType(new Integer(1));

generics.arraylist=new ArrayList<String>();

generics.arraylist=new ArrayList<Integer>();

}

}

通配符的上下界:

这个概念也很好理解,当使用通配符时,<? extends Generics> 表示某种特定类型 ( Generics或者其子类 ) 的泛型,<? super Generics>示某种特定类型 ( Generics或者其超类 ) 的泛型。因为泛型的擦除是有上界的,如果直接使用?,那么有些不关联的类,只能使用到Object的方法,因为编译器只能确定该类是Object的子类。

而使用了<? extends Generics>之后,所有的Generics类的方法,这个泛型均能使用。<? extends Generics>这种形式在很多场景中被广泛使用。

Tags:

猜你喜欢

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表