字符串实例化与stringbuffer实例化

时间:2012-08-16 11:29:04

标签: java

如果

,我无法弄明白
String ab = "hello";        //straight initialization

String ab_1 = new String ("hello_1");  //initializing using new

两者都有效,但

StringBuffer bfr = new StringBuffer("hi");   //works only with new

仅在使用new创建时才有效。

为什么String可以直接实例化,但StringBuffer需要new运算符。有人可以解释我的主要原因。

8 个答案:

答案 0 :(得分:6)

所有对象都需要使用new进行实例化。只能从文字(int i = 0;)实例化基元。

唯一的例外是:

  • 字符串,允许特殊的初始化结构:
   String s = "abc"; //can be instantiated from a literal, like primitives
  • null instantiation:Object o = null;

它在Java Language Specification #3.10

中定义
  

文字是基本类型值,String类型或null类型的源代码表示。

注意:数组也有专门的初始化模式,但这不是文字:

   int[][] a = { { 00, 01 }, { 10, 11 } };

答案 1 :(得分:2)

使用String s1 = "hello";String s2 = new String("hello");会产生细微差别。

 public static void main(String[] arg ) {
    String s1 = "Java";
    String s2 = "Java";
    String s3 = new String("Java");
    System.out.println(s1==s2); //true
    System.out.println(s1==s3); //false

    StringBuilder sb = new StringBuilder(25); //initial capacikacity
    sb = new StringBuilder(10);
    sb.append(s1).append(" uses immutable strings.");
    sb.setCharAt(20, 'S');
    System.out.println(sb);
}

在上面的代码中,“Java”被称为String文字。为了节省内存,这两次出现在代码中,它是相同的字符串文字,因此s1和s2实际上是指内存中的同一个对象。虽然s1.equals(s3)为真,但它们不会在内存中引用相同的对象,如上所示。

在实践中,我们总是使用.equals来比较字符串并且它们是不可变的,因此我们无法更改s1引用的数据(至少不容易)。但是如果我们能够改变s1引用的数据,那么s2会随之改变。

StringBuilder允许您修改基础数据:我们经常使用它将一个String附加到另一个String,如上所示。我们很高兴StringBuilder sb2 = "what?"是非法的,因为在StringBuilders的情况下,有两个引用相同的数据(意思是sb1 == sb2)更有可能导致sb1的变化导致意外变化的问题在sb2。

答案 2 :(得分:1)

 String ab = "hello";        //straight initialization
 String ac = "hello";  // create one more reference ac

String是使用new关键字时的特殊情况,将创建一个新的String对象。请注意,对象始终位于堆上 - 字符串池不是与堆分开的单独内存区域。字符串池就像一个缓存。

就像这样,因为字符串是java大量使用的东西,使用新的关键字创建String对象也很昂贵,这也是java引入StringPool概念的原因。

如果声明一个变量ac具有相同的值,则java将不会创建新对象(String),它将仅引用池中已存在的同一对象(hello)。

 String ab_1 = new String ("hello_1");  //initializing using new

在内存中创建对象很简单,ab_1将引用该对象。

答案 3 :(得分:1)

字符串在Java中是一个非常特殊的情况(在我看来这不是一件好事,但这无关紧要。)

与其他对象不同,字符串可以直接实例化,就像它们是常量一样。 执行此操作时,String常量将添加到String常量池中,并像处理它一样处理。让我举个例子。

String a = "abc";
String b = "abc";

当您将a实例化为“原始”字符串时,它会被添加到池中,当您实例化b时,从池中返回相同的对象,因此如果您这样做:< / p>

a == b;

你会得到...... true,因为它实际上是同一个对象。如果使用new实例化两者,则会得到错误,因为您正在比较两个不同对象的引用(new强制创建不同的对象)。

答案 4 :(得分:1)

根据'where'字符串'存储'还有另外一个区别 - 内存或字符串常量池。

  

为了提高Java的内存效率,JVM预留了一个特殊区域   内存称为“字符串常量池”。什么时候编译   遇到一个字符串文字,它检查池是否相同   字符串已存在。如果找到匹配项,则引用新的   literal指向现有的String,没有新的String字面值   对象已创建。 (现有的String只有一个额外的   参考。)

String s = "abc"; // creates one String object and one reference variable

在这个简单的例子中,“abc”将进入池中,s将引用它。

String s = new String("abc"); // creates two objects, and one reference variable

在这种情况下,因为我们使用了new关键字,Java将创建一个新的String对象 在普通(非池)内存中,s将引用它。另外,字面意思是“abc” 放在游泳池里。

答案 5 :(得分:1)

字符串由java编译器专门处理。当您键入字符串文字(例如"hello")时,编译器会在内部为您创建一个新的String对象。

StringBuffer没有执行此类操作(尽管Java在内部使用StringBuffer用于其他目的 - 用于实现字符串连接)。

有关详细信息,请参阅Difference between string object and string literal

其他指示:

答案 6 :(得分:0)

String是一个可变类,并且具有可以从字符串文字创建String对象的内置构造函数。

在String的情况下也没有异常(就像创建原始.e.g int i = 0一样)。 String还执行构造函数来初始化以下(只是差异是它的抽象而不是直接可见):

String str = "ABC";

因为这里“ABC”也代表一个String对象,它不能由程序员直接使用,但它驻留在String池中。当执行此语句时,JVM将在内部调用私有构造函数,以使用驻留在池中的“ABC”对象创建对象。

答案 7 :(得分:0)

基本上,由于使用了很多字符串,Java提供了一种实例化字符串的简写解决方案。

而不是总是使用它,

String str = new String ("hello");

Java使它能够做到这一点:

String str = "hello";