Item 45: 将局部变量的作用域最小化
书说: 推荐在第一次使用这个局部变量的时候才初始化。如果初始化的条件还不足,说明还没到时候初始化。例外: try-catch
Item 46: for-each 优于for循环与while循环
主要是for-each 的代码看起来更加简洁, 效率稍微提高。
Item 49: 基本类型优于装箱类型
我觉得看stackoverflow的这一篇帖子说得更清楚一些:
http://stackoverflow.com/questions/5199359/why-do-people-still-use-primitive-types-in-java
总结下来, 有几点原因:
- 性能
对原帖子的代码做了一下修改,直接对两者进行了对比:
12345678910111213141516Date d1 = new Date();Long sum1 = 0L; // uses Long, not longfor(long i = 0; i <= Integer.MAX_VALUE / 2; i++) {sum1 += i;}System.out.println(sum1);Date d2 = new Date();long sum2 = 0L; // uses long, not Longfor(long i = 0; i <= Integer.MAX_VALUE / 2; i++) {sum2 += i;}System.out.println(sum2);Date d3 = new Date();System.out.println("Long: " + (d2.getTime() - d1.getTime()));System.out.println("long: " + (d3.getTime() - d2.getTime()));
输出:
1234576460751766552576576460751766552576Long: 4608long: 350可以看到, 使用装箱类型(
Long
)耗时4.6s, 如果使用基本类型(long) 只需要0.35s这个性能损耗来自对原始的基本类型的封装。需要自动的boxing / unboxing.这里面多少会有性能损失。
当然, 如果在你的实际应用之中,你觉得这个性能损耗也还行, 也可以~
- null值
装箱类型有可能是null, 而原始的基本类型有个默认值(0)比如下面的极端例子, 会抛出NullPointerException
但是编译的时候是检查不出来的:123Integer i1 = null;int i2 = i1; - 装箱类型是奇怪的类!
比如下面的代码:1234567public static void main(String[] args) {System.out.println(new Integer(5) == new Integer(5));System.out.println(new Integer(500) == new Integer(500));System.out.println(Integer.valueOf(5) == Integer.valueOf(5));System.out.println(Integer.valueOf(500) == Integer.valueOf(500));}输出:
1234falsefalsetruefalse(1) / (2) 是因为他们地址不一样,返回
false
很好理解。为什么(3)返回true, 而(4)返回false?
- 首先:Integer是类, 正确的比较方法是使用
equal
- 其次:5处在最接近0的256个整数[-128, 127]的区间之中,JVM自动有特殊处理,使其返回的是同一个对象
把上面的代码改一下,把
==
改成<
12345System.out.println(<span class="hljs-keyword">new</span> Integer(<span class="hljs-number">5</span>) < <span class="hljs-keyword">new</span> Integer(<span class="hljs-number">5</span>));System.out.println(<span class="hljs-keyword">new</span> Integer(<span class="hljs-number">500</span>) < <span class="hljs-keyword">new</span> Integer(<span class="hljs-number">500</span>));System.out.println(Integer.valueOf(<span class="hljs-number">5</span>) < Integer.valueOf(<span class="hljs-number">5</span>));System.out.println(Integer.valueOf(<span class="hljs-number">500</span>) < Integer.valueOf(<span class="hljs-number">500</span>));输出结果就比较符合我们的直觉了,都是输出的
false
- 首先:Integer是类, 正确的比较方法是使用
那什么时候才需要使用装箱类型?
在Java之中, 在一些集合类型,比如Map、List,或者参数化类型,比如ThreadLocal<Integer>,不能是基本类型。
本文原创, 原文地址:http://www.flyml.net/2017/03/16/effective-java-ch8-common-design/
Item 52: 通过接口引用对象
如果有合适的接口类型存在, 那么对于参数、返回值、变量和域来说, 都应该使用接口类型进行声明。
1 2 3 4 5 |
// Good List<String> list1 = new ArrayList<String>(); // Bad ArrayList<String> list2 = new ArrayList<String>(); |
使用接口而不是直接使用具体的实现类的好处是:灵活
当我们需要变更底层的实现方法的时候,比如需要从ArrayList
切换到LinkedList
,对外提供的接口、方法等等都不需要变更。
除非真的需要具体类里面的特殊方法, 才使用具体的类。
Item 53: 接口优先于反射机制
略
Item 56: 遵守普遍接受的命名规则习惯
这部分更详细、更完整的,应该参考:
- Google Java 编程规范https://google.github.io/styleguide/javaguide.html
- 阿里巴巴的Java编程规范https://bbs.aliyun.com/read/306592.html?page=e
本文原创, 原文地址:http://www.flyml.net/2017/03/16/effective-java-ch8-common-design/
本文原创, 原文地址:
http://www.flyml.net/2017/03/16/effective-java-ch8-common-design/

文章评论