java代码中的坑
1.Integer 类型数值比较:
public
static
void
main(String[] args) {
// TODO Auto-generated method stub
Integer a =
1
;
Integer b =
1
;
Integer c =
2000
;
Integer d =
2000
;
System.out.println(a==b);
System.out.println(c==d);
}
public
static
Integer valueOf(
int
i) {
if
(i >= -
128
&& i <= IntegerCache.high)
return
IntegerCache.cache[i +
128
];
else
return
new
Integer(i);
}
public
boolean
equals(Object obj) {
if
(obj
instanceof
Integer) {
return
value == ((Integer)obj).intValue();
}
return
false
;
}
解决方法:
每次拿到一个变量值,都判空:非空一个逻辑;空一个逻辑即可
3.List list=new ArrayList();
循环的插入
例如list.add(a);
a必须在循环内部new
如果重复插入同一个元素多次,最终只插入一次,相同元素会替换
4.String.split()方法参数需要转译
String[] arr = amtStr.split("\\.");
String[] arr = amtStr.split("\\|");
对于最后存在空值的情况,默认会出现忽略空值,导致分隔后的字段个数有误,解决方法:先用##代替空格,后面再替换
/**
*
* 按照|分割文件一行内容,用"|##|"代替空格||,避免结尾||分割后丢失问题
*
* @param lineData
*/
private String[] splitLineData(String lineData){
while (true) {
lineData = lineData.replaceAll("[|][|]", "|##|");
if (!lineData.contains("||")) break;
}
if (lineData.lastIndexOf("|") == (lineData.length() - 1)) {
lineData = lineData + "##";
}
String[] datas = lineData.split("\\|");
return datas;
}
5.创建目录时尽量用创建多级目录的new File().mkdirs(),不要用new File().mkdir(),避免报错
String path = "D:/bfjTest/BFJ/123/456";
new File(path).mkdirs();
6.JSP页面乱码问题
JSP页面提交到后台的参数中文乱码问题解决:
String objAccountName = request.getParameter("objAccountName");
objAccountName=new String(objAccountName.getBytes("ISO8859-1"),"utf-8");
后台返回JSP页面的中文乱码问题解决:
@RequestMapping(value="/merChgNotice",method = RequestMethod.POST,produces = "application/json;charset=utf-8")
7.BigDecimal
1)BigDecimal字段的累加问题
必须要赋值,否则起不到累加效果。区别于基本类型
failAmt = failAmt.add(jyMcBatDfDl.getDfAmt());
2)BigDecimal比较值大小:
可以通过BigDecimal的compareTo方法来进行比较。
返回的结果是int类型,-1表示小于,0是等于,1是大于。
8.properties属性文件内容中
=左右两边不能有空格,对于密钥等很长的字符串拷贝时不能换行
9.标准的关闭流写法
1 public void processFile(String fName) throws FileNotFoundException, IOException { 2 FileInputStream fis; 3 4 try { 5 fis = new FileInputStream(fName); 6 int sz; 7 byte[] byteArray = new byte[BLOCK_SIZE]; 8 while ((sz = fis.read(byteArray)) != -1) { 9 processBytes(byteArray, sz); 10 } 11 } 12 finally { 13 if (fis != null) { 14 try { 15 fis.close(); 16 } catch (IOException e) { 17 log(e); 18 } 19 } 20 } 21 }
10.报销系统,跟钱相关的比较多,金额字段,格式转换时要注意了
Double转String,直接用toString是科学计数法,超过7位的都是用科学计数法显示字符串的。。。。所以导致20100000.00分转化成String为2.01E7。
解决方法:使用功能强大的BigDecimal
注:跟钱有关的用BigDecimal,不用Double
11.变量要么是引用 ,要么是基础类型
这是对的,变量不是对象。也就是说在下面这个例子里,s不是个对象,也不是字符串,它只是一个字符串的引用。
String s = "Hello";
这个能解释很多的问题,比如: 问题:如果说字符 串是不可变的,为什么我能修改它? s+=“!”
s就变成Hello! 了,
回答:在Java里是不可变的,你改变的只是引用而已。原字符串Hello还存在,只是又多了一个
Hello!字符串,S指向后者而已
12.==比较的是引用,不是内容-----------------这里比较不光是指字符串,int,char,Integer比较也是一样的
让人更混乱的是,有时候用==是能比较内容的。如果你有两个一样的不可变值,JVM会尝试引用 同一个对象 。
String s1 = "Hi", s2 = "Hi";
Integer a = 12, b = 12;
这两个例子中用到了对象池,所以最后引用 的是同样的对象。s1==s2和a==b都是返回true,JVM已经把两个引用 都指向了同一个对象。然而,如果稍微改下代码,JVM没有把对象放到池里的话,==就会返回false,可能会让你意想不到。这个时候你得用equals了。
String s3 = new String(s1);
Integer c = -222, d = -222;
s1 == s2 // is true
s1 == s3 // is false
s1.equals(s3) // is true
a == b // is true
c == d // is false (different objects were created)
c.equals(d) // is true
对于整型来说,对象池缓存的范围是-128到127(还有可能更高)。
13.Java通过传值进行引用传递
所有的变量都是传值,包括引用。这就是说如果你有个变量,它是一个对象的引用,这个引用会被拷贝后再传参,而不是传递的对应的那个对象。
public static void addAWord(StringBuilder sb) {
sb.append(" word");
sb = null;
}
StringBuilder sb = new StringBuilder("first ");
addWord(sb);
addWord(sb);
System.out.println(sb); // prints "first word word"
引用的对象可以改变,不过如果修改拷贝的这个引用,对调用方是没有影响的。
14.Object.toString
toString的默认行为是打印类的的内部名称还有对象的hashCode。 上面已经提到,hashCode并不是内存地址,尽管它是用16进制打印的。同样的,类名,尤其是数组的类名,更容易让人头晕。比如说String[]的名称是[Ljava.lang.String; 这个[表明它是个数组,L说明它是Java语言(Language)创建的类,并不是基础类型比如byte这些,顺便提一下byte内部名称是B。;号标识类的结束。比如你有个这样的数组:
String[] words = { “Hello”, “World” };
System.out.println(words);
输出会是这样:
[Ljava.lang.String;@45ee12a7
很不幸你只知道这是个对象数组。如果你只有一个Object实例words,这样是不够的,你得调用下Arrays.toString(words)。这极其恶劣地破坏了封装的原则,在StackOverflow上面这也是最常见的一类问题。
我问过Oracle的好些个工程师,从他们的反馈感觉,这个问题目前很难解决。
15.字符串操作:toString(),toLowerCase(),toUpperCase()
person.getName().toString()
要判断person.getName()是不是为null,如果是null,转字符串,转大小写会报空指针错
16.字符串连接误用:不要用+拼接,要用 StringBuilder , StringBuffer
String s = ""; for (Person p : persons) { s += ", " + p.getName(); } s = s.substring(2);
StringBuilder sb = new StringBuilder(persons.size() * 16); // well estimated buffer for (Person p : persons) { if (sb.length() > 0) sb.append(", "); sb.append(p.getName); }
StringBuilder错误的写法
StringBuffer sb = new StringBuffer(); sb.append("Name: "); sb.append(name + '\n'); sb.append("!"); ... String s = sb.toString();
问题在第三行,append char比String性能要好,另外就是初始化StringBuffer没有指定size,导致中间append时可能重新调整内部数组大小。如果是JDK1.5最好用StringBuilder取代StringBuffer,除非有线程安全的要求。还有一种方式就是可以直接连接字符串。缺点就是无法初始化时指定长度。
正确的写法:
StringBuilder sb = new StringBuilder(100); sb.append("Name: "); sb.append(name); sb.append("\n!"); String s = sb.toString();
StringBuilder 性能好
StringBuffer 线程安全