Double Brace Initialization
双括号初始化,创建一个从指定类(外部大括号)派生的匿名类,并在该类(内部大括号)中提供初始化块。
每次使用双括号初始化时,都会生成一个新类,创建的类具有指向周围外部类的隐式this指针。
例如:
| Map source = new HashMap(){{ put("firstName", "John"); put("lastName", "Smith"); put("organizations", new HashMap(){{ put("0", new HashMap(){{ put("id", "1234"); }}); put("abc", new HashMap(){{ put("id", "5678"); }}); }}); }};
|
…将产生这些类:
Test$1$1$1.class
Test$1$1$2.class
Test$1$1.class
Test$1.class
Test.class
当然,如果你这样只做一次,它将不需要太多的初始化时间。
优点非常明显:
- 对于熟悉该使用方法的人而言,它具有更好的可读性以及更好的维护性。
- 在使用Double Brace Initialization的时候,我们实际上创建了一个匿名类。匿名类有一个性质,那就是该匿名类实例将拥有一个包含它的类型的引用。如果我们将该匿名类实例通过函数调用等方式传到该类型之外,那么对该匿名类的保持实际上会导致外层的类型无法被释放,进而造成内存泄露。
- 另外一个缺点则是破坏了equals()函数的语义。在为一个类型实现equals()函数的时候,我们可能需要判断两个参与比较的类型是否一致。
最常见的一种解决方案就是使用第三方类库。例如由Apache Commons类库提供的ArrayUtils.toMap()函数就提供了一种非常清晰的创建Map的实现:
| Map<Integer, String> map = (Map) ArrayUtils.toMap(new Object[][] { {1, "one"}, {2, "two"}, {3, "three"} });
|
类实例化顺序
| public class App { public App(String name) { System.out.println(name + "'s constructor called"); }
static { System.out.println("static initializer called"); }
{ System.out.println("instance initializer called"); }
static { System.out.println("static initializer2 called"); }
{ System.out.println("instance initializer2 called"); }
public static void main( String[] args ) { new App("one"); new App("two"); } }
|
ThreadLocal
提供线程局部变量。这些变量与普通变量不同,因为每个访问一个线程(通过其get或set方法)的线程都有其自己的,独立初始化的变量副本。
ThreadLocal实例通常是希望将状态与线程关联的类中的私有静态字段(例如,用户ID或事务ID)。
只要线程是活动的并且ThreadLocal 实例是可访问的,则每个线程都对其线程局部变量的副本持有隐式引用。线程消失后,其线程本地实例的所有副本都将进行垃圾回收(除非存在对这些副本的其他引用)。
| import java.util.concurrent.atomic.AtomicInteger;
public class UniqueThreadIdGenerator {
private static final AtomicInteger uniqueId = new AtomicInteger(0);
private static final ThreadLocal < Integer > uniqueNum = new ThreadLocal < Integer > () { @Override protected Integer initialValue() { return uniqueId.getAndIncrement(); } };
public static int getCurrentThreadId() { return uniqueId.get(); } } // UniqueThreadIdGenerator
|
Compare and swap (CAS)
| public class SimulatedCAS { private int value;
public synchronized int getValue() { return value; }
public synchronized int compareAndSwap(int expectedValue, int newValue) { int oldValue = value; if (value == expectedValue) value = newValue; return oldValue; } }
public class CasCounter { private SimulatedCAS value;
public int getValue() { return value.getValue(); }
public int increment() { int oldValue = value.getValue(); while (value.compareAndSwap(oldValue, oldValue + 1) != oldValue) oldValue = value.getValue(); return oldValue + 1; } }
|
Lock-free and wait-free algorithms
| public class PseudoRandomUsingSynch implements PseudoRandom { private int seed;
public PseudoRandomUsingSynch(int s) { seed = s; }
public synchronized int nextInt(int n) { int s = seed; seed = Util.calculateNext(seed); return s % n; } }
public class PseudoRandomUsingAtomic implements PseudoRandom { private final AtomicInteger seed;
public PseudoRandomUsingAtomic(int s) { seed = new AtomicInteger(s); }
public int nextInt(int n) { for (;;) { int s = seed.get(); int nexts = Util.calculateNext(s); if (seed.compareAndSet(s, nexts)) return s % n; } } }
|