简体   繁体   English

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

[英]some questions about super() method in Java

In the book "Effective Java",I can't understand the result when I run the following code. 在“有效的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());
      }
}

I can't understand why the result is six. 我不明白为什么结果是六。 I know that the addAll() method in parent class calls the add() method. 我知道父类中的addAll()方法调用add()方法。 But there is no 'count++' in add() method in parent class. 但是父类的add()方法中没有“ count ++”。 I initially thinK that subclass overrides the add() method,so the super().addAll() calls the add() method in subclass. 我最初是ThinK,该子类重写了add()方法,所以super()。addAll()调用了子类中的add()方法。 But when run the following code,I'm confused. 但是,当运行以下代码时,我很困惑。

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();

      }
}

Why the result is 'this is parent'? 为什么结果是“这是父母”? According to the example in 'Effective Java', I think the result should be 'this is son'. 根据“有效Java”中的示例,我认为结果应该是“这是儿子”。 Please tell me what's wrong with me. 请告诉我我怎么了。

Below is java implementation of addAll() method. 下面是addAll()方法的Java实现。 As seen here, it calls add() internally. 如此处所示,它在内部调用add()。 So, you should increment your count in add() method alone. 因此,您应该单独在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;
   }

So, when you call addAll() with a collection of 3 elements, count is increment immediately to 3 and then it increments by 1 each time your add() method is called. 因此,当您调用具有3个元素的集合的addAll()时,count会立即增加到3,然后每次调用add()方法时,count就会增加1。

I can't understand why the result is six. 我不明白为什么结果是六。

When you invoke super.addAll(c) , you invoke the addAll() method of the super class. 调用super.addAll(c) ,将调用超类的addAll()方法。

And addAll() in HashSet uses the implementation defined in AbstractCollection that iterates on the collection in parameter and invokes add() on each element : 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;
}

So this code performs twice the incrementation : 因此,这段代码执行了两次递增:

@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
}

Here : 这里 :

 count+= size; // + 3

and here : 和这里 :

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

The key point is polymorphism . 关键是多态性 Often, there are two versions of a method, with the same signature, but in two different classes, and both versions are accessible to code that's running. 通常,方法的两个版本具有相同的签名,但是在两个不同的类中,并且正在运行的代码都可以访问这两个版本。 The JVM has to decide which one to call, it bases its decision on the actual class of the object - not on the type of the variable that references the object, and not on which class it's currently running code from. JVM必须决定要调用哪一个,它的决定是基于对象的实际 -而不是引用对象的变量的类型,而不是当前运行代码的类。

In other words if x is a variable that refers to an InstrumentHashSet and you call x.add(something) , it's the add method in the InstrumentHashSet class that gets called. 换句话说,如果x是引用InstrumentHashSet的变量,并且您调用x.add(something) ,则将调用InstrumentHashSet类中的add方法。

In your example, when you call super.addAll , this calls addAll in the HashSet class, which in turn calls add once for each object that's being added. 在您的示例中,当您调用super.addAll ,这将调用HashSet类中的addAll ,后者依次为要添加的每个对象调用一次add But because your object is an InstrumentHashSet , it's the InstrumentHashSet version of the add method that gets called. 但是因为您的对象是InstrumentHashSet ,所以它是被调用的add方法的InstrumentHashSet版本。

So your code runs count += size; 因此,您的代码运行count += size; (which sets count to 3) then makes three calls to your add method, each of which increments count . (将count设置为3)然后对add方法进行三个调用,每个调用都会递增count The end result is that count is 6. 最终结果是count为6。

I initially thinK that subclass overrides the add() method,so the super().addAll() calls the add() method in subclass. 我最初是ThinK,该子类重写了add()方法,所以super()。addAll()调用了子类中的add()方法。 But when run the following code,I'm confused. 但是,当运行以下代码时,我很困惑。

-- You are Correct - 你是对的

In ColorPoint, In print you are explicitly making a call to parents method and hence it results in "this is parent". 在ColorPoint中,在打印中,您明确地调用了parent方法,因此结果为“ this is parent”。 When you use super.someMethod() you explicitly telling to call parents method irrespective whether it is ovveriden by child or not 当您使用super.someMethod()时,您明确告诉要调用父方法,而不管它是否被子对象ovveriden

When it will override and print "this is son", below code will print "this is son" 当它覆盖并打印“ 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();

}
}

Changes In Above Code: 以上代码中的更改:

  1. Move print method to parent and remove from Colorpoint 将打印方法移至父级并从Colorpoint中删除
  2. inside print change super.method() to method() 内部打印将super.method()更改为method()

Explanation: 说明:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM