Wednesday, 20 April 2016

Effective Java Item 78: Serialization proxy

 class Period implements Serializable{  
   private final Date start;  
   private final Date end;  
   
   public Period(Date start, Date end){  
     if (start.compareTo(end) > 0){  
       throw new IllegalArgumentException(start + " after "+end);  
     }  
     this.start = start;  
     this.end = end;  
   }  
   
   public Date start(){  
     return new Date(start.getTime());  
   }  
   
   public Date end(){  
     return new Date(end.getTime());  
   }  
   
   @Override  
   public String toString() {  
     return "start "+start+ " end "+end;  
   }  
   
   private static class PeriodProxy implements Serializable{  
     private final Date start;  
     private final Date end;  
   
     PeriodProxy(Period period){  
       this.start = period.start;  
       this.end = period.end;  
     }  
   
     private Object readResolve(){  
       return new Period(start, end);  
     }  
   }  
   
   private Object writeReplace(){  
     return new PeriodProxy(this);  
   }  
   
   private void readObject(ObjectInputStream in) throws InvalidObjectException{  
     throw new InvalidObjectException("Proxy required");  
   }  
   
 }  
   
 public class SerializationProxy {  
   public static void main(String[] args) throws Exception{  
     Calendar cal1 = Calendar.getInstance();  
     cal1.set(2015, Calendar.JANUARY, 1);  
     Calendar cal2 = Calendar.getInstance();  
     cal1.set(2016, Calendar.JANUARY, 1);  
     Period period = new Period(cal1.getTime(), cal2.getTime());  
     System.out.println(period);  
     Period deserializePeriod = serializeAndDeserialize(period);  
     System.out.println(deserializePeriod);  
   }  
   
   private static <T> T serializeAndDeserialize(T serialized) throws Exception {  
     File serializeFile = new File("_serialized");  
     // serialize  
     try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(serializeFile))) {  
       out.writeObject(serialized);  
     }  
     // deserialize  
     try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(serializeFile))) {  
       @SuppressWarnings("unchecked")  
       T deserialized = (T) in.readObject();  
       return deserialized;  
     }  
   }  

Tuesday, 19 April 2016

Effective Java Item 71: Lazy initialization, holder class, double checking

static field uses holder class

 private static class ValueHolder{  
     static final String value = "Lazy initialized";  
   }  
   
   public static String getValue(){  
     return ValueHolder.value;  
   }  

instance field uses double check

 private volatile String value;  
   
   public String getValue(){  
     String result = value;  
     if (result == null){  
       synchronized (this){  
         result = value;  
         if (result == null){  
           value = result = "LazyInitialized";  
         }  
       }  
     }  
     return result;  
   }  

if you don't mind re-creating instance again, You can use single check

 public String getValue(){  
     String result = value;  
     if (result == null){  
       value = result = "LazyInitialized";  
     }  
     return result;  
   }  

Monday, 18 April 2016

Effective Java Item 69: Synchronized map vs ConcurrentMap

Synchronized map

 public static void main(String[] args){  
     Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<String, String>());  
     syncMap.put("1","1");  
     syncMap.put("2","2");  
     syncMap.put("3","3");  
     for (String key : syncMap.keySet()){  
       addValue(syncMap);  
     }  
   }  
   
   private static void addValue(Map<String, String> map){  
     map.put("4", "4");  
   }  

Throws ConcurrentModificationException

 Exception in thread "main" java.util.ConcurrentModificationException  
      at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)  
      at java.util.HashMap$KeyIterator.next(HashMap.java:1453)  

ConcurrentHashMap never throws ConcurrentModificationException

 Map<String, String> syncMap = new ConcurrentHashMap<>();  

Sunday, 17 April 2016

Effective Java Item 66: Volatile, synchronization, and AtomicLong

volatile

 class SerialNumber{  
   private static volatile long nextSerialNumber = 0;  
   
   public static long nextSerialNumber(){  
     return nextSerialNumber++;  
   }  
 }  
   
 public class MyConcurrency extends Thread{  
   
   private static List<Long> numbers = new ArrayList<>();  
   
   private static synchronized void add(long number){  
     numbers.add(number);  
   }  
   
   public static void main(String[] args) throws Exception{  
     new MyConcurrency().start();  
     new MyConcurrency().start();  
     new MyConcurrency().start();  
     Thread.sleep(10*1000); //Make sure threads all end  
     Set<Long> hashSet = new HashSet<>();  
     for(long i : numbers) {  
       if(!hashSet.add(i)){  
         System.out.println("Has duplicate "+i);  
       }  
     }  
     System.out.println("Finish");  
   }  
   
   @Override  
   public void run() {  
     long nextSerialNumber;  
     do{  
       nextSerialNumber = SerialNumber.nextSerialNumber();  
       add(nextSerialNumber);  
     }while(nextSerialNumber < 10000);  
   }  
 }  

Found duplicates

 Has duplicate 4528  
 Has duplicate 5280  
 Has duplicate 7274  
 Has duplicate 9376  
 Finish  

Correct implementation using synchronized

 class SerialNumber{  
   private static long nextSerialNumber = 0;  
   
   public static synchronized long nextSerialNumber(){  
     return nextSerialNumber++;  
   }  
 }  

Correct implementation using AtomicLong

 class SerialNumber{  
   private static final AtomicLong nextSerialNumber = new AtomicLong();  
   
   public static long nextSerialNumber(){  
     return nextSerialNumber.getAndIncrement();  
   }  
 }  

Saturday, 16 April 2016

Threadlocal example

Business layer can access userId without passing the parameter from web layer.

 
 package threadlocal;  
   
 class SecurityContext {  
   
   private String userId = null;  
   
   public String getUserId() {  
     return userId;  
   }  
   
   public void setUserId(String userId) {  
     this.userId = userId;  
   }  
 }  
   
 class MyThreadLocal {  
   private static final ThreadLocal userThreadLocal = new ThreadLocal();  
   
   public static void set(SecurityContext user) {  
     userThreadLocal.set(user);  
   }  
   
   public static void unset() {  
     userThreadLocal.remove();  
   }  
   
   public static SecurityContext get() {  
     return (SecurityContext)userThreadLocal.get();  
   }  
 }  
   
 class BusinessService {  
   
   public void businessMethod() {  
     SecurityContext securityContext = MyThreadLocal.get();  
     System.out.println(securityContext.getUserId());  
   }  
 }  
   
 public class Main extends Thread{  
   public static void main(String[] args){  
     new Main().start();  
     new Main().start();  
   }  
   
   @Override  
   public void run() {  
     SecurityContext securityContext = new SecurityContext();  
     securityContext.setUserId(getName());  
     MyThreadLocal.set(securityContext);  
     new BusinessService().businessMethod();  
     MyThreadLocal.unset();  
   }  
 }  
   
Reference: http://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/

Effective Java Item 49: Auto boxed type NullPointerException

Seems quite innocuous, but throws NPE

Example 1

   public static void main(String[] args){  
     Boolean b = null;  
     call(b);  
   }  
   
   public static void call(boolean b){  
     System.out.println(b);  
   }  

Example 2

   public static void main(String[] args){  
     Integer i = null;  
     if (i == 42){  
       System.out.println(i);  
     }  
   }  

Thursday, 14 April 2016

jQuery return false; vs e.preventDefault()

return false;

is equal to

e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();

So the lesson is never use 'return false' unless you completely understand it.

Reference: http://fuelyourcoding.com/jquery-events-stop-misusing-return-false/comment-page-2/#comment-73556