67. Autoboxing - primitives Primitives does not work well with Collections or any other class that work on Object void visit(String page) { int val = 0; if (stats.containsKey(page)) { val = ((Integer) stats.get(page)).intValue(); } Integer newVal = new Integer(++val) ; stats. put (page, newVal); }
107. May be used together with package, class, interface, field, method, parameter, constructor and local variables @MyAnnotation(“value”) public class MyClass { @MyAnnotation(value = “value”) int var = ...; @MyAnnotation(“value”, myDefault=”noDefault”) public void method() @MyAnnotation(“value”) public MyClass(@MyAnnotation(“param”) String arg) {
108.
109. If classes are not available they silently “disappear” @HiddenAnnotation("Ha") public static void main(final String[] args) throws Exception{ Method m = AnnotationTest.class. getMethod("main", String[].class); Annotation[] as = m.getDeclaredAnnotations() ; for (Annotation a: as) { if (a instanceof HiddenAnnotation){ System.out.println("Value=" + ((HiddenAnnotation)a).value() ); } } }
110.
111. Contains interfaces and core classes which makes it easier and safer to work with concurrency
129. Atomic check and take action methods V putIfAbsent(K key, V value); boolean remove(Object key, Object value); V replace(K key, V value); boolean replace(K key, V oldValue, V newValue);
153. Uses Future and Callable Callable<String> worker = new Callable<String>() { int c = 0; public String call() { try {Thread.sleep(2000L);}catch(Exception ignore){} return "jobb no " + c++; } }; ExecutorService exe = Executors.newSingleThreadExecutor(); Future<String> result = exe.submit(worker); while(!result.isDone()) { // Do something other } String s = result.get();
159. Non blocking counting AtomicLong at = new AtomicLong(); // one thread, no synchronzied long current = at.get(); // another thread increment, no sync at.incrementAndGet();
181. Getting the mbean server and managing an object public static interface My { public String getMyName(); } public static class MyImpl implements My { String n; MyImpl(String s) { n = s; } public String getMyName(){return n;} } ArrayList servers = MBeanServerFactory.findMBeanServer(null); if (servers.size() > 0) { server = (MBeanServer)servers.get(0); StandardMBean b = new StandardMBean(new MyImpl("Peter"), My.class); server.registerMBean(b, new ObjectName("test:name=Peter")); }
206. Also hard to test: requires deployment in runtime environment public void service(ServiceManager sm) { ds = (DataSource)sm.lookup(“myDataSource”); }
235. Simple logging interceptor Object target; LoggingInterceptor(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { log("TRACE", "Calling " + method.getName()); return method.invoke(target, args); } My m = (My)Proxy.newProxyInstance(Thread.currentThread(). getContextClassLoader(), new Class[]{My.class}, new LoggingInterceptor(new MyImpl())); String s = m.hello();
236.
237.
238.
239.
240. First part static class ThreadLocalInterceptor<T> implements InvocationHandler { Object target; Class targetClass; ThreadLocal<T> local; ThreadLocalInterceptor(Object target, ThreadLocal<T> local) { this.target = target; this.local = local; targetClass = target.getClass(); }
241. ThreadLocalInterceptor – part 2 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // Need to use real target class! Method targetMethod = targetClass. getDeclaredMethod(method.getName(), method.getParameterTypes()); InjectThreadLocal a = targetMethod. getAnnotation(InjectThreadLocal.class); if (a != null) { Field f = targetClass.getField(a.name()); if (f != null) { Object tl = local.get(); if (f.getType().isAssignableFrom(tl.getClass())) { f.set(target, tl); } } } return method.invoke(target, args); }