- Thread抛出异常就死亡了。但是线程池却会生成一个新的线程
尽量使用接口引用对象
不用接口引用的情况:
没有合适的接口的情况。例如: 值类型,String和StringBuilder,Random。通常是final类型.
如果程序依赖于实现了某个接口的类的额外方法,例如LinkedHashMap
不要使用字符串连接操作符来合并多个字符串,除非性能无关紧要。相反,应该使用StringBuilder的append方法。另一种方法是,使用字符数组,或者每次只处理一个字符串,而不是将它们组合起来。
以为字符串的不可变,当两个字符串连接在一起时,他们的内容就会被拷贝
1 | StringBuilder b = new StringBuilder(numItems() * LINE_WIDTH); |
foreach可以遍历iterable接口
foreach循环在简洁性与预防bug方面有着传统的for循环无法比拟的优势.
除了一下情况:
过滤- 将删除特定元素remove方法
转换- 使用列表迭代器或者数组索引,以便设定元素的值
平行迭代- 如果并行遍历多个集合,就需要显示的控制迭代器和索引变量
http://blog.csdn.net/zhtzyh2012/article/details/46675065
循环提供特殊机会将变量作用域最小化.(无论传统for,还foreach).for循环,都允许声明循环变量,它们的作用域被限定在正好的作用范围之内.(范围包括循环体,以及循环体之前的初始化,测试,更新).如果循环终止之后不再需要循环变量内容,for循环优于while循环.
几乎每个局部变量的声明都应该包含一个初始化表达式.如果没有足够信息来对一个变量进行有意义的初始化,就应该推迟这个声明,直到可以初始化为止.例外情况是与try..catch有关.
for循环比while循环另外优势:更简短,增加可读性.
1 | public static void main(String[] args) { |
最好不要用序数来索引数组,而要使用EnumMap
EnumMap源代码学习
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 public V put(K key, V value) {
typeCheck(key);
int index = key.ordinal();
Object oldValue = vals[index];
vals[index] = maskNull(value);
if (oldValue == null)
size++;
return unmaskNull(oldValue);
}
public V remove(Object key) {
if (!isValidKey(key))
return null;
int index = ((Enum<?>)key).ordinal();
Object oldValue = vals[index];
vals[index] = null;
if (oldValue != null)
size--;
return unmaskNull(oldValue);
}
public V get(Object key) {
return (isValidKey(key) ?
unmaskNull(vals[((Enum<?>)key).ordinal()]) : null);
}
public boolean containsKey(Object key) {
return isValidKey(key) && vals[((Enum<?>)key).ordinal()] != null;
}
实现函数对象的几种方式:
- C语言的函数指针
- lambda表达式
- 函数式接口
函数对象主要用于策略模式.只用一次的话,使用匿名内部类;多次使用的话,可以导出成一个成员域(static final修饰)
实例:
java.util.Comparator
实现函数对象的几种方式:
- C语言的函数指针
- lambda表达式
- 函数式接口
函数对象主要用于策略模式.只用一次的话,使用匿名内部类;多次使用的话,可以导出成一个成员域(static final修饰)
实例:
java.util.Comparator
当类实现接口时 ,接口就充当可以引用这个类的实例的类型(type)。因此,类实现了接口,就表明客户端可以对这个类的实例实施某些动作。为了任何其他目的而定义接口是不恰当的。
有一种接口被称为常量接口(constant interface),它不满足上述条件。这种接口没有方法,只有静态final域。常量接口模式是对接口的不良使用。这样做不仅会暴露该类的实现细节到导出API中,还会产生一个更糟糕的情况。就是在将来的发行版中,如果类不再需要使用这些常量,它依然必须实现这个接口,以确保二进制兼容性。如果非final类实现了常量接口,它的所有子类的命名空间也会被接口中的常量所“污染”。
反例
Java平台类库中有几个常量接口,例如java.io.ObjectStreamConstants。这些接口应该被认为是反面的典型,不值得效仿。
方案。
1.如果常量与某个现有类或接口紧密相关,就应该把这些常量添加到这个类或接口中。
2.如果这些常量可以被看作枚举类型的成员,就应该用枚举类型(enum type)。
3.用不可实例化的工具类( utility class)。使用静态导入(import static)避免常量修饰.
- 至少传递一个
1 | private static <E> void varargs(Object obj,E...varargs){ |
泛型编程只能接受引用类型
打印数组tostring,会导致没有意义的字符结果
可变参数每次调用都会导致有一次数组分配和初始化
EnumSet静态工厂最大限度地减少创建枚举集合的成本
1 | public static <E extends Enum<E>> EnumSet<E> of(E first, E... rest) { |
- Arrays.toString(int[] args)可以打印数组,而不是可变参数
Lambda没有文档和名字,如果不能方法体太长或者不能自解释的话,那么就不要放到lamdba中。
Lambda不能使用this访问自身。this在Lambda是访问的外部类。如果要在方法体中访问自身的话,那么就不能使用Lambda
不要在创建函数对象的时候使用匿名内部类,除非创建的对象不是函数式接口。
1 | public enum Operation { |