从anonymuos内部类访问外部类的最终局部变量

时间:2022-12-18 00:10:49

Java anonymuos inner class allows to seamlessly access variables declared on the outer object's method's stack, as long as they ar declared final.

Java anonymuos内部类允许无缝访问在外部对象的方法堆栈上声明的变量,只要它们声明为final。

But, what if I have a variabe with the same name declared inside the inner class? Is there any way to explicitly refer to the outer variable?

但是,如果我在内部类中声明了具有相同名称的变量,该怎么办?有没有办法明确引用外部变量?

public class Outer {
    public static void main(String[] args) throws Throwable {
        new Outer().call();
    }

    private void call() throws Throwable {
        final String str = "I'm the outer String!";
        SwingUtilities.invokeAndWait(new Runnable() {

            @Override
            public void run() {
                String str = "I'm the inner String!";

                // This prints the inner String
                System.out.print(str);

                // So, can I have explicitly access to the outer String?
            }
        });
    }
}

BTW, this is different then this question, since it regards local stack variables.

顺便说一下,这个问题与此问题不同,因为它涉及本地堆栈变量。

5 个解决方案

#1


You may use the str outer variable inside the run function only up to the point of declaring the new local variable with the same name. At this point your new variable shadows the other one.

您可以在run函数内部使用str外部变量,直到声明具有相同名称的新局部变量为止。此时,您的新变量会影响另一个变量。

If you want to use both past declaring the second str, you will have to store it in some other object.

如果要同时使用两者来声明第二个str,则必须将其存储在其他对象中。

Your run method gets a private stack frame within the current thread stack. New variable simply gets added to that stack. After executing run, the stack frame is removed.

您的run方法在当前线程堆栈中获取私有堆栈帧。新变量只是添加到该堆栈。执行run后,删除堆栈帧。

What you want is to access method parameters outside it's scope (after the new str is added to the stack).

你想要的是访问它的范围之外的方法参数(在新的str添加到堆栈之后)。

However the stack frame for the outer str is only accesible to the java debug architecture. Consider this a security concern.

但是,外部str的堆栈帧只能访问java调试体系结构。考虑这是一个安全问题。

#2


This is interesting. Outer.this.str certainly does not work, since str is a local variable inside a method and not in a class.

这是有趣的。 Outer.this.str肯定不起作用,因为str是方法内部的局部变量而不是类。

In my tests I used the Java 8 lambda notation:

在我的测试中,我使用了Java 8 lambda表示法:

final String str = "I'm the outer String!";
SwingUtilities.invokeAndWait(() -> {
    String str = "I'm the inner String!"; // error: str is already defined in this scope

    // This prints the inner String
    System.out.print(str);

    // So, can I have explicitly access to the outer String?
    }
);

Here the compiler actually outputs an error, saying that the variable str is already defined in this scope. In your example though it does not seem like there's a way to access the outer variable.

这里编译器实际输出一个错误,表示变量str已在此范围内定义。在你的例子中,虽然似乎没有办法访问外部变量。

You just shadowed str with the variable inside the anonymous class (which I didn't think would be possible in Java... But I guess it works as long as it's an actual anonymous class).

你只是用匿名类中的变量来遮蔽str(我认为这在Java中是不可能的......但我猜它只要它是一个真正的匿名类就可以工作)。

#3


If you want to access class variable, then you may call

如果要访问类变量,则可以调用

Outer.this.str

But it is not class variable, it is local variable, declared inside of call method. And declaration of str inside of run method is hiding (shadowing) the outer str variable.

但它不是类变量,它是局部变量,在call方法中声明。并且run方法内部的str声明隐藏(遮蔽)外部str变量。

If you want to avoid hard-to-catch bugs in your code, you should avoid such approach with variables.

如果你想避免代码中难以捕获的bug,你应该避免使用变量这样的方法。

Conclusion: you cannot refer to outer local variable str from your run method, because there is a variable with the same name, declared inside of your run method and it is shadowing outer local str variable.

结论:您不能从run方法引用外部局部变量str,因为在run方法内部声明了一个具有相同名称的变量,并且它正在影响外部本地str变量。

#4


You can refer to the variable in the outer class if hidden by a variable in the inner class by doing this:

如果通过这样做隐藏内部类中的变量,则可以引用外部类中的变量:

System.out.println(Outer.this.str);

Update: I don't think you can refer to the variable in the method once it has been hidden. One of the reason to avoid shadowing variables by duplicating names. Another; it gets confusing.

更新:我不认为一旦隐藏了方法中的变量就可以引用它。通过复制名称来避免影子变量的原因之一。另一个;它变得令人困惑。

#5


It works, if the field you reference from Inner is a field in Outer.class. If it is a localVariable, the localVariable of the inner-Class will be used.

如果您从Inner引用的字段是Outer.class中的字段,则它可以工作。如果它是localVariable,则将使用inner-Class的localVariable。

public class Outer {
    private String shadowed = "Outer";

    public static void main(String[] args) throws Throwable {
        new Outer().call();
    }

    private void call() throws Throwable {
        final String str = "I'm the outer String!";
        shadowed = "OuterString";

        SwingUtilities.invokeAndWait(new Runnable() {
            private String shadowed = "Outer";

            @Override
            public void run() {
                String inner = "I'm the inner String!";
                shadowed = "InnerString";

                // different reference identifier
                System.out.println(inner);
                System.out.println(str);

                // same reference identifier
                System.out.println(shadowed);
                System.out.println(Outer.this.shadowed);
            }
        });
    }
}

#1


You may use the str outer variable inside the run function only up to the point of declaring the new local variable with the same name. At this point your new variable shadows the other one.

您可以在run函数内部使用str外部变量,直到声明具有相同名称的新局部变量为止。此时,您的新变量会影响另一个变量。

If you want to use both past declaring the second str, you will have to store it in some other object.

如果要同时使用两者来声明第二个str,则必须将其存储在其他对象中。

Your run method gets a private stack frame within the current thread stack. New variable simply gets added to that stack. After executing run, the stack frame is removed.

您的run方法在当前线程堆栈中获取私有堆栈帧。新变量只是添加到该堆栈。执行run后,删除堆栈帧。

What you want is to access method parameters outside it's scope (after the new str is added to the stack).

你想要的是访问它的范围之外的方法参数(在新的str添加到堆栈之后)。

However the stack frame for the outer str is only accesible to the java debug architecture. Consider this a security concern.

但是,外部str的堆栈帧只能访问java调试体系结构。考虑这是一个安全问题。

#2


This is interesting. Outer.this.str certainly does not work, since str is a local variable inside a method and not in a class.

这是有趣的。 Outer.this.str肯定不起作用,因为str是方法内部的局部变量而不是类。

In my tests I used the Java 8 lambda notation:

在我的测试中,我使用了Java 8 lambda表示法:

final String str = "I'm the outer String!";
SwingUtilities.invokeAndWait(() -> {
    String str = "I'm the inner String!"; // error: str is already defined in this scope

    // This prints the inner String
    System.out.print(str);

    // So, can I have explicitly access to the outer String?
    }
);

Here the compiler actually outputs an error, saying that the variable str is already defined in this scope. In your example though it does not seem like there's a way to access the outer variable.

这里编译器实际输出一个错误,表示变量str已在此范围内定义。在你的例子中,虽然似乎没有办法访问外部变量。

You just shadowed str with the variable inside the anonymous class (which I didn't think would be possible in Java... But I guess it works as long as it's an actual anonymous class).

你只是用匿名类中的变量来遮蔽str(我认为这在Java中是不可能的......但我猜它只要它是一个真正的匿名类就可以工作)。

#3


If you want to access class variable, then you may call

如果要访问类变量,则可以调用

Outer.this.str

But it is not class variable, it is local variable, declared inside of call method. And declaration of str inside of run method is hiding (shadowing) the outer str variable.

但它不是类变量,它是局部变量,在call方法中声明。并且run方法内部的str声明隐藏(遮蔽)外部str变量。

If you want to avoid hard-to-catch bugs in your code, you should avoid such approach with variables.

如果你想避免代码中难以捕获的bug,你应该避免使用变量这样的方法。

Conclusion: you cannot refer to outer local variable str from your run method, because there is a variable with the same name, declared inside of your run method and it is shadowing outer local str variable.

结论:您不能从run方法引用外部局部变量str,因为在run方法内部声明了一个具有相同名称的变量,并且它正在影响外部本地str变量。

#4


You can refer to the variable in the outer class if hidden by a variable in the inner class by doing this:

如果通过这样做隐藏内部类中的变量,则可以引用外部类中的变量:

System.out.println(Outer.this.str);

Update: I don't think you can refer to the variable in the method once it has been hidden. One of the reason to avoid shadowing variables by duplicating names. Another; it gets confusing.

更新:我不认为一旦隐藏了方法中的变量就可以引用它。通过复制名称来避免影子变量的原因之一。另一个;它变得令人困惑。

#5


It works, if the field you reference from Inner is a field in Outer.class. If it is a localVariable, the localVariable of the inner-Class will be used.

如果您从Inner引用的字段是Outer.class中的字段,则它可以工作。如果它是localVariable,则将使用inner-Class的localVariable。

public class Outer {
    private String shadowed = "Outer";

    public static void main(String[] args) throws Throwable {
        new Outer().call();
    }

    private void call() throws Throwable {
        final String str = "I'm the outer String!";
        shadowed = "OuterString";

        SwingUtilities.invokeAndWait(new Runnable() {
            private String shadowed = "Outer";

            @Override
            public void run() {
                String inner = "I'm the inner String!";
                shadowed = "InnerString";

                // different reference identifier
                System.out.println(inner);
                System.out.println(str);

                // same reference identifier
                System.out.println(shadowed);
                System.out.println(Outer.this.shadowed);
            }
        });
    }
}