通配符
在泛型中,我们可以用一个通配符
”
?
”
来代替一个未知的类型。例如,使用下面的代码为某种
animal
指定一个
cage
:
Cage<? extends Animal> someCage = ...;
"? extends Animal"
表示一种未知的类型,它可能是
animal
的一种子类型,也可能是
animal
自己本身,总的来讲就是某种
animal
。上面的例子是一种受限通配符,它的上限就是
Animal
。如果需要装下某种
animal
的
cage
,那么就可以被用作是
lion cage
或者
butterfly cage
。
如果使用
super
而不是
extends
则就可以为未知类型指定一个下限
(lower bound)
。例如,
Cage<? super Animal>
表示的也是一种未知类型,其可能是
animal
的一种超类型
(supertype)
,也可能是
animal
自己本身。当然,如果我们用
<?>
来定义一个未知类型,那么这样的未知类型是不受限的。一个不受限的未知类型实质上就是
<? extends Object>
。
虽然
Cage<Lion>
和
Cage<Butterfly>
不是
Cage<Animal>
的子类型,但是却是
Cage<? extends Animal>
的子类型。上面已经定义了
someCage
,那么就可以进行如下赋值:
Cage<Lion> lionCage = ...;
Cage<Butterfly> butterflyCage = ...;
someCage = lionCage; // OK
someCage = butterflyCage; // OK
但是我们还是不能把
butterflies
和
lions
直接
add
到
someCage
:
interface Lion extends Animal {}
Lion king = ...;
interface Butterfly extends Animal {}
Butterfly monarch = ...;
someCage.add(king);
// compiler-time error
someCage.add(monarch);
// compiler-time error
如果
someCage
是一个
butterfly cage
,那么它装入
butterfly
是没有问题的,但是却装不了
lion
。当然,如果
someCage
是一个
lion cage
,那么它装入
lion
是没有问题的,却装不了
butterfly
。也就是我们不能向
someCage
种装入任何
anmial
,那么是不是
someCage
就没有任何用了呢?其实不然,例如下面的代码就用到了
someCage
:
void feedAnimals(Cage<? extends Animal> someCage) {
for (Animal a : someCage)
a.feedMe();
}
这样一来,我们就可以把每种
animal
装入到对应独立的
cage
中,然后依次调用这个方法,如下:
feedAnimals(lionCage);
feedAnimals(butterflyCage);
或者把所有的
animal cage
组合起来,然后可以用下面的代码进行代替:
feedAnimals(animalCage);
类型擦除
(Type Erasure)
当我们实例化一个泛型的时候,编译器使用一种叫做类型擦除
(type erasure)
的技术。在类型擦除的过程中,编译器会去除掉
类与接口中所有和类型参数有关的信息。类型擦除使得用泛型的
java
应用程序能够和该泛型创建之前就存在的
java
库和应用程序相兼容。
例如
Box<String>
在编译的时候产生一个叫做原型
(raw type)
的类型
Box
,而所谓原型就是没有任何参数的泛型类名或者接口名。这也就是说,在运行的时候我们不知道一个泛型类究竟是什么类型的对象。如下的代码在编译的时候就会报错:
public class MyClass<E> {
public static void myMethod(Object item) {
if (item instanceof E
) {
//Compiler error
...
}
E item2 = new E()
;
//Compiler error
E[] iArray = new E[10]
; //Compiler error
E obj = (E)new Object()
; //Unchecked cast warning
}
}
上面黑体代码之所以在编译的时候会报错是因为编译器去除了所有和参数
(
由类型参数
E
代表
)
相关的信息。
有了类型擦除技术之后,就可以让新的代码和遗留的代码共存。但是无论如何,使用原型是一种不好的编程习惯,应该避免在程序中使用。当把遗留代码和泛型代码混合在一起的时候,我们可能会碰到类似于下面的告警:
Note: WarningDemo.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
例如,我们用一个旧的
API
,但参数却用的是一个原型参数,如下的代码所示:
public class WarningDemo {
public static void main(String[] args){
Box<Integer> bi;
bi = createBox();
}
static Box createBox(){
return new Box();
}
}
我们用
-Xlint
:
unchecked
重新编译就会显示出如下附加的信息:
WarningDemo.java:4: warning: [unchecked] unchecked conversion
found
: Box
required: Box<java.lang.Integer>
bi = createBox();
^
1 warning
相关推荐
这是一个使用JAVA实现的泛型编程,分为两部分,第一部分创建泛型类,并实例化泛型对象,得出相加结果。 第二部分用户自行输入0--4,选择要进行的加减乘除运算或退出,再输入要进行运算的两个数,并返回运算结果及...
Java泛型的用法及T.class的获取过程解析 Java泛型是Java编程语言中的一种重要特性,它允许开发者在编写代码时指定类型参数,从而提高代码的灵活性和可读性。本文将详细介绍Java泛型的用法 及T.class的获取过程解析...
Java 泛型详解 Java 泛型是 Java SE 5.0 中引入的一项特征,它允许程序员在编译时检查类型安全,从而减少了 runtime 错误的可能性。泛型的主要优点是可以Reusable Code,让程序员编写更加灵活和可维护的代码。 ...
Java泛型机制详解 Java泛型是Java语言中的一种机制,用于在编译期检查类型安全。Java泛型的出现解决了Java早期版本中类型安全检查的缺陷。Java泛型的好处是可以在编译期检查类型安全,避免了运行时的...
Java泛型是Java编程语言中的一个强大特性,它允许我们在定义类、接口和方法时指定类型参数,从而实现代码的重用和类型安全。在Java泛型应用实例中,我们可以看到泛型如何帮助我们提高代码的灵活性和效率,减少运行时...
1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1.java泛型定义.zip1....
Java泛型是Java编程语言中的一个关键特性,它在2004年随着Java SE 5.0的发布而引入,极大地增强了代码的类型安全性和重用性。本篇文章将深入探讨Java泛型的发展历程、核心概念以及其在实际开发中的应用。 1. **发展...
4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip4.java泛型的限制.zip...
下面我们将详细探讨Java泛型接口的相关知识点。 1. **泛型接口的定义** 泛型接口的定义方式与普通接口类似,只是在接口名之后添加了尖括号`<T>`,其中`T`是一个类型参数,代表某种未知的数据类型。例如: ```java...
下面我们将深入探讨Java泛型方法的概念、语法以及使用示例。 **一、泛型方法概念** 泛型方法是一种具有类型参数的方法,这些类型参数可以在方法声明时指定,并在方法体内部使用。与类的泛型类似,它们提供了编译时...
综上所述,虽然Java泛型在编译后会进行类型擦除,但通过上述技巧,我们仍然能够在运行时获得关于泛型类实例化类型的一些信息。在实际开发中,这些方法可以帮助我们编写更加灵活和安全的代码。在示例文件`GenericRTTI...
Java泛型是Java编程语言中的一个强大特性,它允许在定义类、接口和方法时使用类型参数,从而实现参数化类型。这使得代码更加安全、可读性更强,并且能够减少类型转换的必要。在“java泛型的内部原理及更深应用”这个...
"Java 泛型学习" Java 泛型是 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的...
Java 泛型是一种强大的工具,它允许我们在编程时指定变量的类型,提供了编译时的类型安全。然而,Java 的泛型在运行时是被擦除的,这意味着在运行时刻,所有的泛型类型信息都会丢失,无法直接用来创建对象或进行类型...
Java泛型是Java编程语言中的一个关键特性,它在2004年随着JDK 5.0的发布被引入。这个特性极大地提高了代码的类型安全性和可读性,减少了在运行时出现ClassCastException的可能性。SUN公司的Java泛型编程文档,包括...
Java 泛型使用详细分析 Java 泛型是 Java 语言中的一种类型系统特性,允许开发者在编译期检查类型安全,以避免在运行时出现类型相关的错误。在本文中,我们将详细介绍 Java 泛型的使用方法和实现原理。 一、泛型的...