• 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 + '
    ');  
    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("
    !");  
    String s = sb.toString();

    StringBuilder 性能好

    StringBuffer 线程安全

  • 相关阅读:
    [转]如何烧录tizen镜像文件?(图文教程)
    [转]如何制作tizen镜像文件(图文教程)?
    [转]如何下载tizen源码(图文教程)?
    [转]如何编译tizen源码(图文教程)?
    uclibc,eglibc,glibc之间的区别和联系
    Create a Bootable MicroSD Card
    [Tizen]Creating a Tizen Platform Image from Scratch through Local Build
    OpenSSL加解密
    [20个项目学会BBC micro:bit编程] 11-模拟舵机控制实验
    【BBC micro:bit基础教程】10-micro:bit操作电位计(滑动变阻器)
  • 原文地址:https://www.cnblogs.com/ngy0217/p/java.html
Copyright © 2020-2023  润新知