Java 为什么要使用new创建字符串对象

Java 为什么要使用new创建字符串对象,java,string,Java,String,可能重复: 创建字符串对象有两种方法: 1使用字符串s=hello中的文字创建一个对象 2在字符串s中使用new as=new Stringhello创建两个对象 我想知道为什么我需要选择2种方法?第二种方法只是一种可能性。实际上,大多数开发人员从未使用过。第一种是后者的一个越来越不方便的版本,没有理由使用第二种方式 第二个只是创建了一个到文本的不同链接。从技术上讲,它们将重复使用相同的字符数组。唯一的区别是引用将不同,即==将给出false,但绝不使用==进行字符串比较。第二种方法只是一种可

可能重复:

创建字符串对象有两种方法:

1使用字符串s=hello中的文字创建一个对象 2在字符串s中使用new as=new Stringhello创建两个对象


我想知道为什么我需要选择2种方法?

第二种方法只是一种可能性。实际上,大多数开发人员从未使用过。第一种是后者的一个越来越不方便的版本,没有理由使用第二种方式


第二个只是创建了一个到文本的不同链接。从技术上讲,它们将重复使用相同的字符数组。唯一的区别是引用将不同,即==将给出false,但绝不使用==进行字符串比较。

第二种方法只是一种可能性。实际上,大多数开发人员从未使用过。第一种是后者的一个越来越不方便的版本,没有理由使用第二种方式


第二个只是创建了一个到文本的不同链接。从技术上讲,它们将重复使用相同的字符数组。唯一的区别是引用将不同,即==将给出false,但绝不使用==进行字符串比较。

如果使用new创建字符串,则会得到不同的字符串引用。这可以避免令人毛骨悚然的行为:

String s = "hello";
String t = "hello";
String u = new String("hello");
System.out.println(s==t);
System.out.println(t==u);

打印正确,错误。我真的想不出一个真正的软件可以在哪里使用它。但从某种意义上说,创建新引用“更安全”,因此==不会让我们感到惊讶。

如果您使用new创建字符串,那么您将获得不同的字符串引用。这可以避免令人毛骨悚然的行为:

String s = "hello";
String t = "hello";
String u = new String("hello");
System.out.println(s==t);
System.out.println(t==u);

打印正确,错误。我真的想不出一个真正的软件可以在哪里使用它。但从某种意义上说,创建新引用“更安全”,因此==不会让我们感到惊讶。

它们之间的基本区别是内存分配

第一种选择,即

String s1 = "hello";
当您使用这个函数时,s1被称为字符串文字,s1的内存在编译时分配

但在第二种情况下

String s2 = new String("hello");
在这种情况下,s2被称为表示hello的字符串对象

当您尝试使用第一种情况创建两个字符串文字时,这两个文字只引用一个内存。我的意思是字符串文字与字符串池的概念一起工作。当您创建具有相同内容的第二个字符串文字时,编译器将返回相同的引用,而不是分配新的空间。因此,当您使用==运算符比较这两个文本时,您将得到true

但是在第二种情况下,每次JVM都会为每个对象创建一个新对象。您必须使用equals方法比较它们的内容,但不能使用==运算符

如果您想使用第二个大小写创建一个新的字符串对象,但又不想要一个新对象,那么可以使用intern方法来获取相同的对象

String s = "hello";
String s1 = new String("hello").intern();
System.out.println(s == s1);

在这种情况下,JVM将返回相同的引用,而不是创建新对象。因此,输出将为真

它们之间的基本区别是内存分配

第一种选择,即

String s1 = "hello";
当您使用这个函数时,s1被称为字符串文字,s1的内存在编译时分配

但在第二种情况下

String s2 = new String("hello");
在这种情况下,s2被称为表示hello的字符串对象

当您尝试使用第一种情况创建两个字符串文字时,这两个文字只引用一个内存。我的意思是字符串文字与字符串池的概念一起工作。当您创建具有相同内容的第二个字符串文字时,编译器将返回相同的引用,而不是分配新的空间。因此,当您使用==运算符比较这两个文本时,您将得到true

但是在第二种情况下,每次JVM都会为每个对象创建一个新对象。您必须使用equals方法比较它们的内容,但不能使用==运算符

如果您想使用第二个大小写创建一个新的字符串对象,但又不想要一个新对象,那么可以使用intern方法来获取相同的对象

String s = "hello";
String s1 = new String("hello").intern();
System.out.println(s == s1);

在这种情况下,JVM将返回相同的引用,而不是创建新对象。因此,输出将是真实的

使用新Stringfoo的唯一精神正常的场合是单元测试。您可以确保代码不使用==进行字符串比较,而是使用正确的.equals方法。

使用新Stringfoo的唯一理智的场合是单元测试。您可以确保代码不使用==进行字符串比较,而是使用正确的.equals方法。

这可以理解为每个副本的构造函数。它们在C++中非常有用。净效果是将对象的副本作为参数传递,在本例中为字符串。

这可以理解为每个副本的构造函数。它们在C++中非常有用。net效果是将对象的副本作为参数传递,在本例中为字符串。

有趣的是,.net团队同意您的观点:没有接受另一个字符串对象的字符串构造函数。当您希望在堆中创建字符串对象并希望

他们必须尽快把垃圾收集起来。当您使用文本创建字符串时,它们是在PermGen中创建的,只有在卸载类时才会被垃圾收集。有趣的是,Net团队同意您的观点:没有接受另一个字符串对象的字符串构造函数。当您希望在堆中创建字符串对象并希望快速对其进行垃圾收集时,需要使用方法2。当您使用文本创建字符串时,它们是在PermGen中创建的,只有在类卸载时才会被垃圾收集。您在程序中使用第二种方法吗?下面是一个更严重的示例:假设您有一个非常大的字符串的子字符串。执行新的StringhugeString.substring0,10可防止保留对该巨大字符串的引用,并允许对其进行垃圾收集。这是一个真实的例子。你在程序中使用第二种方法吗?这里有一个更严肃的例子:假设你有一个非常大的字符串的子字符串。执行新的StringhugeString.substring0,10可防止保留对该巨大字符串的引用,并允许对其进行垃圾收集。这是一个真正适合现实世界的情况。但我已经读到使用new创建String对象会创建两个对象,一个对象将使用new创建,另一个对象将使用String literal创建。它将创建对String literal的另一个引用。从技术上讲,它们将重复使用相同的字符数组。唯一的区别是引用将不同,即==将给出false,但从不使用==进行字符串比较。但我已经了解到,使用new创建string对象将创建两个对象,一个对象将使用new创建,另一个对象将使用string literal创建。它将创建对string literal的另一个引用。从技术上讲,它们将重复使用相同的字符数组。唯一的区别是引用将不同,即= =将给出false,但永远不使用= =字符串比较。但是,与Jvaa中的C++字符串相反,是不可变的。因此复印是毫无用处的。是的,这是非常理论化的,但实际上很少使用!但与C++中的字符串相反,Jvaa是不可变的。因此复印是毫无用处的。是的,这是非常理论化的,但实际上很少使用!对象锁1=新的字符串锁;对象锁2=新字符串锁。。。同步锁1{…}?这不是一个很好的例子,但我认为这也是new Stringfoo的一个合理用法。@emory:我不这么认为,因为new Object做同样的工作时,噪音更少,而且没有问题,为什么他要使用字符串呢?`很久以后。Object lock1=new StringLock;对象锁2=新字符串锁。。。同步锁1{…}?这不是一个很好的例子,但我认为它也是new Stringfoo的一个合理用法。@emory:我不这么认为,因为new Object用更少的噪音做同样的工作,而且没有声音,为什么他要用字符串来做呢?`很久以后。这不是问题的预期。当字符串池的内存效率更高时,为什么我们需要使用新关键字并创建更多内存?这不是问题的预期。当字符串池的内存效率更高时,为什么我们需要使用new关键字并创建更多内存。?