• 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之前添加转义字符"",否则会出现编译错误。

  • 相关阅读:
    protected、public、private
    第十五章 面向对象程序设计
    第十四章 重载运算与类型转换
    聚合类
    explicit构造函数
    allocator类
    直接管理内存——new和delete
    智能指针
    Bugku-CTF之点击一百万次
    Bugku-CTF之flag在index里
  • 原文地址:https://www.cnblogs.com/tjlgdx/p/5995545.html
Copyright © 2020-2023  润新知