如果
,我无法弄明白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运算符。有人可以解释我的主要原因。
答案 0 :(得分:6)
所有对象都需要使用new
进行实例化。只能从文字(int i = 0;
)实例化基元。
唯一的例外是:
String s = "abc"; //can be instantiated from a literal, like primitives
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";