操作符

作者: 牙锅子 | 来源:发表于2016-10-16 11:30 被阅读19次

    Java 的数据是通过操作符来操作的。几乎所有操作符都只能操作“基本类型”,但“=”、“==“和”!=“能操作所有对象。String支持”+“和”+=“。

    操作符具有优先级,但建议使用括号明确规定计算顺序。

    public static void main(String[] args) {
       int a = 1;
       int b = 2;
       String str = "123";
       //当一个String类型后紧跟一个非String类型,系统会尝试将非String类型转为String类型
       System.out.println(a + b);
       System.out.println(a + b + str);
       System.out.println(a + str + b);
    }
    

    赋值使用操作符”=“。将右值赋给左值,右值可以为任意常数、变量、表达式(能生成值),左值必须为已命名的变量(已声明为final类型的在某些情况下不行)。

    基本类型的赋值是直接赋值,对象的赋值只是赋值了引用。对于方法中传参也符合这个规则,当然 String 是个特例,你可以把它看成是 char 的包装类就容易理解了。

    public static void main(String[] args) {
       int a = 1;
       int b = 2;
       System.out.println("a=" + a + ";b=" + b);
       a = b;
       System.out.println("将b的值赋给a后,a=" + a + ";b=" + b);
       a = 3;
       System.out.println("修改赋值后的a,b值并未受影响,a=" + a + ";b=" + b);
       Person person1 = new Person(1);
       Person person2 = new Person(10);
       System.out.println("person1=" + person1.toString() + ";person2=" + person2);
       //将person2赋值给person1,person1的之前的引用不再被引用,过一段时间就会被垃圾回收器回收
       person1 = person2;
       System.out.println("将person2的引用赋值给person1,person1=" + person1.toString() + ";person2=" + person2);
       //修改person1的数据将影响person2,因为两者的引用指向同一个对象
       person1.setAge(100);
       System.out.println("修改person1的age将影响person2的age,person1=" + person1.toString() + ";person2=" + person2);
    }
    
    public static class Person {
       private int age;
    
       public Person(int age) {
           this.age = age;
       }
    
       public int getAge() {
           return age;
       }
    
       public void setAge(int age) {
           this.age = age;
       }
    
       @Override
       public String toString() {
           return "Person{" +
                   "age=" + age +
                   '}';
       }
    }
    

    输出如下:

    a=1;b=2
    将b的值赋给a后,a=2;b=2
    修改赋值后的a,b值并未受影响,a=3;b=2
    person1=Person{age=1};person2=Person{age=10}
    将person2的引用赋值给person1,person1=Person{age=10};person2=Person{age=10}
    修改person1的age将影响person2的age,person1=Person{age=100};person2=Person{age=100}
    

    ++:称为自动递增操作符
    --:称为自动递减操作符
    ++i称为前缀式,i++称为后缀式。前缀式先生成值再运算,后缀式先运算再生成值。

    ">"、"<"、">="、"<="、"=="、"!="是关系操作符。表达式为真则返回true,为假返回false。

    其中 boolean 类型只适用"=="和"!="。

    补充:”==“和”!=“用于比较对象的引用是否相等。重写 Object 类的 equals() 方法即可比较对象的值是否相等,但是 equals() 方法默认也是比较对象的引用。

    逻辑操作符

    ”与(&&)“、”或(||)“、”非(!)“根据参数的逻辑关系生成一个布尔值。且只能应用于布尔值的表达式。”与(&&)“和”或(||)“具有”短路“现象。一旦能准确无误的判断表达式的值,就不再计算余下部分。

    直接常量

    L(l):long
    F(f):float
    D(d):double
    0x(0X):十六进制,0-9、a-f
    0:八进制,0-7

    在 Java 中,可以调用 Integer 或者 Long 中相应的方法,将十进制数转化为二进制、八进制或者十六进制。

    public static void main(String[] args) {
       int a = 16;
       //二进制
       System.out.println("Binary="+Integer.toBinaryString(a));
       //八进制
       System.out.println("Octal="+Integer.toOctalString(a));
       //十六进制
       System.out.println("Hex="+Integer.toHexString(a));
    }
    

    位运算符

    位运算符有如下几种:


    77c6a7efce1b9d1688c4b844f1deb48f8
    • 按位与”&“:只有对应的两个二进位均为1时,结果位才为1 ,否则为0。1&1=1,1&0=0,0&1=0,0&0=0
    • 按位或”|“:只要对应的二个二进位有一个为1时,结果位就为1。1&1=1,1&0=1,0&1=1,0&0=0
    • 按位异或”“:参与运算的两个值,如果两个相应位相同,则结果为0,否则为1。00=0,10=1,01=1,1^1=0。按位异或可以实现两个数的交换,而不必借助临时变量。
    • 取反”“:1=0,~0=1
    • 左移”<<“:地位插入0。
    • 右移”>>“:若符号为正,则高位插入0;若符号为负,则高位插入1。
    • 无符号右移“>>>”:无论正负,都在高位插入0。

    以上为操作符,除按位异或“^”外,其余都可与“=”连用。

    验证按位异或”^“可以实现两个数的交换:

    public static void main(String[] args) {
       int a = 16;
       int b = 10;
       System.out.println("异或前,Binary,a=" + Integer.toBinaryString(a) + ";b=" + Integer.toBinaryString(b));
       a = a ^ b;
       b = b ^ a;
       a = a ^ b;
       System.out.println("异或后,Binary,a=" + Integer.toBinaryString(a) + ";b=" + Integer.toBinaryString(b));
    }
    

    输出如下:

    异或前,Binary,a=10000;b=1010
    异或后,Binary,a=1010;b=10000
    

    这里我们来验证下异或运算的效率如何。

    public static final int TIMES = 1000000000;
    
    public static void main(String[] args) {
       exchange1();
       exchange2();
    }
    
    private static void exchange1() {
       long start = System.currentTimeMillis();
       int a = 16;
       int b = 10;
       for (int i = 0; i < TIMES; i++) {
           a = a ^ b;
           b = b ^ a;
           a = a ^ b;
       }
       System.out.println("执行" + TIMES + "次异或操作交换数据要" + (System.currentTimeMillis() - start) + "ms");
    }
    
    private static void exchange2() {
       long start = System.currentTimeMillis();
       int a = 16;
       int b = 10;
       int temp;
       for (int i = 0; i < TIMES; i++) {
           temp = a ;
           a = b;
           b = temp;
       }
       System.out.println("执行" + TIMES + "次使用临时变量交换数据要" + (System.currentTimeMillis() - start) + "ms");
    }
    

    输出如下:

    执行1000000000次异或操作交换数据要1820ms
    执行1000000000次使用临时变量交换数据要4ms
    

    发现使用异或操作实现值得交换竟然没有使用临时变量来的高效。

    三元操作符

    三元操作符的表达式形如:

    //若布尔表达式为真,则计算value1
    //否则,计算value2
    boolean-exp ? value1 : value2
    

    类型转换

    在 Java 中,基本类型的转换有两种方式:

    1. 扩展转换:低精度类型转换成高精度类型,编译器会自动执行,不需要显示申明。如,将 int 转换为 long 类型
    2. 窄化转换:将高精度类型转换为低精度类型,需要显示申明,因为窄化转换会丢失数据。如,将 long 转换为 int 类型。

    Java 中的基本数据类型除 boolean 类型外,都允许类型转换。类也能实现转换,但仅限于同一类。

    WechatIMG34

    截尾和舍入

    Java 中将浮点数转换为 int 或 long ,执行的是截尾操作。如需进行舍入操作,则需要使用 Math.round() 方法。

    public static void main(String[] args) {
       float a = 1.6f;
       System.out.println("(int)a=" + (int) a);
       System.out.println("Math.round(a)=" + Math.round(a));
    }
    

    输出如下:

    (int)a=1
    Math.round(a)=2
    

    以上就是《Java 编程思想》操作符这一章节的读书笔记~

    相关文章

      网友评论

          本文标题:操作符

          本文链接:https://www.haomeiwen.com/subject/yrwoyttx.html