zoukankan      html  css  js  c++  java
  • String相关的常见问题

    检测一个字符串是否在jvm的常量池中

    1. public static boolean inPool(String s) {   
    2.    String s2 = s.intern();   
    3.    if (s2 == s)   
    4.        return true;   
    5.    return false;   
    6.}  

    1》 下面是一些String相关的常见问题:

    String中的final用法和理解

    final StringBuffer a = new StringBuffer("111");
    final StringBuffer b = new StringBuffer("222");
    a=b;//此句编译不通过
    
    final StringBuffer a = new StringBuffer("111");
    a.append("222");//编译通过

    可见,final只对引用的"值"(即内存地址)有效,它迫使引用只能指向初始指向的那个对象,改变它的指向会导致编译期错误。

    至于它所指向的对象的变化,final是不负责的。

    2》 String 常量池问题的几个例子

    下面是几个常见例子的比较分析和理解:


    [1]

    String a = "a1";
    String b = "a" + 1;
    System.out.println((a == b)); //result = true
    String a = "atrue";
    String b = "a" + "true";
    System.out.println((a == b)); //result = true
    String a = "a3.4";
    String b = "a" + 3.4;
    System.out.println((a == b)); //result = true

    分析:JVM对于字符串常量的"+"号连接,将程序编译期,JVM就将常量字符串的"+"连接优化为连接后的值,拿"a" + 1来说,经编译器优化后在class中就已经是a1。在编译期其字符串常量的值就确定下来,故上面程序最终的结果都为true。

    [2]

    String a = "ab";
    String bb = "b";
    String b = "a" + bb;
    System.out.println((a == b)); //result = false

    分析:JVM对于字符串引用,由于在字符串的"+"连接中,有字符串引用存在,而引用的值在程序编译期是无法确定的,即"a" + bb无法被编译器优化,只有在程序运行期来动态分配并将连接后的新地址赋给b。所以上面程序的结果也就为false。

    [3]

    String a = "ab";
    final String bb = "b";
    String b = "a" + bb;
    System.out.println((a == b)); //result = true

    分析:和[3]中唯一不同的是bb字符串加了final修饰,对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量池中或嵌入到它的字节码流中。所以此时的"a" + bb和"a" + "b"效果是一样的。故上面程序的结果为true。

    [4]

    String a = "ab";
    final String bb = getBB();
    String b = "a" + bb;
    System.out.println((a == b)); //result = false
    private static String getBB() {
    return "b";
    }

    分析:JVM对于字符串引用bb,它的值在编译期无法确定,只有在程序运行期调用方法后,将方法的返回值和"a"来动态连接并分配地址为b,故上面程序的结果为false。

    通过上面4个例子可以得出得知:
    String  s  =  "a" + "b" + "c";  
    就等价于String s = "abc";  

    String  a  =  "a";  
    String  b  =  "b";  
    String  c  =  "c";  
    String  s  =   a  +  b  +  c;   

    这个就不一样了,最终结果等于:  

    StringBuffer temp = new StringBuffer();  
    temp.append(a).append(b).append(c);  
    String s = temp.toString();

    由上面的分析结果,可就不难推断出String 采用连接运算符(+)效率低下原因分析,形如这样的代码:

    public class Test {
      public static void main(String args[]) {
         String s = null;
          for(int i = 0; i < 100; i++) {
              s += "a";
          }
       }
    }

    每做一次 + 就产生个StringBuilder对象,然后append后就扔掉。下次循环再到达时重新产生个StringBuilder对象,然后 append 字符串,如此循环直至结束。 如果我们直接采用 StringBuilder 对象进行 append 的话,我们可以节省 N - 1 次创建和销毁对象的时间。所以对于在循环中要进行字符串连接的应用,一般都是用StringBuffer或StringBulider对象来进行 append操作。

    String对象的intern方法理解和分析:

    public class Test4 {
    
       private static String a = "ab";
    
       public static void main(String[] args){
    
             String s1 = "a";
             String s2 = "b";
             String s = s1 + s2;
    
             System.out.println(s == a);//false
             System.out.println(s.intern() == a);//true 
         }
    }

    这里用到Java里面是一个常量池的问题。对于s1+s2操作,其实是在堆里面重新创建了一个新的对象,s保存的是这个新对象在堆空间的的内容,所 以s与a的值是不相等的。而当调用s.intern()方法,却可以返回s在常量池中的地址值,因为a的值存储在常量池中,故s.intern和a的值相 等

  • 相关阅读:
    大数据之路Week08_day02 (Flume架构介绍和安装)
    Hive调优
    hive的shell用法(脑子糊涂了,对着脚本第一行是 #!/bin/sh 疯狂执行hive -f 结果报错)
    Week08_day01 (Hive 自定义函数 UDF 一个输入,一个输出(最常用))
    Week08_day01 (Hive开窗函数 row_number()的使用 (求出所有薪水前两名的部门))
    Week08_day01 (Hive实现按照指定格式输出每七天的消费平均数)
    Week08_day01 (Hive实现WordCount计数)
    SQL中 count(*)和count(1)的对比,区别
    大数据之路week07--day07 (修改mysql默认编码)
    10进制转换成16进制的函数(自写函数模板)
  • 原文地址:https://www.cnblogs.com/surong/p/2459137.html
Copyright © 2011-2022 走看看