javajava 获取泛型的类型第二个类型限制有必要吗

安全检查中...
请打开浏览器的javascript,然后刷新浏览器
< 浏览器安全检查中...
还剩 5 秒&Java泛型的规则和限制_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
Java泛型的规则和限制
&&Java泛型的规则和限制
阅读已结束,下载文档到电脑
想免费下载更多文档?
定制HR最喜欢的简历
你可能喜欢有时候,类和方法需要对类型变量加以约束,比如你有一个方法,你只希望它接收某个特定类型及其子类型作为参数。
下面就举一个方法限定接收参数的类型的例子来说明如何限定类型变量。
首先有几个简单的辅助类:
public class Person extends Animal {
public Person(String name) {
this.name =
public String getName() {
public void setName(String name) {
this.name =
public String toString() {
return &Person [name=& + name + &]&;
public class Student extends Person {
private String studentN
public Student(String name, String registrationNumber) {
super(name);
this.studentNumber = registrationN
public String getStudentNumber() {
return studentN
public void setStudentNumber(String studentNumber) {
this.studentNumber = studentN
public String toString() {
return &Student [studentNumber=& + studentNumber + &, name=&
+ getName() + &]&;
public class Teacher extends Person {
private String teacherN
public Teacher(String name, String teacherNumber) {
super(name);
// TODO Auto-generated constructor stub
this.teacherNumber = teacherN
public String getTeacherNumber() {
return teacherN
public void setTeacherNumber(String teacherNumber) {
this.teacherNumber = teacherN
public String toString() {
return &Teacher [teacherNumber=& + teacherNumber + &, name=&
+ getName() + &]&;
下面是一个测试类,里面包含了一个限定了接收参数的类型的方法:
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Person person = new Person(&li&);
Student student = new Student(&yuncong&, &1&);
Teacher teacher = new Teacher(&wangfang&, &99&);
Building building = new Building(&qiuyuan&);
* test1说明getPersonInfo(T person)方法的参数只能是Person
* 及其子类的实例;
System.out.println(Test.getPersonInfo(person));
System.out.println(Test.getPersonInfo(student));
System.out.println(Test.getPersonInfo(teacher));
* Bound mismatch: The generic method getPersonInfo(T) of type Test is
* not applicable for the arguments (Building). The inferred type
* Building is not a valid substitute for the bounded parameter &T
* extends Person&
// System.out.println(Test.getPersonInfo(building));// error
* T的限定类型决定了在方法中可以调用T的实例的哪些方法;
* @param person
public static &T extends Person& String getPersonInfo(T t) {
return t.toString();
运行测试类的结果如下:
Person [name=li]
Student [studentNumber=1, name=yuncong]
Teacher [teacherNumber=99, name=wangfang]
类型变量的限定只有extends这一个关键字,extends可以接多个接口超类型,但是至多有一个类,如果extends后面跟有类,这个类必须是第一个。多个限定类型用&隔开。如:T extends Person & Comparable&T&。
本文已收录于以下专栏:
相关文章推荐
对java的泛型特性的了解仅限于表面的浅浅一层,直到在学习设计模式时发现有不了解的用法,才想起详细的记录一下。
本文参考java 泛型详解、Java中的泛型方法、&#160;java泛型详解
泛型类型变量的限定
泛型的基础知识可以参考其他教程。
如果在方法前指定了,那么就是说,方法的这个泛型类型和类定义时的泛型类型无关,这个特性让泛型方法可以定义在普通类中而不是泛型类中。
我们都知道,泛...
现在开始深入学习java的泛型了,以前一直只是在集合中简单的使用泛型,根本就不明白泛型的原理和作用。泛型在java中,是一个十分重要的特性,所以要好好的研究下。
一、泛型的基本概念
&#160;泛型...
自限定类型强制泛型当做其自己的边界参数来使用。
* Created by msc on .
class SelfBounded&{
1. 自限定的类型
在java泛型中,经常会出现如下的泛型写法:class SelfBounded&T extends SelfBounded& SelfBounded类接受泛型参数T,而T由一个边...
注意点:Android的反射机制有一个问题,就是Class.getDeclaredFields()返回的变量数组与我们定义的类的变量顺序是不一致的.Android是经过了字母顺序排序的.所以我们需要将...
通过例子来看泛型类在继承中过程中类型变量应该具有怎样的关系。
首先给出几个辅助类:
public class Animal {
package gen...
【0】README0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 通配符类型+通配符的超类型限定 的知识;【1】通配符类型相关1.1)通...
他的最新文章
讲师:王哲涵
讲师:韦玮
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)限制泛型可用类型
JAVA中基本的泛型语法元素大致有三种:限制泛型可用类型、使得类型通配符,以及泛型的继承。下面将分别对这三种语法进行介绍。
1、限制泛型可用类型
我们在定义泛型类时,默认的是可以使用任何类型来实例化泛型类中的类型持有者。我们也可以指定某种类型,使得此泛型类只能通过这种类型或其子类,或实现这个接口的类来实例化类型持有者。
我们在定义类型持有者时,使用extends关键字来进行限制,例如我们可以这样定义泛型类:
public class LimitDemo&T extends List&&
public class LimitDemo&T extends List&
}这表示类型持有者T所代表的类型必须是一个实现了List接口的类型。所以我们要这样产生LimitDemo类的实例:
LimitDemo&ArrayList& demo = new LimitDemo&ArrayList&();&
LimitDemo&ArrayList& demo = new LimitDemo&ArrayList&();因为ArrayList是实现了List接口的类,所以这样写是合法的。如果不是实现List接口的类:
LimitDemo&String& demo = new LimitDemo&String&(); // String没有实现List接口&
LimitDemo&String& demo = new LimitDemo&String&(); // String没有实现List接口
编译器就会报出 &String类型不在T范围内& 的错误:
事实上,当我们不用extends关键字来限制泛型类对象时,编译器默认的是Object类下所有的子类都可以实例化类型持有者。即:
[java] view plaincopyprint?
public class LimitDemo&T&{}&
public class LimitDemo&T&{}等价于:
public class LimitDemo&T extends Object&{}&
public class LimitDemo&T extends Object&{}
2、类型通配符
如果有一个引用名demo,我们希望demo既能引用WildDemo&String&类型,又能引用WildDemo&Integer&类型,该如何实现呢?
不使用通配符的话,我们只能分别定义两个变量,一个是WildDemo&String& demo1,另一个是WildDemo&Integer& demo2,来保存对这两种类型的实例的引用。如果使用通配符,则可以这样写:
// 使用通配符 &#39;?&#39;&&
&&&&&&& WildDemo&?&&
&&&&&&& demo = new WildDemo&Integer&();&
&&&&&&& demo = new WildDemo&String&();&
// 使用通配符 &#39;?&#39;
&&&&&&& WildDemo&?&
&&&&&&& demo = new WildDemo&Integer&();
&&&&&&& demo = new WildDemo&String&();
但要注意的是,通过使用类型通配符声明的名称所引用对象,无法对该对象添加信息,只能获取或移除该对象的信息。如下例:
import java.util.*;&
public class WildDemo&T&&
&&& private T&
&&& // 为x赋值&&
&&& public void setX(T x)&
&&&&&&& this.x =&
&&& // 读取x的值&&
&&& public T getX()&
&&& public static void main(String[] args)&
&&&&&&& WildDemo&Integer& obj = new WildDemo&Integer&();&
&&&&&&& obj.setX(100);&
&&&&&&& // 使用通配符 &#39;?&#39;&&
&&&&&&& WildDemo&?& demo =&
&&&&&&& demo.getX(); // 读取信息,OK&&
&&&&&&& demo.setX(null); // 移除信息,OK&&
&&&&&&& demo.setX(200); // 设置新的信息给X, ERROR&&
import java.util.*;
public class WildDemo&T&
&&& private T
&&& // 为x赋值
&&& public void setX(T x)
&&&&&&& this.x =
&&& // 读取x的值
&&& public T getX()
&&& public static void main(String[] args)
&&&&&&& WildDemo&Integer& obj = new WildDemo&Integer&();
&&&&&&& obj.setX(100);
&&&&&&& // 使用通配符 &#39;?&#39;
&&&&&&& WildDemo&?& demo =
&&&&&&& demo.getX(); // 读取信息,OK
&&&&&&& demo.setX(null); // 移除信息,OK
&&&&&&& demo.setX(200); // 设置新的信息给X, ERROR
3、泛型类的继承
定义父泛型类:
class Parent&T1,T2&{}&
class Parent&T1,T2&{}定义子泛型类从Parent继承而来:
class Child&T1,T2,T3& extends Parent&T1,T2&{}&
class Child&T1,T2,T3& extends Parent&T1,T2&{}
如果子类想保留父类的类型持有者T1,T2,那么父类上所声明的类型持有者的数目在继承下来时必须写全,即class Child&T1,T2)&。如果子类不保留类型持有者,那么继承下来的T1,T2自动变为Object类型。
在实际应用中我们使用泛型应该本着简洁易读的原则来定义泛型类,要尽量避免定义有多重&&的复杂泛型。此文目录:
Java泛型是什么?
通常的泛型的写法示例
为什么要使用Java泛型
通过示例了解PECS原则
一、Java泛型是什么?
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
通俗的讲,泛型就是操作类型的 占位符,即:假设占位符为T,那么此次声明的数据结构操作的数据类型为T类型。
二、通常的泛型写法示例
T 类型,用于泛型类或者泛型方法
  泛型类定义:
public class ApiResult&T& {
省略构造方法和 get,set方法。
  定义泛型方法:
public class JsonUtil {
public &T& T
str2Json(String jsonText,Class target){
T result=null;
//....parse to json
  使用:
  //泛型类使用
ApiResult&User& result=new ApiResult&User&();
result.setResultCode(0);
result.setResultMsg("success");
result.setResultObject(new User());
      ApiResult&List&User&& result2=new ApiResult&List&User&&();
      result.setResultCode(0);
      result.setResultMsg("success");
      result.setResultObject(userList);
      ApiResult&Integer& result3=new ApiResult&Integer&();
      result3.setResultCode(0);
      result3.setResultMsg("success");
      result3.setResultObject(99);
    //泛型方法使用
      String userJsonText="....省略",dogJsonText="....省略";;& & & & & User u=JsonUtil.str2Json(jsonText,User.class);& & & & & User u=JsonUtil.str2Json(jsonText,Dog.class);
 K,V类型,类似Map接口。
public class ResultMap&K,V& {
//省略 set ,get
方法public void put(K key,V value){
this.value=
ResultMap&String,User& resultMap=new ResultMap&&();
resultMap.put("currentUserKey", new User());
?extends 类型
&? extends T& 表示类型的上界,表示参数化类型的可能是T 或是 T的子类
?supper 类型
&? super T& 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object
 三、类型擦除
  先看一个例子,Operate类如下:
public class Operate {
public static void main(String[] args) {
List&String& names=new ArrayList&String&();
names.add("Jack");
names.add("Tom");
names.add("peter");
for(String name:names){
System.out.println("wellcome:"+name);
其对应的class文件反编译之后,我们使用java-gui反编译.exe &查看编译之后的代码如下
发现没有,根本没有&String& 这一部分了。这个限制为String类型的泛型被&擦除&了。写代码的时候,泛型会做校验,类型不对应的,无法add,但是编译之后边去掉了泛型类型。
& 四、什么要使用Java泛型
&在上面 第三部分介绍了&类型擦除&之后,在来说为什么要使用Java泛型就比较好说了。这里的泛型就相当于&约法三章&,先给你定好&规矩&,我这个List&String& 就是用来操作
String类型的,你插入Person对象就不行。说白了就是为了类型安全。所以其好处有:
& 类型安全:通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。
消除强制类型转换:
//该代码不使用泛型:
List li = new ArrayList();
li.put(new Integer(3));
Integer i = (Integer) li.get(0);
//该代码使用泛型:
List&Integer& li = new ArrayList&Integer&();
li.put(new Integer(3));
Integer i = li.get(0);
了解了上面的这么多,已经足够日常使用泛型了。下面了解下PECS原则
五、PECS原则
 先看例子:
此处定义三个类,spiring,summer继承seasonpublic class Season {
public class Spring extends Season {
public class Summer extends Season {
List&? extends Season& list1=new ArrayList&&();
//list1.add(new Spring());//这里编译不通过,因为编译器无法确定list所持有的类型。
List&? extends Season& list2=new ArrayList&Spring&();
list2.add(new Spring());//也是无法通过编译
    //通过上文,我们知道 ?extends Season表示可以接收的类型为 Seaon 或者其子类。
但是此处不行,因为可能传入进来的是spring,或者summer,编译器无法确定具体传递进来的是什么,
所以无法安全的向其中添加对象,但是它可以接收子类类型 的赋值。如下:
List&Spring& list3=new ArrayList&Spring&();
List&? extends Season& list4=list3;//这里和上面的list2做对比,无法直接add spring类型的对象
//但是可以直接将spring类型的list赋值。
List&Season& seasons=new ArrayList&Season&();
List&? super Spring& spring=
spring.add(new Spring());//ok
spring.add(new Summer());//error
spring.add(new Season());//error
spring.add(new Object());//error
List&? super Season& sea=new ArrayList&&();
sea.add(new Spring());//ok
sea.add(new Summer());//ok
sea.add(new Season());//ok
sea.add(new Object());//error
List&? super Spring& spring=new ArrayList&&();
spring.add(new Spring());//ok
spring.add(new Summer());//error
spring.add(new Season());//error
spring.add(new Object());//error
这里 ,PECS原则 如下:
如果要从集合中读取类型T的数据,并且不能写入,可以使用 ? extends 通配符;(Producer Extends)
如果要从集合中写入类型T的数据,并且不需要读取,可以使用 ? super 通配符;(Consumer Super)
如果既要存又要取,那么就不要使用任何通配符。
阅读(...) 评论()

我要回帖

更多关于 java 获取泛型类型 的文章

 

随机推荐