Java 为什么我不应该用构造函数实例化string对象?

Java 为什么我不应该用构造函数实例化string对象?,java,Java,在Java中,strings=“foo”显然优于strings=newstring(“foo”) 为什么??不是在这两种情况下都创建了新的字符串对象吗?为什么第一种情况会阻止调用构造函数 为什么? 因为第二种方法会产生两个字符串对象(原始对象是字符串文本,另加一个显式副本)。我不认为这样更好。我假设您得到的唯一“好处”是,如果您错误地使用“==”运算符而不是equals方法,那么一个字符串的两个不同实例将更快地失败,这将提示您修复代码。(==运算符可能会“成功”并意外失败) 当然,除非您的代码出

在Java中,
strings=“foo”
显然优于
strings=newstring(“foo”)

为什么??不是在这两种情况下都创建了新的字符串对象吗?为什么第一种情况会阻止调用构造函数

为什么?


因为第二种方法会产生两个字符串对象(原始对象是字符串文本,另加一个显式副本)。

我不认为这样更好。我假设您得到的唯一“好处”是,如果您错误地使用“==”运算符而不是equals方法,那么一个字符串的两个不同实例将更快地失败,这将提示您修复代码。(==运算符可能会“成功”并意外失败)


当然,除非您的代码出于任何原因要求您构建两个不同的实例,否则第一种情况是字符串文字,这只是语言为您提供的创建字符串的简写。字符串类构造函数仍然会被调用,只是没有显式调用,这意味着更少的类型和更少的代码混乱

第二种情况是获取已经由文本创建的String对象并将其传递给构造函数,构造函数复制内容以创建新的、单独的String对象。文字仍然存在,因为文字被扣押

很少有必要使用字符串构造函数(几乎只有当您创建了一个非常大的字符串的子字符串并希望释放该字符串其余部分使用的内存时,才需要使用字符串构造函数),因为默认情况下,子字符串使用与原始字符串相同的底层字符数组,只是偏移量和长度不同

为什么?不是在这两种情况下都创建了新的字符串对象吗

否,作为字符串文本的初始表单将被插入,以便只创建一个实例:

String s = "foo";
String s2 = "foo";

s==s2=>true

需要一个
字符串的两个不同实例(具有相同的内容)听起来就像需要两个不同的“实例”一样好一个
int
…也许某个地方有一些糟糕的被滥用的身份映射…但我希望不是:-/是的,考虑到字符串是不可变的,我想不出任何理由有人会需要这样的东西。这就是为什么我说“出于任何理由”可能重复的。(一旦您理解了这两种形式之间的区别,就很明显为什么在几乎所有情况下都首选第一种形式。)第二种方法会产生两个字符串对象-只有当“foo”不在字符串池中时才产生。@KazekageGaara,参考
“foo”
,它必须在“池”中它已经在类的常量池中声明,并在类(或具体方法)被JVMsmall点处理时放在那里:文字仍然存在,因为文字是内部的。如果文字没有传入引用(如在类的常量池中),则可以自由地进行GC,从而有效地释放perm gen(假设JVM使用perm gen,有些不使用)@bestsss:但是文字不总是常量池的一部分吗?常量池是它的类的一部分。常量池中声明的字符串转到perm gen(在Suns JVM下,一些JVM不使用perm gen)。但是在类+类加载器被GC’d之后,JVM可以自由地“释放”另外,所有的类名、文字等都会在“未部署”/“重新部署”@ BestSSS之后泄漏:好的,我们现在在同一个页面上。我在桌面应用程序上工作太多了,考虑到类卸载一个经常出现的情况。我想是这样的:我做了很多中间件,类卸载是每天都要做的事情,所以基本上任何不是来自引导程序或应用程序类加载器的东西都是免费的。