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'}));