乐趣区

Thinking-in-Java操作符

3. 操作符

3.1 静态导入

  • 静态导入:方法中调用静态导入的其他类中的静态方法

<!– 类和静态方法 –>

package com.one;
public class Print {public static void print(String s){System.out.println(s);
    }
}

<!– 测试静态导入的方法 –>

package com.one;
// 静态导入方法
import static com.one.Print.*;
public class TestPrint {public static void main(String[] args) {System.out.println("Nomal Print");
        // 静态导入的方法输出
        print("Simple Print");
    }
}

3.2 使用 Java 操作符

  • 副作用:操作符改变操作数本身的值 <!– 比如 ++、– 这类操作符 ——>

String 类支持 ”+” 和 ”+=”

3.3 优先级

  • 优先级顺序

    • 先乘除后加减
    • 用括号明确计算顺序

3.4 赋值

  • 赋值:使用操作符 ”=”
  • 赋值分类

    • 基本类型赋值:直接将内容复制到另一个地方
    • 对象类型赋值:将“引用”从一个地方复制到另一个地方(一个对象对应多个引用,一个引用可能有 0 或 1 个对象),类似指针,由于原来的指针指向新的对象,所以原来的对象将被垃圾回收器清理,具体可见以下实现

      class Tank{int level;}
      public class Assignment{public static void main(String[] args){
          // 赋值前
          Tank t1 = new Tank();
          Tank t2 = new Tank();
          t1.level = 9;
          t2.level = 47;
          print(t1+","+t2);
          // 第一次赋值
          t1 = t2; 
          print(t1+","+t2);
          // 第二次赋值
          t1.level = 22;
          print(t1+","+t2);
        }
      }
      /*
      output:
      9,47
      47,47
      22,22
      */
  • 别名现象解析

    • 代码片段(见赋值分类的对象类型赋值)
    • 原理分析

      • 第一次赋值是将 t2 的指向修改为与 t1 一致,同时指向同一个对象,因为 t1 和 t2 都是引用
      • 第二次赋值是将 t1 和 t2 指向的同一个对象中的 level 值修改了

3.5 算术操作符

  • 操作符种类

    • 加号 +、减号 -、除号 /、乘号 *,取模 %
    • 整数除法会直接去掉结果的小数位,不会四舍五入
  • Random 方法

    • Random 为生成伪随机数的类,使用 nextInt()/nextFloat()方法获取随机数
    • 产生随机小写字母的方法:Random.nextInt(26)+’a’
    • 如果种子参数相同,则生成的随机数也相同,见下方

      package com.four;
      import java.util.Random;
      public class TestRandom {public static void main(String[] args) {
                      // 种子数相同      
              Random random1 = new Random(10);
              Random random2 = new Random(10);
              int i = random1.nextInt();
              int j = random2.nextInt();
              System.out.println("i="+i);
              System.out.println("j="+j);
          }
      }
      /* output:
      i=-1157793070
      j=-1157793070
      */

3.5.2 一元加、减操作符

  • 一元减号:转变数据的符号,或修改数据类型
  • 一元加号:将数据类型修改为 int 类型 <!– 比如原类型为 char,添加加号输出后,结果是对应的 ASCII 码的值 –>

    package com.four;
    public class TestAdd {public static void main(String[] args) {
            int i = 1;
            char j = 'c';
            short k = 5;
            System.out.println(i);
            System.out.println(j);
            System.out.println(k);
            System.out.println("添加加号");
            System.out.println(+i);
            System.out.println(+j);
            System.out.println(+k);
            System.out.println("添加减号");
            System.out.println(-i);
            System.out.println(-j);
            System.out.println(-k);
        }
    }
    /* output
    1
    c
    5
    添加加号
    1
    99
    5
    添加减号
    -1
    -99
    -5
    */
    // /Users/toyz/Package/Note/Thinking in Java/Practice/Operators/src/com/four/TestAdd.java

3.6 自动递增和递减

  • 分类

    • 前缀递增、前缀递减:先执行运算,后生成值
    • 后缀递增、后缀递减:先生成值,后执行运算

      <!– 测试代码如下 –>

      package com.four;
      import static util.Print.*;
      public class TestIncreasing {public static void main(String[] args) {
              int i = 1;
              int j = i;
              print("i ="+i);
              // 前缀递增
              j = ++i;
              print("前缀递增后");
              print("i ="+i);
              print("j ="+j);
              i = 1;
              j = i;
              // 前缀递减
              j = --i;
              print("前缀递减后");
              print("i ="+i);
              print("j ="+j);
              i = 1;
              j = i;
              // 后缀递增
              j = i++;
              print("后缀递增后");
              print("i ="+i);
              print("j ="+j);
              i = 1;
              j = i;
              // 后缀递减
              j = i--;
              print("后缀递减后");
              print("i ="+i);
              print("j ="+j);
              i = 1;
              j = i;
          }
      }
      /* output
      i = 1
      前缀递增后
      i = 2
      j = 2
      前缀递减后
      i = 0
      j = 0
      后缀递增后
      i = 2
      j = 1
      后缀递减后
      i = 0
      j = 1
      */
      // /Users/toyz/Package/Note/Thinking in Java/Practice/Operators/src/com/four/TestIncreasing.java

3.7 关系操作符

  • 分类

    • 大于、小于、大于等于、小于等于、等于(==)、不等于(!=)
    • 等于和不等于适用所有基本数据类型,其他比较符不使用 boolean 类型

3.7.1 对象的等价性

  • == 和!= 比较的是对象的引用 <!– 即使对象的内容相同,两个对象的引用也不同 –>

    package com.five;
    
    public class TestEquals {public static void main(String[] args) {
            // 使用 == 比较 基本数据类的相同内容的不同对象
            Integer n1 = new Integer(47);
            Integer n2 = new Integer(47);
            System.out.print("使用 == 比较 相同内容的不同对象:");
            System.out.println(n1 == n2);
    
            // 使用 equals 比较 基本数据类的相同内容的不同对象
            System.out.print("使用 equals 比较 相同内容的不同对象:");
            System.out.println(n1.equals(n2));
    
            // 使用 == 比较 自定义类的相同内容的不同对象
            Dog dog1 = new Dog();
            dog1.setName("spot");
            dog1.setSays("Ruff!");
            Dog dog2 = new Dog();
            dog2.setName("spot");
            dog2.setSays("Ruff!");
            System.out.print("使用 == 比较 自定义类的相同内容的不同对象:");
            System.out.println(dog1 == dog2);
    
            // 使用 equals 比较 自定义类的相同内容的不同对象
            System.out.print("使用 equals 比较 相同内容的不同对象:");
            System.out.println(dog1.equals(dog2));
        }
    }
    /* output
    使用 == 比较 相同内容的不同对象:false
    使用 equals 比较 相同内容的不同对象:true
    使用 == 比较 自定义类的相同内容的不同对象:false
    使用 equals 比较 相同内容的不同对象:false
    */
    // /Users/toyz/Package/Note/Thinking in Java/Practice/Operators/src/com/five/TestEquals.java
  • 总结

    • == 对于基本数据类型,是比较值;对于引用数据类型,是比较地址
    • equals 对于引用的基本数据类型的比较生效,适合比较对象内容,而非比较对象的引用 <!–default–>

3.8 逻辑操作符

  • 分类

    • 与(&&)、或(||)、非(!)
    • 以上三种只能应用于布尔值
    • 在 String 值的地方使用布尔值,布尔值会自动转换成适当的文本

3.8.1 短路

  • 定义:当能够确定一个表达式的值,就不计算余下的部分
  • 演示过程:当判断到 (j<2) 时为 false 时,程序不会执行后续判断,直接输出 false

    package com.seven;
    import static util.Print.*;
    public class ShortCircuit {public static void main(String[] args) {
            int i = 1;
            int j = 2;
            int k = 3;
            print("res:"+((i<2)&&(j<2)&&(k<2)));
        }
    }    

3.9 直接常量

直接常量的后缀字符标注了类型

  • 常用类型

    • L 代表 long
    • F 代表 Float
    • D 代表 Double
    • 十六进制数字:以前缀 0x,后面跟随 0~9 或小写的 a~f 来表示
    • 八进制数字:以前缀 0,后面跟随 0~7 数字来表示

3.9.1 指数计数法

程序设计时使用 e 代表“10 的幂次”,但是在科学和工程领域,e 代表自然对数的基数

3.10 按位操作符

  • 运算方式

    • &、|、^、~
    • 与、或、异或、取反
    • 异或:相同则为零,不同则为 1 <!– 比如两个开关控制一个灯,1 为开,0 为关。当两个开关都为关,则关,两个开关都为开则关,两个开关一个开则为开 –>
  • 运算规则

    1. &: 1&1=1 , 1&0=0 , 0&1=0 , 0&0=0
    2. |: 1|1=1 , 1|0=1 , 0|1=1 , 0|0=0
    3. ^: 1^1=0 , 1^0=1 , 0^1=1 , 0^0=1
    4. ~: ~1=0 , ~0=1
  • 进制运算

    1. 二进制转为十六进制:小数点左边向左开始,右边向右开始,各取 4 位,不足的向左(向右)补零

      1. 二进制:010101 —— 十六进制:15
      2. 第一步:二进制分为:01,0101
      3. 第二步:补全:0001,0101
      4. 第三步:0001 为 1,0101 为 5(计算的时候要把顺序倒过来,0101 看成 1010 计算)
  • 使用二进制表示负数

    1. 获得原码:00101111
    2. 获得反码:11010000
    3. 获得补码(反码加一):11010001

      <!– 原码末尾为零,反码加一需要向前进位 –>

3.11 移位操作符

  • 左移操作符(<<): 操作数向左移动,低位补零
  • 右移操作符(>>):操作数向右移动,当符号为正,高位补零;当符号为负,高位补 1
  • 无符号右移操作符(>>>):无论正负,都在高位插入零

byte 和 short 类型使用位移运算时,会先转换成 int 类

3.12 三元操作符

  • if-else 操作符,形式为 boolean-eep ? value1 : value2

    当结果为 true 时,就计算 value1;当结果为 false,就计算 value2

  • 使用时需要注意可读性

3.13 字符串操作符 + 和 +=

  • 需要考虑计算的优先级
package com.thirteen;

import static util.Print.*;

public class PrintString {public static void main(String[] args) {
        int x = 0 , y = 1 , z = 2;
        String s = "x,y,z";
        System.out.println(s+x+y+z);
        System.out.println(s+(x+y+z));
        System.out.println(x+y+z+s);
        System.out.println(x+""+s);
        System.out.println(""+x);
        System.out.println(x+y+z);
    }
}/* output
x,y,z012
x,y,z3
3x,y,z
0x,y,z
0
3
*/

3.15 类型转换操作符

  • 窄化转换:将能容纳更多信息的数据类型转化成无法容纳这么多信息的数据类型,存在风险
  • 扩展转换:新类型能够容纳更多信息,安全,不会造成任何信息的丢失

Java 允许将任何基本数据类型转换成别的基本数据类型,但布尔类型不允许任何转换

“类”数据类型不允许类型转换,除非使用特殊方法

3.15.1 截尾和舍入

  • 截尾

    1. float 和 double 转换成整型
  • 舍入

    1. 使用 java.lang.Math 中的 round()方法

3.15.2 提升

表达式中的最大数据类型决定了表达式最终结果的数据类型 <!– 比如,double 乘以 float,结果为 double–>

3.16 Java 没有 sizeof

所有数据类型在所有机器中的大小都是相同的

退出移动版