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

some questions about super() method in Java

书中"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());
      }
}

我不明白为什么结果是六。我知道 parent class 中的 addAll() 方法调用了 add() 方法。但是parentclass的add()方法中没有'count++'。我最初认为subclass覆盖了add()方法,所以super().addAll()调用了subclass中的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();

      }
}

为什么结果是'this is parent'?根据'Effective Java'中的例子,我认为结果应该是'this is son'。请告诉我我怎么了。

下面是 java addAll() 方法的实现。如此处所示,它在内部调用 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() 时,计数会立即增加到 3,然后每次调用 add() 方法时它都会增加 1。

I can't understand why the result is six.

当您调用 super.addAll(c) 时,您会调用超级 class 的 addAll() 方法。

并且 HashSet 中的 addAll() 使用 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

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

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

在您的示例中,当您调用 super.addAll 时,这会在 HashSet class 中调用 addAll,后者又会为每个调用一次 add正在添加的对象。但是因为你的对象是一个 InstrumentHashSet,它是被调用的 add 方法的 InstrumentHashSet 版本。

因此您的代码运行 count += size;(将 count 设置为 3),然后对您的 add 方法进行三次调用,每次调用递增 count。最终结果是count是6.

我最初认为是子类重写了add()方法,所以super().addAll()调用了子类中的add()方法。但是当运行下面的代码时,我就糊涂了。

-- 你是对的

在 ColorPoint 中,在打印中,您明确地调用了 parents 方法,因此它导致了 "this is parent"。当您使用 super.someMethod() 时,您明确告诉您调用 parents 方法,而不管它是否被 child 或

验证

当它覆盖并打印 "this is son" 时,下面的代码将打印 "this is son"

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. 将打印方法移至 parent 并从 Colorpoint 中删除
  2. inside print 将 super.method() 更改为 method()

解释:

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