黑马程序员技术交流社区

标题: 求助呀,,,崩溃了,, [打印本页]

作者: 汉谟拉比    时间: 2014-7-7 16:31
标题: 求助呀,,,崩溃了,,
import java.util.*;
class Person
{
        private String name;
        Person(String name)
        {
                this.name = name;
        }
        public String getName()
        {
                return name;
        }
}
class Student extends Person
{
        Student(String name)
        {
                super(name);
        }       
}
class FanxingDemo1
{
        public static void main(String[] args)
        {
                ArrayList<Person> a1 = new ArrayList<Person>();
                a1.add(new Person("zhangsan"));
                a1.add(new Person("zhnsagk"));
                a1.add(new Person("lisi"));
                a1.add(new Person("werrda"));
                ArrayList<Student> a2 = new ArrayList<Student>();
                a2.add(new Student("xuesheng1..."));
                a2.add(new Student("xuesheng2..."));
                a2.add(new Student("xuesheng3..."));
                a2.add(new Student("xuesheng4..."));
                sop(a1);
        }
        public static void sop(ArrayList<? super Student> a)
        {
                Iterator<? super Student> i = a.iterator();
                while(i.hasNext())
                {
                        //System.out.println(i.next());
                        System.out.println(i.next().getName());
                }
        }
}
为什么最后访问不到Person类里面的getName()方法吗,,,诧异呀,,,谁来破解一些,,,我是小白呀


作者: 汉谟拉比    时间: 2014-7-7 16:33
我想练习一下泛型应用,,,这个怎么就不行了呢
作者: 汉谟拉比    时间: 2014-7-7 16:34
如果将<? super Student>改成<? extends Person>则完全正常运行呀,,求解
作者: 汉谟拉比    时间: 2014-7-7 16:47
木有人进来呀:'(
作者: 谭荣强    时间: 2014-7-7 17:34
转换一下就ok了.为什么要转换我也不打清楚,估计是因为通配符
Person p = (Person) i.next();                         
System.out.println( p.getName());

System.out.println(((Person) i.next()).getName());
作者: 汉谟拉比    时间: 2014-7-7 18:12
的确。强转之后可以,但是不太明白什么原理呀,,,
作者: EarlyHeart    时间: 2014-7-8 03:05
本帖最后由 EarlyHeart 于 2014-7-8 03:06 编辑

不清楚楼主对泛型通配符了解的多不,所以多写了一些,如果了解,无视第1点,直接看第2点,楼主的问题主要在第2点说明。
1.ArrayList<? super Student>限制ArrayList<T>中的T属于? "super Student"的范围(Student及其父类),也就是说我们在给ArrayList<? super Student>的变量赋值时只能赋泛型为Student及其父类的ArrayList对象,如代码:
  1. public class Demo7 {
  2.         public static void main(String[] args) {
  3.                 ArrayList<? super A> list = new ArrayList<A>();//A属于"A及A的父类"这个范围内故编译成功
  4.                 ArrayList<? super A> list1 = new ArrayList<Object>();//Object也为A的父类故编译成功
  5.                 ArrayList<? super A> list2 = new ArrayList<B>();//B是A的子类,不属于"A及A的父类"这个父类故编译失败
  6.         }
  7. }
  8. class A{}
  9. class B extends A{}
复制代码

ArrayList<? extends A>同理,只不过“? extends A”表示的是A及A的子类
2.楼主的代码中的问题在于:
  1. public static void sop(ArrayList<? super Student> a)
  2.      {
  3.              Iterator<? super Student> i = a.iterator();//注意这里引用变量i代表的是一个包含元素属于"? super Student"范围的Iterator,
  4.                                                                                                      //而这个变量i并不知道自己包含的元素是哪个类型的(他只是知道这个类型的一个范围而已),
  5.                                                                                                      //那么万一这个i所指对象里面放的是一堆Object怎么办呢(也就是如果 a.iterator()返回的是一个Iterator(Object)),
  6.                                                                                                      //很明显Object没有你定义的getName()方法,所以,这里为了以后运行时的安全,i。next()返回的是"? super Student"
  7.                                                                                                      //这个范围的上界,即Object对象,所以便没有我们自己定义的getName()方法。
  8.              while(i.hasNext())
  9.              {
  10.                      //System.out.println(i.next());
  11.                          System.out.println(i.next().getName());
  12.              }
  13.      }
  14.          /*
  15.      public static void sop(ArrayList<? extends Person> a)
  16.      {
  17.              Iterator<? extends Person> i = a.iterator();//而这里"? extends Person"代表的是Person及其子类,而无论Person还是它的子类都有我们自己定义的getName()方法,
  18.                                                                                                      //所以这个范围内的任何类型具备getName方法(实际上这里a.iterator()返回的是Iterator<Person>,依旧去了上界),因此
  19.                                                                                                       //可以编译通过。
  20.              while(i.hasNext())
  21.              {
  22.                      //System.out.println(i.next());
  23.                          System.out.println(i.next().getName());
  24.              }
  25.      }
  26.      */
复制代码

作者: ahuhxl    时间: 2014-7-8 08:18
楼上解释相当精辟!
作者: ★八月⊰~    时间: 2014-7-8 09:33
7#解释的相当靠谱
作者: on-on    时间: 2014-7-8 09:49
学习了,哈哈
作者: 黄宝宝    时间: 2014-7-8 09:53
楼上解释得很清楚
作者: 汉谟拉比    时间: 2014-7-8 22:41
谢谢EarlyHeart哦,,,学习了




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