![](/img/trans.png)
[英]Instantiate Java anonymous inner class with generic using Class in variable
[英]Java: Anonymous inner class using a local variable
如何在此处的匿名内部子类中获取传递给此方法的userId
值?
public void doStuff(String userID) {
doOtherStuff(userID, new SuccessDelegate() {
@Override
public void onSuccess() {
Log.e(TAG, "Called delegate!!!! "+ userID);
}
});
}
我收到此错误:
不能在不同方法中定义的内部类中引用非最终变量 userID
我很确定我不能将它分配为 final,因为它是一个具有未知值的变量。 我听说这种语法确实以某种方式保留了作用域,所以我认为一定有一个我还不太了解的语法技巧。
正如这里的其他人所说,局部变量必须是 final 才能被内部类访问。
这就是(基本上)为什么会这样......如果你编写以下代码(长答案,但是,在底部,你可以获得简短版本:-):
class Main
{
private static interface Foo
{
void bar();
}
public static void main(String[] args)
{
final int x;
Foo foo;
x = 42;
foo = new Foo()
{
public void bar()
{
System.out.println(x);
}
};
foo.bar();
}
}
编译器大致这样翻译:
class Main
{
private static interface Foo
{
void bar();
}
public static void main(String[] args)
{
final int x;
Foo foo;
x = 42;
class $1
implements Foo
{
public void bar()
{
System.out.println(x);
}
}
foo = new $1();
foo.bar();
}
}
然后这个:
class Main
{
private static interface Foo
{
void bar();
}
public static void main(String[] args)
{
final int x;
Foo foo;
x = 42;
foo = new $1(x);
foo.bar();
}
private static class $1
implements Foo
{
private final int x;
$1(int val)
{
x = val;
}
public void bar()
{
System.out.println(x);
}
}
}
最后到这个:
class Main
{
public static void main(String[] args)
{
final int x;
Main$Foo foo;
x = 42;
foo = new Main$1(x);
foo.bar();
}
}
interface Main$Foo
{
void bar();
}
class Main$1
implements Main$Foo
{
private final int x;
Main$1(int val)
{
x = val;
}
public void bar()
{
System.out.println(x);
}
}
重要的是它将构造函数添加到 $1。 想象一下,如果你可以这样做:
class Main
{
private static interface Foo
{
void bar();
}
public static void main(String[] args)
{
int x;
Foo foo;
x = 42;
foo = new Foo()
{
public void bar()
{
System.out.println(x);
}
};
x = 1;
foo.bar();
}
}
您会期望 foo.bar() 会打印出 1 但它实际上会打印出 42。通过要求局部变量是 final 不会出现这种令人困惑的情况。
当然你可以将它指定为 final - 只需将该关键字放在参数的声明中:
public void doStuff(final String userID) {
...
我不确定你说它是一个未知值的变量是什么意思; 最后的意思是,一旦将值分配给变量,就不能重新分配。 由于您没有在方法中更改 userID 的值,因此在这种情况下将其设为 final 没有问题。
在 Java 8 中,这已经发生了一些变化。 您现在可以访问实际上是final 的变量。 Oracle 文档中的相关片段和示例(重点是我的):
但是,从 Java SE 8 开始,本地类可以访问封闭块的 final 或有效 final 的局部变量和参数。
有效最终:非最终变量或参数在初始化后其值永远不会改变,实际上是最终的。
例如,假设变量
numberLength
未声明为 final,并且您在PhoneNumber
构造函数中添加突出显示的赋值语句: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; }
由于这个赋值语句,变量
numberLength
不再有效。 因此,Java 编译器会生成类似于“从内部类引用的局部变量必须是最终的或有效的最终”的错误消息,其中内部类PhoneNumber
尝试访问numberLength
变量:if (currentNumber.length() == numberLength)
从 Java SE 8 开始,如果您在方法中声明本地类,则它可以访问该方法的参数。 例如,您可以在 PhoneNumber 本地类中定义以下方法:
public void printOriginalNumbers() { System.out.println("Original numbers are " + phoneNumber1 + " and " + phoneNumber2); }
该方法
printOriginalNumbers
访问参数phoneNumber1
和phoneNumber2
方法的validatePhoneNumber
使它成为final
有什么问题
public void doStuff (final String userID)
声明方法
public void doStuff(final String userID)
该值需要是最终的,以便编译器可以确保它不会改变。 这意味着编译器可以随时将值绑定到内部类,而无需担心更新。
该值不会在您的代码中更改,因此这是一个安全的更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.