黑马程序员技术交流社区

标题: 泛型问题 [打印本页]

作者: 左耳的鱼    时间: 2013-6-29 21:12
标题: 泛型问题
本帖最后由 左耳的鱼 于 2013-6-30 21:16 编辑

package cn.itcast.generic3;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

public class GenericDemo2 {

        /**
         * @param args
         */
        public static void main(String[] args) {
                ArrayList<Worker> al = new ArrayList<>();
                al.add(new Worker("张三"));
                al.add(new Worker("李四"));
                al.add(new Worker("王五"));
                show(al);
               
                HashSet<Student> hs = new HashSet<>();
                hs.add(new Student("赵六"));
                hs.add(new Student("冯七"));
                hs.add(new Student("天一"));
                show(hs);
               
        }

        private static void show(Collection<Person> al) {//此处为什么不能用Person,必须用通用符吗,为什么也不能用Object,不是说父类指向子类吗,为什么写父类类型不行?
                Iterator<Person> it = al.iterator();
                while(it.hasNext()) {
                        Person p = it.next();
                        System.out.println(p.getName());
                }
        }
        //此处我要是改为
        /*private static<Person> void show(Collection<Person> al) {
                Iterator<Person> it = al.iterator();
                while(it.hasNext()) {
                        Person p = (Person)it.next();
                        System.out.println(p.getName());
                }
        }*///改成泛型方法,为什么不行
        /*private static<T> void show(Collection<T> al) {
                Iterator<T> it = al.iterator();
                while(it.hasNext()) {
                        Person p = (Person)it.next();
                        System.out.println(p.getName());
                }
        }*///如果这么改,泛型方法为什么是对的
        /*private static<Object> void show(Collection<Object> al) {
                Iterator<Object> it = al.iterator();
                while(it.hasNext()) {
                        Person p = (Person)it.next();
                        System.out.println(p.getName());
                }
        }*///这么改,改成Object类型,为什么程序是对的
        /*private static<Worker> void show(Collection<Worker> al) {
                Iterator<Worker> it = al.iterator();
                while(it.hasNext()) {
                        Person p = (Person)it.next();
                        System.out.println(p.getName());
                }
        }*///如果类型改成Worker或者Student类型,为什么运行是对的,改成他们的父类就是错的呢,改成Object类型就是对的呢???

}


package cn.itcast.generic3;

public class Person {
        private String name;

        public String getName() {
                return name;
        }

        public void setName(String name) {
                this.name = name;
        }

        public Person(String name) {
                super();
                this.name = name;
        }
        
}



package cn.itcast.generic3;

public class Student extends Person {

        public Student(String name) {
                super(name);        
        }
}



package cn.itcast.generic3;

public class Worker extends Person {

        public Worker(String name) {
                super(name);
               
        }
}
//为什么程序运行不出来

作者: L.I.F.E    时间: 2013-6-29 21:20
限定通配符的上边界:
<? enxtends Person>
作者: 左耳的鱼    时间: 2013-6-29 22:03
L.I.F.E 发表于 2013-6-29 21:20
限定通配符的上边界:

通配符我知道怎么用 我说的是另一种方法表示
作者: 王靖远    时间: 2013-6-29 22:18
泛型不存在继承的关系。张孝祥老师的高新技术里面讲到了
ArrayList<Wroker> al= new ArrayList<Person>();虽然Worker是继承Person的,但是这样写也是行不通的。
作者: 王靖远    时间: 2013-6-30 00:30
private static <Person> void show(Collection<Person> al) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {//此处为什么不能用Person,必须用通用符吗,为什么也不能用Object,不是说父类指向子类吗,为什么写父类类型不行?
                Iterator<Person> it = al.iterator();
                while(it.hasNext()) {
                        Person p = it.next();
               Method method = p.getClass().getMethod("getName");//我把你第一个show方法这里改成反射就可以了。我不知道为什么不用反射p不能调用getName()方法。而泛型定义Object或者T时,p可以调用getName()方法。
               System.out.println(method.invoke(p));
                        
                }
        }
作者: 王靖远    时间: 2013-6-30 01:16
王靖远 发表于 2013-6-30 00:30
private static  void show(Collection al) throws NoSuchMethodException, SecurityException, IllegalAcc ...

我推测是因为类型参数为Person的show方法里,it.next()获得的实例对象是Worker或者Student,但是迭代器的类型参数是Person。Person p = it.next();这句话在右边是子类对象Worker或者Student,而迭代器泛型是Student。右边明明不是Person,泛型却说他是Person,都不用强制转型了。
作者: 王靖远    时间: 2013-6-30 01:23
王靖远 发表于 2013-6-30 01:16
我推测是因为类型参数为Person的show方法里,it.next()获得的实例对象是Worker或者Student,但是迭代器的 ...

(test.Person) p).getName()
这样在参数为Person的show里也能调用到p.getName();不知道为什么
作者: L.I.F.E    时间: 2013-6-30 08:49
张老师讲过:
参数化类型不考虑类型参数的继承关系:
1)Vector<String> v = new Vector<Object>();//错误,不写<Object>可以。
2)Vector<Object>v = new Vector<String>();//错误
下面代码:
Vector v1 = new Vector<String>();
Vector<Object> v = v1;
不会报错,编译器是一个严格按照语法检查的工具,它不考虑运行时的效果,一行一行翻译代码,所以编译会通过。

楼主细细体会!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2