zoukankan      html  css  js  c++  java
  • 【疯狂Java_突破程序员基本功的16课】charpt5 表达式中的陷阱

    5.1 关于字符串的陷阱

    5.1.1 jvm对于字符串的处理

    对于java中的字符直接量,jvm会使用一个字符串池来保存它们:第一次使用某个字符串时,jvm会将其放入字符串池进行缓存。在一般情况下,字符串池中的字符串对象不会被回收,当程序再次使用该字符串时,无需重新创建该对象,而是直接将引用变量指向字符串池中已有的该字符串对象。

    如果将一个字符串表连接表达式赋给一个字符串变量,并且该字符串连接表达式的值在编译时就可确定下来,那么jvm就会在编译时计算该表达式的值,并让它指向字符串池中对应的字符串。参看以下程序:

    public class StringJoinTest{
      public static void main(String[] args){
         String str1="Hello Java的长度:10";
        
    //虽然str不是直接字符串常量,但是因为str2的值在编译期就可以确定,所以str2也会引用字符串池中对应的字符串 String str2="Hello "+ "Java" +"的长度:" +10; System.out.println(str1 == str2); //因为指向的是字符串池中的同一个字符串,所以返回true   } }

    以上程序中对str2的字符串连接表达式中的所有运算数,它们都是字符串直接量、整数直接量,没有变量参与,没有方法参与。因此jvm可以在编译时就确定该字符串连接表达式的值,可以让字符串变量指向字符串池中对应的字符串。但如果使用了变量或方法,那就只能等到运行时才能确定该字符串表达式的值,也就无法在编译时确定该字符串变量的值,也就无法利用jvm的字符串池。但是有一种例外,那就是如果字符串连接运算中的所有变量都可以进行宏替换,那么jvm一样可以在编译时确定字符串连接表达式的值,一样会让字符串变量指向字符串池中对应的字符串。请参看以下程序:

    public class StringJoinTest2{
      public static void main(String[] args){
         String str1="Hello Java的长度:10";
        //虽然str不是直接字符串常量,但是因为str2的值在编译期就可以确定,所以str2也会引用字符串池中对应的字符串
          String str2="Hello "+ "Java" +"的长度:" +10;  
          System.out.println(str1 == str2);    //因为指向的是字符串池中的同一个字符串,所以返回true
        //因为str3中包含了方法调用,所以不能在编译期确定其值
        String str3="Hello "+ "Java" +"的长度:" +"Hello Java".length();  
        System.out.println(str1 == str3);//返回false
        int len = 10;
        //因为str4的值包含了表达式,所以无法在编译期确定其值
        String str4="Hello "+ "Java" +"的长度:" +len;  
        System.out.println(str1 == str4);//返回false
        final String s1= "Hello ";
        String str5=s1+"Java的长度:10";
        System.out.println(str1 == str5);//返回true
      }    
    }   

     5.2.2 复合赋值运算符的陷阱

    有包含下面语句的程序:

    short s = 10;
    s = s-1;

    编译时,会提示错误:

    Type mismatch: cannot convert from int to short
    

     这是因为表达式s-1的类型会自动提升为int,所以程序将一个int类型的值赋值给一个short类型的变量(s)时,导致了编译错误。

    但将上面代码改为如下形式就可以通过编译了:

    short c=10;
    c -= 1;

    这是因为根据java规范,复合赋值运算符包含了一个隐式的类型转化,也就是说下面两条语句并非等价:

    c = c + 1;
    c += 1;

    实际上,c += 1等价于 c = (c的类型)(c+1),这就是复合运算符中包含的隐式的类型转化。

  • 相关阅读:
    信号灯的典型应用
    字符串过滤
    做一些学习的事情一定要坚持下去
    昨天的你造就今天的你,今天的你准备怎么造就明天的你呢?
    vue中计算属性,方法,侦听器
    vue模板语法
    Vue实例的生命周期钩子
    VUE实例
    简单的组件间传值
    前端组件化
  • 原文地址:https://www.cnblogs.com/yangfengtao/p/2776560.html
Copyright © 2011-2022 走看看