- 浏览: 220214 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
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 interface TestInterface { public static final Test test = new Test() { public void doSomething() { System.out.println("这就是实现"); } }; void test(); }
从以上代码中可以看到,在接口当中使用了匿名内部类的方式对接口当中的常量进行了实现,这种编码方式可以说是很好很强大,但由此带来的是什么?接口从此不再稳定,接口和类有了依赖,当Test类方法doSomething改变时,直接影响了接口,而接口应该是一种规范,是稳定不变的
2.静态变量一定要先声明后使用
标题是什么意思?难道可以使用一个没有声明的静态变量吗?请看以下代码
public class Test { static { i = 100; } public static int i = 1; public static void main(String[] args) { System.out.println("此时 i 的输出为 1" + i); } }
从以上代码看到,i先被使用,然后再进行了初始化,那为什么会出现这样的情况?首先要明确,静态变量在类初始化首先被加载的,注意,此时只加载了 i 这个变量,但还没有对 i 进行赋值,然后JVM会根据类中的静态块来顺序执行,以上代码由于静态块static{}放置顺序在前面,所以首先被执行,然后再执行int i = 1的操作
3.不要复写静态方法和静态方法使用类名调用:
在Java中,可以通过子类对父类的方法进行复写从而增强或减弱父类的行为,但复写是针对非静态方法的,我们都知道静态方法是针对类本身的,通过类名进行调用,当然也可以使用对象来调用,但这样Eclipse本身就会给你报个小警告,使用对象调用是不规范的,所以子类和父类应该尽量避免静态方法重名和静态方法使用类名调用
4.构造函数尽量简化
我们都知道,在New出一个新对象时,对象会执行一个方法,此方法名为构造函数,而构造函数当中,应该尽量不出现业务代码,因为构造函数的职责就是为类的创建进行初始化的,例如对对象的属性值进行初始化,而业务代码应该封装在类的方法当中,让构造函数尽量简单
5.用构造代码块精炼代码
现在我们有这样一个需求,在Test类初始化时需要记录日志,但Test类当中有多个构造函数,当然我们可以在每个构造函数当中编写日志,但使用构造代码块将更加的简洁完成以上需求,请看以下代码
public class Test { // 直接编写1对{}代表构造代码块 { System.out.println("我是记录日志的构造代码快"); } public Test() { System.out.println("执行无参构造"); } public Test(String id) { System.out.println("执行有参构造"); } }
以上代码中,构造代码块会增加到每个构造函数中的第一行的位置,这样就代表执行构造代码块再执行构造函数本身的内容
6.使用匿名类的构造函数
在我们开发当中,若想快速实现一个接口,例如是Comparator(比较器),我们会使用匿名类的形式来进行实现,但有没有想过,匿名类的构造函数在何方?我们都知道构造函数是没有重写的,那我们在对自定义的接口使用匿名方式实现时,如何使用构造函数?请看以下代码
public class Test { private Comparator<Test> comparator = new Comparator<Test>() { { System.out.println("其实我可以代替匿名类的构造函数"); } @Override public int compare(Test o1, Test o2) { return 0; } }; }
使用构造代码块就可以实现对匿名类的构造函数.
7.让多重继承成为现实
我们都知道Java当中是单继承的,但我们可以使用婉转的方式来实现多继承,这就需要使用到内部类
public abstract class Runable { private int speed = 10; void run() { System.out.println("running..." + speed); } } public abstract class Flyable { private int speed = 10; void fly() { System.out.println("flying..." + 10); } } //动物能飞,能跑 public class Animal { public void fly() { new Flyable() { }.fly(); } public void run() { new Runable() { }.run(); } }
当然我们可以在Animal中再创建一个内部类继承runable或flyable然后在run或fly中创建内部类来实现,这里只给出最方便快捷的实现
8.让工具类不可实例化
工具类只是帮助我们完成某些特定操作,而且工具类所有方法都应该是static,而且不能实例化,当然很简单就可以完成,只需将构造函数私有化(private)即可,但Java强大的反射机制还是能让我们通过反射形式来实例化工具类,此时更应该在工具类私有的构造函数中加入抛出异常的代码,当初始化时即抛出异常
9.避免对象的浅拷贝
何谓浅拷贝?有经典的案例,请看如下代码
public static void main(String[] args) { int[] numArray = new int[10]; int[] numArray2 = null; // 此种就为浅拷贝,拷贝的是引用 numArray2 = numArray; // 此种为深度拷贝,拷贝的是元素,不是引用 for (int i = 0, size = numArray.length; i < size; i++) { numArray2[i] = numArray[i]; } }
而在Java中,只要实现了Cloneable接口的对象,都被视为具有拷贝能力,但需要注意,clone方法的拷贝为浅拷贝.
9.复写equlas时需要注意的事情:
在复写equlas时需要注意,要考虑Null值得情况,推荐中equlas中使用getClass进行类型的判断,复写equlas时必须复写hasCode方法
10.不主动进行垃圾回收
主动进行垃圾回收是一个非常危险的操作,因为System.gc()需要停止所有的响应来扫描垃圾,所有的请求会全部停止,等待垃圾回收器执行完毕,此时若然堆中存在大量对象时,那这个过程将会非常耗时
总结:
笔者在本文章中只从《改善Java程序的151建议》中提取部分进行归纳性叙述,推荐各位读者购买这本书,该书不仅从事例中学习,而且涉及到原理,底层的实现,不仅告诉你应该怎么做,还告诉你为什么要这样做.
评论
7 楼
yk.yk
2013-09-09
看到第八条,我笑了,怎么一个贱字了得!!
6 楼
happy200318
2013-09-09
mark 学习 学习
5 楼
ray_yui
2013-08-30
unique.wu 写道
第八条,如果还在私有构造方法里,增加抛出异常的代码,那就太过度设计了。。
代码要这样写,会累死的。。
知道有这么一回事就可以了。
看看apache里大部分的工具类里,连默认的private的构造函数都没有加上。
浅克隆,深度克隆,得依赖于具体场景而言,个人认为克隆方法前加上注释,比较合理一点,并不是所有场景需要深度克隆,然而因为没有深度克隆而引起的数据被攥改的情况又很隐蔽,如果可以,有多种需求可以考虑提供一个浅克隆和一个深度克隆的方法,否则,根据场景的需求来克隆了。
代码要这样写,会累死的。。
知道有这么一回事就可以了。
看看apache里大部分的工具类里,连默认的private的构造函数都没有加上。
浅克隆,深度克隆,得依赖于具体场景而言,个人认为克隆方法前加上注释,比较合理一点,并不是所有场景需要深度克隆,然而因为没有深度克隆而引起的数据被攥改的情况又很隐蔽,如果可以,有多种需求可以考虑提供一个浅克隆和一个深度克隆的方法,否则,根据场景的需求来克隆了。
非常感谢你的留言和意见,其实就克隆而言,浅克隆比深克隆就开销上看反而更好.但由于克隆的场景大多是数据库的数据,而我们又大多使用Hibernate,我曾经在使用Hibernate时报出Exception:Found shared references to a collection,这是因为两个对象引用了同一个集合,就是因为浅拷贝引起的,所以我觉得能注意能避免就好
4 楼
unique.wu
2013-08-30
第八条,如果还在私有构造方法里,增加抛出异常的代码,那就太过度设计了。。
代码要这样写,会累死的。。
知道有这么一回事就可以了。
看看apache里大部分的工具类里,连默认的private的构造函数都没有加上。
浅克隆,深度克隆,得依赖于具体场景而言,个人认为克隆方法前加上注释,比较合理一点,并不是所有场景需要深度克隆,然而因为没有深度克隆而引起的数据被攥改的情况又很隐蔽,如果可以,有多种需求可以考虑提供一个浅克隆和一个深度克隆的方法,否则,根据场景的需求来克隆了。
代码要这样写,会累死的。。
知道有这么一回事就可以了。
看看apache里大部分的工具类里,连默认的private的构造函数都没有加上。
浅克隆,深度克隆,得依赖于具体场景而言,个人认为克隆方法前加上注释,比较合理一点,并不是所有场景需要深度克隆,然而因为没有深度克隆而引起的数据被攥改的情况又很隐蔽,如果可以,有多种需求可以考虑提供一个浅克隆和一个深度克隆的方法,否则,根据场景的需求来克隆了。
3 楼
ray_yui
2013-08-23
zoozooll 写道
個人覺得 ,用java來做這些微小的内存優化操作,太虛了.
創建對象時候不知道内存地址,也不知道内存存儲的方式,指針指向方式,更不知道什麽時候釋放.即使能夠做到,也做不了操作.
這種事情還是交給c和c++.java 語言從它出生開始,就是考慮如果方便開發者抛開這些瑣碎問題的,現在又來到這方面自尋煩惱,真是何苦阿
創建對象時候不知道内存地址,也不知道内存存儲的方式,指針指向方式,更不知道什麽時候釋放.即使能夠做到,也做不了操作.
這種事情還是交給c和c++.java 語言從它出生開始,就是考慮如果方便開發者抛開這些瑣碎問題的,現在又來到這方面自尋煩惱,真是何苦阿
非常感谢你的留言,也非常有道理,虽然Java处于的层次确实限制了非常多的操作,但绝对不能说做不到就不尽量去优的方面靠呀,若然你需要一种高内存管理例如网游的服务器端,或者高性能系统,那c++等绝对是优的,但若然你选择java,却认为对底层的管理被封死就肆意挥霍的话,那绝对不是一种好的思想和方案
2 楼
zoozooll
2013-08-23
個人覺得 ,用java來做這些微小的内存優化操作,太虛了.
創建對象時候不知道内存地址,也不知道内存存儲的方式,指針指向方式,更不知道什麽時候釋放.即使能夠做到,也做不了操作.
這種事情還是交給c和c++.java 語言從它出生開始,就是考慮如果方便開發者抛開這些瑣碎問題的,現在又來到這方面自尋煩惱,真是何苦阿
創建對象時候不知道内存地址,也不知道内存存儲的方式,指針指向方式,更不知道什麽時候釋放.即使能夠做到,也做不了操作.
這種事情還是交給c和c++.java 語言從它出生開始,就是考慮如果方便開發者抛開這些瑣碎問題的,現在又來到這方面自尋煩惱,真是何苦阿
1 楼
85113618
2013-08-19
谢谢 啊 学习了
发表评论
-
并发编程 — 实现线程安全
2015-08-12 09:03 2308并发编程系列文章: 初解线程池:http://r ... -
并发编程 — 优化小技巧
2015-08-10 23:54 0并发编程系列文章: 初解线程池:http://r ... -
并发编程 — 判断线程安全
2015-08-05 10:11 5559并发编程系列文章: ... -
并发编程 — volatile
2015-07-30 10:11 2202并发编程系列文章: 初解线程池: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 7557并发编程系列文章: 初解线程池: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-16 09:53 4747前言:由于上一个星期工作繁忙,利用上下班和晚上睡前空余的时间 ... -
Java高质量代码之 — 异常
2013-09-09 09:35 6744前言:由于上一个星期工作繁忙,利用上下班和晚上睡前空余的时间 ... -
Java高质量代码之 — 泛型与反射
2013-08-29 09:36 18073前言:由于上一个星期工作繁忙,利用上下班和晚上睡前空余的时间 ... -
Java高质量代码之 — 枚举与注解
2013-08-27 09:59 15824前言:由于上一个星期工作繁忙,利用上下班和晚上睡前空余的时间 ... -
Java高质量代码之 — 数组与集合(2)
2013-08-23 17:24 2909前言:由于上一个星期工作繁忙,利用上下班和晚上睡前空余的时间 ...
相关推荐
Java中的封装、继承和多态是面向对象编程的核心特性,它们共同构成了Java语言的核心部分,也是构建高质量、可维护和可扩展的Java应用程序的关键。通过理解这些面向对象编程的基本概念和操作,程序员可以更加高效地...
### Java面向对象编程:从C++到Java的理解与过渡 ...通过学习Java的运行机制、面向对象的核心特性、文件结构与命名空间管理以及异常处理等知识,开发者可以更好地适应Java开发环境,编写出高质量的代码。
另外,Javadoc注释(/**…*/)用于生成API文档,是编写高质量代码的必要环节。 在Java面向对象编程中,还有许多其他重要概念,如封装、继承和多态。**封装**意味着隐藏对象的内部细节,提供公共接口供外部访问。**...
Java面向对象编程是Java语言的核心特性,它基于面向对象编程思想,使得代码更易于理解和维护。孙卫琴老师的《深入浅出Java面向对象》是一本深受程序员喜爱的教材,其中的课后习题旨在帮助学生深入理解面向对象的原理...
在实际的Java应用程序开发中,理解并熟练运用这些面向对象的概念和设计模式,能够帮助我们构建可维护、可扩展的高质量软件系统。通过不断的实践和学习,开发者可以更好地掌握Java面向对象编程的精髓,提升自己的编程...
2. **面向对象编程**:Java是一种面向对象的语言,书中重点讲解了类、对象、封装、继承、多态等概念,帮助读者理解和运用面向对象的设计原则和模式。 3. **异常处理**:Java的异常处理机制是其强项之一,书中详细...
"Java面向对象精髓编程"这个主题深入探讨了Java的核心特性——面向对象编程。面向对象编程(Object-Oriented Programming, OOP)是现代软件开发中的重要概念,它通过将数据和操作数据的方法封装在对象中,提高了代码...
Java语言是支持面向对象编程的典型代表之一,它的核心概念包括类、对象、继承、多态和封装。 2. 孙卫琴老师及其书籍:孙卫琴是编写Java相关教材的作者,她出版的书籍以易懂的叙述方式帮助读者理解和掌握Java编程...
面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它基于“对象”的概念,将数据和操作...通过课件、练习和案例分析,你将能够熟练地运用面向对象设计原则来解决问题,提升编程效率和代码质量。
Java面向对象教程是深入理解Java编程的关键,它涵盖了软件工程中的基本原则,并将其应用于实际编程实践。面向对象编程(Object-Oriented Programming, OOP)是一种编程范式,它基于“对象”的概念,这些对象封装了...
面向对象编程(Object-Oriented Programming, OOP)是Java的核心技术之一,它赋予了开发者强大的抽象和模块化设计能力。在Java中,面向对象编程主要包括类、对象、封装、继承、多态等关键概念。 首先,我们来深入...
以上是Java面向对象编程的一些基础面试题及其解析,掌握这些知识对于理解Java OOP设计模式和编写高质量代码至关重要。在实际面试中,面试官可能会结合实际场景深入提问,例如设计模式的应用、集合框架的使用等,因此...
### JAVA面向对象编程思想 #### 一、面向对象的基本概念 面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它通过模拟现实世界中的...正确理解和应用这些概念是编写高质量Java应用程序的基础。
### Java面向对象总结 #### 一、继承 ...通过上述总结,我们可以更好地理解Java中的面向对象特性,特别是继承、多态以及`final`和`static`等修饰符的应用,这对于编写高质量、可维护的Java代码至关重要。
在Java这样的面向对象语言中,遵循一些设计原则可以显著提高代码的质量和可维护性。以下是几个重要的面向对象设计原则的详细解释: 1. **开闭原则(Open-Closed Principle, OCP)** 开闭原则指出,软件实体(如类...
在Java编程领域,面向对象(Object-Oriented Programming, OOP)是一种常用的设计模式,它以对象为中心,强调数据和操作数据的方法。本项目“java面向对象小游戏”就是基于这一编程理念开发的一个飞机类小游戏,旨在...
《清华Java语言与面向对象程序设计》是一门深入讲解Java编程和面向对象设计的课程,旨在帮助学习者掌握Java编程的基础知识以及如何运用面向对象的思想进行软件开发。课程内容覆盖了从基本语法到高级特性,从理论概念...
Java面向对象编程是Java语言的核心特性,它使得代码更加模块化、可维护和易于扩展。孙卫琴老师的Java编程培训讲义深入浅出地讲解了这一主题,旨在帮助学习者理解并掌握面向对象编程的基本概念和实践技巧。 首先,...
面向对象编程是Java的核心特性,它使得代码更加模块化、可维护性和可扩展性更强。在Java中,万物皆对象,即所有的事物都可以抽象成一个对象,对象包含其属性(描述对象的状态)和方法(描述对象的行为)。面向对象...
根据给定文件的信息,我们可以提炼出以下几个关键知识点: ### 1. 面向对象编程(OOP)概览 ...对于软件开发者来说,深入理解面向对象编程和面向切面编程的原理及其应用,对于构建高质量、易维护的软件系统至关重要。