有什么不同

时间:2013-04-10 05:18:18

标签: java string memory encapsulation

int a =10;
a = 30;

&安培;

String a = "abc";
a = "xyz";

有人可以告诉我这里执行了什么类型的任务。

我知道提出这样一个愚蠢的问题几乎不值得,但我只想找到String-assignment&其他对象分配。

我知道像“abc”这样的每个String值都是一个String对象本身,然后在分配给String Object时执行了什么样的操作。比如a = "xyz"

9 个答案:

答案 0 :(得分:5)

当你写

时,

String 不可变

String a ="abc" 

在字符串池中创建内容为abc的字符串,并在您编写时创建 a = "xyz" 在字符串池中使用内容xyz创建另一个字符串,不替换旧字符串。而在int的情况下,值会改变。

答案 1 :(得分:3)

Stringsimmutable,意味着无法更改(在内存中)。

所以当我创建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))来测试它们是否相同。

答案 2 :(得分:3)

int a = 10;
a = 30;

现在a新值,即30

String a = "abc";
a = "xyz";

引用变量a现在指向新String对象,即xyz

答案 3 :(得分:1)

String是immutable.Hence当您重新分配reference时会创建新对象。因此,将在堆中创建新对象XYZ。

String a = "abc";
a = "xyz";

本地定义的基元将在堆栈中。但是,如果将基元定义为对象实例的一部分,则该基元将位于堆上。

int a =10;
a = 30;

所以在上面的例子中,a将在堆栈上。

答案 4 :(得分:1)

  1. int是基本类型 - 不是对象

  2. 在您的String示例中,Java将创建“abc” String对象,将此对象的引用分配给变量a,然后创建“ xyz“ String对象并将此对象的引用分配给变量'a'(覆盖其先前的值)。

答案 5 :(得分:1)

String是一个不可变对象。将值重新分配给String时,系统将重新创建String对象。你的例子实际上是这样的:

  String a = "abs";
  a = new String("xy");

第二,int不是一个对象,它是一个原始变量;它没有任何方法。对于类似的操作,您需要一个Integer对象。

答案 6 :(得分:1)

  

int a = 10

将整数值10分配给int。

类型的新引用变量'a'
  

a = 30

将整数值30分配给相同的参考变量'a'。

  

字符串a =“abc”

创建一个新的String对象“abc”并将其分配给String类型的新引用变量“a”。

  

α= “XYZ”

创建一个新的String对象“xyz”并使变量“a”指向它。现在堆内存中有两个String对象,“abc”和“xyz”。字符串“abc”的引用现在已丢失,除非您将另一个变量指向它。

答案 7 :(得分:1)

String是不可变的。您无法更改String的值;每次都实例化一个新的Stringint不同;你不创建新的基元实例,如果它足够小(即介于-1和5之间),it will push a constant value onto the stack

好吧,让我们在更深层次上看一下。

这是一个示例类,用于说明对int和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...!";
    }
}

这是字节码正在做的事情(幕后的人)。我使用上面的链接作为字节码实际含义的参考。

// 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
}

因此,我们小班的相关部分是:

  • 字节 30推入堆栈(它足够小,可被视为一个字节)
  • 将其存储到变量1
  • 将常数5推入堆栈
  • 将其存储到变量1中,覆盖我们的30
  • 从常量池加载第一个字符串“This is not a word”
  • 参考存储到变量2
  • 从常量池加载第二个字符串“我们又做了一次......!”
  • 参考存储到变量2

最大的区别是我们每次存储String时都存储引用。由于它是一个原始的,我们不会因为它而烦恼。

是你的不同之处。

答案 8 :(得分:0)

此操作使用两种不同的JVM指令:

  1. astore保存对象的引用
  2. istore保存int值
  3. 你真的想从中找到什么?