什么是泛型:
Generic
programming means to write code that can be reused for objects of many
different types.
摘自《
Core java
》
为什么使用泛型
主要是为了类型转换。如果不使用泛型,那么每次都得显式的就行类型转换。
如:
不使用泛型:
List
list = …
String
str = (String)list.get(1);
使用泛型:
List<String>
list = …
String
str = list.get(1);
如何定义泛型:
使用
<Type variable>
中带有类型,该类型可以是具体类型
.
比如
: String.
也可以不是具体类型,比如
<? Extends Number>.
具体类型
(reifiable
type)
和非具体类型
(unreifiable type)
(非)具体化类型后面再介绍
<
Type variable >
即表明声明了泛型,可以在类、方法、字段等处定义泛型。
什么是类型参数(
type parameter
)
、
参数化类型(
parameterized type
)
比如,类
List<String>
,称
String
为类型参数。
List<String>
为参数化类型,因为
List
被
String
参数化了。
子类型(
subtypes
)及替换原则
Integer
是
Number
的子类,能放置
Number
的地方都能放置
Integer
,这便是
Java
中的替换原则。
Substitution
Principle: a variable of a given type may be assigned a value of any
subtype of that type, and a method with a parameter
of
a given type may be invoked with an argument
of any subtype
of that type
。
--
摘自
Java Generics & Collections
数组
Integer[]
是
Number[]
的子类,那是不是
List<Integer>
也是
List<Number>
的子类?其实不是,他们其实是同一类型。可以通过以下代码判断。
List<Number> numList
= …
List<Integer> intList
= …
System.out.println(numList.getClass()
== intList.getClass())
如果我们需要在泛型中拥有类似于数组的该特性(
Integer[]
是
Number[]
的子类),我们就得使用通配符
(wildcard).
通配符
(wildcard)
及
访问原则
上述说过,数组
Integer[]
是
Number[]
的子类,
List<Integer>
确不是
List<Number>
的子类。要实现类似于数组的该特性,就需要通配符来实现
: List< ? extends Number> .
?
表示通配符,表示任意类型(继承
Object
的任意类型)。
?
extends T
表示继承或实现
T
的类型。即
T
的任意子类型
,
比如
? extends Number
表示继承自
Number
的任意类型,可以是
Integer, Double …
?
super T
表示
T
的任意父类型(
super type
),比如:
? Super ArrayList
表示
ArrayList
的任意父类型,可以是
List, AbstractList…
。
?
表示
? extends Object
通过通配符,我们可以实现类似于数组的功能:
List<Integer>
intList = …;
List<Number>
numList=…;
List<?
Extends Number> list1 = intList;
List<?
Extends Number> list2 = numList;
List<?
Super Number> list3 = numList;
这样我们可以向数组一样进行类型转换。但却不能像数组一样进行以下方式的赋值:
Number[]
nums = …
Nums[0]
= Integer.valueOf(2)..
如果编写以下代码:
List<?
Extends Number> list = … ;
List.add(Integer.valueOf(2))
//
编译器报错。
List.add(Double.valueOf(2))
//
编译器报错
为什么呢?
<? Extends Number>
不是表示
Number
的任意子类型么?
使用替换原则不是应该正确的么?
该问题的源头就是因为
<? Extends Number>
表示
Number
的子类型。但是我们却不知道到底是哪个具体的类型。因此
List< ? extends Number>
可以指向其任意的子类型。比如,
List<Integer>, List<Number>,List<Double>.
如果是
list
是指向
ArrayList<Double>, list.add(Integer.valueOf(2))
合法的话,那么
list
中就存在
Double
、
Integer
等
Number
子类型的对象,
ArrayList<Double>
中的元素类型就不一样。那么
list.get(..)
就有可能返回
Integer
类,就可能出现问题,由于泛型有个基本原则:
Cast-iron
guarantee:
所以编译器在编译级别就将可能导致类型转化的错误屏蔽掉。
当然我们可以调用
list.add(null),
因为
null
是任意类型的子类型,可以安全的使用,但很多时候没有用处。
如果使用
list.get(..)
就不会有问题,因为
list
存的就是
Number
子类对象,任何子类都能转为其基类(
Number
)。
同样的道理,以下代码无法编译:
List<?
Super Integer> list = …
Integer
in = list.get(0); //
编译过不去
因为
List
存的是
Integer
的基类型,但是我们并不知道具体是哪个基类。所以就无法进行转化
,
当然我们可以调用
Object obj = list.get(0)
。
如果使用
list.add(Integer.valueOf(2))
却不会有问题,因为
list
存的是
Integer
的父类,那么必然可以存
Integer
类型。
因此利用
< ? extend …> <? Super …>
时,一般使用一个原则:
The Get and Put Principle: use
an
extends
wildcard when you only get values out of a structure, use a
super
wildcard
when you only put values into a structure, and
don't use a wildcard when you both get and put.
类型参数
VS
通配符
比如我们需要将一个list的数据拷贝到另一个list中。
假设方法在类Collections中定义:
public static <T> void copy(List<?
super T> dst, List<? extends T> src)
List<Object> objs = Arrays.<Object>asList(2,
3.14, "four");
List<Integer> ints = Arrays.asList(5,
6);
List<Object> objs = Arrays.<Object>asList(2,
3.14, "four");
List<Integer> ints = Arrays.asList(5,
6);
Collections.copy(objs, ints);
assert objs.toString().equals("[5,
6, four]");
由以下方法调用,
<Object>
表示
T
为
Object
Collections.copy(objs, ints);
Collections.<Object>copy(objs,
ints);
Collections.<Number>copy(objs,
ints);
Collections.<Integer>copy(objs,
ints);
比较以下几种方法签名:
1:public static <T> void copy(List<T>
dst, List<T> src)
2:public static <T> void copy(List<T>
dst, List<? extends T> src)
3:public static <T> void copy(List<?
super T> dst, List<T> src)
4:public static <T> void copy(List<?
super T> dst, List<? extends T> src)
比较:
1
:限制最大,必须要求
dst
和
src
是同一类型,比如同是
List<Integer>.
该方法不能用于
上述的例子
collectioins.copy(objs,ints)
2: 仅仅使用于T为Object时。即Collections.<Object>copy(objs,
ints)方式
3:仅仅使用于T为Integer时,Collections.<Integer>copy(objs,
ints);
4
:可应用于
T
为
Object
、
Number
、
Integer
时。
以上例子摘自
– Java Generic & Collections
简单的总结一下:
泛型方法签名尽可能的使用
wildcard
,其可用范围更广。如果需要严格限制为同一类型时,就可以使用
type parameter
。
Wildcard capture
译为
捕捉通配符???
何为
wildcard capture.
顾名思义
:
就是捕捉通配符的类型。
看以下例子:
Pair<T>有first
和second两个变量。分别有对应的set, get 方法。
public
static void swap(Pair<?> p){
? t = p.getFirst(); // ERROR
p.setFirst(p.getSecond());
p.setSecond(t);
}
但是用T确实没有问题:
public static <T> void swapHelper(Pair<T>
p)
{
T t = p.getFirst();
p.setFirst(p.getSecond());
p.setSecond(t);
}
因此我们经常使用swapHelper(Pair<T>
p)来实现swapHelper(Pair<?> p):
public static void swap(Pair<?>
p) { swapHelper(p); }
这种情况,我们叫T 捕捉了
通配符(T captures the wildcard).我们并不知道wildcard表示什么类型,但是我们知道其必然是一个明确的类型。因此可以用T去捕捉它。(这里有点绕,知道T可以捕捉?即可)。
注意的是:要用T捕捉?,那么要保证wildcard必须是表示同一、明确的类型(尽管我们不知道这是什么类型)。
比如
ArrayList<List<T>>就不能用来捕捉ArrayList<List<?>>,因为ArrayList可能包含两个或以上List<?>,每个List<?>拥有不同的类型。
以上例子摘自—Core Java
擦除(
erasure
)
泛型定义:
泛型方法:
Bridge Method
具体化类型
(reifiable type)
泛型对象创建
消除
Unchecked
warning
反射与泛型
Effective generic
相关推荐
标题中的“Java Generic 介绍”涵盖了泛型的基本概念、使用方式以及其背后的原理。以下是对这一主题的详细阐述: 1. **泛型的基本概念**:泛型是Java中的一种模板类或接口,它允许开发者在定义类、接口和方法时使用...
在Java编程语言中,泛型(Generic)是一个强大的特性,它允许我们在编译时检查类型安全,并且可以消除运行时的类型转换。泛型引入的主要目的是提高代码的重用性、安全性和效率,同时减少类型转换的繁琐工作。这篇...
本文将深入探讨Java中的浅复制和深复制,并以Android为背景,结合具体的实例讲解如何实现Java泛型深拷贝。 首先,我们要理解浅复制和深复制的概念。浅复制(Shallow Copy)是指创建一个新的对象,然后将原对象引用...
在《java-generic.rar》压缩包中包含的《java generic.pdf》文件,很可能是详细阐述了以下几个关于Java泛型的核心知识点: 1. **类型参数化**:泛型的核心在于类型参数化,这使得我们可以在定义类、接口和方法时...
【Japag - Java generic command line GUI 开源项目详解】 Japag,全称为 Java Application for Providing a Generic GUI,是一个开源项目,专为那些希望通过图形用户界面(GUI)而非命令行来运行各种命令行应用...
java高手真经 全光盘源代码 打包rar 第1部分(2个程序包) HelloWorld.zip 01.Java入门样例Hello...javageneric.zip 27.Java泛型编程 javaannotation.zip 28.Java注释符编程 javafeature.zip 29.Java5.0语言新特性
看到那些要积分的很不酸,发布免费版本。 第1部分(2个程序包) HelloWorld.zip 01.Java入门样例...javageneric.zip 27.Java泛型编程 javaannotation.zip 28.Java注释符编程 javafeature.zip 29.Java5.0语言新特性
看到很多人都分卷打包的,下载很是不方便,还浪费积分,我就整合压缩打包到一个包里面,里面包含全部...javageneric.zip 27.Java泛型编程 javaannotation.zip 28.Java注释符编程 javafeature.zip 29.Java5.0语言新特性
Java 泛型是Java SE 5.0引入的一项重要特性,极大地增强了代码的类型安全性和重用性。泛型接口是泛型在接口中的应用,它允许我们在接口中定义带有类型参数的方法,使得实现该接口的类可以使用不同的数据类型。下面...
标题中的"Generic_MT4_java_generic_mt4_"暗示了一个与MetaTrader 4 (MT4)交易平台相关的编程项目,可能是一个自定义的智能交易系统(Expert Advisor,EA)或指标,使用了Java语言,并且具有通用性。这个“Generic_...
Java中的泛型是Java SE 5.0引入的一项重要特性,极大地增强了代码的类型安全性和重用性。泛型方法是泛型概念的一个关键部分,它允许我们在方法签名中使用类型参数,从而使方法能够处理不同类型的参数。在这个“Java...
Java1.5泛型指南中文版(Java1.5 GenericTutorial)
此外,还介绍了一种名为 JGL (Java Generic Library) 的第三方库,该库在 Java Collection Framework 出现之前就已经存在,并且提供了一些额外的功能。 #### 八、总结 《Java Collection Framework》这本书不仅是...
### Java泛型的使用详细讲解 #### 一、引言 在Java开发中,泛型是一种重要的语言特性,它能够帮助开发者在不增加代码量的情况下处理多种数据类型,同时还能保持代码的清晰度和可读性。本文将详细介绍Java泛型的...