一 i++ 和 ++ i 深入分析
两种方式均为自增,不同点在于 i++ 是在先参与运算后再加1,而++i 则是先加1,再参与运算
示例1
public class Test{
public static void main(String [] args){
int i = 1;
int s = ++i;//先把i+1 然后赋值给了s
int x= i++;//先把i赋值给x,再把i+1
System.out.printLn(i);
System.out.printLn(s);
System.out.printLn(x);
}
}
输出结果为 3,2,2
( i++:是先把i拿出来使用,然后再+1; ++i :是先把i+1,然后再拿出来使用;)
示例2
int i=5; int s=(i++)+(++i)+(i--)+(--i)=24;
输出结果 24
5 = (i++) //i先赋值给左边,i再加1 此时 i = 6
7 = (++i) // i先加1 再赋值给左边 此时 i= 7
7 = (i--) // i先赋值给左边,i再减1 此时 i= 6
5 = (--i) // i先减1 再赋值给左边,此时 i= 5
所以4个算式的结果相加 = 5+7+7+5 = 24
示例3
public class Test{ public static void main(String [] args){ int i = 1; System.out.printLn(i+++i++); System.out.printLn("i="+i); System.out.printLn(i+++++i); System.out.printLn("i="+i); System.out.printLn(i+++i+++i++); System.out.printLn("i="+i); } }
程序运行结果
3
i= 3
8
i= 5
18
i= 8
用括号分割计算即可 如第一个算式
int i = 1; 计算 (i++)+(i++)
int a = (i++); //i 先赋值给 a(此时a=1) i再加1 此时i=2
int b = (i++); //i 先赋值给 b(此时b=2) i再加1 此时i=3
上列算式的和= a+b = 3
示例4
int x = 1,y = 2,z = 3; y+= z--/++x 表达式的值是()
z-- 等于3 此时z = 2;
++x等于2 此时x= 2;
3/2 = 1 (除法运算符,结果向下取整)
y=y+1 = 3;
所以结果为3
二 / 和 %
运算符 / :除法运算符,并且运算结果遵从向下取整。
如 1/2 = 0;4/3 = 1;
运算符 % :模运算(即取余数)
(1)、当运算符左边小于右边,结果就等于左边;
(2)、当运算符左边大于右边,就和算术中的取余是一样的效果
如 1%2 = 1; 2%2 = 0;3%5 = 3;
三 "==",equals 和 hashCode
3.1 理解”==“的含义
主要有两个作用
1、基础数据类型:比较的是他们的值是否相等,比如两个int类型的变量,比较的是变量的值是否一样
2、引用数据类型:比较的是引用的地址是否相同,比如说新建了两个User对象,比较的是两个User的地址是否一样。
3.2 理解 equals() 的含义
如下图 看下 equals()的源码
内部实现是用的 "==", 所以equals()比较的也是引用地址
到这里,好像发现 "=="和equals() 没什么区别,别急,继续往下看
3.3 重写equals()
1、String中equals()方法
从上面我们知道,发现 "=="和equals ()没什么区别,equals()好像没什么意义存在,因为都是比较的引用地址,
不过后来String重写了equals()方法,重写之后,String中的equals()方法其实比较的是字符串的内容是否一样。
2 测试
boolean result = "bba".equals(new String("bba"));
结果为true 比较的值内容
但 boolean result = "bba" == new String("bba");
结果为false ,比较的引用地址("bba"存在常量池中,new String("bba") 这新对象存于堆中)
所以如果编写的类,希望能否比较该类创建的2个对象的内容是否相等,那么可以重写equals()方法,由开发人员来决定在什么情况下即认为2个对象的内容相等
如一个Person 类,是人名字相等代码2个对象内容相等,还是名字+身份证号相等,代表2个对象内容相等,由开发人员在重写equals()方法里决定。
3.4 hashCode()
hashCode()方法是继承自Object类,返回对象在内存中地址转换(hash计算)成的1个int值,用来鉴定2个对象引用是否相等。虽然equals()方法也是用来判断2个对象是否相等的,但它区别于hashCode()。
equals()方法是给用户调用的,判断2个对象是否相等,可以重写equals()方法,hashCode()方法,用户一般不会去调用它。
例如在hashMap中由于key是不可以重复的,在判断重复时就判断了hashCode()这个方法,也用到了equals()方法,
此处不重复,只要equals()和hashCode()有1个不等就可以了。hashcode()更像一个对象的ID编码,它与equals()不同之处在于它返回的是int型,比较起来不直观。
3.5 为什么说,在覆盖equals()方法的同时,要覆盖hashCode()方法?
如果类覆盖了equals()方法,而不覆盖hashCode()方法会导致什么后果,我们实例说明
我们知道hashMap中要求key唯一,如果只覆盖了equals而没有覆盖hashCode, 则两个不同的instance a和b虽然equals结果(业务逻辑上)相等,但却会有不同的hashcode,
把这2个实例对象当做hashMap的key时候,会当做不同的key,这样hashMap里面会同时存在a和b两个key,而实际上我们需要hashMap里面只能保存其中一个,
因为从业务逻辑方向看它们是相等的。
hashCode()和equals()关系如下
1 a.equals(b) 返回true 那么调用a,b两个对象任意一个的hashCode()返回值都一样
2 a.equals(b) 返回false 调用a,b两个对象hashCode()值无要求,可相等可不等
3 调用a,b两个hashCode()值不相等,equals()也不相等
4 调用a,b两个hashCode()值相等,equals()可以不等
其实总结下来就是,equals()等,hashCode必须等,hashCode()等了,不要求equals相等不相等,因为hashCode()是散列算法,是会有概率相等的。