天天看点

第3章:操作符

在最底层,java中的数据是通过使用操作符来操作的

  • 操作符优先级:先乘除后加减.
  • 赋值:Test类非常简单,它的两个实例t1和t2.当将t2赋值给t1的时候,接着又修改t1,因为赋值操作的是一个对象的引用,所以修改t1的时候也改变了t2的值.这是由于t1和t2包含的是相同的引用,他们指向相同的对象(原本t1包含的对象的引用,是指向一个值为9的对象.在对t1赋值的时候.这个引用被覆盖,也就是丢失了;会被垃圾回收器自动清理) 这种特殊的现象通常称为”别名现象”,是java操作对象的一种基本方式.在这个例子中想要避免别名问题可以这么写t1.level=t2.level,这样可以保持2个对象的独立性,而不是将t1和t2绑定到相同的对象.
public class Test {
    int level;
    public static void main(String[] args) {
        Test t1 = new Test();
        Test t2 = new Test();
        t1.level = ;
        t2.level = ;
        System.out.println(t1.level + "===" + t2.level);//9===47
        t1=t2;
        System.out.println(t1.level + "===" + t2.level);//47===47
        t1.level=;
        System.out.println(t1.level + "===" + t2.level);//27===27
    }
}
           
  • 自动递增和递减:++a 前缀递增表示操作符位于变量或者表达式的前面 与a++后缀递增操作符位于变量或者表达式的后面.

    前缀递增和递减:会先执行运算,在生成值.

    后缀递增和递减:会先生成值,再执行运算.

public class Test {
    public static void main(String[] args) {
       int i=;
        System.out.println(i);//1
        System.out.println(++i);//2
        System.out.println(i++);//2
        System.out.println(i);//3
        System.out.println(--i);//2
        System.out.println(i--);//2
        System.out.println(i);//1
    }
}
           
  • 关系操作符:

    关系操作符==和!=也适用于所有对象,但这两个操作符比较的是对象的引用.

public static void main(String[] args) {
     Integer n1= new Integer();
     Integer n2= new Integer();
        System.out.println(n1==n2);//false
        System.out.println(n1!=n2);//true
    }
           

如果想要比较两个对象的实际内容是否相同,可以使用equals() 但这个方法不适用于基本类型,基本类型直接使用==或!=即可

public static void main(String[] args) {
     Integer n1= new Integer();
     Integer n2= new Integer();
        System.out.println(n1.equals(n2));//true
    }
           

假设你创建了自己的类,就像下面的结果:事情变得令人费解结果又是false这是由于equals()默认行为是比较引用.所以除非在自己的新类中覆盖equals()方法,否则不可能表现出我们希望的行为

public class Test {
    int i;
    public static void main(String[] args) {
        Test v1 = new Test();
        Test v2 = new Test();
        v1.i = v2.i = ;
        System.out.println(v1.equals(v2));//false
    }
}
           

当覆盖equals()后得到的结果是 true

public class Test {
    int i;

    public static void main(String[] args) {
        Test v1 = new Test();
        Test v2 = new Test();
        v1.i = v2.i = ;
        System.out.println(v1.equals(v2));//true
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Test)) return false;

        Test test = (Test) o;

        return i == test.i;
    }
}
           
  • 逻辑运算符:

    当使用逻辑运算符的时候,我们会遇到一种短路现象.即一旦能够准确无误的确定整个表达式的值,就不会再计算余下的表达式.因此整个表达式靠后的部分有可能不会被计算.

  • 直接常量:如果在程序中使用直接常量,编译器可以准确的知道要生成什么样的类型,但有时候也是模棱两可的.如果发生这种情况必须对编译器加以指导,用与直接常量相关的某些字符来额外增加一些信息.后缀添加标识符L代表long,F代表float,D代表double.
  • 按位操作符:按位操作符用来操作整数,基本数据类型中的单个比特(bit)即二进制位.按位操作符会对两个参数中对应的位执行布尔代数运算,并最终生成一个结果.
  • 类型转换:在执行向下转型(窄化转换)的操作,也就是说将能容纳更多信息的数据类型转换成无法容纳那么多信息类型的时候就面临丢失数据的危险.这时候最好进行显式的转换.在执行向上转型(扩展转换)则不必显式转换.

    在执行窄化转化时,必须要注意截尾与舍入的问题.例如将92.7转换成int变成92,因此将float或double转换成int的时候,总是对该数字执行截尾,如果想要四舍五入.就需要使用java.lang.Math的round()发法.

    提升:如果对基本数据类型执行算数运算或按位运算,大家会发现,只要类型比int小(即char byte或short)那么在运算之前,这些值都会自动转换成int,这样一来生成的结果就是int.如果将一个float和一个double值相乘,结果就是double;将一个int和一个long值相加结果就是long.