• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
Joanna Qian
Stay Hungry, Stay Foolish!
博客园    首页    新随笔    联系   管理    订阅  订阅
Java中的String类的学习

一、String类对象的实例化方式

1.直接使用"" 定义字符串赋值给String类的对象

2.使用String类中的构造方法:public String(String str);

public class StringDemo{
    public static void main(String args[]){
        String str="Hello world!";  //直接赋值实例化String类的对象
        String str=new String("Hello world!"); //通过String类的构造方法实例化String类的对象
        System.out.println(str);
    }    
}

二、String类对象的比较问题

1、==操作符——比较两个对象的内存地址,并未比较两个字符串的数值

public class StringDemo{
    public static void main(String args[]){
        String str1="Hello";
        String str2=new String("Hello");
        String str3=str2;
        System.out.println(str1==str2); //false
        System.out.println(str1==str3); //false
        System.out.println(str2==str3); //true
    }    
}

2、equals方法——比较两个字符串的内容(public boolean equals(String other))

public class StringDemo{
    public static void main(String args[]){
        String str1="Hello";
        String str2=new String("Hello");
        String str3=str2;
        System.out.println(str1.equals(str2)); //true
        System.out.println(str1.equals(str3)); //true
        System.out.println(str2.equals(str3)); //true
    }    
}

严格来说,equals比较的是堆内存中的内容

面试题:请解释String的两种比较方式?

  • "=="比较的是两个字符串的内存地址的数值,属于数值比较
  • equals()比较的是两个字符串的内容

注意:一个字符串常量是String的匿名对象

java中String并不是一个基本数据类型,所以Java会自动把一个字符串常量当成一个String类的匿名对象来处理

public class StringDemo{
    public static void main(String args[]){
        String str="Hello";
        
        System.out.println("Hello".equals(str); //true
    }    
}

小技巧:开发中使用以下方式可以避免NullPointException

例如:

public class StringDemo{
    public static void main(String args[]){
        String str="null";        
        System.out.println(str.equals("Hello"); 
    }    
}

会产生空指针异常NullPointException

改进: 通过字符串常量调用equals()方法,该常量永远不会是null,所以可以避免空指针异常

public class StringDemo{
    public static void main(String args[]){
        String str="null";        
        System.out.println("Hello".equals(str)); 
    }    
}

3、两种实例化方法的比较

1)java的共享设计模式

共享设计是在JVM中为用户提供一个对象池,当用户创建了一个 新的且池中没有的对象时,处理将这个对象分配内存之外,还会在对象池中进行保留,以后如果有其他对象社么了与之一样的内容时候,不会重复申明,而是从对象池中取出内容继续使用,String类正是使用该机制。

当用户采用直接赋值实例化String对象的时候,如果是第一次定义,则会自动将对象内容保留在字符串对象池中,以后如果其他的字符串对象依然采用直接赋值的话,可以直接通过对象池取出已经保存的内容继续使用,而不会重新开辟新的空间,如以下程序:

public class StringDemo{
    public static void main(String args[]){
        String str1="Hello";
        String str2="Hello";
        String str3="Hello";         
        System.out.println(str1==str1); //true
        System.out.println(str1==str3); //true
        System.out.println(str2==str3); //true
    }    
}

其内存关系为

2)通过String类的构造方法

但通过该法创建的String对象的内容不能自动入池,

但用户可以使用String类中的intern()方法手工入池。例如:

public class StringDemo{
    public static void main(String args[]){
        String str1=new String("Hello");
        String str2="Hello";
        String str3="Hello";         
        System.out.println(str1==str1); //false
        System.out.println(str1==str3); //false
    }    
}

但是:

public class StringDemo{
    public static void main(String args[]){
        String str1=new String("Hello").intern();
        String str2="Hello";
        String str3="Hello";         
        System.out.println(str1==str1); //true
        System.out.println(str1==str3); //true
    }    
}

面试题:String对象的两种实例化方式的区别?

  • 直接赋值:只开辟一个堆内存空间,而且采用共享设计模式,可以自动入池,以备下次对象继续使用
  • 构造方法:开辟两个内存空间,其中一块将成为垃圾,且不会自动入池,但可以采用intern()方法继续手工入池

4、字符串的内容一旦声明则不可改变

public class StringDemo{
    public static void main(String args[]){
        String str="Hello";
        str += "World";
        str = str +"!!!"
        System.out.println(str); // 输出为Hello World!!!
    }    
}

其内存空间变化如下

 可以看出实际上对于String中的字符串内容并没有发生任何的变化,而最后内容的改变实际上改变的是String对象的内存地址的指向,所以字符串内容依然没有任何变化,但这样会产生大量的垃圾,所以在开发中对以下代码必须要进行回避:

public class StringDemo{
    public static void main(String args[]){
        String str="";
        for(int x=0; x<1000;x++){
            str += x;
        }
        System.out.println(str); 
    }    
}

相当于“断开-连接”1000次,且产生大量的垃圾空间;在实际开发中,可以用StringBuffer来实现上述代码功能,而不产生大量垃圾。

posted on 2012-08-23 03:30  Joanna Qian  阅读(441)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3