- 博客(50)
- 收藏
- 关注
原创 (45):将局部变量的作用域最小化
(1):在第一次使用某个局部变量的地方进行声明。Java可以在任何可以出现语句的地方声明变量。 这条规则可以让我们在需要的地方声明变量,从而缩小作用域。(2):几乎每个局部变量的声明都应该包含一个初始化表达式。(3):for循环,都允许声明循环变量,它们的总用域被限定在正好需要的范围之内。(4):使用另一个局部变量来限制一个局部变量的迭代范围。for(int i =0,n = expe
2017-04-21 10:40:56 566
原创 (44):为所有导出的API元素编写文档注释
要想使一个API真正可用,就必须为其编写文档。Java提供了Javadoc工具,使得为API编写文档变得非常容易。Javadoc利用特殊格式的文档注释,根据源代码自动生成API文档。示例:/** * Returns the element at the specified position in this list. * * This method is not guaranteed
2017-04-21 10:06:39 371
原创 (43):返回零长度的数组或者集合,而不是null
对于一个返回能够null的方法,我们需要额外的代码去处理它,这样做很容易出错。因为我们很容易忘记处理null有人认为null返回值比零长度数组更好,因为避免了分配数组所需要的开销。这种观点是错误的,原因有两点:(1):在这个级别上去担心性能是没有意义的,除非能证明这个方法正是造成性能问题的源头。(2):对于不返回任何类型调用,返回同一个零长度数组是可能的简而言之:返回类型为数组或者
2017-04-20 11:26:51 361
原创 (42):慎用可变参数
可变参数指的是可以接受一个或多个指定类型的参数static int sum(int... args) { int sum=0; for(int arg : args) sum += arg; return sum;}上面就是可变参数的实例,可以是sum()=0也可以是sum(1,2,3)=6。可变参数的机制通过先创建一个数组,数组的大小为在调用位置
2017-04-20 10:45:23 430
原创 (41):慎用重载
对于重载的方法选择是静态的(而对于被覆盖的方法的选择是动态的),要调用哪个重载方法是在编译时做出决定的。看下面这个例子:public class CollectionClassifier{ public static String classify(Set s){ return "Set"; }
2017-04-19 11:31:50 252
原创 (40):谨慎设计方法签名
(1):谨慎的选择方法名称(2):不要过于追求提供便捷的方法。当一项操作被经常使用的时候,可以考虑。(3):避免过长的参数列表(4):对于参数类型优先使用接口而不是类。有三种方法可以缩短过长的参数列表(1):把方法分解成多个方法(2):创建辅助类,然后把参数放到辅助类例,我们只要传入辅助类的对象就行。(3):从对象构造到参数调用都采用Builder模式。(参见条目2)
2017-04-19 10:58:08 360
原创 (39):必要时进行保护性拷贝
看下面这个例子public final class Period{ private final Date startTime; private finale Date endTime; public Period(Date startTime , Date endTime) {
2017-04-19 10:30:20 300
原创 (38):检查参数的有效性
绝大多数方法和构造器对于传递给他们的参数值都会有某些限制。例如索引值必须是非负数,对象引用不能为null,等等。所以我们应该尽量对这些限制在程序开始进行检查。对于公有的方法,要用Javadoc的@throws标签 在文档中说明违反参数值限制时会抛出的异常。通常这样的异常为IllegalArgumentException,IndexOutOfBoundsException。但是并不是每个方法我们
2017-04-18 14:26:17 587
原创 (37):用标记接口定义类型
所谓标记接口,就是指一个接口里面什么都没有,只是标记实现类具有某种属性。例如serilizeable就是这样一个接口,他只是告诉jvm,继承于这个接口的CLASS需要序列化处理,而我们根本不用实现这个接口的方法。优点:1.标记接口定义的类型是由被标记类的实例实现的;标记注解则没有定义这样的类型。2.可以被更精确地进行锁定。如果注解类型利用@Target(ElementType.
2017-04-18 11:02:33 554
原创 (36):坚持使用Override注解
这其实也没什么好说的。总之,当我们要重写时,一定要添加Override注解,这既可以告诉别人这是重写的方法,也可以使编译器替你防止大量的错误。
2017-04-17 11:12:48 289
原创 (35):注解优先于命名模式
所谓命名模式有些程序元素需要通过某种工具进行特殊处理。例如:JUnit测试框架要求用户一定要用test作为测试方法名称的开头。这种方法缺陷很大,列如不小心写错了名称,测试失败却没有任何提示。相比较而言,注解可以完美解决这些缺点。大多数程序员不必定义注解类型,但是所有的程序员都应该使用Java平台所提供的预定义的注解类型,还要考虑使用IDE或者静态分析工具所提供的任何注解 总之,有了
2017-04-17 10:41:37 304
原创 (34):使用接口模拟可伸缩的枚举
在java中一个枚举是无法直接去扩展另一个枚举的,但通过接口我们可以变相的实现这一点。public interface Operation { double apply(double x, double y);}public enum BasicOperation implements Operation { PLUS("+") { public double
2017-04-17 10:24:01 461
原创 (33):用EnumMap代替序数索引
当我们需要使用Map类型,且Map的key可以被做成枚举类型,我们应该考虑使用EnumMap。现在有这么一个问题,有一座花园,里面有很多花。花总共有三种类型,我们想把它分类分出来。public class Herb { public enum Type { ANNUAL, PERENNTAL, BIENNIAL } // private stati
2017-04-14 11:19:07 712
原创 (32):用EnumSet代替位域
位域:就是用int枚举模式,将2的不同倍数赋予每个常量,这种表示法让你用OR位运算将几个常量合并到一个集合中(int值),称作位域(bit field)。位域的写法就不介绍了,总之这种写法缺陷比较大。我们应该用EnumSet代替它。public class Text { public enum Style { BOLD, ITALIC, UNDERLINE, S
2017-04-14 10:54:21 576
原创 (31):用实力域代替序数
我们知道枚举数天生就是有值的,默认是从0开始,那么我们需要从1开始怎么办呢?可以这么写public enum Ensemble { SOLO, DUET, TRIO, QUARTET, QUINTET, SEXTET, SEPTET, OCTET, NONET, DECTET; public int numberOfMusicians() { return o
2017-04-14 10:25:45 292
原创 (30):用enum代替int常量
我们常常会需要int全局常量 如下:public static final int APP_START=1;public static final int APP_PAUSE=0;public static final int APP_STOP =2;public static final int PLAY_START=1;public static final int P
2017-04-13 15:17:38 678
原创 (29):优先考虑类型安全的异构容器
泛型常用于以及一些单元素容器。但一般来说一个set只有一个类型参数,表示他的元素类型,一个Map有两个类型参数,表示键和值。考虑这么一种情况,数据库中的字段都是不同类型,怎么将一条数据加入到容器中。我们需要一个容器能够容纳不同类型的值。简单一想我们用Map不就行了,但这样有个缺点,我们无法通过键来确定值得类型,也就是说我们取值的时候是无法获得值得类型的。还有一种想法我们是不是可以制定一个规
2017-04-13 10:55:48 286
原创 (28):利用有限制通配符来提高API的灵活性
正如我们所知参数化类型是不可变的,也就是说List和List是没有任何关系的即使type1和type2是父子类的关系。当type1参数作为泛型参数时,type2即使是type1的子类,也不能作为泛型参数。看下面的例子:public class Stack { public Stack(); public void push(E e); public E
2017-04-12 15:45:02 280
原创 (27):优先考虑泛型方法
就如类可以从泛型中受益一般,方法也可以。静态工具方法尤其适合与泛型化。JDK中的Collections泛型中的所有“算法”方法都泛型化了。public static Set union(Set s1,Set s2){ Set result = new HashSet(s1); result.addAll(s2); return result;}
2017-04-12 15:14:16 329
原创 (26):优先考虑泛型
观察下面的代码:public class Stack { private E[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements =
2017-04-12 11:29:30 324
原创 java三种遍历集合的方法
(1):使用聚合操作在JDK 8和更高版本中,迭代集合可以通过获取流并对其执行聚合操作。聚合操作通常与lambda表达式结合使用,使编程更具表现力,使用较少的代码行。以下代码顺序遍历一组形状并打印出红色对象:myShapesCollection.stream().filter(e - > e.getColor()== Color.RED).forEach(e - > Syste
2017-04-12 10:50:23 839
原创 (25):列表优先于数组
数组是协变的(convariant),如果Sub是Super的子类型,那么数组类型Sub[]就是Super[]的子类型。Object[] obs=new Long[1]; obs[0]="hhe"; 这是可以的 泛型却是不可变的,List不是List的子类型。List list=new ArrayList();//编译错误list.add("hhe"); 数
2017-04-11 15:16:21 323
原创 (24):消除非受检警告
如果无法消除警告,同时又可以证明引起警告的代码是类型安全的。可以用一个@SuppressWarnings("unchecked")注解来禁止这条警告。 如果发现要在长度不止一行的方法或构造器中使用SuppressWarnings注解,可以将它移到一个局部变量的声名中,虽然必要声名一个新的局部变量,不过这么做还是值得的。SuppressWarnings注解方在return 语句中是非法的,每当使
2017-04-11 14:59:38 484
原创 (23):请不要在新代码中使用原生态类型
每种泛型都定义一个原生态类型(raw type),即不带任何实际类型参数的泛型名称。例如List为参数化类型List就是原生态类型。原生态类型是无法提供编译前检查的也就是说我们能在一个list中添加两个不同类型的值的。这是很不合理的,所以我们应该避免使用原生态类型。参数化类型就有效避免了这个问题。它能够提供编译前检查,并且可以自动完成类型转化。这个原则应该是刚开始学习编程就应该养成的习惯,这里
2017-04-11 11:01:03 245
原创 java移位简介
首先,移位运算符有三种,其操作类型只支持:byte / short / char / int和long五种。(注意这些类型取值范围)>> 右移运算符,二进制数据向右移动*位,高位补0(等同于除2的n次方)>>> 无符号右移运算符,不管移动前最高位是0还是1,右移后左侧产生的空位部分都以0来填充。所以平时的一般乘除能用移位代替的就用移位,这样能提高点性能。
2017-04-11 10:56:47 255
原创 (22):优先考虑静态成员类
嵌套类是指被定义在另一个类的内部的类。嵌套类存在的目的应该只是为了它的外围类提供服务。如果嵌套类将来有可能会用于其他的某个环境,它就应该是顶层类。嵌套类有四种:静态成员类,非静态成员类,匿名类,局部类。除了第一种,其他三种称为内部类。静态成员类是最简单的一种嵌套类。最好把它看做是普通的类,只是碰巧被声明在另一个类的内部而已。从语法上来讲,静态成员类和非静态成员类之间唯一的区别是,静
2017-04-10 17:05:57 381
原创 (21):用函数对象表示策略
为了在java中实现策略模式,要声明一个接口来表示该策略,并且为每一个策略声明一个实现了该接口的类。当一个具体策略只被使用一次时,通常使用匿名类来声明和实例化这个具体策略类。当一个具体策略类时设计用来重复使用的时候,它的类通常就要被实现为私有的静态成员类,并通过公有的静态final域被导出,其类型为该策略接口。策略模式具体请看:http://blog.csdn.net/ahui2333/a
2017-04-10 15:45:36 261
原创 策略模式
策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。下面就通过一个具体的例子来演示一下:假设现在要设计一个贩卖各类书籍的电子商务网站的购物车系统。一个最简单的情况就是把所有货品的单价乘上数量,但是实际情况肯定比这要复杂。比如,本网站可能对所有的高级会员提供每本20%的促销折
2017-04-10 15:29:22 224
原创 (20):类层次优先于标签类
所谓标签类,指的是一个类中充斥着许多样板代码,下面这个就是典型的标签类public class Figure1{ enum Shape { RECTANGLE, CIRCLE } // Tag field - the shape of this figure final Shape shape; //
2017-04-10 14:58:59 355
原创 (19):接口只用于定义类型
当类实现接口时,接口就充当可以引用这个类的实例类型。因此,类实现了接口,就表明客户端对这个类的实例可以实施某些动作。为了任何其他目的而定义的接口是不恰当的。常量接口就是一种错误的用法public class PhysicalConstants { private PhysicalConstants() {} public static final double AV
2017-04-10 14:43:04 644
原创 (18):接口优先于抽象类
因为java只允许单继承,所以抽象类受到了极大的限制。但是接口一点定义,被其他类广泛应用时,其扩张就变得很困难。而抽象类的演变比接口的演变容易得多。骨架通过对导出的每个重要接口都提供一个抽象的骨架实现类,把接口和抽象类的优点结合起来 。接口的作用仍然是定义类型,但是骨架实现类接管了所有域接口实现相关的工作 。static List intArrayAsList(final int[] a)
2017-04-10 10:38:01 443
原创 (17):要么为继承而设计,并提供文档说明,要么就禁止继承
对于专门为了继承而设计并且具有良好文档说明的类而言,该类的文档必须精确地描述覆盖每个方法所带来的影响。该类必须有文档说明它可覆盖的方法的自用性。对于每个公有的或受保护的方法或者构造器,它的文档必须指明该方法或者构造器调用了哪些可覆盖的方法,是以什么顺序调用的,每个调用的结果又是如何影响后续的处理过程的。更一般的,类必须在文档中说明,在哪些情况下它会调用可覆盖的方法。 如果具体的类没有实现标准的
2017-04-07 16:48:15 344
原创 (16):复合优先于继承
继承是实现代码重用的的有力手段,但它未必是最好的方法。对于普通的具体类进行跨越包边界的继承,则是非常危险的。这里的继承指的是一个类扩展另一个类的继承而非接口继承。继承的一大缺点在于打破了封装性。子类依赖于超类中特定的功能实现细节。意味着超类如果发生版本变化,子类有可能受到破坏。除非超类是专门为了扩展而设计的。public class InstrumentedHashSet extend
2017-04-06 15:02:58 352
原创 (15):使可变性最小化
不可变类只是其实例不能被修改的类。每个实例中包含的所有信息都必须在创建该实例的时候就提供,并在对象的整个生命周期内固定不变。为了使类成为不可变,要遵循下面五条规则:(1)不要提供任何会修改对象状态的方法(2)保证类不会被扩展(3)使所有的域都是final的(4)使所有的域都成为私有的(5)确保对于任何可变组件的互斥访问。public final class Complex{
2017-04-06 10:55:00 352
原创 ( 14 ) : 在公有类中使用访问方法而非公有域
class Point{public double x;public double y;}这种写法暴露了自己的成员,我们无法控制其他类访问这些成员。这是很违背面向对象的原则的。所以我们应该将类成员设为私有,改为使用set、get函数来控制其访问。
2017-04-05 17:31:45 304
原创 (13):使类和成员的可访问性最小化
设计良好的模块会隐藏所有的实现细节,把它的API与它的实现清晰的隔离开来。然后,模块之间只通过它们的API进行通信,一个模块不需要知道其他模块的内部工作情况。这被称封装。封装可以有效的解除组成系统各个模块的耦合关系。访问控制机制(access mode)决定了类,接口,成员的可访问性。正确的使用访问修饰符,对于实现信息隐藏是非常关键的。第一条规则:尽可能使每个类和成员不被外界访问。尽可能使
2017-04-05 10:55:39 301
原创 (12):考虑实现Comparable接口
如果一个类实现了Comparable接口,就表明它的实例具有内在的排序关系。为实现了Comparable接口的对象数组排序就是这么简单。Array.sort(a); 一旦类实现了Comparable接口,它就可以跟许多泛型算法以及依赖于该接口的集合实现进行协作。你付出了很小的努力就可以获得非常强大的功能。事实上,Java平台类库中的所有值类都实现了Comparable接口。如果你正在编写
2017-04-01 10:39:17 330
原创 (11):谨慎的覆盖clone
当我们想要克隆一个对象时,也就是说我们想要两个一模一样的对象,但想要这两个对象各自开辟空间的时候,我们通常要实现cloneable接口。但是接口没给我们提供clone的实现,但Object类却给我们提供了一个受保护的clone实现。一般来讲我们直接在子类重写的clone方法调用super,clone()可以得到我们想要的结果。import java.util.Date;public cl
2017-03-31 15:25:02 384
原创 (10):始终要覆盖toString
虽然Object提供了toString的实现,但它返回的是类名+@+散列码,这不是我们想看到的,所以强烈建议重写toString方法,把它展示成我们想要的结果。
2017-03-31 14:59:27 335
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人