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