int a =10;
a = 30;
&
String a = "abc";
a = "xyz";
谁能告诉我这里执行了什么样的任务。
我知道问这样一个愚蠢的问题几乎不值得,但我只想找出字符串赋值和其他对象赋值之间的区别。
据我所知,像“abc”这样的每个字符串值本身就是一个字符串对象,那么当它被分配给String Object
. 喜欢a = "xyz"
。
int a =10;
a = 30;
&
String a = "abc";
a = "xyz";
谁能告诉我这里执行了什么样的任务。
我知道问这样一个愚蠢的问题几乎不值得,但我只想找出字符串赋值和其他对象赋值之间的区别。
据我所知,像“abc”这样的每个字符串值本身就是一个字符串对象,那么当它被分配给String Object
. 喜欢a = "xyz"
。
字符串是不可变的,当你写的时候
String a ="abc"
在字符串池中创建一个内容为 abc 的字符串,当您编写
a = "xyz"
另一个字符串时,在内容为 xyz 的字符串池中创建另一个字符串,旧的字符串不会被替换。而在 int 的情况下,值会改变。
Strings
表示immutable
它们无法更改(在内存中)。
所以当我创建一个String
String a = "abc";
然后我分配它
a = "xyz"
发生的事情是a
指向内存"abc"
,但现在是一个全新的字符串并指向"xyz"
int
另一方面,现在他们只是改变了,他们是mutable
。所以当我创建一个int
int a = 10
;
然后分配它
a = 30
;
发生的事情是a
指向 10 的内存,但现在 10 已更改为 30 但 a 仍指向相同的内存。
注意:这就是你可以说的原因if (String1 == String2)
。这将测试它们是否指向相同的内存位置。因此,您必须if (String1.equals(String2))
测试它们是否是相同的单词。
int a = 10;
a = 30;
现在a
有新值,即 30
String a = "abc";
a = "xyz";
引用变量a
现在指向新的字符串对象,即xyz
String 是一个不可变的对象。当您将值重新分配给 String 时,系统会重新创建 String 对象。您的示例实际上是这样工作的:
String a = "abs";
a = new String("xy");
其次,int 不是对象,它是原始变量;它没有任何方法。对于类似的操作,您需要一个 Integer 对象。
整数 a=10
将整数值 10 分配给 int 类型的新引用变量“a”。
a=30
将整数值 30 分配给相同的引用变量“a”。
字符串 a="abc"
创建一个新的字符串对象“abc”并将其分配给字符串类型的新引用变量“a”。
一个=“xyz”
创建一个新的字符串对象“xyz”并使变量“a”指向它。现在堆内存中有两个 String 对象,“abc”和“xyz”。除非您创建另一个变量指向它,否则对字符串“abc”的引用现在将丢失。
A String
is immutable. You cannot change the value of a String
; you instantiate a new String
every time. int
is different; you don't create new instances of primitives, and if it's sufficiently small (i.e. between -1 and 5, inclusive), it will push a constant value onto the stack.
Well, let's take a look at it on a deeper level.
Here's a sample class which illustrates assignment to an int and a String.
public class StackOverflow {
public static void main(String[] args) {
int anInt = 30;
anInt = 5;
String aWord = "This is not a word";
aWord = "And we did it again...!";
}
}
Here's what the bytecode is doing (the man behind the curtain). I'm using the above link as reference into what the bytecode actually means.
// class version 51.0 (51)
// access flags 0x21
public class StackOverflow {
// compiled from: StackOverflow.java
// access flags 0x1
public <init>()V
L0
LINENUMBER 1 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this LStackOverflow; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x9
public static main([Ljava/lang/String;)V
L0
LINENUMBER 3 L0
BIPUSH 30
ISTORE 1
L1
LINENUMBER 4 L1
ICONST_5
ISTORE 1
L2
LINENUMBER 6 L2
LDC "This is not a word"
ASTORE 2
L3
LINENUMBER 7 L3
LDC "And we did it again...!"
ASTORE 2
L4
LINENUMBER 8 L4
RETURN
L5
LOCALVARIABLE args [Ljava/lang/String; L0 L5 0
LOCALVARIABLE anInt I L1 L5 1
LOCALVARIABLE aWord Ljava/lang/String; L3 L5 2
MAXSTACK = 1
MAXLOCALS = 3
}
So, the relevant portions of our little class are:
The big differences is that we're storing references every time we store the String. We're not bothering with that with an int, due to it being a primitive.
And that is your difference.
字符串是不可变的。因此,当您重新分配引用时会创建新对象。因此将在堆中创建新对象 XYZ。
String a = "abc";
a = "xyz";
本地定义的原语将在堆栈上。但是,如果将原语定义为对象实例的一部分,则该原语将位于堆上。
int a =10;
a = 30;
所以在上述情况下, a 将在堆栈上。
int
是原始类型 - 不是对象
在您的字符串示例中,Java 将创建“abc” String
对象,将此对象的引用分配给变量a
,然后创建“xyz”字符串对象并将对该对象的引用分配给变量“a”(覆盖其先前的值)。