过早的声明不仅会使它作用域扩大,而且结束也过晚
如果在初始的时候,没有足够的信息对变量进行有意义的初始化,可以推迟声明,当然try catch例外
另外,一种使局部变量最小化的实践是
for(int i=0,n=expensiveComputation();i<n;i++){ doSomething(i); }
enum Face { ONE, TWO, THREE, FOUR, FIVE, SIX } public class DiceRolls { public static void main(String[] args) { Collection<Face> faces = Arrays.asList(Face.values()); for (Iterator<Face> i = faces.iterator(); i.hasNext(); ) for (Iterator<Face> j = faces.iterator(); j.hasNext(); ) System.out.println(i.next() + " " + j.next()); // Preferred idiom for nested iteration on collections and arrays // for (Face face1 : faces) // for (Face face2 : faces) // System.out.println(face1 + " " + face2); } }
while容易出错,而且变量范围大
Iterator<Element> i = c.iterator(); while(i.hasNext()){ doSomething(i.next()); } for(Iterator<Element> i =c.iterator();i.hasNext();){ doSomething(i.next()); } ... Iterator<Element> i2 = c2.iterator(); //BUG,拷贝出错了 while(i.hasNext()){ doSomething(i.next()); } //compile error for(Iterator<Element> i2 =c2.iterator();i.hasNext();){ doSomething(i.next()); }
for(Iterator i = c.iterator();i.hasNext();){ doSomething(i.next()); } for(int i=0;i<a.length;i++){ doSomething(a[i]); } //迭代器和索引变量容易引起一些混乱,特别是循环多层嵌套的情况下
public class NestedIteration { public static void main(String[] args) { Collection<Suit> suits = Arrays.asList(Suit.values()); Collection<Rank> ranks = Arrays.asList(Rank.values()); List<Card> deck = new ArrayList<Card>(); //BUG,NoSuchElementException for (Iterator<Suit> i = suits.iterator(); i.hasNext(); ) for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); ) deck.add(new Card(i.next(), j.next())); // Preferred idiom for nested iteration on collections and arrays // for (Suit suit : suits) // for (Rank rank : ranks) // deck.add(new Card(suit, rank)); } }
A、过滤条件,可以使用iterator的remove方法
B、需要使用索引值的情况
它们执行二进制浮点运算,为了在广泛的数值范围上提供较为精确的快速近似计算而精心设计的,但没有提供精确的结果,不适合需要精确值的货币计算。
用BigDecimal替代double,不好的地方就是与基本类型做比较相对麻烦,而且比较慢。
public class Arithmetic { public static void main(String[] args) { System.out.println(1.03 - .42); System.out.println(); System.out.println(1.00 - 9 * .10); System.out.println(); howManyCandies1(); System.out.println(); howManyCandies2(); System.out.println(); howManyCandies3(); } // Broken - uses floating point for monetary calculation! public static void howManyCandies1() { double funds = 1.00; int itemsBought = 0; for (double price = .10; funds >= price; price += .10) { funds -= price; itemsBought++; } System.out.println(itemsBought + " items bought."); System.out.println("Change: $" + funds); } public static void howManyCandies2() { final BigDecimal TEN_CENTS = new BigDecimal( ".10"); int itemsBought = 0; BigDecimal funds = new BigDecimal("1.00"); for (BigDecimal price = TEN_CENTS; funds.compareTo(price) >= 0; price = price.add(TEN_CENTS)) { itemsBought++; funds = funds.subtract(price); } System.out.println(itemsBought + " items bought."); System.out.println("Money left over: $" + funds); } public static void howManyCandies3() { int itemsBought = 0; int funds = 100; for (int price = 10; funds >= price; price += 10) { itemsBought++; funds -= price; } System.out.println(itemsBought + " items bought."); System.out.println("Money left over: "+ funds + " cents"); } }
A、对于需要精确值的,请不要用float和double
B、BigDecimal的好处是可以进行四舍五入的控制
C、如果数值范围没有超过9位的十进制数,可以使用int,如果不超过18位的十进制数,使用long,超过18位的,必须使用BigDecimal
D、如果性能比较关键,自己又不介意记录小数值,涉及的数又不太大的话,可以使用int或long
A、基本类型只有值,而装箱基本类型有引用的概念,允许值相等但是引用不等
B、基本类型只有功能完备的值,而装箱类型,有null值
C、基本类型比装箱类型更节省时间和空间
Integer i; .... if(i == 42){ } //可能报空指针错误,因为如果没有赋值,若是类成员,默认为null,不可以用== 跟int比较 //但另外,装箱类型与原始类型进行比较,只要不是null,可以自动拆箱 //Integer first,Integer second if(first == second){ //这里是引用比较,不是值比较 }
A、作为集合元素、键值时
B、参数泛型时
A、如果是数值,用int、float、BigInteger类型
B、如果是布尔,用true/false
枚举类型更适合用来表示常量
String compoundKey = className + "#" + i.next();
这种情况,容易出现结果混乱,通常解析的时候,过程相对缓慢,繁琐,容易出错,使用Scala的Case类的模式匹配正好。
尽量使用泛型
为连接n个字符串而且重复地使用字符串连接操作符,需要n的平方级的时间
在方法里头,用StringBuilder,如果是类成员范围的,如果线程安全的话,需要StringBuffer,但一般不怎么在类成员范围内使用。因而StringBuilder足够。
List<String> list = new Vector<String>(); //优于 Vector<String> list = new Vector<String>();
同理,在参数、返回值类型也适用。这样做的目的,是可以更改实现,特别是对外部系统暴露接口时,更改实现的时候,不需要调用方更改类型。
A、丧失了编译时类型检查的好处
B、执行反射访问所需要的代码非常笨拙和冗长
C、性能损失
A、反射功能只是在设计时被用到,普通程序不应该在运行时以反射访问对象
比如容器初始化阶段、比如在开发阶段用代码生成器生成增删改查方法
B、以有限形式使用,可以获得许多好处的情况下,可以使用
比如远程服务框架等
A、提供访问特定于平台的机制,比如访问注册表等
B、提供访问遗留代码库的能力
C、通过本地语言提升系统性能
这点不值得提倡,容易导致不可移植,以及代码维护性问题
A、本地语言不安全
B、本地方法难以调试
C、胶合代码难以阅读
com.sun等,以Internet域开头
使用util替代utilities
使用HttpUrl替代HTTPURL
NEGATIVE_INFINITY
T表示任意的类型,E表示集合的元素类型,K和V表示映射的键值类型,X表示异常
类型序列可以使用T,U,V,或者T1,T2,T3
A、执行动作的方法,常用动词或动词短语了来命名,比如append,drawImage
B、布尔值,常以is开头后面跟名称或名称短语,很少用has
isDigit,isProbablePrime,isEmpty,isEnabled,hasSiblings
C、类型转换,使用toType命名,比如toString,toArray
D、返回视图,使用asType,比如asList
E、返回基本类型,使用typeValue,比如intValue
F、静态工厂经常使用valueOf,of,getInstance,newInstance,getType,newType
(1)API设计时考虑性能
特别是设计数据结构的时候,如果合理,可以避免不变要的join
(2)优化前后要进行测量
考虑优化的重心在哪里