简体   繁体   中英

issues with use of this keyword in java

I am new to java and trying to understand the use of this keyword in java.As per documentation if instance and local variables have same name then local variables mask the instance variables.We use this keyword so that instance variable may not be masked by local variable.Below is the program i was writing to understand the use of this key work but even after use of this keyword instance variable is still getting masked.

class Box{
int height=5;
int length=10;
int breadth=15;


int CalcVol(){
int vol = height*breadth*length;
return vol;
}

Box(int height, int length,int breadth){
this.height = height;
length = length;
breadth = breadth;

System.out.println("height  is "  + height);

}

}

class MyBox{

public static void main(String args[]){
Box mybox1 = new Box(10, 20, 30);
int vol=mybox1.CalcVol();
System.out.println("volume is"  + vol);

}
}

What i am thinking is that variable "height" printed in Box constructor should print 5 ie value of instance variable but its printing 10 ie the value passed as parameter.Please help me on this.

You need to add this before every field you want to access :

Box(int height, int length,int breadth){
// ...and move this statement to the beginning, otherwise this.height gets overriden.
System.out.println("height  is "  + this.height);

this.height = height;
this.length = length;
this.breadth = breadth;


}

Otherwise, length = length and breadth = breadth have no effect.

It is a name collision problem.

Within the constructor Box are the parameters height , length , and breadth . Those are also names of three fields within Box .

In Java, one considers member variables and block variables to be "closer" than field variables. As such, if you use the exact same name for both (as you have done), the assignment

 height = height

will assign the parameter height to the exact same value it held (effectively a noop).

To avoid this issue, you will specify which height you are assigning.

 this.height = height;

which is shorthand for "this class's height" or "the field height". When there is no name collision, the compiler will assume you meant the field variable; because there is nothing else with that name in the block.

As an aside, this is a really good reason to learn how to use the final keyword. Final means that the variable can be assigned once, and only once. It prevents it from being reassigned in situations you probably would never want.

For example

public Box(final int height, final int width, final int breadth) {

would then throw a compliation error upon

  height = height;

because you are reassigning the value of height. Such techniques are very valuable when writing code, because they prevent you from writing something you think is a field assignment, when you really wrote a parameter assignment.

You are performing an assignment here, which will make this.height take on the value of the parameter height .

this.height = height;

If you want to print the original value of this.height , put the print above the assignment and print with this.height .

System.out.println("height  was "  + this.height);

More completely, your constructor should look like this. Note that you need to prefix with the this keyword on every access to any instance variable that is shadowed by a local variable.

Box(int height, int length,int breadth){
    System.out.println("height  was "  + this.height);
    this.height = height;
    this.length = length;
    this.breadth = breadth;
}

For your class:

class Box{
    int height=5;
    int length=10;
    int breadth=15;

    Box(int height, int length,int breadth){
        this.height = height;
        length = length;
        breadth = breadth;

        System.out.println("height  is "  + height);

    }

 }

When you construct Box, the following is happening:

  1. Instance variable height is being set to the constructor parameter height
  2. Constructor parameter length is being set to itself (not changing instance variable length )
  3. Constructor parameter breadth is being set to itself (not changing instance variable breadth ).

What you probably want to do in the constructor is set your instance variables with the values passed into the constructor like this:

Box(int height, int length,int breadth){
    this.height = height;
    this.length = length;
    this.breadth = breadth;
}

Rather than not understanding the usage of the this keyboard in Java, I think OP isn't understanding object oriented programming in general, seeing how he's trying to print out "5" when the value has already changed. The this keyword becomes a lot less confusing once you understand that concept.

Suppose you have your class Box, and it only has one value, height:

class Box {
    // This is a instance variable, that is, each new instance of Box 
    // has a different height variable even if they are all equal to 5
    // initially. It's a different variable in memory.
    int height = 5; 

    // Here's our constructor that sets this instance's value of height
    Box(int height){
        this.height = height;
    }

When you make a new Box, you are making a new Box Object - for each object the height will initially start at 5, but you are changing the height of that instance of Box in your constructor.

Box box1 = new Box(10); // Height was originally 5, but changed to 10 in the constructor
Box box2 = new Box(20); // Height was originally 5, but changed to 20 in the constructor
Box box3 = new Box(30); // Height was originally 5, but changed to 30 in the constructor

When you get to the following line of code in your original program:

System.out.println("height  is "  + height);

It doesn't matter if it was this.height or height , it will never return 5. You already changed the value of the instance's height in the constructor .

So then. How do we print out a default height of 5? You can't. Not with the same variable name. You have to define constants in the class (like final int HEIGHT = 5 ) which represent the default values for that class, or use another constructor that doesn't set those values.

class Box{

    int height=5;
    int length=10;
    int breadth=15;

    int CalcVol(){
        int vol = height*breadth*length;
        return vol;
    }

    Box() {
        System.out.println("height  is "  + height);
    }

    Box(int height, int length,int breadth) {
        this.height = height;
        this.length = length;
        this.breadth = breadth;
        System.out.println("height  is "  + height);
    }
}

class MyBox{

    public static void main(String args[]){

        Box mybox1 = new Box(10, 20, 30); // this will never print 5, and always 10
        Box mybox2 = new Box(); // this will always print 5

    }
}

However, if you move the print statement above the assignment and used this.height , like Maxim Bernard did, then it will print out 5, since we didn't change the value yet.

    Box(int height, int length,int breadth) {
        System.out.println("height  is "  + this.height); // this will print out 5
        this.height = height;
        this.length = length;
        this.breadth = breadth;
    }

If this is really confusing, rather than trying to understand Java's this keyword I suggest just reading a few articles on OOP. You'll understand then that this simply means the current instance of a class .

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