- 浏览: 220197 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
zi_wu_xian:
顶5楼,POI操作word和excel还是太复杂了,并且针对d ...
使用POI操作Excel和Word -
贝塔ZQ:
poi操作word、excel代码好多啊,用插件试试吧,网上不 ...
使用POI操作Excel和Word -
wap816:
@CacheEvict(value = ...
SpringEL详解及应用 -
string2020:
List<Map<String,Map<St ...
开源工具 — Apache Commons Collections -
uniqueX:
mark!
并发编程 — 判断线程安全
前言:由于上一个星期工作繁忙,利用上下班和晚上睡前空余的时间拜读了秦小波老师的《改善Java程序的151建议》,感觉廓然开朗,注意到了很多平时在编写代码中并不会注意的问题,甚至感觉自己对Java只是略懂皮毛,不足以登大雅之堂,特此与读者分享读书笔记,以下内容摘自《改善Java程序的151建议》一书和笔者的理解
Java高质量代码系列文章
面向对象篇:http://ray-yui.iteye.com/blog/1926984
数据类型篇:http://ray-yui.iteye.com/blog/1927251
字符串篇:http://ray-yui.iteye.com/blog/1927647
数组与集合(1):http://ray-yui.iteye.com/blog/1928170
数组与集合(2):http://ray-yui.iteye.com/blog/1930155
枚举与注解:http://ray-yui.iteye.com/blog/1931408
泛型与发射:http://ray-yui.iteye.com/blog/1933127
异常:http://ray-yui.iteye.com/blog/1938946
杂:http://ray-yui.iteye.com/blog/1942591
1.莫让常量蜕变为变量
请观察以下代码
public class Test { public static final int CONST = new Random().nextInt(); }
在上面代码中如此声明常量,常量将会根据Random返回的随机数而作出改变,这种常量的定义方式是极不可取的,不应该将常量的值在运行期间修改
2.三元操作符类型务必一致
请观察以下代码
public class Test { public static void main(String[] args) { int i = 80; String str1 = String.valueOf(i < 100 ? 90 : 100); String str2 = String.valueOf(i < 100 ? 90 : 100.0); System.out.println(str1.equals(str2)); // 输出为false } }
按惯性的理解,变量i的值小于100,应该str1和str2都只取三元运算符中的一个值,也就是90,但从上面的例子当中,看出并不是如此,这是因为Java是强类型,编译器在编译时必须要确定值的类型,条件为真时返回int,条件为假时返回float,编译器是不允许的,所有通过转换,将三元运算表达式的返回值转换为类型返回较大者
3.别让null值和空值威胁变长方法
在Java5以后,我们可以使用变长方法,请看以下代码
public class Test { public static void test(String str, Integer... test) { } public static void test(String str, String... test) { } public static void main(String[] args) { test("Hello", null); } }
通过以上方式就可以声明为变长方法,变长参数必须在方法接受参数的最后声明,一个方法只能拥有一个变长参数,若然使用上面的代码,读者会发现编译不通过的现象,这是因为编译器无法明确究竟正在调用哪个test方法,所以在使用变长参数时需要注意,尽量不要出现上面代码中的坏味道代码,若然业务真需求如此,我们可以使用以下方式进行代替
public class Test { public static void test(String str, Integer... test) { } public static void test(String str, String... test) { } public static void main(String[] args) { String str = null; test("Hello", str); } }
4.养成良好习惯,显式声明UID
在javaEE编程当中,对象需要进行网络传输,所以我们应该继承serializable接口,而EJB更是强制要求实现该接口,在我们使用IDE进行开发,没有显式声明UID,eclipse会马上送你一个黄色警告,其实UID的作用就是在JVM序列化时,会比较数据流中的UID与类中的UID是否相同,若然相同则表明类没有发生改变,这是一种非常好的机制,可以保证对象即使在网络或磁盘中'翻滚'一次,仍然能保持'出淤泥而不染'
5.使用序列化类私有方法解决部分属性持久化
我们都知道,在序列化到磁盘或数据库当中时,static和transient是不会被记录到序列化当中的,但若然我们业务需要将某些变量不对外泄露,但又需要保持到数据库或分布式当中时,可以使用如下代码
public class Test implements Serializable { private static final long serialVersionUID = -6201315277372663567L; private Integer num; private Integer num2; private String str; private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); oos.writeInt(num); } private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ois.defaultReadObject(); num = ois.readInt(); num2 = 0; } // 省略 get/set }
通过以上代码,在反序列时,num2变量的值会等于0,从而安全的将信息进行隐藏,Java在调用objectOutputStream类把一个对象转换成流数据时,会通过反射检查被序列化的类是否有writeObject方法,并检查是否符合私有,无返回值等方法签名,若有则会委托方法进行对象序列化,而defaultWriteObject则是惯例写在第一句,代表按默认规则写入对象,而writeInt则是一个队列,先进先出.读取时同理
6.避免在循环中读取数据库
在项目当中,归功与Hibernate的功劳令到我们获取数据库中数据的手续变得非常简单,导致我们在某些时候的编码当中,忽略了使用HQL等手段获取数据,而是在循环当中使用简单的get方法来获取,这导致了产生N+1的问题,若然数据关连较多而且懒加载设置不合理时,效率将会异常减慢,从而导致性能瓶颈的出现,在编写代码特别是在循环当中操作时,要格外注意
7.使用ThreadLocal时需要注意释放
请观察以下代码
public class Test { ThreadLocal<String> test = new ThreadLocal<String>(); public String getTest() { String str = test.get(); if (str == null) { test.set(""); } return str; } public void setTest(String str) { test.set(str); } public void removeTest() { test.remove(); } }
在JavaEE等Web开发当中ThreadLocal的应用非常之多,因为它能将变量提升为线程级别,而恰好我们的Web是基于请求/响应的模式,每次请求就是一个线程,其实原理简单来说可以是将某变量放入了线程的ThreadLocalMap,从而将变量提升为线程级别,关于更多原理请查阅其他文章,而我们需要注意的是removeTest方法,remove方法是JDK1.5后新增的,用来解决ThreadLocal释放资源的问题避免内存溢出,但JDK1.4时就已经提供了自动释放来解决这个问题,为什么1.5还需要增加remove方法?这是因为我们Web程序需要容器,而容器需要提供性能一般都采用线程池,导致线程循环再用不能释放,违背了JDK1.4中新增的线程销毁时自动释放,导致ThreadLocal的变量残留,所以在开发当中要注意remove从而释放资源
总结:
笔者在本文章中只从《改善Java程序的151建议》中提取部分进行归纳性叙述,推荐各位读者购买这本书,该书不仅从事例中学习,而且涉及到原理,底层的实现,不仅告诉你应该怎么做,还告诉你为什么要这样做.
发表评论
-
并发编程 — 实现线程安全
2015-08-12 09:03 2308并发编程系列文章: 初解线程池:http://r ... -
并发编程 — 优化小技巧
2015-08-10 23:54 0并发编程系列文章: 初解线程池:http://r ... -
并发编程 — 判断线程安全
2015-08-05 10:11 5557并发编程系列文章: ... -
并发编程 — volatile
2015-07-30 10:11 2201并发编程系列文章: 初解线程池:http://r ... -
数据库储存不确定实体
2014-07-08 09:52 2294相信在项目开发当中都曾经遇到过,有某些要储蓄到数 ... -
同步操作降低效率解惑
2014-06-30 10:20 3295相信在读者刚接触Java的时候,都曾经学习到线程 ... -
并发编程 — 并发数据结构
2014-06-24 09:58 6640并发编程系列文章: 初解线程池:http://r ... -
并发编程 — 并发数据类型
2014-06-16 10:03 5451并发编程系列文章: 初解线程池:http://r ... -
并发编程 — 详解线程池
2014-06-03 09:51 6014本文章需要对JDK5 Executor框架有所了解,请读者先 ... -
并发编程 — 初解线程池
2014-05-28 09:57 7556并发编程系列文章: 初解线程池:http://r ... -
线程池详解
2014-05-26 18:20 0本文章需要对JDK5 Executor框架有所了 ... -
高级字节码生成工具 — Javassist
2014-03-11 09:57 6426AOP系列文章: Spring AOP:http ... -
实现AOP — CGLIB
2014-03-06 09:50 3977AOP系列文章: Sp ... -
实现AOP — Spring AOP
2014-03-03 10:02 4269AOP系列文章: Spring AOP:http ... -
cglib
2014-01-11 19:11 0什么是CGLIB? CGLIB是一个强大的高性能 ... -
Java高质量代码之 — 异常
2013-09-09 09:35 6743前言:由于上一个星期工作繁忙,利用上下班和晚上睡前空余的时间 ... -
Java高质量代码之 — 泛型与反射
2013-08-29 09:36 18072前言:由于上一个星期工作繁忙,利用上下班和晚上睡前空余的时间 ... -
Java高质量代码之 — 枚举与注解
2013-08-27 09:59 15822前言:由于上一个星期工作繁忙,利用上下班和晚上睡前空余的时间 ... -
Java高质量代码之 — 数组与集合(2)
2013-08-23 17:24 2908前言:由于上一个星期工作繁忙,利用上下班和晚上睡前空余的时间 ... -
Java高质量代码之 — 数组与集合(1)
2013-08-21 12:24 7253前言:由于上一个星期工作繁忙,利用上下班和晚上睡前空余的时间 ...
相关推荐
在这个系统中,Java被用来编写业务逻辑、数据访问和控制层代码。 2. **S2SH框架**: - **Struts**:这是一个MVC框架,负责处理HTTP请求,管理和转发页面流程,提供表单验证等功能。 - **Spring**:核心功能包括...
高清工具主要用于提升游戏的画面质量,使游戏在高分辨率显示器上能够展现出更加细腻、清晰的视觉效果。这类工具可能涉及纹理映射优化、抗锯齿算法增强等技术手段,以达到更好的视觉体验。 ### 通关存档 通关存档是...
zxing.java源码解析 前言 成为一名专业程序员的道路上,需要坚持练习、学习与积累,技术方面既要有一定的广度,更要有自己的深度。 笔者作为一位tool mad,将工作以来用到的各种优秀资料、神器...:高质量的技术社区 :
zxing.java源码解析 前言 成为一名专业程序员的道路上,需要坚持练习、学习与积累,技术方面既要有一定的广度,更要有自己的深度。 笔者作为一位tool mad,将工作以来用到的各种优秀资料、神器...:高质量的技术社区 :
zxing.java源码解析 前言 成为一名专业程序员的道路上,需要坚持练习、学习与积累,技术方面既要有一定的广度,更要有自己的深度。 笔者作为一位tool mad,将工作以来用到的各种优秀资料、神器...:高质量的技术社区 :
zxing.java源码解析 前言 成为一名专业程序员的道路上,需要坚持练习、学习与积累,技术方面既要有一定的广度,更要有自己的深度。 笔者作为一位tool mad,将工作以来用到的各种优秀资料、神器...:高质量的技术社区 :
zxing.java源码解析 前言 成为一名专业程序员的道路上,需要坚持练习、学习与积累,技术方面既要有一定的广度,更要有自己的深度。...:高质量的技术社区 :企业级应用,关注软件开发领域 国内老牌技术
作为一个开源项目,daza.io不仅为用户提供了高质量的内容推荐,也为开发者提供了一个学习和贡献的平台。开源意味着代码的透明度,任何人都可以查看、研究其代码,甚至提出改进意见或添加新功能。这对于技术爱好者和...
zxing.java源码解析 前言 成为一名专业程序员的道路上,需要坚持练习、学习与积累,技术方面既要有一定的广度,更要有自己的深度。 笔者作为一位tool mad,将工作以来用到的各种优秀资料、神器...:高质量的技术社区 :
CDMA的优点包括:提供高质量的语音编码技术,能够降低通话中的噪音,提高通话质量。 在Android-telephony中,cdma文件夹提供了CDMA具体的电话功能API,包括CdmaCellLocation、CdmaSignalStrength等类。 1.1) ...
zxing.java源码解析 前言 成为一名专业程序员的道路上,需要坚持练习、学习与积累,技术方面既要有一定的广度,更要有自己的深度。 笔者作为一位tool mad,将工作以来用到的各种优秀资料、神器...:高质量的技术社区 :
智能组卷系统的目标是根据教学目标、学生能力以及考试要求,自动地从题库中选择并组合出高质量的试卷。这一过程涉及到许多复杂的约束和目标,如难度平衡、知识点覆盖、题型分布等,而遗传算法恰好能有效地处理这类...
以上原则和实践都是"Clean Code Args"的核心,遵循这些指导,可以使Java代码更加清晰、可读,从而提升整个项目的技术质量。在实际工作中,开发者们应当不断学习和实践,以达到"Clean Code"的标准。
8. **测试与调试**:单元测试、集成测试是保证代码质量的重要环节,JUnit和Mockito是Java开发中的常用测试工具。 9. **持续集成/持续部署(CI/CD)**:项目可能使用Jenkins或GitHub Actions等工具实现自动化构建和...
它旨在确定系统在高压力环境下的行为,比如处理大量并发请求,或者在内存、CPU等资源极度紧张的情况下。通过压力测试,我们可以发现系统在峰值负载下的瓶颈,以便优化和增强其容量。 3. **软件测试**:软件测试是一...
1. TypeScript:这是一种由Microsoft开发的编程语言,它是JavaScript的超集,增加了静态类型系统、类和接口等特性,提高了代码质量和可维护性。 2. Angular2:Angular是一个流行的前端开发框架,这里提到的是其第二...
百度地图毕业设计源码 前言 成为一名专业程序员的道路上,需要坚持练习、学习与积累,技术方面既要有一定的广度,更要有自己的深度。 笔者作为一位tool mad,将工作以来用到的各种优秀...:高质量的技术社区 :企业级应
1. **初始化方法的改进**:传统的随机初始化可能导致初始种群质量不高,改进方法可能包括使用更好的启发式策略生成初始种群,或者结合其他算法如模拟退火、粒子群优化等生成初始解。 2. **适应度函数的优化**:适应...