当前位置: 首页 > 知识库问答 >
问题:

如何使对象的变量成为最终变量?[副本]

谷梁宏恺
2023-03-14

我有一个关于java中最终变量的问题,我已经编写了一个简短的代码来演示这个问题。java8的语言规范规定:

一旦分配了最终变量,它始终包含相同的值。如果最终变量包含对对象的引用,则对象的状态可能会因对该对象的操作而改变,但该变量始终引用同一对象。语言规范

为了进一步研究,我在一个小示例代码中尝试了三件事。我尝试的第一件事是创建一个Intger类型的对象并为其分配非最终引用。然后我也为它分配了一个最终引用。在第二个实验中,我对原始int做了同样的事情。两个实验都导致相同的结果,即编译器不允许我增加最终引用,但允许增加非最终引用,并且在Output中只有非最终变量增加。

在我的第三个实验中,我使用了List并再次分配了对List的非最终引用和最终引用。在这里,我被允许使用最终引用和非最终引用来调用add(),并且在这两个引用中,大小都被更新了。

我的测试代码:

public void testFunction () {
    Integer nonFinalInteger = 4;
    final Integer finalInteger = nonFinalInteger;

    nonFinalInteger++;
    //Compiler shows error
    //finalInteger++;

    System.out.println("nonFinal Integer: " + nonFinalInteger);
    System.out.println("final Integer: " + finalInteger + "\n");

    int nonFinalInt = 4;
    final int finalInt = nonFinalInt;

    nonFinalInt++;

    //Compiler shows error
    //finalInt++;

    System.out.println("nonFinal primitive int: " + nonFinalInt);
    System.out.println("final primitive int: " + finalInt + "\n");

    List<String> nonFinalVar = new ArrayList<String>();
    final List<String> finalVar = nonFinalVar;

    finalVar.add("Hello");
    //Compiler does not show error
    nonFinalVar.add("World");

    System.out.println("nonFinal List Size: " + nonFinalVar.size());
    System.out.println("final List Size: " + finalVar.size() + "\n");
}

输出:

nonFinal Integer: 5
final Integer: 4

nonFinal primitive int: 5
final primitive int: 4

nonFinal List Size: 2
final List Size: 2

我现在的问题是:有没有一种方法可以保护对象的状态而不必更改其类的代码?假设我们停留在一个列表中,不允许您添加或删除元素。是否可以以某种方式标记列表,以便编译器显示错误(或至少某种警告)?

编辑:

似乎我在示例中使用数组引起了一些混淆。我的问题应该涉及任何类型的对象,因此我没有在问题或标签中输入List。我的意思不是告诉编译器禁止更新引用,我只是想知道是否有一种方法隐式地告诉编译器拒绝调用可能会改变对象状态的函数。

目前,包装类的想法似乎是最吸引人的,尽管它仍然缺少一件事:它不会阻止我或其他人完全更改对象的状态。最终的变量总是有这个“不接触”的特点,我在这里寻找。

共有1个答案

呼延才俊
2023-03-14

这是一个令人困惑的问题。我将尝试解释它:

当您将一个变量声明为final时,其结果是可以以两种不同的形式分配其值:

  • 在定义最终变量的同一行中分配值。
  • 如果最终变量B是类A的属性,那么B的值可以在A类的构造函数中分配。

但重要的是,当我说赋值时,我指的是形式为:final ArrayList的赋值

现在变量myArray总是指向该arraylist,并且不能以相同的形式再次赋值:myArray=new arraylist

简而言之:当你把一个变量C标记为final时,你就是这么做的,即不能将C指定给另一个对象,但目标对象可以随时更改其状态。

 类似资料:
  • 在Java8中,Java设计者提出了一个有效的final变量的概念,即一个如果被“final”追加就不会给编译器带来错误的变量。我的问题是,这个新提出的“有效最终”概念比经典的“最终”提供了什么?作为一名Java开发人员,我实际上得到了什么好处?

  • 问题内容: 我读了这个问题不可变对象,并留下了关于不可变对象,并最终场一个问题: 为什么我们需要不可变类中的实例变量为最终变量? 例如,考虑以下不可变的类: 如果在上面的代码中没有set方法,而实例变量仅在构造函数中设置,为什么要求将实例变量声明为final? 问题答案: 有没有 要求 这样做的变量。但是,当您确实明确打算永远不更改变量时,通常这样做是一种好习惯,因为这不仅可以使变量避免错别字或其

  • 问题内容: 将实例变量作为最终变量有什么意义? 那么将该变量设置为静态最终变量会更好吗? 原因是如果任何对象都不能更改它,那么它与类(静态)变量相同,对吗? 问题答案: 不。 表示该类的所有实例都相同。 表示在初始分配后无法分配。因此,两个实例的非静态最终变量的值可能不同。 您可能有很多原因想使变量为final;最好的方法之一就是清晰度。如果我读了一个方法并且注意到foo是最终的,那么我不必担心它

  • 问题内容: 这个问题已经在这里有了答案 : 为什么在匿名类中只能访问最终变量? (15个答案) 为什么实例变量“忽略Lambda表达式中使用的变量必须是最终变量或实际上是最终变量”警告[重复] (2个答案) Lambdas:局部变量不需要最终变量,实例变量不需要 (10个答案) 2年前关闭。 当我编写此代码时,我收到一个编译时错误,该错误是: “ lambda中的变量必须是final或有效的fin

  • 问题内容: 在SO和google中寻找了这个问题的答案,但找不到任何答案。 我有以下代码: 编译器返回以下内容: 从内部类内部访问局部变量变量;需要宣布为最终 为什么必须最终决定的技术原因是什么? 问题答案: 这是因为您正在使用匿名内部类。发生的是编译器为您创建了类。它将其称为您的外部类,并添加和编号,例如,等等。 该类具有对自动初始化的外部类的引用,因此其实例可以使用外部类的方法和字段。 但是您