Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Anonymous inner class using a local variable

How can I get the value of userId passed to this method in my anonymous inner subclass here?

public void doStuff(String userID) {
    doOtherStuff(userID, new SuccessDelegate() {
        @Override
        public void onSuccess() {
            Log.e(TAG, "Called delegate!!!! "+ userID);
        }
    });
}

I get this error:

Cannot refer to a non-final variable userID inside an inner class defined in a different method

I'm pretty sure I can't assign it as final since it's a variable with an unknown value. I had heard that this syntax does preserve scope in some way, so I think there must be a syntax trick I don't quite know yet.

like image 651
Alex Wayne Avatar asked Jul 14 '10 22:07

Alex Wayne


People also ask

Can anonymous class access local variable?

An anonymous class cannot access local variables in its enclosing scope that are not declared as final or effectively final. Like a nested class, a declaration of a type (such as a variable) in an anonymous class shadows any other declarations in the enclosing scope that have the same name.

How do you declare an inner class anonymously in Java?

It is an inner class without a name and for which only a single object is created. An anonymous inner class can be useful when making an instance of an object with certain “extras” such as overriding methods of a class or interface, without having to actually subclass a class.

Can an anonymous inner class be declared private?

Restriction on Anonymous Inner classAnonymous inner class cannot be declared as public, private, protected, or static. It cannot access local variables of its enclosing scope that are not declared as final or effectively final.


1 Answers

In Java 8, this has changed a little bit. You can now access variables that are effectively final. Relevant snippet and example from the Oracle documentation (emphasis mine):

However, starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final.

Effectively final: A non-final variable or parameter whose value is never changed after it is initialized is effectively final.

For example, suppose that the variable numberLength is not declared final, and you add the highlighted assignment statement in the PhoneNumber constructor:

PhoneNumber(String phoneNumber) {
    numberLength = 7; // From Kobit: this would be the highlighted line
    String currentNumber = phoneNumber.replaceAll(
        regularExpression, "");
    if (currentNumber.length() == numberLength)
        formattedPhoneNumber = currentNumber;
    else
        formattedPhoneNumber = null;
}

Because of this assignment statement, the variable numberLength is not effectively final anymore. As a result, the Java compiler generates an error message similar to "local variables referenced from an inner class must be final or effectively final" where the inner class PhoneNumber tries to access the numberLength variable:

if (currentNumber.length() == numberLength)

Starting in Java SE 8, if you declare the local class in a method, it can access the method's parameters. For example, you can define the following method in the PhoneNumber local class:

public void printOriginalNumbers() {
    System.out.println("Original numbers are " + phoneNumber1 +
        " and " + phoneNumber2);
}

The method printOriginalNumbers accesses the parameters phoneNumber1 and phoneNumber2 of the method validatePhoneNumber

like image 74
mkobit Avatar answered Sep 27 '22 22:09

mkobit