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);
     
    }
一般我们习惯用==比较,相信很多人一看到这段代码,就会感觉输出的结果是true,true;实际上这段代码的输出结果是true,false;这是为什么呢?同样的对象为什么比较的结果不一样呢?
先来分析下Integer a=1;的实现方式,1是数字是怎么放到Integer这个对象中去的;我们知道这是JDK5新增的语法自动装箱和拆箱功能实现的,可是具体的这个装箱功能室如何实现的呢?我们先来看下Integer.valueOf()这个方法,因为这是Integer默认的装箱的实现方式:
public static Integer valueOf(int i) {
       if(i >= -128 && i <= IntegerCache.high)
           return IntegerCache.cache[i + 128];
       else
           return new Integer(i);
   }
这是JDK5的时候新增的方法,先来简单分析下这个方法具体做了什么事情;原来她内部维护了一个缓存池,它总是Integer缓存池中获取Integer对象,超出了其缓存池缓存池(-128到127),它才new新的Integer对象。只要在这个范围内,都是直接取出对象而不是创建,所以值总是相等的,但是如果超过了这个范围,那么它就会穿件新的对象(-2147483648到-128和127到2147483647)(Integer.MAX_VALUE:2147483647,Integer.MIN_VALUE:-2147483648),一旦是创建的对象,那么比较的是对象自然是不相等,即使值是相等的。
 
所以比较Integer要用a.intValue()==b.intValue()
或者用equals()方法,因为equals方法是用值去比较的,永远相等;
public boolean equals(Object obj) {
 if (obj instanceof Integer) {
     return value == ((Integer)obj).intValue();
 }
 return false;
 }
 
 
2.空指针
null.get()或者null.set()都是空指针
解决方法:

每次拿到一个变量值,都判空:非空一个逻辑;空一个逻辑即可

 

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 }
View Code

 

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 线程安全

posted @ 2018-11-29 19:39  点点积累  阅读(1084)  评论(0编辑  收藏  举报