简体   繁体   中英

Difference between super and this in the commands below?

What is the difference between these commands when I have a class A and a Class B where B extends A , and they have a common instance variable size and the commands below are called from a method printSize1 inside B?

class A {
    protected int size;
}

class B extends A {
    protected int size=7; 

    public void printSize1() {
        System.out.println(((A)this).size)
        System.out.println(super.size);
    }
}

Also I have the same question with these two. I have a class A and a class B where B extends A, and they both have a method with the same name printSize and an instance variable size and the below commands are called from a method printSize2 inside class B.

class A {
    protected int size;

    public void printSize() {
        System.out.println("Size=" + size);
    }
}

class B extends A {
    protected int size=7;

    public void printSize2 {
        ((A) this).printSize();
        super.printSize();
    }

    public void printSize() {
       System.out.println ("MSize="+size);
    }
}

i have a class A and a Class B where B extends A which they have a common instance variable size

No, they don't. They have separate instance variables called size . One is in the part of the object associated with A, and the other is in the part of the object associated with B. Let's call them A$size and B$size . For them to have a common instance variable, you'd remove the declaration of size from B so they're both using A$size .

Redeclaring an ancestor's non- private instance variable (field) is always a bad idea, because it leads to this sort of confusion.

Both of the below output 0 for your example code, because they're both accessing A$size , which you never assign a value to, so it has the default value 0 :

System.out.println(((A)this).size);  // 0
System.out.println(super.size);      // 0

So the question is: Why are they both using A$size and not B$size ? Because of the type of the reference we're using to look up size . In both cases, the type of the reference is A , because the type of (A)this is A (via cast) and the type of super in a method in B is also A . Since the type of the reference is A , it's A 's size that gets used.

In this particular case there isn't much of a difference between the two, but there would be if you added another layer to the hierarchy:

class A {
    protected int size = 1;
}
class B extends A {
    protected int size = 2;
}
class C extends B {
    protected int size = 3;

    void printSize() {
        System.out.println(((A)this).size);  // 1
        System.out.println(super.size);      // 2
        System.out.println(this.size);       // 3
    }
}

Moral of the story: Don't redeclare instance variables declared by an ancestor (unless the ancestor's version is private ).

Note that this is different for variables than it is for methods. Instance methods are polymorphic. Instance variables are not. With methods, you get the method associated with the final type of the object (unless you use super or a qualified super , because those are special and bypass polymorphism).

This is what's coming into play in your second example in printSize2 . Because methods are polymorphic, it doesn't matter that you've cast this to be type A in ((A)this).printSize() , you still get B 's printSize . But super.printSize() is special because super is special and bypasses polymorphism, giving B access to A 's printSize .

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