在Java中,我们使用final
关键字和变量来指定其值不可更改。但我看到您可以更改类的构造函数/方法中的值。同样,如果变量是statice
,那么这是一个编译错误。
代码如下:
import java.util.ArrayList;
import java.util.List;
class Test {
private final List foo;
public Test()
{
foo = new ArrayList();
foo.add("foo"); // Modification-1
}
public static void main(String[] args)
{
Test t = new Test();
t.foo.add("bar"); // Modification-2
System.out.println("print - " + t.foo);
}
}
上面的代码工作良好,没有错误。
现在将变量更改为static
:
private static final List foo;
现在是编译错误。这个final
是如何工作的?
Final关键字有多种使用方法:
其他用法:
一个静态类变量将从JVM的一开始就存在,并且应该在类中初始化。如果执行此操作,将不会出现错误消息。
这是一个很受欢迎的面试问题。通过这些问题,面试官试图了解您对对象在构造函数、方法、类变量(静态变量)和实例变量方面的行为理解程度。
import java.util.ArrayList;
import java.util.List;
class Test {
private final List foo;
public Test() {
foo = new ArrayList();
foo.add("foo"); // Modification-1
}
public void setFoo(List foo) {
//this.foo = foo; Results in compile time error.
}
}
在上面的例子中,我们已经为'test'定义了一个构造函数,并给它一个'set foo'方法。
关于构造函数:每次创建对象只能使用new
关键字调用构造函数一次。您不能多次调用构造函数,因为构造函数不是为这样做而设计的。
关于方法:一个方法可以被调用任意多次(甚至从来没有),编译器知道这一点。
方案1
private final List foo; // 1
foo
是一个实例变量。当我们创建test
类对象时,实例变量foo
将被复制到test
类的对象中。如果我们在构造函数内部分配foo
,那么编译器知道构造函数只会被调用一次,所以在构造函数内部分配它没有问题。如果我们在方法内部赋值foo
,编译器知道一个方法可以被多次调用,这意味着该值必须被多次更改,这对于final
变量是不允许的。所以编译器决定构造函数是一个好的选择!只能为最终变量赋值一次。
情景2
private static final List foo = new ArrayList();
foo
现在是一个静态变量。当我们创建test
类的实例时,foo
不会复制到对象,因为foo
是静态的。现在foo
不是每个对象的独立属性。这是test
类的属性。但是foo
可以被多个对象看到,并且如果使用new
关键字创建的每个对象最终将调用test
构造函数,该构造函数在创建多个对象时更改值(请记住,static foo
不是在每个对象中复制的,而是在多个对象之间共享的。)
场景3
t.foo.add("bar"); // Modification-2
上面的修改-2
来自您的问题。在上面的情况下,您不是在更改第一个引用的对象,而是在foo
中添加允许的内容。如果您试图将new ArrayList()
分配给foo
引用变量,编译器会抱怨。
规则如果您初始化了final
变量,则不能将其更改为引用其他对象。(本例中为arraylist
)
final类不能被子类化
不能重写final方法。(此方法在超类中)
最终方法可以重写。(用语法的方式读这个。这个方法在一个子类中)
始终允许初始化final
变量。编译器确保您只能执行一次。
请注意,对final
变量中存储的对象调用方法与final
的语义无关。换句话说:final
只是关于引用本身,而不是关于被引用对象的内容。
Java没有对象不变的概念;这是通过仔细地设计对象来实现的,是一个远非微不足道的努力。
问题内容: 在Java中,我们使用带有变量的关键字来指定其值不被更改。但是我看到你可以在类的构造函数/方法中更改值。同样,如果变量是,则为编译错误。 这是代码: 上面的代码工作正常,没有错误。 现在将变量更改为: 现在是编译错误。这真的如何运作? 问题答案: 你总是允许初始化一个变量。编译器确保你只能执行一次。 请注意,对存储在final变量中的对象的调用方法与的语义无关。换句话说:仅与引用本身有
我试图理解关键字的用途,显然它允许我们对泛型进行反思。 然而,当我把它排除在外时,它的工作也一样好。有人想解释一下这什么时候会有实际的不同吗?
问题内容: 让我们从一个简单的测试用例开始: 任何人都在乎猜测什么将作为输出打印(在底部显示,以免立即破坏惊喜)。 问题是: 为什么原始和包装的整数表现不同? 为什么反射访问与直接访问返回不同的结果? 最困扰我的人-为什么String表现得像原始的而不是像? 结果(java 1.5): 问题答案: 内联编译时常量(在javac编译时)。参见JLS,尤其是15.28定义了常量表达式,而13.4.9讨
从https://projects.spring.io/spring-framework/,我有一个spring framework hellpworld程序。我删除了注释。然而,程序仍然可以像以前一样运行。为什么?这里的角色是什么?
问题内容: 关键字如何使变量不可变?维基百科说没有。 问题答案: 在Java中,术语 final 是指引用,而不 可变 是指对象。将修饰符分配给引用意味着它不能更改为指向另一个对象,但是如果对象是可变的,则可以对其进行修改。 例如: 就像Wikipedia文章中提到的那样,如果您来自C ++,则必须分离出into 和不可变的概念。
我正试图将eclipse中的java项目导出为可运行的jar,但由于某种原因,可运行的jar无法工作。如果双击可执行jar,它什么也不做。我尝试将所需库提取并打包到生成的JAR中。 所以我也尝试导出一些更简单的项目,那些工作很好。最大的区别是我的真实项目有文件:图像和xml文件。 在代码中引用它们,如下所示: