关于Java中泛型的问题

老冯_f 发布于 2014/03/21 09:27
阅读 499
收藏 0

【DevOps必读】产品经理与程序员之间如何破局?>>>

import java.util.*;
public class F4 {
	public static void main(String[] args) {
		
		TreeSet<? super Student> t1=new TreeSet<Person>();
		//t1.add(new Person());这里为什么报错呢
		t1.add(new Student());
		}
}

class Person{}
class Student extends Person{}

上段代码在初始化的时候new TreeSet<Person>();这里已经说明了<Person>,那为什么不能添加Person类型的对象呢?

加载中
1
110hxl
110hxl

TreeSet<? super  Student>的集合只能存放Student类型以及其子类。附上个人对泛型的理解

http://my.oschina.net/u/782865/blog/203933

http://my.oschina.net/u/782865/blog/198906

1
yxmsw2007
yxmsw2007
String是Object的子类,但List<String>不是List<Object>的子类
1
香农312
香农312
import java.util.*;
public class F4 {
    public static void main(String[] args) {

        TreeSet<? super Student> t1=new TreeSet<Person>();
        //t1.add(new Person());这里为什么报错呢
        t1.add(new Student());
        //t1.add(new Teacher());
        t1.add(new BanZhang());
    }
}

class Person{}
class Student extends Person{}
class BanZhang extends Student{}

class Teacher extends Person{}




当你add一个Person对象的时候,其实不一定是Student这个类的超类,比如你add一个Teacher时,
它不是Student的超类,却是一个Person,这样当然要绝交呀。对于? super XX的泛型,添加元素的时候
只能添加XX的子类及其自身,比如例子中的add一个BanZhang是允许的.这样说不知道你理解了没有。
香农312
香农312
回复 @女汉子_油菜花 : 今天才看到回复,稍后给你一个例子,你感受下。TreeSet<Person>后面Person的作用
老冯_f
老冯_f
对于你说的 我理解了 但是new TreeSet<Person>(),这里的<Person>作用是啥呢
1
antipro
antipro

TreeSet<? super Student> t1 这样的声明表示这个t1包含的类至少是Student或他的超类。因此向t1添加Student的子类是可行的,因为子类可以被造型成超类来处理,但是添加Student的超类或者完全不相干的类是不行的。

TreeSet<? extends Student> t1这样的声明表示这个t1包含的类是Student或他的子类,因此从这个t1获取Student类是可行的。


你说的“上段代码在初始化的时候new TreeSet<Person>();这里已经说明了<Person>,那为什么不能添加Person类型的对象呢?”这句话,说明你还在被等式右边的初始化困扰,其实这个初始化没什么意义,决定t1行为的是他的声明,也就是等式左边的部分。


1
业余编程人士
业余编程人士

虽然初始化编译通过 但是毫无意义。 我觉得你已经转进去了 记住无论泛型怎么设计都是提供便利的 都要遵循OOP的思想。 就试想一下 一个set 集合 或者一个 无论什么集合怎么可能可以加父类 如果这样 Object也可以加  Object所有子类也可以加 什么都可以加了.

super 和 extends 的通配符捕获 99% 都需要写在方法签名里面捕获的 而不是用于初始化 因为初始化无意义 这在 oracle 的 java tutorial里面有计到



老冯_f
老冯_f
我确实是转进去了。。。。目前对泛型的理解就是一锅粥
1
香农312
香农312

为方便演示,把TreeSet改为List了,其实原理是一样的。

/**
 * @author chengyongchun
 * @date 14-3-25 上午8:52
 */
import java.util.*;
public class F4 {
    public static void main(String[] args) {

        List<? super Student> t1=new ArrayList<Student>();
        //t1.add(new Person());这里为什么报错呢
        Student student = new Student();
        student.setName("name");
        t1.add(student);
        //t1.add(new Teacher());
        t1.add(new BanZhang());
        //因为集合里存储的是Student对象,不能强制转换为Teacher,如果是ArrayList<Person>在本列子中等价于ArrayList,
        System.out.println(((Teacher)t1.get(0)).getName());//抛ClassCastException
        System.out.println(((Student) t1.get(0)).getName());
    }
}

class Person{
    private String name;

    public String getName(){
        return this.name;
    }

    public void setName(String name){
        this.name = name;
    }
}
class Student extends Person{}
class BanZhang extends Student{}

class Teacher extends Person{}



其实ArrayList<Student>只是说明集合里存储的具体是什么类型,在从集合里取出元素的时候用的着。如例子所演示的那样

0
老冯_f
老冯_f
求该帖不沉
0
红薯
红薯

你为什么要写 <? super Student> 呢?直接写 <Student> 不就好了?

老冯_f
老冯_f
我就是想了解一下这个泛型的规则。。。
0
涵小涵
涵小涵
有这种
TreeSet<? super Student>

写法么?印象中只见过

TreeSet<? extends Student>



可能见的太少了,同求解答


0
渠富林
渠富林

"? super Student"指地是目标类型是Student或者Student的直接子类,是Student的父类当然不行了。补充一点,Student子类的子类也是不行的,因为不是直接子类,如果改成"? extends Student" 那么只要是继承自Student的类就都可以add了。

老冯_f
老冯_f
上限限定不能添加吧
返回顶部
顶部