并不简单的Java操作符

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

     操作符接受一个或多个参数,并生成一个新值。有些操作符可能会改变操作数自身的值,这被称为“副作用”(因为在产生新值的同时自己也被改变了),除了“=”、“==”和“!=”能操作所有的对象外,其他操作符只能操作“基本类型”。

    一、赋值操作符-------“=”

赋值的意思就是把右边的值复制给左边,右边的值可以是任何常数、变量或者表达式,但左边的值必须是一个明确的已命名的变量,也就是说必须有一个物理空间可以存储等号右边的值。但是不能把任何东西赋给一个常数,常数不能在左边例如  0=a 是错误的,赋值可以划分为两种情况:

1.基本数据类型赋值

   基本类型存储了实际的数值,而并非指向一个对象的引用,所以在为其赋值的时候,是直接将一个地方的内容复制到了另一个地方。例如 a=b,那么b的内容就复制给a,若接着又修改了a,而b根本不会这种修改的影响

2.对象的赋值

  对一个对象进行操作时,我们真正操作的是对对象的引用,所以将一个对象赋值给另一个对象,实际是将引用从一个对象赋值给另一个对象,实际将引用从一个地方复制到另一个地方。如果对对象使用c=d,那么都指向原本只有d指向的那个对象。

通过下面这个例子可以说明这个问题

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;
    System.out.println("1: t1.level: " + t1.level +
          ", t2.level: " + t2.level);
    t1 = t2;
    System.out.println("2: t1.level: " + t1.level +
          ", t2.level: " + t2.level);
    t1.level = 27;
    System.out.println("3: t1.level: " + t1.level +
          ", t2.level: " + t2.level);
  }
}
程序输出的结果是

1: t1.level: 9, t2.level: 47
2: t1.level: 47, t2.level: 47
3: t1.level: 27, t2.level: 27

在这个程序中,创建了两个Tank类的实例,并对每个实例的level赋予了不同的值,然后将t2赋给t1,接着又修改了t1,但由于赋值操作的是一个对象的引用,所以修改t1的同时也修改了t2! 这是由于t1和t2包含的是相同的引用,他们指向相同的对象(原本t1包含的对对象的引用,是指向一个值9的对象。在对t1赋值的时候,这个引用被覆盖,也就是丢失了,而那个不再被引用的对象由“垃圾回收器”自动清理)

这种特殊的现象通常称作“别名现象”,是Java操作对象的一种基本方式。

3.方法调用中的别名问题

其实在方法中也会产生这种别名现象

class Letter {
  char c;
}

public class PassObject {
  static void f(Letter y) {
    y.c = 'z';
  }
  public static void main(String[] args) {
    Letter x = new Letter();
    x.c = 'a';
    System.out.println("1: x.c: " + x.c);
    f(x);
    System.out.println("2: x.c: " + x.c);
  }
}

这个程序中的运行结果是

1: x.c: a
2: x.c: z

二、关系运算符

主要讲一下==和!=以及equals方法。

先看一个程序

public class Equivalence {
  public static void main(String[] args) {
    Integer n1 = new Integer(47);
    Integer n2 = new Integer(47);
    System.out.println(n1 == n2);
    System.out.println(n1 != n2);
  }
}
的输出结果是

false

true

尽管两个对象的内容相同,但是==和!=比较的是对象的引用,两个对象的引用是不同的,所以一个输出false一个输出true,如果想要比较对象的值就得需要用equals方法,但是这个方法不适合基本类型数据的比较,基本类型还是用==和!=来比较。

public class EqualsMethod {
  public static void main(String[] args) {
    Integer n1 = new Integer(47);
    Integer n2 = new Integer(47);
    System.out.println(n1.equals(n2));
  }
}
这个程序的输出结果就是true,因为比较的是对象的值而不是对象的引用,因此值相等就输出true。

但是并不是所有的equals方法都管用,就像下面这个例子

class Value {
  int i;
}

public class EqualsMethod2 {
  public static void main(String[] args) {
    Value v1 = new Value();
    Value v2 = new Value();
    v1.i = v2.i = 100;
    System.out.println(v1.equals(v2));
  }
}
这个程序的输出结果是false,可能会令你大吃一惊,这是由于equals的默认行为是比较引用,所以除非在自己的新类中覆盖equals()方法,否则不可能表现出我们希望的行为。大多数的java类库都实现了equals()方法,以便用来比较对象的内容,而非比较对象的引用。

三、位运算

位运算符的细节

 

 <<

空位补0,被移除的高位丢弃,空缺位补0。

>>

被移位的二进制最高位是0,右移后,空缺位补0;

最高位是1,空缺位补1。

>>>

被移位二进制最高位无论是0或者是1,空缺位都用0补。

&

二进制位进行&运算,只有1&1时结果是1,否则是0;

|

二进制位进行 | 运算,只有0 | 0时结果是0,否则是1;

^

相同二进制位进行 ^ 运算,结果是0;1^1=0 , 0^0=0

不相同二进制位 ^ 运算结果是1。1^0=1 , 0^1=1

 

&&(短路与):当左边为假时,右边不参加运算

 

&(单与)两边都运算不论结果咋样(|||也是同样的道理)

移位运算

向左移动几位就是该数乘以2的几次幂

 

向右移动几位就是该数除以2的几次幂

 

移位运算比普通的运算要简单方便,局限性只能对2的次幂进行运算

 

>>>无符号右移,无论高位是什么都用0补位

位运算的用途

用途:

1.&运算获取某个字段内的二进制最后几位数是啥

2.如果取中间的某一段则先将其后面的通过>>>运算将其舍掉

3.一个数抑或另外一个数两次后结果还是这个数(加密运算可以用)

四、类型转换
• 自动类型转换(也叫隐式类型转换)  
• 强制类型转换(也叫显式类型转换) 
• 类型转换的原理 
• 什么时候要用强制类型转换?
• 表达式的数据类型自动提升
• 所有的byte型、short型和char的值将被提升到int型。
• 如果一个操作数是long型,计算结果就是long型;
• 如果一个操作数是float型,计算结果就是float型;
• 如果一个操作数是double型,计算结果就是double型。

• 自动类型提升
byte b = 3;
int x = 4;
x = x + b;//b会自动提升为int类型进行运算。
• 强制类型转换
byte b = 3;
b = b + 4;//报错
b = (byte)(b+4);//强制类型转换,强制将b+4的结果转换为byte类型,再赋值给b。
本片博文就是挑选了一些重要的运算符给大家讲讲,谢谢大家的阅读!

你可能感兴趣的:(java,运算符)