Java – why does shadow affect ‘final’ behavior?

Here are three sscces. I think they should be compiled and behave the same The only thing I want to change is the first line "run"

Chart 1

public class FinalExperiment {
    private TinyThing thing;

    public static void main(String[] args) {
        FinalExperiment instance = new FinalExperiment();
        instance.run();
    }

    public void run() {
        final TinyThing thing = new TinyThing();
        System.out.println("Got a thing here: " + thing);
    }

    private static class TinyThing {
        public TinyThing() {}
        public String toString() { return "Hello!"; }
    }
}

This is valid; It compiles successfully and prints: "one thing: Hello!"

Chart 2

public class FinalExperiment {
    private TinyThing thing;

    public static void main(String[] args) {
        FinalExperiment instance = new FinalExperiment();
        instance.run();
    }

    public void run() {
        final TinyThing otherThing = thing;
        System.out.println("Got a thing here: " + otherThing);
    }

    private static class TinyThing {
        public TinyThing() {}
        public String toString() { return "Hello!"; }
    }
}

This is valid; It compiles successfully and prints: "there's something here: null"

Chart 3

public class FinalExperiment {
    private TinyThing thing;

    public static void main(String[] args) {
        FinalExperiment instance = new FinalExperiment();
        instance.run();
    }

    public void run() {
        final TinyThing thing = thing;
        System.out.println("Got a thing here: " + thing);
    }

    private static class TinyThing {
        public TinyThing() {}
        public String toString() { return "Hello!"; }
    }
}

Unable to compile with this message:

FinalExperiment.java:10: error: variable thing might not have been initialized
            final TinyThing thing = thing;
                                    ^
1 error

Why? The only difference between figure 2 and figure 3 is that I hide something in the running method It seems that the compiler should not pay more attention simply because shadows are happening

Solution

Yes, a shadow occurs in Figure 3, but you are actually trying to declare a final variable and assign it to yourself

final TinyThing thing = thing;  // Assign to self!

It has not been assigned a value, so you will receive an uninitialized compiler error This happens whether the local variable is final or not

To reference instance variables, use this qualification

final TinyThing thing = this.thing;  // Bypass shadowing.

This will compile and result in the same output as Figure 2:

Got a thing here: null

This sample cannot be compiled in the same way, for example:

public class SelfDefineExample {
    public static void main(String[] args) {
        int i = i;
    }
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>