Annotations in Java & The Singleton Class Explained

 

Lightbox-Game-Friday

Annotations in Java provide a means to describe classes, fields, and methods. Essentially, they are a form of metadata added to a Java source file, they can’t affect the semantics of a program directly. However, annotations can be read at run-time using Reflection & this process is known as Introspection. Then it could be used to modify classes, fields, or methods.

This feature is often exploited by Libraries & SDKs (hibernate, JUnit, Spring Framework) to simplify or reduce the amount of code that a programmer would otherwise do in order to work with these Libraries or SDKs. Therefore, it’s fair to say Annotations and Reflection work hand-in hand in Java.

We also get to limit the availability of an annotation to either compile-time or runtime. Below is a simple example on creating a custom annotation

01. Driver.java

package io.hamzeen;
import java.lang.annotation.Annotation;
public class Driver {
public static void main(String[] args) {
Class<TestAlpha> obj = TestAlpha.class;
if (obj.isAnnotationPresent(IssueInfo.class)) {
Annotation annotation = obj.getAnnotation(IssueInfo.class);
IssueInfo testerInfo = (IssueInfo) annotation;
System.out.printf("%nType: %s", testerInfo.type());
System.out.printf("%nReporter: %s", testerInfo.reporter());
System.out.printf("%nCreated On: %s%n%n",
testerInfo.created());
}
}
}

02. TestAlpha.java

package io.hamzeen;
import io.hamzeen.IssueInfo;
import io.hamzeen.IssueInfo.Type;
@IssueInfo(type = Type.IMPROVEMENT, reporter = "Hamzeen. H.")
public class TestAlpha {
}

03. IssueInfo.java

package io.hamzeen;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * @author Hamzeen. H.
 * @created 10/01/2015
 * 
 * TestInfo annotation definition
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface IssueInfo {
public enum Type {
BUG, IMPROVEMENT, FEATURE
}
Type type() default Type.BUG;
String reporter() default "Vimesh";
String created() default "10/01/2015";
}

The Singleton Class Explained

nyker2

Understand three different ways to define the Singleton class in Java, and why one of them is preferred.

There are a handful of ways to define a Singleton class in Java. They aren’t that difficult, yet doing it the correct way matters. Here I have listed three ways of doing it. However, only the third, which uses an on-demand holder acronym is preferred as the singleton instance created here is thread-safe and unique.

Trivia 1: Why we don’t import classes like System, Integer and String?
Answer: The package java.lang.*; is implicitly imported.

Trivia 2: Can the main method of a Java program reside in an abstract class?
Answer: Yes it can! See the Driver class below.

1. Eager Singleton

package design.com.hamzeen;
public class EagerSingleton {
private static EagerSingleton ins = new EagerSingleton();
public static EagerSingleton getInstance() {
return ins;
}
private EagerSingleton() {
}
}

2. Lazy Singleton

package design.com.hamzeen;
public class LazySingleton {
private static LazySingleton ins;
public static LazySingleton getInstance() {
if (ins == null) {
ins = new LazySingleton();
}
return ins;
}
private LazySingleton() {
}
}

3. Singleton Holder

package design.com.hamzeen;
public class SingletonHolder {
public static SingletonHolder getInstance() {
return Holder.ins;
}
private final static class Holder {
private static final SingletonHolder ins = 
new SingletonHolder();
}
private SingletonHolder() {
}
}

4. The Driver and Output

package design.com.hamzeen;
public abstract class Driver {
public static void main(String[] args) {
EagerSingleton a1 = EagerSingleton.getInstance();
EagerSingleton a2 = EagerSingleton.getInstance();
System.out.println(a1.toString());
System.out.println(a2.toString());
LazySingleton b1 = LazySingleton.getInstance();
LazySingleton b2 = LazySingleton.getInstance();
System.out.println(b1.toString());
System.out.println(b2.toString());
SingletonHolder c1 = SingletonHolder.getInstance();
SingletonHolder c2 = SingletonHolder.getInstance();
System.out.println(c1.toString());
System.out.println(c2.toString());
}
}

 

Courtesy: Dzone