import java.util.TreeSet;public class TreeSetTest {
/**
 * @param args
 */
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeSet set = new TreeSet();
//set.add(new Parent(3));
//set.add(new Parent(3));
set.add(new Child());
//set.add(new Child());
set.add(new Parent(4));
set.add(new Parent(4));
System.out.println(set.size());
}
} class Parent implements Comparable {
private int age = 0;
public Parent(int age){
this.age = age;
}
public int compareTo(Object o) {
System.out.println("method of parent");
Parent o1 = (Parent)o;
return age>o1.age?1:age<o1.age?-1:0;
}} class Child extends Parent { public Child(){
super(3);
}
public int compareTo(Object o) { // TODO Auto-generated method stub
System.out.println("method of child");
// Child o1 = (Child)o;
return 1;
}
}
各位热心人看一下,子类实例化,但是父类还实现了接口,到底是什么一个顺序?Java对象实例

解决方案 »

  1.   

    关键还是看compareTo方法的执行的情况。
      

  2.   

    Comparable 是使对象间可以执行比较操作(一般在对象排序时用的比较多)。
    子类没有其它特别的属性,完全不必要再复写父类的compareTo方法了。另外,new一个子类对象,会调用父类构造方法,但是最终实例化完成的对象,依然是子类型的。
    这个实例化调用方法的顺序,与comparable接口的实现没啥关系,这个接口只是提供了一个compareTo方法而已。
      

  3.   

    我自己是这么分析的,首先先给你引入个重写的例子public class TestParentChild
    {
    public static void main(String[] args)
    {
    new Test2().say();
    }
    }class Test1
    {
    public void say()
    {
    System.out.println("Parent");
    }
    }class Test2 extends Test1
    {
    @Override
    public void say()
    {
    System.out.println("Child");
    }
    }
    //结果:Child再回来说你的那个例子set.add(new Child());
    就用Child里面的实现,Child继承自父类也实现了接口Comparable
    通过这样Comparable comparable = (Comparable) new Child();可以验证
    所以用子类的比较,所以输出method of child
    返回1,对于添加第一个对象没什么可考虑的,添就行了。set.add(new Parent(4));
    同上面例子,添加父类就调父类的,因为和子类一点关系都没有啊(我是这么理解的)
    所以就用父类的比较方法了,所以输出method of parent
    不过你写这个连续套用的三元比较式我说的不一定准确了,看的很晕
    我自己分析思路是按照新生成的这个对象去比较set里的对象
    4>3 真,所以取1
    返回1,排列在这个对象排列在set里的对象后面set.add(new Parent(4));
    再次添加父类,类似,不过多比较了个对象
    新对象生成后比较set里面第一个对象输出一次method of parent,返回1;
    新对象比较set里面第二个对象输出一次method of parent,返回0;
    集合的特性不允许重复,所以不添加到set了所以最终set.size()也就是2,
    两个元素可以用System.out.println(set);看到
    //[com.nyohh.test1.Child@39443f, com.nyohh.test1.Parent@1afae45]//包名可能不同至于想看到内容是谁的话,可以添加个名字属性。看看具体添加的父类对象是第几次添加的。package com.nyohh.test1;import java.util.Comparator;
    import java.util.TreeSet;public class TreeSetTest
    {
    /**
     * @param args
     */
    public static void main(String[] args)
    {
    // TODO Auto-generated method stub
    TreeSet set = new TreeSet();
    // set.add(new Parent(3));
    // set.add(new Parent(3));
    set.add(new Child());
    // set.add(new Child());
    set.add(new Parent(4,"zhangsan"));
    set.add(new Parent(4,"lisi"));
    System.out.println(set.size()); for (Object object : set)
    {
    Parent p=(Parent) object;
    System.out.println(p.getName());
    }

    }
    }class Parent implements Comparable
    {
    private int age = 0;

    public String name; public Parent(int age,String name)
    {
    this.age = age;
    this.name=name;
    } public String getName()
    {
    return name;
    } public int compareTo(Object o)
    {
    System.out.println("method of parent");
    Parent o1 = (Parent) o;
    int value= age > o1.age ? 1 : age < o1.age ? -1 : 0;
    if (value==0)
    {
    System.out.println(this.name+"没有被添加进去,因为set的特性");
    }
    return value;
    }}class Child extends Parent
    { public Child()
    {
    super(3,"system");
    } public int compareTo(Object o)
    { // TODO Auto-generated method stub
    System.out.println("method of child");
    // Child o1 = (Child)o;
    return 1;
    }
    }
      

  4.   

    u011325635 你好,我试了并且也运行了一下,当
    set.add(new Child());
    set.add(new Parent(4,"zhangsan"));
    set.add(new Parent(4,"lisi"));
    运行结果如下:我觉得是不是只有存入两个对象时才调用comparTo方法,当我改为如下代码时输出才有method of child
    set.add(new Parent(3,"wangwu"));
    set.add(new Child());
    set.add(new Parent(4,"zhangsan"));
      

  5.   

    在你保存这个java的时候已经被编译为class文件了,你要实例化父子两个对象都是可以的,顺序是根据你实例的顺序,Treeset集合保存对象的顺序是有自己的机制的,不是根据你添加的顺序保存的。。
      

  6.   

    是类的话基本都可以实现接口(除了final 抽象类),具体执行顺序,你得看main方法里面的执行顺序
      

  7.   


    因为是第一段代码先添加了Child对象“system”,set里面只有这一个方法,所以没法调用Child类中的compareTo方法,而第二段代码child是放在第二个中添加的所以会显示method of child.
      

  8.   

    好像也是你说 的这个道理,但是我感觉,你编译后生成class文件,再运行的话,不是还是要逐语句的执行吗?所以我调试运行的结果,我是这么去猜测和推理的,我其实是不太明白,Comparable接口原来在这个程序里面是给set里面的对象排序的。
      

  9.   

     * 1.TreeSet的比较是从中间开始比,如果小,然后再和小的比较
     * 2.如果大了,就和大的再比较
     * 3.TreeSet是要比较所有存储的顺序的
    这是我今天查了API,并且又重新调试了程序的收获。
      

  10.   


    你说的比较机制我还真没仔细去看过,按照你说的这个比较顺序是二分排序法,学习时候有讲过这个:public class BinarySearchTest
    {
    public static void main(String[] args)
    {
    int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };// 二分查找前提数组必须是有序数组
    int value = 10;
    System.out.println(binarySearch(arr, value));
    } private static int binarySearch(int[] array, int value)
    {
    int low = 0;
    int high = array.length;
    int middle; while (low <= high)
    {
    middle = (low + high) / 2; if (value == array[middle]){return middle;}
    if (array[middle] > value){high = middle - 1;}
    if (array[middle] < value){low = middle + 1;} }
    return -1;
    }
    }
      

  11.   

    package com.nyohh.test1;import java.util.TreeSet;public class TreeSetTest
    {
    public static void main(String[] args)
    {
    TreeSet<Parent> set = new TreeSet<Parent>(); set.add(new Child());
    System.out.println("下面第2次##################################");
    set.add(new Parent(4, "zhangsan"));
    System.out.println("下面第3次##################################");
    set.add(new Child());
    System.out.println("下面第4次##################################");
    set.add(new Parent(4, "lisi"));
    System.out.println("下面第5次##################################");
    set.add(new Parent(4, "zhangsan"));
    System.out.println("下面第6次##################################");
    set.add(new Child());
    System.out.println("下面第7次##################################");
    set.add(new Child());// 这里我发现的个偶发的问题,我自己添加的child时候都是偶数次,按照二分查询偶数次中间2个那个都可以,所以我修改为奇数次添加child
    // set.add(new Parent(4, "lisi"));
    System.out.println("###########添加结束分割线##################"); System.out.println("==============================");
    System.out.println(set.size()); System.out.println("==============================");
    for (Parent object : set)
    {
    System.out.println(object.getName());
    } }
    }class Parent implements Comparable<Object>
    {
    private int age = 0; public String name; public Parent(int age, String name)
    {
    this.age = age;
    this.name = name;
    } public String getName()
    {
    return name;
    } @Override
    public int compareTo(Object o)
    {
    System.out.println("method of parent");
    Parent o1 = (Parent) o;
    int value = age > o1.age ? 1 : age < o1.age ? -1 : 0; if (value == 0)
    {
    System.out.println("===============在Parent的compareTo()输出谁没被添加进去===============");
    System.out.println(this.name + "没有被添加进去,因为set的特性");
    } return value;
    }}class Child extends Parent
    { public Child()
    {
    super(3, "子类借住父类无参构造的填充");
    } @Override
    public int compareTo(Object o)
    { System.out.println("method of child,");
    return 1;
    }
    }给你个修正后更纠结的例子,看注释哪里
    因为一直返回1,所以比中间4大后,比6大,比7大,到结尾了,所以添加到最后。
      

  12.   

    我确定,按照主程序原来那样真的没有method of child的输出。我感觉只要是添加的是Child的对象,那么就会一直被添加到set中,我认为是向父类强制转换造成的问题。
    所以应该和在奇数次和偶数次添加没有多大关系,你发的截图注释部分是不是还有什么信息?你是要强调,排序也要偶数次还是?
      

  13.   

    截图只是告诉你,我的上面运行的结果是有的,就是官方版本+JDK1.6,真心解释不出来了,我知识储备有限能力有限截图只是给你看下我运行结果,第一个添加child有的。二分查找法,我只是看教程里面说:在偶数时候是随意比较中间2个中的一个,所以举偶数次有点不常规,所以改换奇数次添加child