关于Java中的super()方法的一些问题

时间:2017-07-31 11:37:19

标签: java super

在本书#34; Effective Java"中,当我运行以下代码时,我无法理解结果。

public class InstrumentHashSet<E> extends HashSet<E>{

      private int count;
      @Override
      public boolean add(E e) {
          // TODO Auto-generated method stub
          count++;
          return super.add(e);
      }
      @Override
      public boolean addAll(Collection<? extends E> c) {
          // TODO Auto-generated method stub
          int size = c.size();
          count+= size;
          return super.addAll(c);
      }

      public int getCount(){
          return count;
      }
      public static void main(String[] args) {
          InstrumentHashSet<String> s = new InstrumentHashSet<String>();
          s.addAll(Arrays.asList("xinwa1","xinwa2","xinwa3"));
          System.out.println("hashSet count:"+s.getCount());
      }
}

我无法理解为什么结果是六。我知道父类中的addAll()方法调用add()方法。但是没有“计数++”。在父类的add()方法中。我最初瘦的那个子类重写了add()方法,所以super()。addAll()调用子类中的add()方法。但是当运行以下代码时,我很困惑。

class Point {
      public int x;
      public int y;

      public Point(int x,int y) {
           this.x= x;
           this.y= y;
      }

      public void method() {
           System.out.println("this is parent");
      }

}

public class ColorPoint extends Point{

      public ColorPoint(int x, int y) {
           super(x, y);
      }

      @Override
      public void method() {
           System.out.println("this is son");
      }

      public void print() {
           super.method();
      }

      public static void main(String[] args) {
           ColorPoint c = new ColorPoint(1, 2);
           c.print();

      }
}

为什么结果是&#39;这是父母&#39;?根据“有效Java”中的例子,我认为结果应该是“这是儿子”。请告诉我我的错误。

4 个答案:

答案 0 :(得分:0)

下面是addAll()方法的java实现。如此处所示,它在内部调用add()。因此,您应该仅在add()方法中增加计数。

public boolean More ...addAll(Collection<? extends E> c) {
       boolean modified = false;
        Iterator<? extends E> e = c.iterator();
        while (e.hasNext()) {
            if (add(e.next()))
                modified = true;
        }
        return modified;
   }

因此,当您使用3个元素的集合调用addAll()时,count会立即递增到3,然后每次调用add()方法时递增1。

答案 1 :(得分:0)

  

我无法理解为什么结果是六。

当您调用super.addAll(c)时,您将调用超类的addAll()方法。

addAll()中的HashSet使用AbstractCollection中定义的实现,该实现迭代参数中的集合并在每个元素上调用add()

public boolean addAll(Collection<? extends E> c) {
    boolean modified = false;
    for (E e : c)
        if (add(e))
            modified = true;
    return modified;
}

因此,此代码执行两次增量:

@Override
public boolean addAll(Collection<? extends E> c) {
    // TODO Auto-generated method stub
    int size = c.size();
    count+= size; // + 3
    return super.addAll(c); // + 3
}

这里:

 count+= size; // + 3

在这里:

 return super.addAll(c); // + 3

答案 2 :(得分:0)

关键点是多态。通常,有两个版本的方法,具有相同的签名,但是在两个不同的类中,并且两个版本都可以运行的代码访问。 JVM必须决定调用哪一个,它的决定权基于对象的实际 - 而不是引用该对象的变量的类型,而不是它所在的类#& s当前正在运行代码。

换句话说,如果x是引用InstrumentHashSet的变量并且您调用x.add(something),则它是add中的InstrumentHashSet方法被调用的类。

在您的示例中,当您致电super.addAll时,会调用addAll类中的HashSet,而add类会针对每个对象调用InstrumentHashSet一次被添加。但由于您的对象是InstrumentHashSet,因此调用add方法的count += size;版本。

因此,您的代码会运行count(将add设置为3)然后对您的count方法进行三次调用,每次调用都会增加count。最终结果是tiles = [ {text: 'One', cols: 1, rows: 2, color: 'lightblue'} ]; 为6。

答案 3 :(得分:0)

我最初瘦瘦的那个子类重写了add()方法,所以super()。addAll()调用子类中的add()方法。但是当运行以下代码时,我很困惑。

- 你是正确的

在ColorPoint中,在打印中,您明确地调用parent方法,因此它会导致“this is parent”。当你使用super.someMethod()时,你明确告诉你调用parent方法,无论是否是孩子的ovveriden

当它覆盖并打印“这是儿子”时,下面的代码将打印“这是儿子”

class Point {
public int x;
public int y;

public Point(int x,int y) {
    this.x= x;
    this.y= y;
}


public void method() {
    System.out.println("this is parent");
}

}

public void print() {
    method();
}

public class ColorPoint extends Point{

public ColorPoint(int x, int y) {
    super(x, y);
}


@Override
public void method() {
    System.out.println("this is son");
}


public static void main(String[] args) {
    ColorPoint c = new ColorPoint(1, 2);
    c.print();

}
}

以上代码中的变更:

  1. 将打印方法移至父级并从Colorpoint中删除
  2. 内部打印将super.method()更改为方法()
  3. 说明:

    You are using object which is instance of ColorPoint, all methods
    will be called from ColorPoint class implemenation, if any method is
    not present it will call parents method.
    
    When you call print on ColorPoint, it is not present in ColorPoint,
    so call print() in method(but you are still using ColorPoint
    instance).
    
    Now print calls method, it is present in ColorPoint, so call method
    in ColorPoint and not parent.
    
    Whenever you call method like super.method() then it will always try
    to call method from super