为什么它说“不能引用在不同方法中定义的内部类中的非最终变量 i”?

发布于 2024-12-11 04:28:38 字数 351 浏览 0 评论 0原文

我有按钮单击侦听器,在 onCreate() 方法中我有一个局部变量,例如

 onCreate() {

 super.onCreate();

 int i = 10;

 Button button = (Button)findViewById(R.id.button);

 button.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            i++;
        }   
    });

为什么 java 要求使我成为最终的?

I have button click listener and in onCreate() method I have a local variable like

 onCreate() {

 super.onCreate();

 int i = 10;

 Button button = (Button)findViewById(R.id.button);

 button.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            i++;
        }   
    });

Why java asks for to make me final ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

去了角落 2024-12-18 04:28:38

当 onCreate() 方法返回时,局部变量将从堆栈中清除,因此它们将不再存在。但匿名类对象 new View.OnClickListener() 引用了这些变量。因为这是错误的行为,所以 java 不允许你这样做。

最终确定后,它就成为常量。因此它存储在堆中并且可以在匿名类中安全地使用。

When the onCreate() method returns, your local variable will be cleaned up from the stack, so they won't exist anymore. But the anonymous class object new View.OnClickListener() references these variables. Of cause it's wrong behavior so java don't allow you to do this.

After it is final it becomes a constant. So it is storing in the heap and can be safely used in anonymous classes.

错々过的事 2024-12-18 04:28:38

您的匿名内部类通过获取局部变量的副本来引用其封闭范围 - 如果您想更改匿名内部类中 int 的值,您需要做一些黑客操作:

final int[] arr = new int[1];
arr[0] = 10;
Button button = (Button)findViewById(R.id.button);

button.setOnClickListener(new View.OnClickListener() {
  arr[0]++;
}

Your anonymous inner class refers to its enclosing scope by taking copies of the local variables - if you want to change the value of an int in an anonymous inner class, you need to do some hackery:

final int[] arr = new int[1];
arr[0] = 10;
Button button = (Button)findViewById(R.id.button);

button.setOnClickListener(new View.OnClickListener() {
  arr[0]++;
}
烟花肆意 2024-12-18 04:28:38

因为您是在匿名内部类中访问它。你不能那样做。您可以将其设为最终的,然后从匿名内部类读取它,但随后您无法递增它。

选项:

  • 使其成为外部类的实例变量 使其
  • 成为匿名内部类的实例变量
  • 使用包装器 - 例如单元素数组、AtomicInteger 或类似的东西

我可能会这样做赞成第二个选项,除非我需要从其他地方获取 i 。老实说,我认为第三种选择有点令人讨厌。

Because you're accessing it within an anonymous inner class. You can't do that. You can make it final and then read it from the anonymous inner class, but you then can't increment it.

Options:

  • Make it an instance variable of the outer class instead
  • Make it an instance variable of the anonymous inner class instead
  • Use a wrapper - e.g. a single-element array, an AtomicInteger or something like that

I would probably favour the second option unless I needed to get at i from anywhere else. I regard the third option as a bit of a nasty hack, to be honest.

寒尘 2024-12-18 04:28:38

使变量 final 是必要的,因为在幕后,像这样的匿名内部类只是 编译为包含方法范围之外的嵌套类的语法糖

这意味着内部类无法访问该方法内部声明的任何变量,因此编译器会使用另一个技巧 - 并复制类的隐藏构造函数中的值。为了避免程序员因该副本未更新以匹配方法中变量的更改而感到困惑,它必须是最终的以确保不存在此类更改。

由于您的目标是拥有一个递增的整数,并且只有引用必须是最终的(对象本身不必是不可变的),因此您可以声明一个 final AtomicInteger i ,然后根据需要从打回来。

Making the variable final is necessary because under the hood, anonymous inner classes like that are simply syntactic sugar that compile to a nested class outside the scope of the containing method.

This means that none of the variables declared inside of the method are accessible to the inner class, so the compiler pulls another trick - and copies the value in a hidden constructor for your class. To avoid programmer confusion where this copy is not updated to match changes to the variable in the method, it must be final to make sure there are no such changes.

Since your goal here is to have an incrementing integer, and only the reference must be final (the object itself need not be immutable) you could declare a final AtomicInteger i and then increment it as you wish from the callback.

乖不如嘢 2024-12-18 04:28:38

由于您需要增加 i 变量,因此您无法将其确定为最终值。您可以将其设为班级成员。

Since you need to increment the i variable you can't make it final. You could make it a class member instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文