【问题标题】:Why can I change class member but not the class variable or even a primitive value [duplicate]为什么我可以更改类成员但不能更改类变量甚至原始值[重复]
【发布时间】:2019-01-27 19:02:42
【问题描述】:

如果我有这样一个简单的类:

public class Example{
    int y = 2;
    String z = "textExample";
}

为什么在 Listener 中我可以更改该类的变量的成员,但现在是变量本身?或者就此而言,甚至是诸如int 之类的原语。

在另一个类中想象这个函数:

public class newClass {

protected void doActivate() {
    ItemCreation model = new Itemcreation(); //A class with visible moving parts
    Example ex = new Example();
    int i = 2;

    model.getSourceProperty().addListener((o, oldVal, newVal) -> {
           //do stuff
           ex.z = "sss"; //THIS I CAN DO and Works


           Example exTmp = new Example();
           ex = exTmp; //This complains with message: Local variable ex defined in an enclosing scope must be final or effectively final

          i= 4;//This also complains with message: Local variable i defined in an enclosing scope must be final or effectively final

    });
}

我在网上看了很多,但没有找到任何答案。我所发现的只是“Java 语言有一个特性,即从(匿名)内部类中访问的局部变量必须是(有效地)最终的”。但如果是这样,我为什么要更改Example 类的成员,这不是最终的?

【问题讨论】:

  • 因为对类实例的引用是最终的(或实际上是最终的)不会影响您更改其成员的能力。不能重新分配最终变量。这并不意味着它所引用的对象不能在其内部进行任何更改。
  • final 变量不一定是不可变的。在上下文中,它只是意味着在引用之前需要为引用分配一个值,并且不能重新分配一个不同的值。
  • 因为一个是字段,一个是本地参数。 local 参数不允许更改(因为它们会被复制),但字段可以更改。
  • 关键字是本地。当它说“局部变量”时,它对你意味着什么?
  • 对不起,伙计们,但“局部变量范围的问题。如何解决?”这个问题并没有完全解决我的问题。它从来没有说明什么为我回答了这个问题,这就是@khelwood 所说的Because a reference to a class instance being final (or effectively final) doesn't affect you're ability to change its members. 我认为反对票是不公平的。

标签: java


【解决方案1】:

为此,您需要一个最终标记的对象包装器。

查看提供您需要的功能的 atomic 包: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html

示例:

protected void doActivate() {
    ItemCreation model = new Itemcreation(); //A class with visible moving parts
    final AtomicReference<Example> ex = new AtomicReference<>(new Example());
    final AtomicInteger i = new AtomicInteger(2);

    model.getSourceProperty().addListener((o, oldVal, newVal) -> {
        ex.get().z = "sss";
        Example exTmp = new Example();
        ex.set(exTmp);
        i.set(4);
    });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-13
    • 2011-01-19
    • 2015-09-09
    • 1970-01-01
    • 1970-01-01
    • 2010-10-01
    • 2011-09-02
    相关资源
    最近更新 更多