26

I'm reading my Deitel, Java How to Program book and came across the term shadowing. If shadowing is allowed, what situation or what purpose is there for it in a Java class?

Example:

public class Foo {

    int x = 5;

    public void useField() {
        System.out.println(this.x);
    }
    public void useLocal() {
        int x = 10;
        System.out.println(x);
    }
}
Jayson
  • 2,021
  • 3
  • 25
  • 26

5 Answers5

42

The basic purpose of shadowing is to decouple the local code from the surrounding class. If it wasn't available, then consider the following case.

A Class Foo in an API is released. In your code you subclass it, and in your subclass use a variable called bar. Then Foo releases an update and adds a protected variable called Bar to its class.

Now your class won't run because of a conflict you could not anticipate.

However, don't do this on purpose. Only let this happen when you really don't care about what is happening outside the scope.

Yishai
  • 90,445
  • 31
  • 189
  • 263
  • 8
    I like your final point "Only let this happen when you really don't care about what is happening outside the scope." ... you'll know when to begin caring when something weird starts going on with your instance variable value :))) Anyway, It's a good practice to always use the this.variable_name inside your methods that are setting the value of a instance variable... – luigi7up Nov 29 '12 at 23:13
17

It can be useful for setters where you don't want to have to create a separate variable name just for the method parameter eg:

public void setX(int x) {
    this.x = x;
}

Apart from that I'd avoid them.

Tom Jefferys
  • 13,090
  • 2
  • 35
  • 36
  • 1
    That's a terrible reason to shadow variables. Shadowing always opens you up to potential errors, and it's easier to name variables with scope information, as well as to change the name of the parameter, than to include "this." every time. – Rick Mar 18 '14 at 22:44
  • 6
    For a simple setter, as in the example above I think it's fine, renaming the parameter would make things ugly. Anything more complicated than this, I agree, avoid completely. – Tom Jefferys Mar 19 '14 at 10:07
9

One major purpose is to confuse people. It's bad practice and should be avoided.

Robert Munteanu
  • 67,031
  • 36
  • 206
  • 278
5

Shadowing is not really a java only term. In any instance where a variable declared in a scope has the same name as one in a bigger scope, that variable is shadowed.

Some common uses for shadowing is when you have inner and outer classes and want to maintain a variable with the same name.

If you can avoid it though, you should since it may cause confusion.

z -
  • 7,130
  • 3
  • 40
  • 68
3

The two common uses are constructors and set methods:

public Foo(int x) {
    this.x = x;
}

public void setX(int x) {
    this.x = x;
}

Very occassionally it's useful if you want a copy of the variable at a single instant, but the variable may change within the method call.

private void fire() {
    Listener[] listeners = this.listeners;
    int num = listeners.length;
    for (int ct=0; ct<num; ++ct) {
        listeners[ct].stateChanged();
    }
}

(Of course, a contrived example made unnecessary with the posh for loop.)

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • It's not necessary to shadow for either of these cases. – Rick Mar 18 '14 at 22:45
  • 2
    @Rick Nobody was talking about it being necessary. Shadowing isn't necessary. – Tom Hawtin - tackline Mar 19 '14 at 00:06
  • I'm saying, one should never shadow. Just name the variables differently. – Rick Mar 19 '14 at 07:47
  • 1
    @Rick That's a matter of style. The convention is that you should shadow. – Tom Hawtin - tackline Mar 19 '14 at 10:37
  • Unfortunately, that style makes the use of tools like -Wshadow more difficult to use. Don't choose style over robustness. – Rick Mar 19 '14 at 21:47
  • @Rick `-Wshadow` sounds like a C thing, javac would use an `-Xlint` option for warnings. Googling throws up gcc. OpenJDK doesn't have an equivalent, for the obvious reason that it's conventional for Java. I strongly disagree that it is detrimental to robustness. In my experience using Hungarian-like conventions for different scopes causes vastly more errors than getting the wrong scope when shadowing. – Tom Hawtin - tackline Mar 20 '14 at 01:38
  • I'm really not seeing the issue with "this.x=x". It's explicit and clear. – RichieHH Jan 16 '15 at 18:46
  • Noob question... in the contrived example... the field could end up pointing to a different array due to calling `stateChanged()` within the loop. Would encapsulating the field, via an accessor providing a clone of the array, be a better design for a user unfamiliar with the implementation details of `stateChanged()`? – John Apr 12 '18 at 08:43