简体   繁体   中英

some questions about super() method in Java

In the book "Effective Java",I can't understand the result when I run the following code.

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. But there is no 'count++' in add() method in parent class. I initially thinK that subclass overrides the add() method,so the super().addAll() calls the add() method in subclass. 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'. Please tell me what's wrong with me.

Below is java implementation of addAll() method. As seen here, it calls add() internally. So, you should increment your count in add() method alone.

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.

I can't understand why the result is six.

When you invoke super.addAll(c) , you invoke the addAll() method of the super class.

And addAll() in HashSet uses the implementation defined in AbstractCollection that iterates on the collection in parameter and invokes add() on each element :

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.

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.

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. But because your object is an InstrumentHashSet , it's the InstrumentHashSet version of the add method that gets called.

So your code runs count += size; (which sets count to 3) then makes three calls to your add method, each of which increments count . The end result is that count is 6.

I initially thinK that subclass overrides the add() method,so the super().addAll() calls the add() method in subclass. 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". When you use super.someMethod() you explicitly telling to call parents method irrespective whether it is ovveriden by child or not

When it will override and print "this is son", below code will print "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
  2. inside print change super.method() to 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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