String初始化差异

时间:2012-03-04 13:05:33

标签: java memory-management

首先道歉,如果这是一个非常基本的问题,我只是想知道以下字符串定义之间的区别

String x= "hello";
String y = new String("hello");

我知道在java中,String是一个类,它既不是原语也不是包装器(如果这是一种误解,请纠正我)。考虑一个A类,到目前为止我已经看过任何类的以下声明。我认为A c;有效且A a = new A();也有效。我对A a ="xyz";感到困惑,这就是我们在第一种类型的定义中声明一个String的方式。我确信上面两个定义是完全不同的,就像我说x==y它返回false。我知道y是对String对象的引用。什么是x,它是如何存储在内存中的,有趣的是我发现x和y都可以访问String类的所有方法。

那么一个人比另一个人更有优势。我知道每个人的适用性。

6 个答案:

答案 0 :(得分:8)

来自Joshua Bloch的第二版“Effective Java”:

String s = new String("stringette");// DON'T DO THIS!
     

每次执行时,该语句都会创建一个新的String实例,   并且这些对象创作都不是必需的。争论的   字符串构造函数(“stringette”)本身就是一个String实例,   功能上与所创建的所有对象完全相同   构造函数。如果此用法发生在循环中或经常调用   方法,可以不必要地创建数百万个String实例。该   改进版只是以下内容:

String s = "stringette";

答案 1 :(得分:5)

你得到的前几个答案是不正确的。 两个语句之间存在差异。但首先是TL;DR版本:在99.99999%的情况下使用String x = "hello";

完整答案:

这两者之间的主要区别在于,在第一种情况下,字符串是隐含的interned;在第二种情况下,它不是。这是一个非常真实的区别,虽然它只在特定情况下发挥作用。因此,在第一种情况下,如果您有任何其他字符串具有相同系列的字符("hello"),则您的x将引用用于的一个共享对象所有这些地方(这很有用,因为String实例是不可变的)。在第二种情况下,您明确表示您需要(无论出于何种原因)拥有String个实例,该实例的字符序列与其他任何字符分开。这样做的理由非常非常少。

关于x==y,在Java中,您使用equals而不是==来比较字符串的相等性。与对象引用一起使用时,==运算符会比较引用(例如,两个变量都指向同一个对象),而不是对象内容。

所以:除非你有充分的理由做第二次,否则首先要把第一种形式推到第二种形式。

答案 2 :(得分:1)

String a = "hello"; //this kind of declaration always return "singlton" instance.
String b = "hello";
String c = new String("hello"); //This kind of declaration always return a new instance.

SO a ==b;a !=c

答案 3 :(得分:0)

很简单,x的值是一个字符串。正常java.lang.String

你已经习惯了原始类型的文字(例如,73.14159,或true'q'),但它似乎你可能没有意识到的是,某些对象类型也有文字形式。我唯一能想到的是java.lang.String,您可以在其中"hello"java.lang.Class撰写SomeClass.class

答案 4 :(得分:0)

  

我知道y是对String对象的引用。什么是x [...]?

xy都是对String个对象的引用。 x是对intern ed字符串的引用(正如TJ Crowder已经在他的回答中写的那样),y是对具有相同内容的第二个String对象的引用内容。这意味着:

x == y       --> false
x.equals(y)  --> true
y.equals(x)  --> true
  

那么一个人比另一个人更有优势。我知道每个人的适用性。

始终使用第一个直接版本。我遇到并发现有效的唯一有效异常是测试代码,它明确要确保要测试的代码不使用==进行字符串比较,而是使用适当的x.equals(y)方法。

答案 5 :(得分:0)

初始化String的另一种方法是

String str =("abc");

起初看来这会产生错误(因为括号),但事实并非如此。令人惊讶的。