当前位置: 首页 > 面试题库 >

Java原语是不变的吗?

唐昊焜
2023-03-14
问题内容

如果方法具有局部变量i

int i = 10;

然后分配一个新值:

i = 11;

这会分配一个新的内存位置吗?还是只替换原始值?

这是否意味着基元是不可变的?


问题答案:

这会分配一个新的内存位置吗?还是只替换原始值?

Java并没有真正保证变量将与内存位置相对应。例如,i如果编译器发现您从未真正使用过它的值,或者如果它可以在代码中进行跟踪,则您的方法可能以存储在寄存器中的方式进行了优化,或者甚至根本不存储。直接使用适当的值。

但是,把它放在一边。。。如果我们在这里将抽象化为局部变量表示调用堆栈上的存储位置,则i = 11只需修改该存储位置上的值即可。它不需要使用新的存储位置,因为变量i是唯一引用旧位置的东西。

这是否意味着基元是不可变的?

是和否:是的,基元是不可变的,但是不,这不是因为上述原因。

当我们说某物是可变的时,我们的意思是它可以被突变:在仍然具有相同标识的情况下进行更改。例如,当您长出头发时,您正在突变自己:您仍然是您,但是您的属性之一是不同的。

就基元而言,它们的所有属性完全由它们的身份决定;无论什么,1总是意味着1,并且1 + 1永远是2。您无法更改。

如果给定int变量具有值1,则可以将其更改为具有值2,但这是标识的全部更改:它不再具有以前的值。这就像改变me指向别人而不是指向我一样:它实际上并没有改变
,只是改变了me

当然,对于对象,您通常可以同时执行以下两项操作:

StringBuilder sb = new StringBuilder("foo");
sb.append("bar"); // mutate the object identified by sb
sb = new StringBuilder(); // change sb to identify a different object
sb = null; // change sb not to identify any object at all

通常来说,这两种方法都将描述为“更改sb”,因为人们会同时使用“ sb”来引用 变量 (包含引用)和引用的 对象 (引用一个 对象
时)。只要您记得区别时,这种松散就可以了。



 类似资料:
  • 问题内容: 我知道“可变”和“不可变”是应该用来描述对象改变诸如Java和Objective C之类的面向对象语言中的值的能力的术语。但是,我想提出它,因为它与我的语言有关有关原始数据的问题。我知道,当我更改持有不可变对象的变量的值时,实际上是在创建一个新对象。但是,我想知道C中的基本数据的行为是否类似于不可变对象。我的意思是,当我更改保存原始数据的变量的值时,将创建新数据并由该变量引用。还是现有

  • 问题内容: C#和Java都定义 易失性读取具有获取语义 易失性写入具有释放语义 我的问题是: 这是定义volatile的唯一正确方法。 如果没有,如果语义相反,情况会完全不同,即 易失性读取具有释放语义 易失性写入具有语义 问题答案: 获取/释放语义的作用并不在于其他线程多久才能看到volatile字段本身的新写入的值,而在于易失性操作在不同线程之间建立事前联系的方式。如果线程A读取了一个vol

  • 问题内容: 这可能是有史以来最愚蠢的问题,但我认为对于Java新手来说,这非常令人困惑。 有人可以澄清什么是不变的吗? 为什么是String一成不变的? 不可变对象的优点/缺点是什么? 为什么诸如StringBuilderString之类的可变对象优先于String,反之亦然? 一个很好的例子(在Java中)将不胜感激。 问题答案: 不可变是指一旦对象的构造函数完成执行,该实例将无法更改。 这很有

  • 我试图了解Java原语和包装器是如何工作的。让我们考虑以下示例。 由于整数是不可变的和非原语,语句将编译为以下内容 这将创建大约10000个整数对象(每次调用新)和将整数拆箱为int的成本。 我说的对吗?

  • 问题内容: 在Objective-C中,您可以区分原子性质和非原子性质: 根据我的理解,您可以安全地从多个线程读取和写入定义为原子的属性,而同时从多个线程中写入和访问非原子属性或ivars可能导致不确定的行为,包括严重的访问错误。 因此,如果您在Swift中有这样的变量: 我可以安全地并行读写该变量吗?(不考虑这样做的实际含义)。 问题答案: 假设尚无底层文档,这还为时尚早,但是您可以从汇编中学习

  • 类经常会有多个构造函数。时间一长,成员变量和构造器很难保持同步。避免这个的最好方式就是在变量声明的时候初始化而不是在构造函数内初始化。你应该使用初始化语法为静态变量和实例变量进行初始化。 在 C# 中,当你声明变量的时候构建变量是很自然的。当你声明变量时直接进行初始化: public class MyClass { // declare the collection, and init