A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 庄星睿 于 2012-6-16 08:55 编辑

找了好长时间一直没找到问题,发帖子问,大家都能运行,说我文件没编译或是运行错了,没办法,自己找原因吧,看了N变代码,一个一个排除,最后装回了jdk 1.6
版本的,运行成功没错误,跟视频上讲 的一样,但安装了最新的jdk 1.7版本,后运行出了如下的问题,麻烦帮忙看一下,我看了1.7版的新特性里面没找到。另外建议论坛里自学视频的,最好把jdk和API更新到最新版本,会发现很多问题。
  1. import java.util.*;

  2. class TreeSetDemo
  3. {
  4.     public static void sop(Object obj)
  5.     {
  6.         System.out.println(obj);
  7.      }
  8.     public static void main(String[] args)
  9.    {
  10.          TreeSet ts=new TreeSet();

  11.           ts.add(new Student("张三",30));  //还是这一行有问题
  12.           //ts.add(new Student("李四",20));
  13.           //ts.add(new Student("王五",10));
  14.          //ts.add(new Student("丽丽",25));
  15.          sop(ts);
  16.          Iterator it=ts.iterator();
  17.           while (it.hasNext())
  18.         {
  19.               Student s=(Student)it.next();
  20.               sop(s.getName()+"......."+s.getAge());
  21.          }
  22.      }

  23. }

  24. class Student
  25. {
  26.        private String name;
  27.        private int age;
  28. public Student(String name,int age)
  29. {
  30.      this.name=name;
  31.      this.age=age;
  32. }
  33. public String getName()
  34. {
  35. return this.name;
  36. }
  37. public int getAge()
  38. {
  39. return this.age;
  40. }

  41. }
复制代码
这里我只存一个对象应该是可以存进去的啊,还没调用比较呢,可是运行结果还是

还有后面我调用了compareTo的方法也有问题:
  1. import java.util.*;

  2. class TreeSetDemo
  3. {
  4. public static void sop(Object obj)
  5. {
  6. System.out.println(obj);
  7. }
  8. public static void main(String[] args)
  9. {
  10. TreeSet ts=new TreeSet();

  11. ts.add(new Student("张三",30));
  12. ts.add(new Student("李四",20));
  13. ts.add(new Student("王五",10));
  14. ts.add(new Student("丽丽",25));
  15. sop(ts);
  16. Iterator it=ts.iterator();
  17. while (it.hasNext())
  18. {
  19. Student s=(Student)it.next();
  20. sop(s.getName()+"......."+s.getAge());
  21. }
  22. }


  23. }

  24. class Student implements Comparable
  25. {
  26. private String name;
  27. private int age;
  28. public Student(String name,int age)
  29. {
  30. this.name=name;
  31. this.age=age;
  32. }
  33. public String getName()
  34. {
  35. return this.name;
  36. }
  37. public int getAge()
  38. {
  39. return this.age;
  40. }
  41. public int compareTo(Object obj)
  42. {
  43. if (!(obj instanceof Student))
  44. throw new RuntimeException("不是学生类");
  45. Student s=(Student)obj;
  46. System.out.println(this.name+"......compareto ......."+s.name);
  47. if (this.age>s.age)
  48. return 1;
  49. if (this.age==s.age)
  50. return 0;
  51. //return this.name.compareTo(s.name);  //这里先不执行
  52. return -1;
  53. }
  54. }
复制代码
运行结果:

张三这个对象还是相当于被传入了两次,第一个问题异常,应该也是第一个对象存了两次造成的吧,我找到原因了,谁能解释一下为什么jdk7.0以后TreeSet集合里存
对象的时候第一次存就会调用compareTo()方法。。。。。求解原理???

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

8 个回复

倒序浏览
首先对于第一个是不会报异常的,很有可能是你没有重新编译
运行了以前编译过的class文件

对于第二个在我的电脑上也没有出现两次存入张三的情况
结果:
李四......compareto .......张三
王五......compareto .......张三
王五......compareto .......李四
丽丽......compareto .......李四
丽丽......compareto .......张三
[com.test.Student6@1e63e3d, com.test.Student6@1004901, com.test.Student6@1b90b39, com.test.Student6@18fe7c3]
王五.......10
李四.......20
丽丽.......25
张三.......3
回复 使用道具 举报
本帖最后由 庄星睿 于 2012-6-15 13:34 编辑
陌花╮有意、 发表于 2012-6-15 13:09
首先对于第一个是不会报异常的,很有可能是你没有重新编译
运行了以前编译过的class文件


第一个编译不会报异常,但运行时会报异常,我重新编译了,还是这样的,要不我把.class文件发给你,你运行一下,在反编译一下,看下代码都是一样的
回复 使用道具 举报
第一个代码是正确的,我编译过,没问题,可能是你修改了代码,没有重新编译,运行的还是之前的class文件。
李四......compareto .......张三
王五......compareto .......张三
王五......compareto .......李四
丽丽......compareto .......李四
丽丽......compareto .......张三
[xixi.Student@12b6651, xixi.Student@4a5ab2, xixi.Student@1888759, xixi.Student@6e1408]
王五.......10
李四.......20
丽丽.......25
张三.......30
这是我第2个代码运行的结果,张三同样只存了一次,你每次修改完代码后,记得要编译再运行啊!
回复 使用道具 举报
李盼 发表于 2012-6-15 14:34
第一个代码是正确的,我编译过,没问题,可能是你修改了代码,没有重新编译,运行的还是之前的class文件。
...

我找到原因了,麻烦你换成jdk1.7的再运行一下,知道原因请回复!
回复 使用道具 举报
庄星睿 发表于 2012-6-15 15:41
我找到原因了,麻烦你换成jdk1.7的再运行一下,知道原因请回复!

我没有用jdk7
回复 使用道具 举报
Exception in thread "main" java.lang.ClassCastException: com.practise.Student1 cannot be cast to java.lang.Comparable
        at java.util.TreeMap.compare(TreeMap.java:1188)
        at java.util.TreeMap.put(TreeMap.java:531)
        at java.util.TreeSet.add(TreeSet.java:255)
        at com.practise.TreeSetDemo2.main(TreeSetDemo2.java:24)
请查看源代码:
程序执行的顺序好像是这样的:13.   ts.add(new Student("张三",30));   
                                                   运行到此处,add()方法会调用put()方法:
public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }
put()方法是这样的:
public V put(K key, V value) {
        Entry<K,V> t = root;
        if (t == null) {
            compare(key, key); // type (and possibly null) check

            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
此处的compare()又调用的是compareTo():
final int compare(Object k1, Object k2) {
        return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
            : comparator.compare((K)k1, (K)k2);
    }
回复 使用道具 举报
黄连兵 发表于 2012-6-15 17:10
Exception in thread "main" java.lang.ClassCastException: com.practise.Student1 cannot be cast to jav ...

我大概理解了,我也找了源码文件,只在TreeSet.java文件里找到了
public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }
那个 put方法 和compare方法都在哪个文件里呢,我想比较一下1.6和1.7版本的源码,还有1.7为什么要判断容器为null时要增加一次比较判断呢?这样做有什么好处吗?
回复 使用道具 举报
庄星睿 发表于 2012-6-15 17:37
我大概理解了,我也找了源码文件,只在TreeSet.java文件里找到了
public boolean add(E e) {
        ret ...

异常都提示了:
      at java.util.TreeMap.compareTreeMap.java:1188)(
          at java.util.TreeMap.put(TreeMap.java:531)
去java安装目录的src.zip里可以找得到。
至于为什么null也要比较,我觉得是不是因为map里是允许存入null键和null值的关系呢?这个纯属个人理解有待继续研究。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马