一、赋值
赋值使用操作符“=”,它是将右边的值赋值给左边,右值可以是任何的常数、变量、表达式,但左值必须是一个明确、已命名的变量。
1、基本类型赋值和对象赋值的区别
● 基本类型存储了实际的数值,在对其赋值时,是直接将一个地方的内容复制到另外一个地方,如下:
int a = 10, b = 5;
b = a;//a的内容复制给了b,然后修改b,a的值不受影响
System.out.println(a + "==" + b);//10==10
● 对一个对象进行操作时,我们真正操作的是一个对象的引用,如果将一个对象赋值给另外一个对象,实际是将“引用”从一个地方复制到另外一个地方,如下:
class Number {
int a;
}
public class AssignAction1 {
public static void main(String[] args) {
Number num1 = new Number();
Number num2 = new Number();
num1.a = 10;
num2.a = 20;
System.out.println(num1.a + "==" + num2.a);//10==20
num1 = num2;
System.out.println(num1.a + "==" + num2.a);//20==20
System.out.println(num1 == num2);//true,num1和num2都指向原本num2指向的对象
num1.a = 25;
System.out.println(num1.a + "==" + num2.a);//25==25,num1和num2指向的对象相同,所以这里是一样的
}
}
二、自动递增和递减
递增和递减不仅改变了变量的值,并且以变量的值作为生成的结果。递增和递减,通常分为“前缀式和后缀式”,“前缀式”会先执行运算再生成值,“后缀式”是先生成值再执行运算,如下:
public static void main(String[] args) {
int i = 1;
int j = i++;//i先赋值再自增,所以j为1
if (i == (++j) && ((i++) == j)) {//i完成自增为2,j先完成自增再比对也为2,后面i先与j比对之后再完成自增
i += j;//i完成第二次自增为3,j为2
System.out.println("i=" + i);//5
}
}
三、关系操作符
关系操作符生成的是一个布尔结果,它们计算的是操作数的值之间的关系。关系操作符包括:大于(>)、小于(<)、大于等于(>=)、小于等于(<=)、等于(==)、不等于(!=)。其中等于和不等于适用于所有的基本数据类型,而其他比较符不适用于boolean类型。
1、测试对象的等价性
示例1:
public class Example2 {
public static void main(String[] args) {
Integer num1 = new Integer(20);
Integer num2 = new Integer(20);
System.out.println(num1 == num2);//false,它们不是一个对象
System.out.println(num1.equals(num2));//true,它们的值是相等的
int num3 = 20;
Integer num4 = 20;
System.out.println(num1 == num3);//true,比较时先将num1调用intValue方法拆箱成基本数据类型,然后用拆箱后的int类型值和num3进行比较
System.out.println(num1 == num4);//false,比较的是对象引用,一个是创建了新的对象,一个使用的是常量池中的对象
Integer i = 20;
Integer j = 20;
System.out.println(i == j);//true,当没有明确要创建一个对象并且值在-128~127之间时,不会创建新的对象,会直接使用常量池中的Integer对象,所以为true
Integer a = 128;
Integer b = 128;
System.out.println(a == b);//false,值超过128了,常量池中没有要创建新的对象
}
}
示例2:
class Num {
int val;
public Num() {
}
public Num(int val) {
this.val = val;
}
}
public class Example3 {
public static void main(String[] args) {
Num num1 = new Num(20);
Num num2 = new Num(20);
System.out.println(num1.equals(num2));//false,这是由于Num类没有重写equals方法,java默认是比较引用
}
}
四、逻辑操作符中的短路运算
public static void main(String[] args) {
int i = 10, j = 0;
System.out.println(i > 11 & i / j < 0);//非短路运算,报算术异常
System.out.println(i > 11 && i / j < 0);//false
/**
* 短路运算,由于&&代表两个都为true,结果才为true,而i>11已经为false了,结果自然就是false,
* 因而&&后面的内容并没有参与逻辑运算,||是一样的
*/
}
五、直接常量
@Test
public void example1() {
int i = 0xffff;//十六进制
System.out.println(i);//10进制为65535
System.out.println(Integer.toBinaryString(i));//转换为二进制为1111-1111-1111-1111
int j = 0777;//八进制
System.out.println(j);//十进制为0777
System.out.println(Integer.toBinaryString(j));//转换为二进制为111-111-111
float f = 3.15F;//默认为double,如果不加F会报错
long l = Integer.MAX_VALUE + 1L;//和long类型的值进行运算会自动提升类型,所以结果为2147483648
long l2 = 2147483648L;//默认为int,已经超出int的最大范围,如果不加后缀L会报错
}
六、指数计数法
保留两位小数参考:Java保留两位小数的几种写法总结
@Test
public void example2() {
float f = 3.15e2f;
System.out.println(f);//315.0,默认保留一位小数
System.out.println(String.format("%.2f", f));//315.00,.2代表小数点后保留的有效位数
double d = 3.3335e3;
System.out.println(d);//3333.5,默认保留一位小数
BigDecimal decimal = new BigDecimal(d);
BigDecimal decimal1 = decimal.setScale(2);
System.out.println(decimal1);//3333.50,保留两位小数
double d2 = 12345e-4;
System.out.println(d2);//1.2345
}
七、按位操作符
按位操作符用来操作整数基本数据类型中的单个比特,即二进制位,它会对两个参数中对应的位执行布尔代数运算,最终生成一个结果。
@Test
public void example3() {
System.out.println(1 & 1);//1
System.out.println(1 & 0);//0
System.out.println(0 & 0);//0
System.out.println(1 | 1);//1
System.out.println(1 | 0);//1
System.out.println(0 | 0);//0
System.out.println(1 ^ 1);//0
System.out.println(1 ^ 0);//1
}
按位“非 ~“,也称为取反操作符,它属于一个一元操作符,只对一个操作符进行操作(其他的操作符都是二元的)。
System.out.println(10 & 5);//1010 & 0101 结果:0000
System.out.println(10 | 5);//1010 | 0101 结果:1111 ,10进制就是15
System.out.println(10 ^ 6);//1010 ^ 0110 结果:1100 ,10进制就是12
我们可以执行按位的"与"、按位"或"、按位"异或"运算,但不能执行按位"非"的运算。按位操作符也可以进行逻辑运算,只是不具备短路运算的功能。在移位表达式中,不能使用布尔运算。
八、移位操作符
public class Example7 {
@Test
public void example1() {//左移:按照操作符右侧指定的数位将操作符左边的数向左移,在低位补0
int i = 5 << 3; //结果:左边的数*2^右边的数,这里是5*2^3=5*8=40
/**
* 分析:
* 5在二进制中是110
* 110往左移3位就是101000
* 101000在转换成十进制就40
*/
System.out.println(i);//40
}
@Test
public void example2() {//右移:按照操作符右侧指定的数位将操作符左边的数向右移,符号为正在高位插入0,符号为负在高位插入1
int i = 40 >> 3; //结果:左边的数/2^右边的数取模,这里是40/2^3=40/8=5(只限正数)
/**
* 分析:
* 40在二进制中是0010 1000,往右移3位就是0000 0101
* 101在十进制中是5
*/
int k = 1 >> 3; //0
System.out.println(i);//5
System.out.println(k);//0
int n = -1 >> 3;//-1
/**
* 分析:
* 1在二进制中是0000 0001
* -1在二进制中是1的反码+1,即1111 1110 + 1 = 1111 1111
* 1111 1111往右移三位,高位插1,结果还是1111 1111,即-1
*/
int m = -5 >> 5;//5是0000 0101,-5是1111 1011,往右移5位高位插1还是1111 1111,即-1
System.out.println(n);//-1
System.out.println(m);//-1
//注:int其实是32位的,这里偷懒了哈
}
@Test
public void example3() {//无符号右移无论正负,高位都是插0
int i = -1 >>> 3;//-1在二进制中是1111 1111 1111 1111 1111 1111 1111 1111,往右移三位高位插0
System.out.println(i);//536870911 0001 1111 1111 1111 1111 1111 1111 1111
}
@Test
public void example4() {//移位与=组合使用,左边只能是已经赋值的变量
int i = 3;
i <<= 3;
System.out.println(i);//24
}
}
如果对char、byte、short类型的值进行移位处理,那么在移位之前,它们会转换成int类型,并且得到的结果也是一个int类型的值。只有数值右端低5位才有用,这样可以防止我们移位超过int型值所具有的位数。
九、三元操作符
@Test
public void example5() {
int i = 3 > 2 ? 5 : 10;
System.out.println(i);//5
boolean b = false;
int j;
j = b ? 20 : 30;
System.out.println(j);//30
String s = "test";
s = s.equals("001") ? "yes" : "no";
System.out.println(s);//no
}
十、类型转换
@Test
public void example1() {
byte b = 5;
int i = b + 6;
System.out.println(i);//11,byte类型自动提升了
int j = 10;
short s = (short) (j - 6);
System.out.println(s);//4,计算之后将结果强制转换成short,损失精度
float f = 20.7f;
int k = (int) f;
System.out.println(k);//20,将float强制转换成int,对数字进行示截尾
System.out.println(Math.round(f));//21,四舍五入
}