[案例1】

 public boolean equalNode(JudgeNode a, JudgeNode b) {
return a.getId() == b.getId();
}

【点评】

应在JudgeNode类里定义equals()方法(估计刚从面向过程语言"转行"过来...)。

【案例2】

 public String[] getMsg() {
List<String> msgList = new ArrayList<String>(2);
msgList.add(linkStatus.get(AC)); msgList.add(getLinkMsg());
String[] result = new String[msgList.size()];
msgList.toArray(result);
return result;
}

【点评】

可简化为return new String[]{linkStatus.get(AC), getLinkMsg()};

【案例3】

 private boolean bInteger(Object[][] values, int i) { //开发环境真实代码
boolean b = false;
try {
b = values[0][i] instanceof Integer;
} catch(Exception e) {
logger.error("values[0][i] instanceof Integer error:"+e);
b = false;
}
return b;
}

【点评】

1. instanceof为运算符,不会抛出空指针等异常;从上下文得知,values[0][i]也不会出现越界等异常。

因此,通过instanceof判断类型时无须捕获异常。进一步,bInteger()方法毫无意义,完全可以在调用处直接用instanceof判断。

2. 使用slf4j日志组件时,logger.error(与log.warn)接受Throwable参数,以打印异常名和详细的堆栈信息(可能内部调用e.printStackTrace())。

但书写打印语句时,需要注意格式。例如:

 logger.error("Best print: ", e);
logger.error("Good print: {}", e); //a.
logger.error("Bad print: " + e); //b. 或 + e.toString()
logger.error("Bad print: " + e.getMessage()); //c. 或: {}", e.getMessage())

a句仍可打印异常名和堆栈信息,但多输出一对花括号"{}";b句仅打印异常名;c句打印异常消息字符串。以空指针异常(Runtime异常)为例,b句打印"java.lang.NullPointerException",c句打印"null"(过于简陋)。

【案例4】

 public DBBatch(int count) throws SQLException {
con = ConnnectionManager.getConnection(DBConsts.DB_SOURCE_NAME);
preparedStatement = con.prepareStatement(DBConsts.SQL);
result = preparedStatement.executeQuery();
this.count = count;
}
public void close() { //close result\statement\connection
}

【点评】

应避免在构造函数里申请资源。若构造函数DBBatch(int count)里preparedStatement.executeQuery()发生异常,上面的preparedStatement、con将无法关闭。此时,外部获取不到DBBatch对象引用,也就无法调用DBBatch.close()方法,导致资源泄露。

【案例5】

 private static String listToString(List<String> columnList) {
StringBuilder colName = new StringBuilder(1000); //
for(String s : columnList) {
colName.append(s + ",");
}
colName.deleteCharAt(colName.length() - 1); //
return colName.toString();
}

【点评】

1. StringBuffer的初始容量为16个字节。若待处理的数据远大于16个字节,最好在创建StringBuffer时给出适当的初始容量,以减少不必要的扩容操作(容量不足时会通过Arrays.copyOf创建2倍容量的新数组来装载老数据)。但此处new StringBuilder(1000)初始化指定的长度显然过大,会造成空间浪费。

StringBuilder不同创建方式的初始容量如下:

1) StringBuilder()                  // 默认分配16个字节的空间
2) StringBuilder(int size)   // 默认分配size个字节的空间
3) StringBuilder(String str)  // 默认分配16个字节 + str.length()个字节空间
4) StringBuilder(String str)  // 默认分配16个字节 + str.length()个字节空间
5) StringBuilder(CharSequence charSeq) // 默认分配16个字节 + charSeq.length()个字节空间

    优选方式3,不建议方式4、5(进行字符串拼接时会面临再次扩容的问题)。

相关资料还可参考《浅谈JAVA中HashMap、ArrayList、StringBuilder等的扩容机制》。

2. columnList为空集合时,例如List<String> columnList = Collections.emptyList(),会抛出下标越界异常(StringIndexOutOfBoundsException)。

3. 可用String.join(",", columnList)代替。若期望"[a, b, c, d]"的输出格式,直接用columnList.toString()即可。

【案例6】

 private static boolean checkName1(String name) { //循环10000000次,耗时350ms
List<String> nameList = new ArrayList<String>();
nameList.add("LiLei"); nameList.add("HaMeimei"); nameList.add("HeDan");
nameList.add("Jame"); nameList.add("Lucy"); nameList.add("Beth");
if(nameList.contains(name)) {
return true;
}
return false;
} private static boolean checkName2(String name) { //循环10000000次,耗时1729ms
Set<String> nameSet = new HashSet<String>() {
{ add("LiLei"); add("HaMeimei"); add("HeDan");
add("Jame"); add("Lucy"); add("Beth");
}};
return nameSet.contains(name);
} private static final List<String> NAME_LIST = new ArrayList<String>() {
{ add("LiLei"); add("HaMeimei"); add("HeDan");
add("Jame"); add("Lucy"); add("Beth");
}};
private static boolean checkName3(String name) { //循环10000000次,耗时110ms
return NAME_LIST.contains(name);
} private static final Set<String> NAME_SET = new HashSet<String>() {
{ add("LiLei"); add("HaMeimei"); add("HeDan");
add("Jame"); add("Lucy"); add("Beth");
}};
private static boolean checkName4(String name) { //循环10000000次,耗时52ms
return NAME_SET.contains(name);
} private static boolean checkName5(String name) { //循环10000000次,耗时46ms
return "LiLei".equals(name) || "HaMeimei".equals(name) || "HeDan".equals(name) ||
"Jame".equals(name) || "Lucy".equals(name) || "Beth".equals(name);
}

【点评】

1. 不要使用"if(expression) return true; else return false;"的写法,应改为"return expression;"。

2. List的contains()方法内部调用indexOf()遍历查找整个数组,效率较低。若涉及大规模数据操作,应选用Map等容器。

3. 本案例采用《Java字符串连接的多种实现方法及效率对比》中的计时方法,统计checkName1~5()的执行效率。结果一目了然~

【案例7】

 Map<String, String> apMap = constructApMap();
for(String apId: apMap.keySet()) {
String apType = apMap.get(apId);
... ...

【点评】

建议使用apMap.entrySet遍历Map,而不是keySet+get(实际上遍历两次)。虽然Map get方法"很快",但也不能浪费!

相关资料参见《keySet 与entrySet 遍历HashMap性能差别》。

entrySet简化语法(Java 8函数式编程):

 Map<String, Object> map = new HashMap<>();
map.forEach((key, value)-> {
... ...
});

【案例8】

 private double[] devanningArray(List<Double> origin) {
double[] target = new double[origin.size()];
for(int i = 0; i < origin.size(); ++i) {
target[i] = origin.get(i);
... ...

【点评】

ArrayList随机访问,时间复杂度O(1);LinkedList随机访问,时间复杂度O(n)。

建议:1) 优先for-each,即for(e:list){};2) 若必须随机访问,建议从接口契约上约束,如fun(ArrayList array){}。

附Java容器类的特征概述:

ArrayList封装数组,适用于“读多写少”的场景;
LinkedList双向链表,适用于“写多”的场景,随机访问效率低;
Vector、Stack鸡肋
HashMap、HashTable关联容器,HashTable同步
TreeMap红黑树实现,有序:按逻辑大小排序
LinkedHashMap有序:按插入顺序排序
HashSet、TreeSet、LinkedHashSet封装对应的Map
ConcurrentHashMap
ConcurrentLinkedQueue、ConcurrentLinkedDueue无锁队列,慎用
ArrayBlockingQueue、LinkedBlockingQueue 阻塞队列
CopyOnWriteArrayList、CopyOnWriteArraySet 慎用
工具、封装类:
Arrays.asList、Collections.unmodifiableList\Set\Map\Collection
Collections.synchronizedList\Set\Map\Collection

Java编程常见缺陷汇总(一)的更多相关文章

  1. 50道经典的JAVA编程题(汇总)

    这是一次不可思议的编程历程.从2013年的最后一天开始做这份题,中间连续好几天的考试,包括java考试(今天考试的JAVA编程题),直到今天完成了.挺有成就感的...废话不多说了,来电实质性的吧. 全 ...

  2. Java编程:常见问题汇总

    每天在写Java程序,其实里面有一些细节大家可能没怎么注意,这不,有人总结了一个我们编程中常见的问题.虽然一般没有什么大问题,但是最好别这样做. AD: 每天在写Java程序,其实里面有一些细节大家可 ...

  3. java中常见异常汇总(根据自己遇到的异常不定时更新)

    1.java.lang.ArrayIndexOutOfBoundsException:N(数组索引越界异常.如果访问数组元素时指定的索引值小于0,或者大于等于数组的长度,编译程序不会出现任何错误,但运 ...

  4. NDK(22)JNI编程如何避免常见缺陷

    转自 : http://www.ibm.com/developerworks/cn/java/j-jni/index.html 避免常见缺陷 假设您编写了一些新 JNI 代码,或者继承了别处的某些 J ...

  5. Java Socket常见异常处理 和 网络编程需要注意的问题

    在java网络编程Socket通信中,通常会遇到以下异常情况: 第1个异常是 java.net.BindException:Address already in use: JVM_Bind. 该异常发 ...

  6. 大数据揭示的10个常见JAVA编程错误

    初学者最常犯的编程错误是什么呢?有可能他们总是混淆等值(==)与赋值(=),或者 & 和 &&:也有可能是他们在循环中使用错误的分隔符(for (int i = 0, i &l ...

  7. Java编程的逻辑 (90) - 正则表达式 (下 - 剖析常见表达式)

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  8. Java编程的逻辑 (64) - 常见文件类型处理: 属性文件/CSV/EXCEL/HTML/压缩文件

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

  9. Java学习笔记(六)——google java编程风格指南(下)

    [前面的话] 年后开始正式上班,计划着想做很多事情,但是总会有这样那样的打扰,不知道是自己要求太高还是自我的奋斗意识不够?接下来好好加油.好好学学技术,好好学习英语,好好学习做点自己喜欢的事情,趁着自 ...

随机推荐

  1. tablespace(表空间) / segment(断) / extent(盘区)/ block(块)/datafile(文件)之间的关系

    tablespace(表空间) / segment(断) / extent(盘区)/ block(块)之间的关系   tablespace : 一个数据库划分为一个或多个表逻辑单位,即表空间,每个表空 ...

  2. JSAP102

    JSAP102 1.API //案例:禁用文本框 <body> <input type="button" value="禁用" id=&quo ...

  3. .Net转Java.04.踩到switch的坑

    今天线上有个NullPointerException 的异常,我翻了一下代码,抛异常的竟然是switch语句 我有种不祥的预感,本地做了实验 结果是 Java的switch如果传入null值,会抛出  ...

  4. 网络编程之 keepalive(zz)

    link1: http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/ link2: http://dev.csdn.net/article/849 ...

  5. echarts-环形图处理图列中的点击,使百分比的数据列不发生变化,默认追加其他选项

    将下列代码copy的echarts编辑器中 app.title = '环形图'; var $legendData = ['直接访问','邮件营销','联盟广告','视频广告','搜索引擎']; var ...

  6. MySQL优化的一些基础

    在Apache, PHP, mysql的体系架构中,MySQL对于性能的影响最大,也是关键的核心部分.对于Discuz!论坛程序也是如此,MySQL的设置是否合理优化,直接 影响到论坛的速度和承载量! ...

  7. python接口自动化测试(八)-unittest-生成测试报告

    用例的管理问题解决了后,接下来要考虑的就是报告我问题了,这里生成测试报告主要用到 HTMLTestRunner.py 这个模块,下面简单介绍一下如何使用: 一.下载HTMLTestRunner下载: ...

  8. 读吴恩达算-EM算法笔记

    最近感觉对EM算法有一点遗忘,在表述的时候,还是有一点说不清,于是重新去看了这篇<CS229 Lecture notes>笔记. 于是有了这篇小札. 关于Jensen's inequali ...

  9. win下查找端口占用进程并定位到具体程序

    很多时候,我们会在服务器上运行多个java程序,但是在任务管理器里看到的都是一样的图标,想要找到我们想要的那个进程咋办呢? 列出所有端口进程 C:\Users\desp>netstat -ano ...

  10. 【原创 Hadoop&Spark 动手实践 5】Spark 基础入门,集群搭建以及Spark Shell

    Spark 基础入门,集群搭建以及Spark Shell 主要借助Spark基础的PPT,再加上实际的动手操作来加强概念的理解和实践. Spark 安装部署 理论已经了解的差不多了,接下来是实际动手实 ...