![](https://img-blog.csdnimg.cn/20201014180756913.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
effective java
dengjie532054105
这个作者很懒,什么都没留下…
展开
-
1.考虑用静态工厂代替构造函数
好处:1.静态工厂函数是有名字的,而且可以是很好的表示的名字。如构造函数BigInteger(int,int,Random)可能返回素数。我们可以给他增加一个静态工厂方法名为:BigInteger.probablePrime()这个方法已经加入到1.4版本中了。 2.比构造方法好的是,每次静态工厂被调用不一定非要去实例对象。因为你可以使用单例模式结合静态工厂,造一个static的存原创 2010-01-27 17:37:00 · 319 阅读 · 0 评论 -
避免不必要的使用被检查异常
被检查的异常是JAVA语言的一个很好的特性。与返回代码不一样的,它们在强迫程序员处理例外的条件,大大提高了可靠性。但是,过分的使用检查异常会让API使用起来很麻烦。特别是一个方法抛出一个或者多个被检查异常的时候,调用该方法的代码就必须在一个或是多个catch块中处理这些异常,或者它必须声明这些异常,以便让它们传播出去。这样会增加程序员负担。好的API应该避免去设计这些检查性异常。原创 2010-02-06 16:39:00 · 374 阅读 · 0 评论 -
尽量使用标准的异常
我们尽量去使用JDK的标准异常。为什么?第一,使用标准异常和程序员原来已经熟悉的API是一致的。第二,可读性好。不会出现程序员不熟悉的异常。第三,使用异常类越少,意味着内存占用就越小,并且装载这些类的时间开销也越小。最常用的异常是:IllegalArgumentException,当调用者传递的参数值不合适的时候,这个异常就会出来。比如说,一个参数是指“用户跑步多少原创 2010-02-06 16:39:00 · 321 阅读 · 0 评论 -
谨慎设计方法的原型
我们如何设计一个好的方法,好的方法应该是怎么样的?以下有些一些参考的准则:1.谨慎选择方法的名称。在命名的过程中,我们应该命名让客户更容易理解,在一些词语的选择上可以参考JAVA API中的命名。比如说我们要移除一个元素,我们是选择delete还是remove开头,你会发现JAVA API中大部分都是remove开头的。这样你可以做出比较明智的决定。 2.不要过于追求提供便利的方法原创 2010-02-03 15:04:00 · 245 阅读 · 0 评论 -
通过接口引用对象
1.这个很多人现在都在做啦。所谓的面向接口编程,不过这个只是这个概念的一部分而已。好处就是编程灵活,类型不会受到很大的限制。举个例子看看就懂:List projects=new ArrayList();有空也加上1.5以后的泛型最好。比如说你把上面的ArrayList改成了Vector也是对的,因为Vector也实现了List接口。2.列外的情况:如果没有合适的接口存在,那原创 2010-02-04 10:25:00 · 1356 阅读 · 0 评论 -
使用反射机制
一.反射机制的问题:1.你损失了编译时类型检查的好处。2.写的反射代码很笨拙和冗长。3.性能损失。老的反射性能惨啊,但是现在好多了。但是还是慢上2倍的样子。反射功能最初是为了基于组件的应用创建工具而设计的,这样的工具通常需要根据需要装载的类,并且用反射功能找出他们支持哪些方法和构造方法。比如说spring启动的时候去做的一些事情很多时候就用到了反射,当然在启动服务器的时候你根本不用原创 2010-02-04 10:25:00 · 355 阅读 · 0 评论 -
只针对不正常的条件才使用异常
public class TryTest { private static String[] arrayStr=new String[5]; /** * @param args */ public static String getElemtsInArray(){ int i=0; try{原创 2010-02-06 14:17:00 · 448 阅读 · 0 评论 -
每个方法抛出的异常都要有文档
我们应该做好代码的文档,特别是API的文档。对于异常更是如此。经典:总是要单独的声明被检查的异常,并且利用Javadoc的@throws标记,准确的记录下每个异常被抛出的条件。前面我们就说了未被检查的异常代表了编程上的错误,可以让程序员熟悉这些错误有助于让他们避免错误。对于接口的方法,我们也应该去记录该方法抛出的异常。因为接口是通用的约定。原创 2010-02-08 11:04:00 · 423 阅读 · 0 评论 -
不要忽略异常
我们平时要忽略一个异常是相当容易的,我们只需要try包围起来,然后空catch块处理一下就行了。空的catch块会使异常达不到应用的目的。我们不应该把异常警告忽略掉。原创 2010-02-08 11:08:00 · 350 阅读 · 0 评论 -
努力使失败保持原子性
这个意思是说,当一个对象抛出异常之后,我们总是期望这个对象仍然保持一种定义良好的可用状态,对于被检查异常而又为中恢复出来。所以,一般而言,一个失败的方法调用应该使对象保持“它被调用之前的状态”。这个是失败原子性。对于非可变对象是肯定没有关系的,他们的值和域都是会保持不变的。对于可变对象要获得原子性失败的方法就是在执行操作之前做参数的有效性检查,这可以使得对象的状态被改变以前,适原创 2010-02-08 11:07:00 · 569 阅读 · 0 评论 -
对共享可变数据的同步访问
一般认为同步就是一般的互斥行文。不是很全面。同步的意义:同步不仅可以阻止一个线程看到对象处于不一致的状态中,它还可以保证通过一系列看似顺序执行的状态转变序列,对象从一种一致的状态变迁到另外一种一致的状态。每一个线程进入到一个被同步的方法或是代码块的时候,它会看到由同一个锁控制的以前所有状态转变的结果。当线程退出了这个被同步的区域之后,任何线程在进入到由这同一把锁同步的区域时,它就可以看到由前面原创 2010-02-08 17:20:00 · 559 阅读 · 0 评论 -
避免过多的同步
原因:过多的同步可能会导致性能降低,死锁,甚至不确定的行为。为了避免死锁的危险,在一个被同步的方法或是代码块中,永远不要放弃对客户的控制。换句话说,在一个被同步的区域内部,不要调用一个可被改写的公有或是受保护的方法。因为从包含该同步区域的类的角度来看,这样的方法是一个外来者,这个类不知道该方法会做什么事情,也控制不了它。例如,客户可以为这个外来的方法提供一个实现,并且在该方法中创建另外一个原创 2010-02-08 17:21:00 · 502 阅读 · 0 评论 -
不要依赖线程调度器
当有多个线程可以运行时,线程调度器决定哪个线程将会运行,以及运行的时间。但是不同的JVM其调度器的策略大相径庭。所以我们不要去依赖策略的细节。任何依赖线程调度器而达到正确性或性能要求的程序,很可能是不能被移植的。我们应该写的是健壮的可以移植的线程应用程序,我们应该尽量的确保在任何给定时刻只有少量的可运行线程。这样线程调度器就没有其他多余的选择。这样可以摒弃线程调度算法不同引起的问题。原创 2010-02-09 15:29:00 · 867 阅读 · 0 评论 -
线程安全性的文档化
并非出现synchronized关键字就是线程安全性文档化了。实际上,一个类支持的线程安全性有很多级别。一个类为了可被多个线程安全的使用,必须在文档中清楚的说明它所支持的线程安全性级别。下面就是线程安全性级别:非可变(immutable):这个类的实例对于客户代码而言是不变的。所以,不需要外部的同步。这样的例子包括:String,Integer和BigInteger。线程安原创 2010-02-09 15:30:00 · 702 阅读 · 0 评论 -
对于可恢复的条件使用被检查的异常,对于程序错误使用运行时异常
JAVA提供了3种可抛出结构:被检查的异常(checke exception),运行时异常(runtime exception)和错误(error)。那我们什么使用正确的异常模式呢?使用一个被检查的异常原则:如果期望调用者能够恢复,对于这样条件就应该使用被检查异常。比如你做一个API方法,就要抛出一个异常,这样的异常就算是检查性的,因为用户用你的方法就要去捕获异常或是抛出。运行原创 2010-02-06 16:11:00 · 543 阅读 · 0 评论 -
通过接口引用对象
1.这个很多人现在都在做啦。所谓的面向接口编程,不过这个只是这个概念的一部分而已。好处就是编程灵活,类型不会受到很大的限制。举个例子看看就懂:List projects=new ArrayList();有空也加上1.5以后的泛型最好。比如说你把上面的ArrayList改成了Vector也是对的,因为Vector也实现了List接口。2.列外的情况:如果没有合适的接口存在,那原创 2010-02-04 10:24:00 · 336 阅读 · 0 评论 -
单例的一些东东
import java.io.ObjectStreamException; /** * */ /** * 单例类,提供灵活采用静态工厂方法来制造单例的方式.并且这里采用私有构造函数来强化保证了不能通过new的方式在外部进行实例化. * @author jayd * */public class Elvis implements java.io.Se原创 2010-01-28 11:07:00 · 226 阅读 · 0 评论 -
不创建重复的没有意义的对象
如这样一句话:String s=new String("dengjie");这里new String是一个对象分配空间了,里面的dengjie这个字符串又是一个String的实例又多创建一个对象。其实这话等价于String s="dengjie";这样就OK了。因为上面那个语句被反复调用就白白浪费了内存空间去多实例一个没有啥意义的对象。而且后面那个好处是不管多少次的调用都是一个对象原创 2010-01-28 16:14:00 · 256 阅读 · 0 评论 -
对所有对象都通用的方法规范(改写equals方法)
一.改写Object的equals方法的通用约定:改写equals方法可能会出现一些不好的错误,有些是很严重的逻辑错误。避免问题的最容易的办法就是不去改写该方法。在这样情况下,每个实例只与它自己相等。如果下面的任务一个条件满足的话,那就是我们所期望的结果:1.一个类的每个实例本质上都是唯一的。比如说Thread,Object所提供的equals方法实现対这样的类是正确的,不需要重写。2原创 2010-01-28 17:19:00 · 454 阅读 · 0 评论 -
最好别去重写clone函数,JAVA这个函数原则不优良。
具体。很多,大概是提倡用静态工厂的拷贝函数或是拷贝构造函数来做CLONE的功能,专家级的大佬们都很少去使用clone函数,这个话还是听听好些。原创 2010-02-01 16:56:00 · 606 阅读 · 0 评论 -
改equals时总要改hashCode
为啥呢?因为每一个对象都有自己的对应的散列码,这个码是靠hashCode方法返回得到的。我们equals方法判定的两个对象相等,那么就一定要做到散列码相等,因为一些集合类需要用到散列码。比如说List,Set,Map等等。比如说下面类:/** * *//** * @author Administrator * */public class Phone原创 2010-02-01 16:15:00 · 257 阅读 · 0 评论 -
支持非可变性
概念:一个非可变性的类是一个简单的类,每个实例包括的信息都是他在被创建的时候就提供出来的,并且在对象的生命周期内不是不能更改的。这样的类如:String,BigInteger等等。为什么会有这样的类呢?他们包含了优雅的设计思想:简单,不可变,稳定。 其实有点很提倡使用非可变类,但是不一定非要使用。下面创建一个优雅的非可变类的5点:1.不要提供任何可以修改对象的方法。2.保证没有原创 2010-02-02 13:08:00 · 292 阅读 · 0 评论 -
哥最喜欢的一条:复合优先继承(仅限于extends)
没啥好说的,继承过来的会有自用性,就是你调用一个方法的时候,可能有些域会被重新计算机2次。还有继承还不能访问私有的域。反正问题是多多的。继承也只能继承一个。我还是喜欢组合的手段来做到。当然适配器模式两个都要用,这也是适配器能关联两个不相关的类的能力。 这里面可能涉及到对包装类的讨论,装饰者等设计模式的讨论。其实都是很有意思的。自己可以去GOOGLE一下原创 2010-02-02 14:20:00 · 237 阅读 · 0 评论 -
方法上的通用准则
1.检查传入参数的有效性,一般都会做个判断是否NULL,或是不符合业务逻辑的要求,然后针对要求抛出异常或是其他处理。但是也要注意,如果业务上要求不是那么严格,而且你判断检测的过程可能会消耗大量资源的时候,您应该权衡利弊一下。 2.需要的时候做保护性拷贝:如:import java.util.Date;/** * *//** * @author Admi原创 2010-02-03 14:15:00 · 307 阅读 · 0 评论 -
为所有到处的API做文档注释(大牛们做JAR包的时候需要做好的事情哦)
我们如何好的生成规范的API文档,我们就要使用JAVADOC哦。要自己手动去写API的也不介意哈。不过我觉得一个核心框架一定要写好注释做好包。这个就是绝对的经典。做好质量和友善的规范,估计用户才会很好使用您努力汗水的结晶。 为了正确的编写出来API文档,你必须在每个被导出的类,接口,方法和域声明做好文档注释。每个方法的文档应该清晰的描述他与客户的关系以及之间应该遵守的约定。但是也有原创 2010-02-03 16:03:00 · 1760 阅读 · 0 评论 -
返回零长度的数组而不是NULL(经典的做法,很友善哦)
private List cheesesInStock; public Cheese[] getCheeses(){ if(cheesesInStock.size()==0){ return null; } } 看到这个代码了吧。没有cheese的时候返回的是null,其实这个连业务逻辑上来说也是原创 2010-02-03 15:40:00 · 500 阅读 · 0 评论 -
在对于精确计算的要求下请不要使用float和double
在对于精确计算的要求下请不要使用float和double,这2个基本类型的出现就是用来快速的近试算法。不信你试试:System.out.println(1.0-9*0.1);结果是:0.09999999999999998这样结果是没有人能够接受的。如果需要精确计算用BigDecimal类或是int,long等类型。原创 2010-02-03 17:40:00 · 648 阅读 · 0 评论 -
连接字符串连接的性能
1.字符串连接操作符"+"。性能问题:为连接N个字符串而重复地使用字符串连接操作符,要求N的平方级的时间。这个是由于字符串是非可变的类而导致的问题,感觉就是像单例一样。当两个字符串被连接的时间,他们的内容都要被拷贝。2.为了获得可接受的性能,我们一般使用StringBuffer替代String,用来存储构造字符串的过程。public String statement(){ St原创 2010-02-04 10:20:00 · 308 阅读 · 0 评论 -
通过接口引用对象
1.这个很多人现在都在做啦。所谓的面向接口编程,不过这个只是这个概念的一部分而已。好处就是编程灵活,类型不会受到很大的限制。举个例子看看就懂:List projects=new ArrayList();有空也加上1.5以后的泛型最好。比如说你把上面的ArrayList改成了Vector也是对的,因为Vector也实现了List接口。2.列外的情况:如果没有合适的接口存在,那原创 2010-02-04 10:23:00 · 384 阅读 · 0 评论 -
JAVA序列化
JAVA的序列化API,它提供了一个框架,用来将对象编码成一个字节流,以及从字节流编码中重新构建对象。将一个对象编码成一个字节流,这个是序列化过程,反过来就是饭序列化。一旦一个对象被序列化后,则它的编码可以从一个正在运行的虚拟机被传递到另外一个虚拟机上,或者被存储在磁盘上,供以后反序列化使用。序列化技术为远程通信提供了标准的线路,这样我们的JAVABEAN组件结构提供了标准的永久数据格式。原创 2010-02-09 15:30:00 · 329 阅读 · 0 评论