点击进入我的博客

3.1更简单的打印语句

System.out.println("imbug");

通过编写一个小类库,并通过import static该方法来实现简化打印(基本没啥用)。

public class Print {
    public static void println(String str) {
        System.out.println(str);
    }
}
import static s1.Print.println;

public class Test {
    public static void main(String[] args) {
        println("imbug");
    }
}

3.2 使用Java操作符

  • 操作符接受一个或多个参数,并生成一个新值
  • 有些操作符可能会改变操作数本身的值
  • 几乎所有的操作符都只能操作基本类型===!=能操作所有的对象;String类支持++=操作符

3.3 优先级

运算符优先级表.png

  • 操作符是有优先级的。
  • 个人认为:死记硬背操作符的优先级除了应付大学考试和智障笔试题之外,并无卵用~只要理解了运算符的原理再来看优先级有易如反掌了~
  • 如果有人写这样的代码请打死他System.out.println(a<<=b+=c>>=5);
  • System.out.println()中的+运算符可能会表示字符串拼接,还有可能进行字符串转换。

3.4 赋值

赋值=的意思是取右边的值把它复制给左边。
左边的值必须是明确的、已命名的变量。
右值可以是任何常熟、变量或者表达式(只要它能生成一个值)。
基本类型传递的是值,对象类型传递的是引用。

3.5 算术操作符

+-*/%
/:整数的除法会直接干掉小数位而不是四舍五入
+-:还可以用作正负号

3.6 自动递增和递减

++--
前缀式:++a先执行运算再生成值,即++a == a is true
后缀式:a++先生成值再执行运算,即a == a++ is true

3.7 关系运算符

><>=<=!===

  • 关系操作符生成的是一个boolean的结果。
  • 大于小于大于等于小于等于不适用于boolean类型
  • 等于不等于适应于全部基本数据类型对象类型
  • 等于不等于作用于对象类型时比较的是引用(我更倾向于用C++中的地址来理解这个概念)
  • 对基本数据类型的包装类、StringBigIntegerBigDecimalequals方法比较的是值
  • 如果你自己的class没有重写equals方法,那么equals方法使用的是Objectequals方法,即比较引用。

数值的包装类

    Integer x1 = new Integer(10);
    Integer x2 = new Integer(10);
    System.out.println("x1 == x2: " + (x1 == x2));
    System.out.println("x1.equals(x2): " + x1.equals(x2));
    // x1 == x2: false
    // x1.equals(x2): true
    Integer y1 = 10;
    Integer y2 = 10;
    System.out.println("y1 == y2: " + (y1 == y2));
    System.out.println("y1.equals(y2): " + y1.equals(y2));
    // y1 == y2: true
    // y1.equals(y2): true
    Integer z1 = 1000;
    Integer z2 = 1000;
    System.out.println("z1 == z2: " + (z1 == z2));
    System.out.println("z1.equals(z2): " + z1.equals(z2));
    //z1 == z2: false
    //z1.equals(z2): true

上述代码的.class文件反编译后的代码

    Integer x1 = new Integer(10);
    Integer x2 = new Integer(10);
    System.out.println((new StringBuilder()).append("x1 == x2: ").append(x1 == x2).toString());
    System.out.println((new StringBuilder()).append("x1.equals(x2): ").append(x1.equals(x2)).toString());
    Integer y1 = Integer.valueOf(10);
    Integer y2 = Integer.valueOf(10);
    System.out.println((new StringBuilder()).append("y1 == y2: ").append(y1 == y2).toString());
    System.out.println((new StringBuilder()).append("y1.equals(y2): ").append(y1.equals(y2)).toString());
    Integer z1 = Integer.valueOf(1000);
    Integer z2 = Integer.valueOf(1000);
    System.out.println((new StringBuilder()).append("z1 == z2: ").append(z1 == z2).toString());
    System.out.println((new StringBuilder()).append("z1.equals(z2): ").append(z1.equals(z2)).toString());
通过new Integer新建对象
  • new Integer每次都会新建对象,所以==的结果为false
自动装箱与拆箱
  • 自动装箱:用赋值运算符=把一个数值或基本类型变量赋值给一个包装类变量(Integer y1 = 10)。装箱调用的是Integer.valueOf(10)方法。
  • 自动拆箱:用赋值运算符=把一个包装类赋值给一个基本类型变量(int y3 = y1),或者是在包装类进行数值运算时。拆箱调用的是Integer#intValue()方法。
  • 装箱方法的坑(笔面试题):下面是Integer.valueOf(int i)的源代码。可以看出当装箱的数值在-128到127之间是,返回的对象是IntegerCache中提前new出来的对象,所以y1 == y2的结果是true;当装箱的数值超出该范围,则返回的是new出来的对象,所以z1 == z2的结果为false
  • 其他的装箱方法:ByteShortIntegerLong的范围都是[-128,127];Character的范围是[0,127];FloatDouble全部是new出来的新对象;Boolean都是预定义好的truefalse。有趣的是,这些代码作者是一样的,但写法各不相同。
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
备注内容:可以从https://varaneckas.com/jad/下...;或者可用从http://jd.benow.ca/下载反编译...

3.8 逻辑操作符

&&||!

  • 逻辑运算符只能根据两个布尔值参数的逻辑关系,生成一个布尔值。
布尔值短路
  • 即一旦能够明确无误地确定整个表达式的值,就不再计算表达式剩余的部分了
  • &&:遇到第一个false则不执行后边的代码
  • ||:遇到第一个true则不执行后边的代码
    public static boolean func1() {
        System.out.println("func1");
        return true;
    }

    public static boolean func2() {
        System.out.println("func2");
        return false;
    }

    public static boolean func3() {
        System.out.println("func3");
        return true;
    }
    if(func1() && func2() && func3());  // 不执行func3中的内容
    if(func1() || func2() || func3());  // 不执行func2和fanc3中的内容
  • 面试题:如何不使用条件语句控制流程。
    // 不使用if来控制该流程
    if(func1()) {
        func2();
    }
    // 方法
    boolean var = func1() && func2();

3.9 直接常量

  • 前缀0x0X:表示16进制数字
  • 前缀0:表示8进制数字
  • 后缀lL:表示long类型。在写代码的时候,由于小写的l容易和数字1混淆,所以各种规范中都不建议(禁止)使用小写的l表示长整数。最简单就全部用大写就好了!
  • 后缀fF:表示float类型。
  • 后缀dD:表示double类型。
  • eE:指数计数,表示10的幂

3.10 按位操作符

&|^
&=|=^=

  • boolean:可以把boolean值看成单比特值对待,&|^的操作相同,但是不能用于布尔值

3.11 移位操作符

<<:高位(包括符号位)舍弃,低位补零。
>>:有符号右移运算,若高位是1,则高位补1;若高位是0,则高位补0。
>>>:无符号右移,最高位补0。

  • 移位操作符只能用来处理整数类型。
  • charbyteshort进行移位操作时,会先被转成int类型,并且结果也是int类型
  • long类型移位还是long

<<=>>=>>>=

  • 注意:在对byteshort进行>>>=无符号右移等于运算时,整个流程是先向上转化成int——进行移位运算——向下转化(强制截取)成byteshort,所以会导致移位后对结果不正确。
    short s = -1;
    System.out.println(Integer.toBinaryString(s));
    // 11111111111111111111111111111111
    System.out.println(Integer.toBinaryString(s >>> 10));
    // 1111111111111111111111
    s >>>= 10;
    System.out.println(Integer.toBinaryString(s));
    // 11111111111111111111111111111111

3.12 三目运算符

boolean-exp ? val1 : val2

3.13 字符串运算符

++=

3.14 操作符常犯错误

  • Java中ifwhile语句必须使用boolean值,所以不会出现==被写成=的问题;除非是两个boolean
  • Java编译器也能够防止逻辑与或(&&||)和按位与或(&|)的问题,除非是两个boolean

3.15 类型转换操作符

  • 既可以对数值进行转换,也可以对数值变量进行转化
  • 向下转化必须要强制转化,否则编译失败(移位等于、算数等于时不会)
  • 向上转化不必显示进行转化
  • 布尔值之外,其他类型都可以互相转化
  • 浮点数转成整数值的时候直接截尾,不会进行四舍五入
  • 表达式的最大数据类型决定了表达式的数据类型

3.16 没有sizeof

Java所有基本数据类型的size是确定的,所以不需要sizeof

3.17 操作符小结

  • charbyteshort在使用算术操作符和移位操作符的时候都会被转成int,必须显示类型转换回原来的类型。以下注释掉的都是编译错误的。
    short s1 = 10;
    short s2 = 10;
    // short s3 = s1 + s2;
    // short s4 = s1 >> 1;
  • charbyteshort在进行复合赋值运算(移位等于、算数等于)时不需要强制转化。
  • int类型要小心结果溢出
  • boolean外,任何基本类型都可以通过类型转换变成其他基本类型
  • 必须留意向下转化的的结果,因为可能存在丢失信息的可能性

卢卡斯哔哔哔
46 声望6 粉丝