Sunday, September 28, 2014

Annotations: Java

Annotation is a tag, of interface type, which will be processed during compile-time or run-time.

The concept of "Annotations" in java is introduced in java 1.5.
These are inserted into the code to provide more information about the code(meta code)

Annotations can be processed by the compiler (or) annotation processing tools, which can be made available at run-time.
eg: Java predefined annotations are processed by "apt.exe" under jdk's bin folder
Servlet specific annotations are processed by a jar called "annotations-api.jar"

Advantages of using Annotations:
1. Provides a kind of information to the compiler, for eg: to detect programmer error(Override) or to suppress warnings
2. Compile-time and Deployment-time processing
3. Run-time processing

Types of Annotations:
There can be two types of annotations
1. Built-in annotations(Predefined)
2. Custom annotations(User-defined)

1. Built-in Annotations:
These are provided by Sun as part of java 1.5
There are 7 built-in annotations

  • Override
  • Deprecated
  • SuppressWarnings
  • Retention
  • Target
  • Documented
  • Inherited


@Override, @Deprecated, @SuprressWarnings - These 3 are called Regular Java Annotations and are used at compile-time.
Remaining 4 (Retention, Target, Documented, Inherited) are used to create custom annotations.

Regular Annotations:

1. @Override
This can be used by the compiler to check whether a method in sub-class is properly overriding its super-class method or not.
The Retention Policy for @Override annotation is SOURCE, which means this java annotation will be discarded completely after compiling the code and would not be included in .class file or byte code.

eg:
I want to override equals method in Object class, whose signature is:
public boolean equals(Object obj)

class OverrideDemo {
        @Override
        public boolean equals(OverrideDemo od) {
                return false;
        }
}

Compiler output:

If you replace equals method parameter "OverrideDemo" with "Object", it gets compiled without any errors.

2. @Deprecated:
This can be specified to all types - variables/classes/methods.

When this is specified for a method, it indicates the developer who are using those API methods, that this method should not be used and it is expected to be removed in future releases.

If developer still uses it, it gives a warning during compile-time.

eg:
@Deprecated
class ClassOne {
}

public class DeprecatedDemo {
        static public void main(String[] args) {
                ClassOne one = new ClassOne();
        }
}

Compiler output:


3. @SuppressWarnings:
This instructs the compiler to suppress warnings of a particular type that are shown during compilation time.

This can be applied only to Classes.

For this annotation type, we must pass the value which should be suppressed. If no value is passed, compiler flags it with following error.
annotation java.lang.SuppressWarnings is missing value

eg:
import java.util.List;
import java.util.ArrayList;

public class ListDemo {
        static public void main(String[] args) {
                List list = new ArrayList();
                list.add("one");
        }
}

Compiler output:


Now if you modify the code as below, to remove "unchecked" or "unsafe" warnings, compiler will not flag any warning.

import java.util.List;
import java.util.ArrayList;

@SuppressWarnings(value="unchecked")
public class ListDemo {
        static public void main(String[] args) {
                List list = new ArrayList();
                list.add("one");
        }
}

Meta Annotations:
These are used to create custom java annotations.
These are part of "java.lang.annotation" package.

1. @Retention:
Retention Policy: The Retention policy determines at which point of time, an annotation should be discarded.

There are 3 types of retention policies, which are specified using an enum class "java.lang.annotation.RetentionPolicy".

  • SOURCE: Annotations are to be discarded by the compiler.
  • CLASS: Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time.  This is the default behavior.
  • RUNTIME: Annotations are to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively.
2. @Target:
This is a meta annotation that defines the target type or type of programming element.
Allowed target types are defined in the enum class "java.lang.annotation.ElementType", which are: TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE.

3. @Documented:
4. @Inherited:

Marker Annotation:
An annotation type with no elements is termed a marker annotation type.

Single Member Annotation:
An annotation with only single member is termed as "Single Member Annotation", whose value can be specified directly or with an attribute called "value".


Marker Annotation Example:

package com;

import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;

@Retention(RetentionPolicy.RUNTIME)
@interface MyMarkerAnnotation {
}

enum AnnotationType {
METHOD, CLASS;
}

@Deprecated
class TestMarkerAnnoationClass {
@MyMarkerAnnotation
@Deprecated
public void markerMethod() {

}
}

public class MarkerAnnotationDemo {

public void testMarkerMethod(String methodName, Class methodClass,
Class annotClass) throws Exception {
try {
Method method = methodClass.getMethod(methodName, null);

boolean annotPresent = method.isAnnotationPresent(annotClass);

if (annotPresent)
System.out.println(methodName + "() has annotation of type: "
+ annotClass.getName());
else
throw new Exception("No such Annotation present");
} catch (SecurityException se) {

} catch (NoSuchMethodException nsme) {

}
}

public void printAnnotations(String clsName, String methName,
AnnotationType annotType) {
try {
if (annotType.equals(AnnotationType.CLASS)) {
Class cls = Class.forName(clsName);
Annotation[] annots = cls.getAnnotations();

System.out.print("Annotations for: " + annotType + " are:");
for (Annotation annot : annots)
System.out.print(" " + annot);
System.out.println();
} else if (annotType.equals(AnnotationType.METHOD)) {
Class cls = Class.forName(clsName);
Method method = cls.getMethod(methName, null);

Annotation[] annots = method.getAnnotations();

System.out.print("Annotations for method: " + methName
+ " of class: " + clsName + " are:");
for (Annotation annot : annots)
System.out.print(" " + annot);
System.out.println();
}
} catch (Exception e) {
e.printStackTrace();
}
}

static public void main(String[] args) throws Exception {
MarkerAnnotationDemo demo = new MarkerAnnotationDemo();

demo.testMarkerMethod("markerMethod", TestMarkerAnnoationClass.class,
MyMarkerAnnotation.class);
// demo.testMarkerMethod("markerMethod", String.class);

demo.printAnnotations("com.TestMarkerAnnoationClass", null,
AnnotationType.CLASS);
demo.printAnnotations("com.TestMarkerAnnoationClass", "markerMethod",
AnnotationType.METHOD);
}
}

Output:
markerMethod() has annotation of type: com.MyMarkerAnnotation
Annotations for: CLASS are: @java.lang.Deprecated()
Annotations for method: markerMethod of class: com.TestMarkerAnnoationClass are: @com.MyMarkerAnnotation() @java.lang.Deprecated()


Single Member Annotation Example:

package com;

import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;

@Retention(RetentionPolicy.RUNTIME)
@interface SingleMemberAnnotation {
String name();
}

class TestSingleMemberAnnot {
@SingleMemberAnnotation(name="Suresh Reddy")
public void singleMemMethod() {
}
}

public class SingleMemberAnnotDemo {
public void testSingleMemberMethod() throws Exception {
Class cls = Class.forName("com.TestSingleMemberAnnot");
Method method = cls.getMethod("singleMemMethod", null);

SingleMemberAnnotation singleMemAnnot = (SingleMemberAnnotation) method
.getAnnotation(SingleMemberAnnotation.class);

System.out.println(singleMemAnnot.name());
}

static public void main(String[] args) throws Exception {
SingleMemberAnnotDemo demo = new SingleMemberAnnotDemo();
demo.testSingleMemberMethod();
}
}

Output:
Suresh Reddy


Single Member Annotation with default value Example:
package com;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;

@Retention(RetentionPolicy.RUNTIME)
@interface DefaultValAnnotation {
public String name() default "Reddy";
}

class DefaultValAnnotClass {
@DefaultValAnnotation()
public void testDefaultValMethod() {

}

@DefaultValAnnotation(name="Suresh Reddy")
public void testDefaultValMethod1() {

}
}

public class DefaultValAnnotDemo {
public void testSingleMemberMethod() throws Exception {
Class cls = Class.forName("com.DefaultValAnnotClass");
Method method = cls.getMethod("testDefaultValMethod", null);

DefaultValAnnotation singleMemAnnot = (DefaultValAnnotation) method
.getAnnotation(DefaultValAnnotation.class);

System.out.println(singleMemAnnot.name());

Method method1 = cls.getMethod("testDefaultValMethod1", null);

DefaultValAnnotation singleMemAnnot1 = (DefaultValAnnotation) method1
.getAnnotation(DefaultValAnnotation.class);

System.out.println(singleMemAnnot1.name());
}

static public void main(String[] args) throws Exception {
DefaultValAnnotDemo demo = new DefaultValAnnotDemo();
demo.testSingleMemberMethod();
}

}

Output:
Reddy
Suresh Reddy

Wednesday, September 17, 2014

JVM Interview Questions

1. Which byte order(Little Endian or Big Endian) JVM uses?

Java used network byte order (which is big endian)

Lets say there are four memory addresses for lower to higher: 1000, 1001, 1002, 1003
and an integer of 32 bits(4 bytes) needs to be stored in these addresses.
integer in HEX format is: 10 AB 5B H4

Little Endian: Least significant byte will be stored in smallest address.
So value - address mapping will be: 10 > 1003, AB > 1002, 5B > 1001, H4 > 1000

Big Endian: Most significant byte will be stored in smallest address.
So value - address mapping will be: 10 > 1000, AB > 1001, 5B > 1002, H4 > 1003

Tuesday, September 9, 2014

Type Conversion in assignments

Its very important to understand when implicit type conversion happens and when we need explicit conversion, in case of primitive types.

Implicit narrowing conversion for primitives assignment happens in situations where ALL of the following conditions are satisfied:
1. The source value/variable(so it should be final) is a CONSTANT EXPRESSION of types: byte/short/char/int
2. The target variable must be of type: byte/short/char
3. The value of the source is determined to be in the range of the target type during compile time.

eg:

Implicit conversions:
short s1 = 11;
short s2 = 'b';
char c1 = 33;
char c2 = (byte) 36;
byte b1 = 45;
byte b2 = (short) 43;
final int i1 = 22;
byte b3 = i1;

Explicit Conversion cases:
int i2 = -20;
final int i3 = i2;
final int i4 = 200;

short s3 = (short) i2; //since i2 is not a constant expression
char c3 = (char) i3; //since i3 value cannot be determined, as it is depending on i2
char c4 = (char) i2; //since i2 is not a constant expression
byte b4 = (byte) 128; //int value not in range
byte b5 = (byte) i4; //final value of i4 variable is not in range

Logical Puzzles

Q: Fill the following structure with numbers from 1 to 8.
No number should have its next number as its adjacent(up/down/left/right/diagonal)



Answer:

2
6 8 5
4 1 3
7