0

Java隐藏特征

 2 years ago
source link: https://perkins4j2.github.io/posts/3350900/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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;
}
}
}



About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK