JAVA拾遗
枚举
枚举允许构造函数和抽象方法
1 | public enum TrafficLight { |
枚举只有一个成员时
单元素的枚举类型已经成为实现
Singleton 的最佳方式 。 Joshua Bloch, Effective JAVA ——
1 | public class Singleton { |
可变参数方法
使用可变参数方法时
1 | public static void printArray(int... is) { |
泛型 (Generic)
容器 (Container)
One of the reasons that generic comes out.
1 | ArrayList<String> strList = new ArrayList<>(); |
Declare a generic class.
1 | class MyList <T> { … } |
Declare a generic function.
1 | public <T> T get(int index) { … } |
类型擦除 (Type Erasure)
If you do this below, you will get an error.
1 | new ArrayList<int>(); // ERROR! |
ERROR: Type argument can not be basic type.
Types are removed from a JAVA program, before it is executed at runtime.
1 | public <T> T add(T a, T b) { |
ERROR: Operator '+' cannot be applied to 'T', 'T'.
However, similar codes in C++ works.
The reason is that in C++ template can be regarded as advanced macro.
But this one in JAVA is okay.
1 | public <T> boolean isSame(T a, T b) { |
T is just a Object. That's why the argument can not be basic type, and that explains why operator '+' is not allowed.
JAVA can not get anything from type argument, and the declaration below causes error.
1 | Class<?> c = ArrayList<String>.class; // ERROR! |
This one is correct.
1 | Class<?> c = ArrayList.class; |
In JAVA, ArrayList<String>
and ArrayList<Integer>
are the same type.
无界通配符 (Unbounded Wildcard) <?>
Wildcard(通配符) <?>
can be used in variable declarations, but not in the definition of a generic type.
1 | Class<?> c = ArrayList.class; |
It is the same as the code below.
1 | Class<? extends Object> c = ArrayList.class; |
上界通配符 (Upper Bound Wildcard) <? extends …>
Use
<? extends …>
in function argument when calling T's member method is required.
1 | void printText(List<? extends TextView> textViews) { |
协变 (Covariance)
In JAVA, it looks fine but wrong.
1 | ArrayList<Fruit> fruits = new ArrayList<Apple>(); // ERROR! |
JAVA's generic is invariant(不变的), so
List<Base>
has no relation toList<Derive>
. Covariance means thatList<Derive>
inheritsList<Base>
, it’ s needed in some situations.
Code like this when covariance is needed.
1 | ArrayList<? extends Fruit> fruits = new ArrayList<Apple>(); |
But the restriction is that any alteration to T
type variable is unavailable as well as function with T
type parameter is not allowed.
1 | fruits.add(Apple()); // ERROR! |
So covariance means read-only.
1 | void printText(List<? extends TextView> textViews) { |
逆变 (Contravariance)
Contravariance is a totally different situation.
1 | ArrayList<? super Apple> apples = new ArrayList<Fruit>(); |
But there still exists restriction.
1 | Apple apple = apples.get(0); |
That contravariance means write-only. See this example below.
1 | void addText(List<? Super TextView> textViews) { |
In a word, follow PECS rule.
PECS Rule
Producer Extends Consumer Super.
多重约束 (Multiple Boundary)
So strange because
A
andB
are interfaces, but still keywordextends
is used here.
1 | interface A { … } |
多线程
同步锁
下例为经典的代理卖票问题
没有同步锁的情况
多个线程同时访问共享的资源 , 将导致线程不同步 , 又称线程不安全 , 。
1 | public void run() { |
线程池
管理线程
可缓存线程池
可回收旧线程: ; 1
2
3
4
5
6
7
8
9ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < 10; ++i) {
final int index = i; // JAVA8
exec.execute(new Runnable() {
public void run() {
...
}
});
}有限线程池
: Executors.newFixedThreadPool(n)
创建一个定长线程池, 可控制线程最大并发数, ; 单一线程池
: Executors.newSingleThreadExecutor()
保证所有任务按指定顺序执行, 只会用唯一的工作线程来执行任务, 相当于线程数量为, FixedThreadPool
。
JNI(Java Native Interface)
使用native
1 | public synchronized void start() { |
❽Optional
1 | Optional.ofNullable(user) |