zoukankan      html  css  js  c++  java
  • java String 深入理解

    • 说出下面程序的输出
    class StringEqualTest {
    
        public static void main(String[] args) {
                String s1 = "Programming";
                    String s2 = new String("Programming");
                    String s3 = "Program" + "ming";
                    String s4=new String(s2);
             String s5 = "Programming";
                    System.out.println(s1 == s2);//false
                    System.out.println(s4 == s2);//false
                    System.out.println(s1 == s3);//true
                    System.out.println(s1 == s1.intern());//true } }

    解释:

    在此引入常量池这个概念:
    常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量

    首先,我们要知道Java会确保一个字符串常量只有一个拷贝。 

    因为例子中的s1和s3中的
    Programming”都是字符串常量,它们在编译期就被确定了,所以s1==s3为true;而”Program”和”ming”也都是字符 串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所以s3也同样在编译期就被解析为一个字符串常量,所以s3也是常量池中 ”kvill”的一个引用。 

    所以我们得出s5==s1==s2; 

    用new String() 创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间。

    所以有s2!=s4

    String对象的intern方法会得到字符串对象在常量池中对应的版本的引用(如果常量池中有一个字符串与String对象的equals结果是true),如果常量池中没有对应的字符串,则该字符串将被添加到常量池中,然后返回常量池中字符串的引用。

    再补充介绍一点:存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String的intern()方法就是扩充常量池的一个 方法;当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用, 如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用;

    案例

    String s0= “kvill”; 
    String s1=new String(”kvill”); 
    String s2=new String(“kvill”); 
    System.out.println( s0==s1 ); 
    System.out.println( “**********” ); 
    s1.intern(); 
    s2=s2.intern(); //把常量池中“kvill”的引用赋给s2 
    System.out.println( s0==s1); 
    System.out.println( s0==s1.intern() ); 
    System.out.println( s0==s2 ); 
    结果为: 
    
    false 
    ********** 
    false //虽然执行了s1.intern(),但它的返回值没有赋给s1 
    true //说明s1.intern()返回的是常量池中”kvill”的引用 
    true
    • 关于equals()和==:

    这个对于String简单来说就是比较两字符串的Unicode序列是否相当,如果相等返回true;String类已经重写过了equals方法。

    而==是比较两字符串的地址是否相同,也就是是否是同一个字符串的引用

    而在符合数据类型中,则equals和==都是比较两对象的地址是否相同,除非重写equals,详见hashcode与equals的区别。

    • 使用equals方法比较两个相同的StringBuffer对象
         StringBuffer sb0=new StringBuffer("hello");
            StringBuffer sb1=new StringBuffer("hello");
            System.out.println(sb0==sb1);
            System.out.println(sb0.equals(sb1));
            System.out.println(sb0.toString().equals(sb1.toString()));
    false
    false
    true

    StringBuffer 类没有重写Object类下的equals方法,所以实质还是==比较,所以如果需要比较两个StringBuffer对象是否相等则toString()方法转为String。

    • .关于String是不可变的 

      这一说又要说很多,大家只要知道String的实例一旦生成就不会再改变了,比如说:String str=”kv”+”ill”+” “+”ans”; 
      就是有4个字符串常量,首先”kv”和”ill”生成了”kvill”存在内存中,然后”kvill”又和” “ 生成 ”kvill “存在内存中,最后又和生成了”kvill ans”;并把这个字符串的地址赋给了str,就是因为String的“不可变”产生了很多临时变量,这也就是为什么建议用StringBuffer的原 因了,因为StringBuffer是可改变的。
    • 可不可以在分割字符串是使用多个分割符
    String str="2012-05-25 13:24:16";
            String[] s=str.split("-|:|\s");
            for(String temp:s){
                System.out.print(temp+" ");
            }
    2012 05 25 13 24 16

    关键点就是在split()方法中使用多个分割符;其实split()方法里的分割符参数是一个正则表达式,所以可以使用或操作符(|)链接多个分割符,这样在分割的时候就会按照所有的分割符对字符串进行分割了。s表示空格,不过在字符串使用过程中还需要在s之前添加转义字符"",否则会出现编译错误。

  • 相关阅读:
    Codeforces 691A Fashion in Berland
    HDU 5741 Helter Skelter
    HDU 5735 Born Slippy
    HDU 5739 Fantasia
    HDU 5738 Eureka
    HDU 5734 Acperience
    HDU 5742 It's All In The Mind
    POJ Euro Efficiency 1252
    AtCoder Beginner Contest 067 C
    AtCoder Beginner Contest 067 D
  • 原文地址:https://www.cnblogs.com/tjlgdx/p/5995545.html
Copyright © 2011-2022 走看看