發(fā)現(xiàn)問題
項(xiàng)目里有發(fā)現(xiàn)“神奇”的代碼,先不考慮代碼邏輯以及實(shí)現(xiàn)方法是否合理,原來代碼實(shí)現(xiàn)大致是這樣:
## department 對(duì)象
public class Department{
private Integer departmentId;
private String departmentName;
private Integer pDepartmentId;
private List<user> departmentMember;
## 省略get\set方法
}
## user 對(duì)象
publci class User{
private Integer userId;
private String name;
##所屬部門編號(hào)
private Integer departmentId;
## 省略get/set方法
}
## 組織部門人員信息
## 獲取部門信息
List<Department> departments= departmentService.getAllDepartments();
## 獲取人員信息
List<User> users=userService.getAllUsers();
## 迭代,拼接數(shù)據(jù)
for(Department dep:departments){
for(User user:users){
//坑點(diǎn)
if(user.getDepartmentId() == dep.getDepartmentId()){
if(null == dep.getDepartmentMember() ){
dep.setDepartmentMember(new ArrayList<User>());
}else{
dep.getDepartmentMember().add(user);
}
}
}
}
坑點(diǎn),看到偽碼大概都能知道了,就是Integer的比較,應(yīng)該使用 equals() 或者 轉(zhuǎn)換成 int進(jìn)行比較,但這里隱藏了Java
的一個(gè)特性,使得 == 的運(yùn)行符合預(yù)期,不正常變得正常了?。?!但是“正常”還得結(jié)合特定的數(shù)據(jù),造來:
CREATE TABLE `b_department` (
`department_id` int(11) NOT NULL AUTO_INCREMENT,
`department_name` varchar(50) DEFAULT NULL,
`p_department_id` int(11) DEFAULT NULL,
PRIMARY KEY (`department_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
如果部門數(shù)據(jù)比較少,數(shù)據(jù)庫中的department_id剛好都小于127,程序運(yùn)行的符合預(yù)期?。?! Why???!
在這里:
為了節(jié)省內(nèi)存,對(duì)于下列包裝對(duì)象的兩個(gè)實(shí)例,當(dāng)它們的基本值相同時(shí),他們總是 ‘相等’的
Boolean
Byte
Character, \u0000 - \u007f(7f是十進(jìn)制的127)
Integer, -128 — 127
延伸 :JVM通過參數(shù)調(diào)整包裹對(duì)象緩存大小
使用Oracle/Sun JDK 6,在server模式下,使用-XX:AutoBoxCacheMax=NNN參數(shù)即可將Integer的自動(dòng)緩存區(qū)間設(shè)置為[-128,NNN]
注意: 區(qū)間的下界固定在-128不可配置,在client模式下該參數(shù)無效。
測(cè)試代碼:
public class TestIntegerCache {
public static void main(String[] args) {
Integer a = 1024;
Integer b = 1024;
System.out.println(a == b);
Integer c = 1025;
Integer d = 1025;
System.out.println(c == d);
Integer e = 20000;
Integer f = 20000;
System.out.println(e == f);
}
}
shell >java TestIntegerCache
false
false
false
shell >java -server TestIntegerCache
false
false
false
shell >java -Djava.lang.Integer.IntegerCache.high=1024 TestIntegerCache
true
false
false
shell >java -server -Djava.lang.Integer.IntegerCache.high=1024 TestIntegerCache
true
false
false
shell >java -Djava.lang.Integer.IntegerCache.high=1025 TestIntegerCache
true
true
false
shell >java -server -Djava.lang.Integer.IntegerCache.high=1025 TestIntegerCache
true
true
false
shell >java -XX:AutoBoxCacheMax=1024 TestIntegerCache
Unrecognized VM option 'AutoBoxCacheMax=1024'
Could not create the Java virtual machine.
shell >java -server -XX:AutoBoxCacheMax=1024 TestIntegerCache
true
false
false
shell >java -server -XX:AutoBoxCacheMax=1025 TestIntegerCache
true
true
false
shell >java -server -XX:+AggressiveOpts TestIntegerCache
true
true
true