我是一个学习Java的C++人.我正在阅读Effective Java,有些事让我很困惑.它说从不写这样的代码:
String s = new String("silly");
Run Code Online (Sandbox Code Playgroud)
因为它会创建不必要的String对象 但相反它应该写成这样:
String s = "No longer silly";
Run Code Online (Sandbox Code Playgroud)
好吧到目前为止......但是,鉴于这个课:
public final class CaseInsensitiveString {
private String s;
public CaseInsensitiveString(String s) {
if (s == null) {
throw new NullPointerException();
}
this.s = s;
}
:
:
}
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";
Run Code Online (Sandbox Code Playgroud)
为什么第一个陈述好吗?不应该
CaseInsensitiveString cis = "Polish";
我如何使CaseInsensitiveString行为String如此上述声明是可以的(有和没有扩展String)?它是什么让它能够传递像这样的文字?根据我的理解,Java中没有"复制构造函数"概念?
Ada*_*eld 108
String是一种特殊的语言内置类.它是为String类只有在你应该避免说
String s = new String("Polish");
Run Code Online (Sandbox Code Playgroud)
因为文字"Polish"已经是类型String,并且您正在创建一个额外的不必要的对象.对于任何其他类,说
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
Run Code Online (Sandbox Code Playgroud)
是正确的(在这种情况下,只有)这样做的事情.
Lei*_*igh 56
我相信使用文字形式(即"foo"而不是新的String("foo"))的主要好处是所有字符串文字都被VM"拦截".换句话说,它被添加到池中,使得创建相同字符串的任何其他代码将使用池化的String而不是创建新实例.
为了说明,下面的代码将为第一行打印为true,但对于第二行则为false:
System.out.println("foo" == "foo");
System.out.println(new String("bar") == new String("bar"));
Run Code Online (Sandbox Code Playgroud)
Ste*_* B. 30
字符串在java中有点特殊处理,它们是不可变的,所以通过引用计数来处理它们是安全的.
如果你写
String s = "Polish";
String t = "Polish";
Run Code Online (Sandbox Code Playgroud)
然后s和t实际上引用相同的对象,并且s == t将返回true,对于"=="对于读取"是同一个对象"的对象(或者,无论如何,我不确定这是否属于实际的语言规范或只是编译器实现的细节 - 所以也许依靠这个并不安全.
如果你写
String s = new String("Polish");
String t = new String("Polish");
Run Code Online (Sandbox Code Playgroud)
那么s!= t(因为你已经明确地创建了一个新的字符串)虽然s.equals(t)将返回true(因为string将此行为添加到equals).
你要写的东西,
CaseInsensitiveString cis = "Polish";
Run Code Online (Sandbox Code Playgroud)
无法工作,因为你认为引用是你的对象的某种短路构造函数,实际上这只适用于普通的旧java.lang.Strings.
Vik*_*kas 20
String s1="foo";
Run Code Online (Sandbox Code Playgroud)
文字将进入池中,s1将参考.
String s2="foo";
Run Code Online (Sandbox Code Playgroud)
这次它将检查"foo"文字是否已经在StringPool中可用,因为它现在存在,所以s2将引用相同的文字.
String s3=new String("foo");
Run Code Online (Sandbox Code Playgroud)
首先在StringPool中创建"foo"文字,然后通过字符串arg构造函数创建String对象,即由于通过new运算符创建对象而在堆中创建"foo",然后s3将引用它.
String s4=new String("foo");
Run Code Online (Sandbox Code Playgroud)
与s3相同
所以 System.out.println(s1==s2);// **true** due to literal comparison.
和 System.out.println(s3==s4);// **false** due to object
比较(s3和s4在堆中的不同位置创建)
Aln*_*tak 12
Strings在Java中很特殊 - 它们是不可变的,字符串常量会自动转换为String对象.
您的SomeStringClass cis = "value"示例无法应用于任何其他类.
你也不能扩展String,因为它被声明为final,意味着不允许进行子类化.
Java字符串很有趣.看起来回答已经涵盖了一些有趣的观点.这是我的两分钱.
字符串是不可变的(你永远不能改变它们)
String x = "x";
x = "Y";
Run Code Online (Sandbox Code Playgroud)
字符串比较取决于您所比较的内容
String a1 = new String("A");
String a2 = new String("A");
Run Code Online (Sandbox Code Playgroud)
a1 不等于 a2a1并且a2是对象引用我认为你试图使用casesensitive类是错误的.不管弦乐.您真正关心的是如何显示或比较值.使用另一个类来格式化字符串或进行比较.
即
TextUtility.compare(string 1, string 2)
TextUtility.compareIgnoreCase(string 1, string 2)
TextUtility.camelHump(string 1)
Run Code Online (Sandbox Code Playgroud)
由于您正在组成课程,因此您可以根据需要进行比较 - 比较文本值.
回答问题的最佳方法是让您熟悉"字符串常量池".在java中,字符串对象是不可变的(即它们的值在初始化后无法更改),因此在编辑字符串对象时,最终会创建一个新编辑的字符串对象,而旧对象只是在特殊内存中浮动,称为"字符串"常数池".通过创建一个新的字符串对象
String s = "Hello";
Run Code Online (Sandbox Code Playgroud)
将只在池中创建一个字符串对象,引用s将引用它,但通过使用
String s = new String("Hello");
Run Code Online (Sandbox Code Playgroud)
你创建了两个字符串对象:一个在池中,另一个在堆中.引用将引用堆中的对象.
| 归档时间: |
|
| 查看次数: |
172472 次 |
| 最近记录: |