Java字符串:";字符串s=新字符串(“愚蠢”)&引用; 我是一个C++学习java的家伙。我正在读有效的Java,有些东西把我弄糊涂了。它说永远不要写这样的代码: String s = new String("silly"); String s = "No longer silly";
因为它会创建不必要的Java字符串:";字符串s=新字符串(“愚蠢”)&引用; 我是一个C++学习java的家伙。我正在读有效的Java,有些东西把我弄糊涂了。它说永远不要写这样的代码: String s = new String("silly"); String s = "No longer silly";,java,string,Java,String,因为它会创建不必要的字符串对象。但应该这样写: String s = new String("silly"); String s = "No longer silly"; 好的,到目前为止还不错……但是,考虑到这一类: public final class CaseInsensitiveString { private String s; public CaseInsensitiveString(String s) { if (s == null) {
字符串对象。但应该这样写:
String s = new String("silly");
String s = "No longer silly";
好的,到目前为止还不错……但是,考虑到这一类:
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";
为什么第一句话可以?难道不是吗
CaseInsensitiveString cis=“Polish”代码>
如何使caseinsensitivitestring
的行为类似于String
,这样上述语句就可以了(无论是否扩展String
)?字符串的什么特点使得它能够像这样传递一个文本?据我所知,Java中没有“复制构造函数”的概念
String
s在Java中是特殊的-它们是不可变的,字符串常量会自动转换为String
对象
您的SomeStringClass cis=“value”
示例无法应用于任何其他类
您也不能扩展字符串,因为它被声明为final
,这意味着不允许进行子分类。您不能。Java中双引号中的内容被编译器特别识别为字符串,不幸的是,您无法覆盖它(或扩展Java.lang.String
——它被声明为final
)。字符串
是该语言的一个特殊内置类。它只适用于字符串
类,您应该避免在其中说
String s = new String("Polish");
因为文字“Polish”
已经是String
类型,并且您正在创建一个额外的不必要对象。对于任何其他类
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
是正确的(在本例中是唯一的)操作。区分大小写字符串和字符串是不同的对象。你不能这样做:
CaseInsensitiveString cis = "Polish";
因为“Polish”是一个字符串,而不是不区分大小写的字符串。如果字符串扩展了不区分大小写的字符串,那么您就可以了,但显然不行
不要担心这里的构造,你不会制造不必要的东西。如果查看构造函数的代码,它所做的只是存储对传入字符串的引用。没有创建任何额外的内容
在字符串s=newstring(“foobar”)的情况下,它正在做一些不同的事情。首先创建文字字符串“foobar”,然后通过构造一个新字符串来创建它的副本。无需创建该副本。在Java中,语法“text”创建类Java.lang.String的实例。任务:
String foo = "text";
是一个简单的赋值,不需要复制构造函数
MyString bar = "text";
因为MyString类不是java.lang.String或java.lang.String的超类,所以无论您做什么都是非法的。首先,您不能创建从String扩展的类,因为String是最终类。java管理字符串的方式与其他类不同,因此只能使用字符串
String s = "Polish";
但是在你的类中,你必须调用构造函数。因此,这段代码很好。我相信使用文本形式(即“foo”而不是新字符串(“foo”)的主要好处是,所有字符串文本都由VM“interned”。换句话说,它被添加到池中,这样创建相同字符串的任何其他代码都将使用池中的字符串,而不是创建新实例
为了说明这一点,以下代码将打印第一行为true,第二行为false:
System.out.println("foo" == "foo");
System.out.println(new String("bar") == new String("bar"));
在第一个示例中,您创建了一个字符串“傻”,然后将其作为参数传递给另一个字符串的复制构造函数,从而生成与第一个字符串相同的第二个字符串。由于Java字符串是不可变的(这经常会让习惯使用C字符串的人感到刺痛),因此这是一种不必要的资源浪费。您应该使用第二个示例,因为它跳过了几个不必要的步骤
但是,字符串文字不是不区分大小写的字符串,因此在上一个示例中无法执行所需的操作。此外,没有办法像C++那样重载一个铸造操作员,所以根本没有办法做你想做的事情。您必须将其作为参数传递给类的构造函数。当然,我可能只会使用String.toLowerCase()并完成它
此外,CaseInsensitiveString应该实现CharSequence接口,也可能实现可序列化和可比较的接口。当然,如果实现Comparable,还应该重写equals()和hashCode()。字符串在java中被特别处理,它们是不可变的,因此通过引用计数来处理它们是安全的
如果你写信
String s = "Polish";
String t = "Polish";
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
然后s和t实际上引用同一个对象,s==t将返回true,因为“==”for objects read“是同一个对象”(或者,无论如何,我不确定这是否是实际语言规范的一部分,或者只是编译器实现的一个细节,所以依赖它可能不安全)
如果你写信
String s = new String("Polish");
String t = new String("Polish");
然后s!=t(因为您已经显式创建了一个新字符串),尽管s.equals(t)将返回true(因为字符串将此行为添加到equals)
你想写的东西
CaseInsensitiveString cis = "Polish";
无法工作,因为您认为引号是对象的某种短路构造函数,而事实上这只适用于普通的旧java.lang.Strings。在大多数JDK版本中,这两个版本是相同的:
字符串s=新字符串(“愚蠢”)
String s=“不再愚蠢”
由于字符串是不可变的,编译器会维护一个字符串常量列表,如果您尝试创建一个新的常量,则会首先检查字符串是否已定义。如果已定义,则返回对现有不可变字符串的引用
为了澄清,当您说“String s=”时,您正在定义一个占用堆栈空间的新变量,那么您是说“不再愚蠢”还是说新字符串(“愚蠢”)完全相同
// Lets test the insensitiveness
CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");
assert cis5 == cis6;
assert cis5.equals(cis6);
C:\oreyes\samples\java\insensitive>type CaseInsensitiveString.java
import java.util.Map;
import java.util.HashMap;
public final class CaseInsensitiveString {
private static final Map<String,CaseInsensitiveString> innerPool
= new HashMap<String,CaseInsensitiveString>();
private final String s;
// Effective Java Item 1: Consider providing static factory methods instead of constructors
public static CaseInsensitiveString valueOf( String s ) {
if ( s == null ) {
return null;
}
String value = s.toLowerCase();
if ( !CaseInsensitiveString.innerPool.containsKey( value ) ) {
CaseInsensitiveString.innerPool.put( value , new CaseInsensitiveString( value ) );
}
return CaseInsensitiveString.innerPool.get( value );
}
// Class constructor: This creates a new instance each time it is invoked.
public CaseInsensitiveString(String s){
if (s == null) {
throw new NullPointerException();
}
this.s = s.toLowerCase();
}
public boolean equals( Object other ) {
if ( other instanceof CaseInsensitiveString ) {
CaseInsensitiveString otherInstance = ( CaseInsensitiveString ) other;
return this.s.equals( otherInstance.s );
}
return false;
}
public int hashCode(){
return this.s.hashCode();
}
public static void main( String [] args ) {
// Creating two different objects as in new String("Polish") == new String("Polish") is false
CaseInsensitiveString cis1 = new CaseInsensitiveString("Polish");
CaseInsensitiveString cis2 = new CaseInsensitiveString("Polish");
// references cis1 and cis2 points to differents objects.
// so the following is true
assert cis1 != cis2; // Yes they're different
assert cis1.equals(cis2); // Yes they're equals thanks to the equals method
// Now let's try the valueOf idiom
CaseInsensitiveString cis3 = CaseInsensitiveString.valueOf("Polish");
CaseInsensitiveString cis4 = CaseInsensitiveString.valueOf("Polish");
// References cis3 and cis4 points to same object.
// so the following is true
assert cis3 == cis4; // Yes they point to the same object
assert cis3.equals(cis4); // and still equals.
// Lets test the insensitiveness
CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");
assert cis5 == cis6;
assert cis5.equals(cis6);
// Futhermore
CaseInsensitiveString cis7 = CaseInsensitiveString.valueOf("SomethinG");
CaseInsensitiveString cis8 = CaseInsensitiveString.valueOf("someThing");
assert cis8 == cis5 && cis7 == cis6;
assert cis7.equals(cis5) && cis6.equals(cis8);
}
}
C:\oreyes\samples\java\insensitive>javac CaseInsensitiveString.java
C:\oreyes\samples\java\insensitive>java -ea CaseInsensitiveString
C:\oreyes\samples\java\insensitive>
String s = "Hello";
String s = new String("Hello");
String s = "Silly";
String s = new String("Silly");
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String str1 = "foo";
String str2 = "foo";
String str1 = new String("foo");
String str2 = new String("foo");
String s1="foo";
String s2="foo";
String s3=new String("foo");
String s4=new String("foo");
new String("text");
new String(new String(new char[]{'t','e','x','t'}));