Friday, 13 March 2015

Java 5 featuers

  1. For each loop
  2. Variable arguments
  3. static import
  4. auto boxing and unboxing
  5. Enum
  6. Co-variant return type
  7. Annotation
  8. Generics

1.For each loop

The for-each loop introduced in Java5. It is mainly used to traverse array or collection elements. The advantage of for-each loop is that it eliminates the possibility of bugs and makes the code more readable.

Advantage of for-each loop:

  • It makes the code more readable.
  • It elimnates the possibility of programming errors.

Syntax of for-each loop:

  1. for(data_type variable : array | collection){}  

Simple Example of for-each loop for traversing the array elements:

  1.     
  2. class ForEachExample1{  
  3.   public static void main(String args[]){  
  4.    int arr[]={12,13,14,44};  
  5.   
  6.    for(int i:arr){  
  7.      System.out.println(i);  
  8.    }  
  9.   
  10.  }   
  11. }  
  12.       

Output:12
       13
       14
       44

Simple Example of for-each loop for traversing the collection elements:

  1. import java.util.*;  
  2. class ForEachExample2{  
  3.   public static void main(String args[]){  
  4.    ArrayList<String> list=new ArrayList<String>();  
  5.    list.add("vimal");  
  6.    list.add("sonoo");  
  7.    list.add("ratan");  
  8.   
  9.    for(String s:list){  
  10.      System.out.println(s);  
  11.    }  
  12.   
  13.  }   
  14. }  
  15.       

Output:vimal
       sonoo
       ratan

2.Variable Arguments

The varrags allows the method to accept zero or muliple arguments. Before varargs either we use overloaded method or take an array as the method parameter but it was not considered good because it leads to the maintenance problem. If we don't know how many argument we will have to pass in the method, varargs is the better approach.

Advantage of Varargs:

We don't have to provide overloaded methods so less code.

Syntax of varargs:

The varargs uses ellipsis i.e. three dots after the data type. Syntax is as follows:
  1. return_type method_name(data_type... variableName){}  

Simple Example of Varargs in java:

  1.     
  2. class VarargsExample1{  
  3.    
  4.  static void display(String... values){  
  5.   System.out.println("display method invoked ");  
  6.  }  
  7.   
  8.  public static void main(String args[]){  
  9.   
  10.  display();//zero argument   
  11.  display("my","name","is","varargs");//four arguments  
  12.  }   
  13. }  
  14.       
Output:display method invoked
       display method invoked

Another Program of Varargs in java:

  1.     
  2. class VarargsExample2{  
  3.    
  4.  static void display(String... values){  
  5.   System.out.println("display method invoked ");  
  6.   for(String s:values){  
  7.    System.out.println(s);  
  8.   }  
  9.  }  
  10.   
  11.  public static void main(String args[]){  
  12.   
  13.  display();//zero argument   
  14.  display("hello");//one argument   
  15.  display("my","name","is","varargs");//four arguments  
  16.  }   
  17. }  
  18.       
Output:display method invoked
       display method invoked
       hello
       display method invoked
       my
       name
       is 
       varargs

Rules for varargs:

While using the varargs, you must follow some rules otherwise program code won't compile. The rules are as follows:
  • There can be only one variable argument in the method.
  • Variable argument (varargs) must be the last argument.

Examples of varargs that fails to compile:

  1.     
  2. void method(String... a, int... b){}//Compile time error  
  3.   
  4. void method(int... a, String b){}//Compile time error  
  5.       

Example of Varargs that is the last argument in the method:

  1.     
  2. class VarargsExample3{  
  3.    
  4.  static void display(int num, String... values){  
  5.   System.out.println("number is "+num);  
  6.   for(String s:values){  
  7.    System.out.println(s);  
  8.   }  
  9.  }  
  10.   
  11.  public static void main(String args[]){  
  12.   
  13.  display(500,"hello");//one argument   
  14.  display(1000,"my","name","is","varargs");//four arguments  
  15.  }   
  16. }  
  17.       

Output:number is 500
       hello
       number is 1000
       my
       name
       is 
       varargs

3. Static import


The static import feature of Java 5 facilitate the java programmer to access any static member of a class directly. There is no need to qualify it by the class name.

Advantage of static import:

  • Less coding is required if you have access any static member of a class oftenly.

Disadvantage of static import:

  • If you overuse the static import feature, it makes the program unreadable and unmaintainable.

Simple Example of static import

  1. import static java.lang.System.*;    
  2. class StaticImportExample{  
  3.   public static void main(String args[]){  
  4.      
  5.    out.println("Hello");//Now no need of System.out  
  6.    out.println("Java");  
  7.   
  8.  }   
  9. }  
  10.       

Output:Hello
       Java
  

What is the difference between import and static import?

The import allows the java programmer to access classes of a package without package qualification whereas the static import feature allows to access the static members of a class without the class qualification. The import provides accessibility to classes and interface whereas static import provides accessibility to static members of the class.

4. Auto boxing and unboxing

The automatic conversion of primitive data types into its equivalent Wrapper type is known as boxing and opposite operation is known as unboxing. This is the new feature of Java5. So java programmer doesn't need to write the conversion code.

Advantage of Autoboxing and Unboxing:

No need of conversion between primitives and Wrappers manually so less coding is required.

Simple Example of Autoboxing in java:

  1.     
  2. class BoxingExample1{  
  3.   public static void main(String args[]){  
  4.     int a=50;  
  5.         Integer a2=new Integer(a);//Boxing  
  6.   
  7.         Integer a3=5;//Boxing  
  8.           
  9.         System.out.println(a2+" "+a3);  
  10.  }   
  11. }  
  12.       

Output:50 5


Simple Example of Unboxing in java:

The automatic conversion of wrapper class type into corresponding primitive type, is known as Unboxing. Let's see the example of unboxing:
  1.     
  2. class UnboxingExample1{  
  3.   public static void main(String args[]){  
  4.     Integer i=new Integer(50);  
  5.         int a=i;  
  6.           
  7.         System.out.println(a);  
  8.  }   
  9. }  
  10.       

Output:50

Autoboxing and Unboxing with comparison operators

Autoboxing can be performed with comparison operators. Let's see the example of boxing with comparison operator:
  1.     
  2. class UnboxingExample2{  
  3.   public static void main(String args[]){  
  4.     Integer i=new Integer(50);  
  5.           
  6.         if(i<100){            //unboxing internally  
  7.         System.out.println(i);  
  8.         }  
  9.  }   
  10. }  
  11.       

Output:50

Autoboxing and Unboxing with method overloading

In method overloading, boxing and unboxing can be performed. There are some rules for method overloading with boxing:
  • Widening beats boxing
  • Widening beats varargs
  • Boxing beats varargs

1) Example of Autoboxing where widening beats boxing

If there is possibility of widening and boxing, widening beats boxing.
  1.     
  2. class Boxing1{  
  3.   static void m(int i){System.out.println("int");}  
  4.   static void m(Integer i){System.out.println("Integer");}  
  5.   
  6.   public static void main(String args[]){  
  7.    short s=30;  
  8.    m(s);  
  9.  }   
  10. }  
  11.       

Output:int

2) Example of Autoboxing where widening beats varargs

If there is possibility of widening and varargs, widening beats var-args.
  1.     
  2. class Boxing2{  
  3.   static void m(int i, int i2){System.out.println("int int");}  
  4.   static void m(Integer... i){System.out.println("Integer...");}  
  5.   
  6.   public static void main(String args[]){  
  7.    short s1=30,s2=40;  
  8.    m(s1,s2);  
  9.  }   
  10. }  
  11.       

Output:int int

3) Example of Autoboxing where boxing beats varargs

Let's see the program where boxing beats variable argument:
  1.     
  2. class Boxing3{  
  3.   static void m(Integer i){System.out.println("Integer");}  
  4.   static void m(Integer... i){System.out.println("Integer...");}  
  5.   
  6.   public static void main(String args[]){  
  7.    int a=30;  
  8.    m(a);  
  9.  }   
  10. }  
  11.       

Output:Integer

Method overloading with Widening and Boxing

Widening and Boxing can't be performed as given below:
  1.     
  2. class Boxing4{  
  3.   static void m(Long l){System.out.println("Long");}  
  4.   
  5.   public static void main(String args[]){  
  6.    int a=30;  
  7.    m(a);  
  8.  }   
  9. }  
  10.       

Output:Compile Time Error


5. Enum 

An enum is a data type which contains fixed set of constants. It can be used for days of the week (SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY and SATURDAY) , directions (NORTH, SOUTH, EAST and WEST) etc. The enum constants are static and final implicitely. It is available from Java 5. Enums can be thought of as classes that have fixed set of constants.

Points to remember for Enum:

  1. enum improves type safety
  2. enum can be easily used in switch
  3. enum can be traversed
  4. enum can have fields, constructors and methods
  5. enum may implement many interfaces but cannot extend any class because it internally extends Enum class

Simple Example of enum in java:

  1.     
  2. class EnumExample1{  
  3.   
  4. public enum Season { WINTER, SPRING, SUMMER, FALL }  
  5.   
  6. public static void main(String[] args) {  
  7. for (Season s : Season.values())  
  8. System.out.println(s);  
  9.   
  10. }}  
  11.       

Output:WINTER
       SPRING
       SUMMER
       FALL

What is the purpose of values() method in enum?

The java compiler internally adds the values() method when it creates an enum. The values() method returns an array containing all the values of the enum.

Internal code generated by the compiler for the above example of enum type

The java compiler internally creates a static and final class that extends the Enum class as shown in the below example:
  1. public static final class EnumExample1$Season extends Enum  
  2. {  
  3.   private EnumExample1$Season(String s, int i)  
  4.     {  
  5.         super(s, i);  
  6.     }  
  7.   
  8.     public static EnumExample1$Season[] values()  
  9.     {  
  10.         return (EnumExample1$Season[])$VALUES.clone();  
  11.     }  
  12.   
  13.     public static EnumExample1$Season valueOf(String s)  
  14.     {  
  15.         return (EnumExample1$Season)Enum.valueOf(EnumExample1$Season, s);  
  16.     }  
  17.   
  18.     public static final EnumExample1$Season WINTER;  
  19.     public static final EnumExample1$Season SPRING;  
  20.     public static final EnumExample1$Season SUMMER;  
  21.     public static final EnumExample1$Season FALL;  
  22.     private static final EnumExample1$Season $VALUES[];  
  23.   
  24.     static   
  25.     {  
  26.         WINTER = new EnumExample1$Season("WINTER"0);  
  27.         SPRING = new EnumExample1$Season("SPRING"1);  
  28.         SUMMER = new EnumExample1$Season("SUMMER"2);  
  29.         FALL = new EnumExample1$Season("FALL"3);  
  30.         $VALUES = (new EnumExample1$Season[] {  
  31.             WINTER, SPRING, SUMMER, FALL  
  32.         });  
  33.     }  
  34.   
  35. }  

Defining enum:

The enum can be defined within or outside the class because it is similar to a class.

Example of enum that is defined outside the class:

  1.     
  2. enum Season { WINTER, SPRING, SUMMER, FALL }  
  3.   
  4. class EnumExample2{  
  5. public static void main(String[] args) {  
  6.   
  7. Season s=Season.WINTER;  
  8. System.out.println(s);  
  9.   
  10. }}  
  11.       

Output:WINTER

Example of enum that is defined within the class:

  1. class EnumExample3{  
  2. enum Season { WINTER, SPRING, SUMMER, FALL; }//semicolon(;) is optional here  
  3.   
  4. public static void main(String[] args) {  
  5. Season s=Season.WINTER;//enum type is required to access WINTER  
  6. System.out.println(s);  
  7.   
  8. }}  
  9.       

Output:WINTER

Initializing specific value to the enum constants:

The enum constants have initial value that starts from 0, 1, 2, 3 and so on. But we can initialize the specific value to the enum constants by defining fields and constructors. As specified earlier, Enum can have fields, constructors and methods.

Example of specifying initial value to the enum constants

  1. class EnumExample4{  
  2. enum Season{   
  3. WINTER(5), SPRING(10), SUMMER(15), FALL(20);   
  4.   
  5. private int value;  
  6. private Season(int value){  
  7. this.value=value;  
  8. }  
  9. }  
  10. public static void main(String args[]){  
  11. for (Season s : Season.values())  
  12. System.out.println(s+" "+s.value);  
  13.   
  14. }}  
  15.       
Output:WINTER 5
       SPRING 10
       SUMMER 15
       FALL 20

Constructor of enum type is private if you don't declare private compiler internally have private constructor

  1. enum Season{  
  2. WINTER(10),SUMMER(20);  
  3. private int value;  
  4. Season(int value){  
  5. this.value=value;  
  6. }  
  7. }  
  8.       

Internal code generated by the compiler for the above example of enum type

  1. final class Season extends Enum  
  2. {  
  3.   
  4.     public static Season[] values()  
  5.     {  
  6.         return (Season[])$VALUES.clone();  
  7.     }  
  8.   
  9.     public static Season valueOf(String s)  
  10.     {  
  11.         return (Season)Enum.valueOf(Season, s);  
  12.     }  
  13.   
  14.     private Season(String s, int i, int j)  
  15.     {  
  16.         super(s, i);  
  17.         value = j;  
  18.     }  
  19.   
  20.     public static final Season WINTER;  
  21.     public static final Season SUMMER;  
  22.     private int value;  
  23.     private static final Season $VALUES[];  
  24.   
  25.     static   
  26.     {  
  27.         WINTER = new Season("WINTER"010);  
  28.         SUMMER = new Season("SUMMER"120);  
  29.         $VALUES = (new Season[] {  
  30.             WINTER, SUMMER  
  31.         });  
  32.     }  
  33. }  

Can we create the instance of enum by new keyword?

No, because it contains private constructors only.

Can we have abstract method in enum?

Yes, ofcourse! we can have abstract methods and can provide the implementation of these methods.

Applying enum on switch statement

We can apply enum on switch statement as in the given example:

Example of applying enum on switch statement

  1. class EnumExample5{  
  2. enum Day{ SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY}  
  3.   
  4. public static void main(String args[]){  
  5.   
  6. Day day=Day.MONDAY;  
  7.   
  8. switch(day){  
  9. case SUNDAY:   
  10.  System.out.println("sunday");  
  11.  break;  
  12. case MONDAY:   
  13.  System.out.println("monday");  
  14.  break;  
  15. default:  
  16. System.out.println("other day");  
  17. }  
  18.   
  19. }}  
  20.       
Output:monday

6. Covariant return type

The covariant return type specifies that the return type may vary in the same direction as the subclass.
Before Java5, it was not possible to override any method by changing the return type. But now, since Java5, it is possible to override method by changing the return type if subclass overrides any method whose return type is Non-Primitive but it changes its return type to subclass type. Let's take a simple example:

Note: If you are beginner to java, skip this topic and return to it after OOPs concepts.


Simple example of Covariant Return Type

  1. class A{  
  2. A get(){return this;}  
  3. }  
  4.   
  5. class B1 extends A{  
  6. B1 get(){return this;}  
  7. void message(){System.out.println("welcome to covariant return type");}  
  8.   
  9. public static void main(String args[]){  
  10. new B1().get().message();  
  11. }  
  12. }  
Output:welcome to covariant return type
As you can see in the above example, the return type of the get() method of A class is A but the return type of the get() method of B class is B. Both methods have different return type but it is method overriding. This is known as covariant return type.

7. Annotation

Java Annotation is a tag that represents the metadata i.e. attached with class, interface, methods or fields to indicate some additional information which can be used by java compiler and JVM.
Annotations in java are used to provide additional information, so it is an alternative option for XML and java marker interfaces.
First, we will learn some built-in annotations then we will move on creating and using custom annotations.

Built-In Java Annotations

There are several built-in annotations in java. Some annotations are applied to java code and some to other annotations.

Built-In Java Annotations used in java code

  • @Override
  • @SuppressWarnings
  • @Deprecated

Built-In Java Annotations used in other annotations

  • @Target
  • @Retention
  • @Inherited
  • @Documented

Understanding Built-In Annotations in java

Let's understand the built-in annotations first.

@Override

@Override annotation assures that the subclass method is overriding the parent class method. If it is not so, compile time error occurs.
Sometimes, we does the silly mistake such as spelling mistakes etc. So, it is better to mark @Override annotation that provides assurity that method is overridden.
  1. class Animal{  
  2. void eatSomething(){System.out.println("eating something");}  
  3. }  
  4.   
  5. class Dog extends Animal{  
  6. @Override  
  7. void eatsomething(){System.out.println("eating foods");}//should be eatSomething  
  8. }  
  9.   
  10. class TestAnnotation1{  
  11. public static void main(String args[]){  
  12. Animal a=new Dog();  
  13. a.eatSomething();  
  14. }}  

Output:Comple Time Error

@SuppressWarnings

@SuppressWarnings annotation: is used to suppress warnings issued by the compiler.
  1. import java.util.*;  
  2. class TestAnnotation2{  
  3. @SuppressWarnings("unchecked")  
  4. public static void main(String args[]){  
  5.   
  6. ArrayList<String> list=new ArrayList<String>();  
  7. list.add("sonoo");  
  8. list.add("vimal");  
  9. list.add("ratan");  
  10.   
  11. for(Object obj:list)  
  12. System.out.println(obj);  
  13.   
  14. }}  

Now no warning at compile time.
If you remove the @SuppressWarnings("unchecked") annotation, it will show warning at compile time because we are using non-generic collection.

@Deprecated

@Deprecated annoation marks that this method is deprecated so compiler prints warning. It informs user that it may be removed in the future versions. So, it is better not to use such methods.
  1. class A{  
  2. void m(){System.out.println("hello m");}  
  3.   
  4. @Deprecated  
  5. void n(){System.out.println("hello n");}  
  6. }  
  7.   
  8. class TestAnnotation3{  
  9. public static void main(String args[]){  
  10.   
  11. A a=new A();  
  12. a.n();  
  13. }}  

At Compile Time:

Note: Test.java uses or overrides a deprecated API.

Note: Recompile with -Xlint:deprecation for details.

At Runtime:

hello n

Custom Annotation

Java Custom annotations or Java User-defined annotations are easy to create and use. The @interface element is used to declare an annotation. For example:
  1. @interface MyAnnotation{}  
Here, MyAnnotation is the custom annotation name.

Points to remember for java custom annotation signature

There are few points that should be remembered by the programmer.
  1. Method should not have any throws clauses
  2. Method should return one of the following: primitive data types, String, Class, enum or array of these data types.
  3. Method should not have any parameter.
  4. We should attach @ just before interface keyword to define annotation.
  5. It may assign a default value to the method.

Types of Annotation

There are three types of annotations.
  1. Marker Annotation
  2. Single-Value Annotation
  3. Multi-Value Annotation

1) Marker Annotation

An annotation that has no method, is called marker annotation. For example:
  1. @interface MyAnnotation{}  
The @Override and @Deprecated are marker annotations.

2) Single-Value Annotation

An annotation that has one method, is called single-value annotation. For example:
  1. @interface MyAnnotation{  
  2. int value();  
  3. }  
We can provide the default value also. For example:
  1. @interface MyAnnotation{  
  2. int value() default 0;  
  3. }  

How to apply Single-Value Annotation

Let's see the code to apply the single value annotation.
  1. @MyAnnotation(value=10)  
The value can be anything.

3) Mulit-Value Annotation

An annotation that has more than one method, is called Multi-Value annotation. For example:
  1. @interface MyAnnotation{  
  2. int value1();  
  3. String value2();  
  4. String value3();  
  5. }  
  6. }  
We can provide the default value also. For example:
  1. @interface MyAnnotation{  
  2. int value1() default 1;  
  3. String value2() default "";  
  4. String value3() default "xyz";  
  5. }  

How to apply Multi-Value Annotation

Let's see the code to apply the multi-value annotation.
  1. @MyAnnotation(value1=10,value2="Arun Kumar",value3="Ghaziabad")  

Built-in Annotations used in custom annotations in java

  • @Target
  • @Retention
  • @Inherited
  • @Documented

@Target

@Target tag is used to specify at which type, the annotation is used.
The java.lang.annotation.ElementType enum declares many constants to specify the type of element where annotation is to be applied such as TYPE, METHOD, FIELD etc. Let's see the constants of ElementType enum:
Element TypesWhere the annotation can be applied
TYPEclass, interface or enumeration
FIELDfields
METHODmethods
CONSTRUCTORconstructors
LOCAL_VARIABLElocal variables
ANNOTATION_TYPEannotation type
PARAMETERparameter

Example to specify annoation for a class

  1. @Target(ElementType.TYPE)  
  2. @interface MyAnnotation{  
  3. int value1();  
  4. String value2();  
  5. }  

Example to specify annoation for a class, methods or fields

  1. @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})  
  2. @interface MyAnnotation{  
  3. int value1();  
  4. String value2();  
  5. }  

@Retention

@Retention annotation is used to specify to what level annotation will be available.
RetentionPolicyAvailability
RetentionPolicy.SOURCErefers to the source code, discarded during compilation. It will not be available in the compiled class.
RetentionPolicy.CLASSrefers to the .class file, available to java compiler but not to JVM . It is included in the class file.
RetentionPolicy.RUNTIMErefers to the runtime, available to java compiler and JVM .

Example to specify the RetentionPolicy

  1. @Retention(RetentionPolicy.RUNTIME)  
  2. @Target(ElementType.TYPE)  
  3. @interface MyAnnotation{  
  4. int value1();  
  5. String value2();  
  6. }  

Example of custom annotation: creating, applying and accessing annotation

Let's see the simple example of creating, applying and accessing annotation.
File: Test.java
  1. //Creating annotation  
  2. import java.lang.annotation.*;  
  3. import java.lang.reflect.*;  
  4.   
  5. @Retention(RetentionPolicy.RUNTIME)  
  6. @Target(ElementType.METHOD)  
  7. @interface MyAnnotation{  
  8. int value();  
  9. }  
  10.   
  11. //Applying annotation  
  12. class Hello{  
  13. @MyAnnotation(value=10)  
  14. public void sayHello(){System.out.println("hello annotation");}  
  15. }  
  16.   
  17. //Accessing annotation  
  18. class TestCustomAnnotation1{  
  19. public static void main(String args[])throws Exception{  
  20.   
  21. Hello h=new Hello();  
  22. Method m=h.getClass().getMethod("sayHello");  
  23.   
  24. MyAnnotation manno=m.getAnnotation(MyAnnotation.class);  
  25. System.out.println("value is: "+manno.value());  
  26. }}  

Output:value is: 10

How built-in annotaions are used in real scenario?

In real scenario, java programmer only need to apply annotation. He/She doesn't need to create and access annotation. Creating and Accessing annotation is performed by the implementation provider. On behalf of the annotation, java compiler or JVM performs some additional operations.

@Inherited

By default, annotations are not inherited to subclasses. The @Inherited annotation marks the annotation to be inherited to subclasses.
  1. @Inherited  
  2. @interface ForEveryone { }//Now it will be available to subclass also  
  3.   
  4. @interface ForEveryone { }  
  5. class Superclass{}  
  6.   
  7. class Subclass extends Superclass{}  

@Documented

The @Documented Marks the annotation for inclusion in the documentation.

8. Generics

The Java Generics programming is introduced in J2SE 5 to deal with type-safe objects.
Before generics, we can store any type of objects in collection i.e. non-generic. Now generics, forces the java programmer to store specific type of objects.

Advantage of Java Generics

There are mainly 3 advantages of generics. They are as follows:
1) Type-safety : We can hold only a single type of objects in generics. It doesn’t allow to store other objects.
2) Type casting is not required: There is no need to typecast the object.
Before Generics, we need to type cast.
  1. List list = new ArrayList();  
  2. list.add("hello");  
  3. String s = (String) list.get(0);//typecasting  
After Generics, we don't need to typecast the object.
  1. List<String> list = new ArrayList<String>();  
  2. list.add("hello");  
  3. String s = list.get(0);  
3) Compile-Time Checking: It is checked at compile time so problem will not occur at runtime. The good programming strategy says it is far better to handle the problem at compile time than runtime.
  1. List<String> list = new ArrayList<String>();  
  2. list.add("hello");  
  3. list.add(32);//Compile Time Error  

Syntax to use generic collection
  1. ClassOrInterface<Type>  
Example to use Generics in java
  1. ArrayList<String>  

Full Example of Generics in Java

Here, we are using the ArrayList class, but you can use any collection class such as ArrayList, LinkedList, HashSet, TreeSet, HashMap, Comparator etc.
  1. import java.util.*;  
  2. class TestGenerics1{  
  3. public static void main(String args[]){  
  4. ArrayList<String> list=new ArrayList<String>();  
  5. list.add("rahul");  
  6. list.add("jai");  
  7. //list.add(32);//compile time error  
  8.   
  9. String s=list.get(1);//type casting is not required  
  10. System.out.println("element is: "+s);  
  11.   
  12. Iterator<String> itr=list.iterator();  
  13. while(itr.hasNext()){  
  14. System.out.println(itr.next());  
  15. }  
  16. }  
  17. }  

Output:element is: jai
       rahul
       jai 

Example of Java Generics using Map

Now we are going to use map elements using generics. Here, we need to pass key and value. Let us understand it by a simple example:
  1. import java.util.*;  
  2. class TestGenerics2{  
  3. public static void main(String args[]){  
  4. Map<Integer,String> map=new HashMap<Integer,String>();  
  5. map.put(1,"vijay");  
  6. map.put(4,"umesh");  
  7. map.put(2,"ankit");  
  8.   
  9. //Now use Map.Entry for Set and Iterator  
  10. Set<Map.Entry<Integer,String>> set=map.entrySet();  
  11.   
  12. Iterator<Map.Entry<Integer,String>> itr=set.iterator();  
  13. while(itr.hasNext()){  
  14. Map.Entry e=itr.next();//no need to typecast  
  15. System.out.println(e.getKey()+" "+e.getValue());  
  16. }  
  17.   
  18. }}  

Output:1 vijay
       2 ankit 
       4 umesh

Generic class

A class that can refer to any type is known as generic class. Here, we are using T type parameter to create the generic class of specific type.
Let’s see the simple example to create and use the generic class.
Creating generic class:
  1. class MyGen<T>{  
  2. T obj;  
  3. void add(T obj){this.obj=obj;}  
  4. T get(){return obj;}  
  5. }  
The T type indicates that it can refer to any type (like String, Integer, Employee etc.). The type you specify for the class, will be used to store and retrieve the data.
Using generic class:
Let’s see the code to use the generic class.
  1. class TestGenerics3{  
  2. public static void main(String args[]){  
  3. MyGen<Integer> m=new MyGen<Integer>();  
  4. m.add(2);  
  5. //m.add("vivek");//Compile time error  
  6. System.out.println(m.get());  
  7. }}  
Output:2

Type Parameters

The type parameters naming conventions are important to learn generics thoroughly. The commonly type parameters are as follows:
  1. T - Type
  2. E - Element
  3. K - Key
  4. N - Number
  5. V - Value

Generic Method

Like generic class, we can create generic method that can accept any type of argument.
Let’s see a simple example of java generic method to print array elements. We are using here E to denote the element.
  1. public class TestGenerics4{  
  2.   
  3.    public static < E > void printArray(E[] elements) {  
  4.         for ( E element : elements){          
  5.             System.out.println(element );  
  6.          }  
  7.          System.out.println();  
  8.     }  
  9.     public static void main( String args[] ) {  
  10.         Integer[] intArray = { 1020304050 };  
  11.         Character[] charArray = { 'J''A''V''A''T','P','O','I','N','T' };  
  12.   
  13.         System.out.println( "Printing Integer Array" );  
  14.         printArray( intArray  );   
  15.   
  16.        System.out.println( "Printing Character Array" );  
  17.         printArray( charArray );   
  18.     }   
  19. }  
Output:Printing Integer Array
        10
        20
        30
        40
        50
        Printing Character Array
        J
        A
        V
        A
        T
        P
        O
        I
        N
        T

Wildcard in Java Generics

The ? (question mark) symbol represents wildcard element. It means any type. If we write <? extends Number>, it means any child class of Number e.g. Integer, Float, double etc. Now we can call the method of Number class through any child class object.
Let's understand it by the example given below:
  1. import java.util.*;  
  2. abstract class Shape{  
  3. abstract void draw();  
  4. }  
  5. class Rectangle extends Shape{  
  6. void draw(){System.out.println("drawing rectangle");}  
  7. }  
  8. class Circle extends Shape{  
  9. void draw(){System.out.println("drawing circle");}  
  10. }  
  11.   
  12.   
  13. class GenericTest{  
  14. //creating a method that accepts only child class of Shape  
  15. public static void drawShapes(List<? extends Shape> lists){  
  16. for(Shape s:lists){  
  17. s.draw();//calling method of Shape class by child class instance  
  18. }  
  19. }  
  20. public static void main(String args[]){  
  21. List<Rectangle> list1=new ArrayList<Rectangle>();  
  22. list1.add(new Rectangle());  
  23.   
  24. List<Circle> list2=new ArrayList<Circle>();  
  25. list2.add(new Circle());  
  26. list2.add(new Circle());  
  27.   
  28. drawShapes(list1);  
  29. drawShapes(list2);  
  30. }}  
drawing rectangle
drawing circle
drawing circle

No comments:

Post a Comment