Java中的“ final”关键字如何工作?(我仍然可以修改对象)

简介: Java中的“ final”关键字如何工作?(我仍然可以修改对象)

如何解决Java中的“ final”关键字如何工作?(我仍然可以修改对象)?
你总是允许初始化一个final变量。编译器确保你只能执行一次。

请注意,对存储在final变量中的对象的调用方法与的语义无关final。换句话说:final仅与引用本身有关,而与引用对象的内容无关。

Java没有对象不变性的概念。这是通过精心设计对象来实现的,这是一项艰巨的工作。

这是一个最喜欢的面试问题。带着这些问题,访问者试图找出你对对象的构造,方法,类变量(静态变量)和实例变量的理解程度。

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”定义了一个构造函数,并为其指定了“ setFoo”方法。

关于构造器: 构造函数可以调用只有一个使用每个对象的创建时间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
以上Modification-2是你的问题。在上述情况下,你没有更改第一个引用的对象,而是在foo其中添加了允许的内容。如果你尝试将a分配new ArrayList()给foo引用变量,则编译器会抱怨。 规则如果已初始化final变量,则无法将其更改为引用其他对象。(在这种情况下ArrayList)

final类不能被子类化final方法不能被覆盖。(此方法在超类中) 最终方法可以重写。(以语法方式阅读。此方法在子类中)

解决方法
在Java中,我们使用final带有变量的关键字来指定其值不被更改。但是我看到你可以在类的构造函数/方法中更改值。同样,如果变量是static,则为编译错误。

这是代码:

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真的如何运作?
声明:地推任务网所有作品(图片、文字)均由用户自行上传分享,仅供网友学习交流。

相关文章
|
26天前
|
Java
java8中List对象转另一个List对象
java8中List对象转另一个List对象
37 0
|
18天前
|
设计模式 安全 Java
Java并发编程实战:使用synchronized关键字实现线程安全
【4月更文挑战第6天】Java中的`synchronized`关键字用于处理多线程并发,确保共享资源的线程安全。它可以修饰方法或代码块,实现互斥访问。当用于方法时,锁定对象实例或类对象;用于代码块时,锁定指定对象。过度使用可能导致性能问题,应注意避免锁持有时间过长、死锁,并考虑使用`java.util.concurrent`包中的高级工具。正确理解和使用`synchronized`是编写线程安全程序的关键。
|
1天前
|
Java 开发者
Java基础知识整理,注释、关键字、运算符
在日常的工作中,总会遇到很多大段的代码,逻辑复杂,看得人云山雾绕,这时候若能言简意赅的加上注释,会让阅读者豁然开朗,这就是注释的魅力!
34 11
|
2天前
|
Java
Java基础之对象的引用
Java基础之对象的引用
5 0
|
6天前
|
安全 Java 开发者
Java并发编程:深入理解Synchronized关键字
【4月更文挑战第19天】 在Java多线程编程中,为了确保数据的一致性和线程安全,我们经常需要使用到同步机制。其中,`synchronized`关键字是最为常见的一种方式,它能够保证在同一时刻只有一个线程可以访问某个对象的特定代码段。本文将深入探讨`synchronized`关键字的原理、用法以及性能影响,并通过具体示例来展示如何在Java程序中有效地应用这一技术。
|
6天前
|
Java
Java中如何克隆一个对象?
【4月更文挑战第13天】
15 0
|
7天前
|
Java API 数据库
深入解析:使用JPA进行Java对象关系映射的实践与应用
【4月更文挑战第17天】Java Persistence API (JPA) 是Java EE中的ORM规范,简化数据库操作,让开发者以面向对象方式处理数据,提高效率和代码可读性。它定义了Java对象与数据库表的映射,通过@Entity等注解标记实体类,如User类映射到users表。JPA提供持久化上下文和EntityManager,管理对象生命周期,支持Criteria API和JPQL进行数据库查询。同时,JPA包含事务管理功能,保证数据一致性。使用JPA能降低开发复杂性,但需根据项目需求灵活应用,结合框架如Spring Data JPA,进一步提升开发便捷性。
|
9天前
|
Java
Java关键字(1)
Java关键字(1)
|
12天前
|
存储 Java 编译器
对象的交响曲:深入理解Java面向对象的绝妙之处
对象的交响曲:深入理解Java面向对象的绝妙之处
46 0
对象的交响曲:深入理解Java面向对象的绝妙之处
|
17天前
|
Java
在Java中,多态性允许不同类的对象对同一消息做出响应
【4月更文挑战第7天】在Java中,多态性允许不同类的对象对同一消息做出响应
17 2