Java学习笔记程序员

java基本功16课:(5)表达式中的陷阱

2017-06-23  本文已影响22人  蓝汝丶琪

1.字符串陷阱

1.1 java创建对象的常见方式如下:

使用Java对象序列化,在保存对象时,会把其状态保存为一组字节,在未来,再将这些字节组装成对象。必须注意地是,对象序列化保存的是对象的”状态”,即它的成员变量。由此可知,** 对象序列化不会关注类中的静态变量**。

1.2 JVM对字符串的处理

        String java=new String("给我丶鼓励"); 
        //test1
        String test1="给我丶鼓励";
        System.out.println(test1==java); //false 一个是在常量区,一个是new出来的内存区   
        //test2
        System.out.println(java.intern()==test1); //true intern()方法是从常量区里返回该对象。
       
  
        String hello="hello";
        String java="java";
        final String str1Final="java";
        final String str2Final=java;

        String str1="hellojava";
        String str2="hello"+"java";   
        String str3=hello+java;
        String str4="hello"+str1Final;
        String str5="hello"+str2Final;

        //test
        //字符串直接量
        System.out.println(str1==str2);  //ture 
        //使用了变量
        System.out.println(str1==str3);  //false 
        //宏替换
        System.out.println(str1==str4);  //true 
        //虽然是final 但不是宏替换
        System.out.println(str1==str5);  //false

解释:为什么第二条是false,其实要理解

      String hello="hello";
      String java="java";
      String str3=hello+java;
      //相当于:
      String str3=(new StringBuilder().append("hello").append("java").toString());

因为new了一个新对象,所以比较肯定是false。
反编译后代码是这样的

        String s = "hello";
        String s1 = "java";
        String s2 = (new StringBuilder()).append(s).append(s1).toString();
        String s3 = (new StringBuilder()).append("hello").append("java").toString();

为什么第4条也是false呢?因为没有在编译期就确定下来的值,所以这个final不是宏替换,只能当不变的"变量"对待,所以接下来跟第二条原理一样了。

  //r如果两个字符串相同,返回true
  if(this==anObject){
      retrun true;
}
//如果anObject是String类型
if(anObject instanceof String){
   String anotherString =(String)anObject;
   //n代表当前字符串的长度
   int n=count;
   //如果两个字符串的长度相等
  if(n==anotherString.count){
    //获取当前字符串,anotherString底层封装的字符数组
    char v1[]=value;
    char v2[]=anotherString.value;
   int i =offset;
   int j =anotherString.offset;
   //逐渐比较v1数组和v2数组里的每个字符
   while(n--!=0){
    if(v1[i++]!=v2[j++])
       return false;
}
   return true;
}
     return false;
}

String 类还实现了Comparable接口,因此程序还可通过String提供的compareTo()方法来判断两个字符串之间的大小,当两个字符串所包含的字符序列相等时,程序通过compareTo()比较,将返回0.

public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;
        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

2.表达式类型的陷阱

2.1 表达式类型

2.2 复合赋值运算符

   a=a+5;
   a+=5; //实际上等价于 a=(a的类型)(a+5);
  short st=5;
  st+=90010;
  System.out.println(st); //将会输出24479
//此时会"溢出",因为系统有一个隐式的类型转换,short只能接受-32768~32767之间的整数,所以就会"溢出",因此会进行高位截断。

3.转义字符的陷阱

4.泛型可能引起的错误

4.1原始类型变量的赋值

4.2原始类型带来的擦除

4.3创建泛型数组的陷阱

5.正则表达式陷阱

5.1String类的一些方法支持正则表达式

6.多线程的陷阱

6.1不要调用 RUN 方法

开启线程是用 start() 方法,而不是 run() 方法。

6.2静态的同步方法

对于同步代码块而言,程序必须显式为它指定同步监视器;对于同步非静态方法而言,该方法的同步监视器是 this —— 即调用该方法的 Java 对象;对于静态的同步方法而言,该方法的同步监视器不是 this,而是该类本身。

上一篇 下一篇

猜你喜欢

热点阅读