Manu M,manumanjunatha.mm@gmail.com

1
Manu M,manumanjunatha.mm@gmail.com

Generics
Assume we want to create a class that will work with various kinds of data. T...
Manu M,manumanjunatha.mm@gmail.com

How Generics Improve Type Safety?
package com.manum.hassan;

Called as Type Parameter
...
Manu M,manumanjunatha.mm@gmail.com



Java professional rarely write generics ,but extensively uses generics from librar...
Manu M,manumanjunatha.mm@gmail.com
TwoGen<Integer, String> tgObj =
new TwoGen<Integer, String>(88, "Generics");
tgObj.show...
Manu M,manumanjunatha.mm@gmail.com


Bound Can be
o Class (only one class at a time)
o Interface, can be one or more.
o C...
Manu M,manumanjunatha.mm@gmail.com

7

compiler has no way to know that you are intending to create Stats objects using on...
Manu M,manumanjunatha.mm@gmail.com
void methD(Gen<? extends C> ref)
void methD(Gen< ? super B> ref)
void methD(Gen< ? supe...
Manu M,manumanjunatha.mm@gmail.com

9
Upcoming SlideShare
Loading in...5
×

Generics

255

Published on

Published in: Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
255
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Generics"

  1. 1. Manu M,manumanjunatha.mm@gmail.com 1
  2. 2. Manu M,manumanjunatha.mm@gmail.com Generics Assume we want to create a class that will work with various kinds of data. This can be done using generics and also by references of type object. Because Object is the superclass of all other classes, an Object reference can refer to any type object. Thus, in pre-generics code, generalized classes, interfaces, and methods used Object references to operate on various types of objects. First let us learn how to create such a class (class that will work with various kinds of data ) Using Object references and problems found in this case. class NonGen { Object ob; NonGen(Object o) { ob = o; } Object getob() { return ob; } void showType() { System.out.println("Type of ob is " + ob.getClass().getName()); } } The cast is annoying but essential! class NonGenDemo { public static void main(String args[]) { NonGen iOb=new NonGen(88); iOb.showType(); int v = (Integer) iOb.getob(); System.out.println("value: " + v); NonGen strOb = new NonGen("Non-Generics Test"); strOb.showType(); String str = (String) strOb.getob(); System.out.println("value: " + str); iOb = strOb; v = (Integer) iOb.getob(); } } Output: References of NonGen class are same , can refer any objects of type NonGen No check during run time, hence unsafe and results into Runtime error Type of ob is java.lang.Integer value: 88 Type of ob is java.lang.String value: Non-Generics Test Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer at com.manum.hassan.NonGenDemo.main(NonGenDemo.java:30) 2
  3. 3. Manu M,manumanjunatha.mm@gmail.com How Generics Improve Type Safety? package com.manum.hassan; Called as Type Parameter class Gen <T> { T ob; Gen(T o) { ob = o; } T getob() { return ob; } void showType() { System.out.println("Type of T is " + ob.getClass().getName()); } } class GenDemo { public static void main(String args[]) { Gen<Integer> iOb = new Gen<Integer>(88); iOb.showType(); No type casting is required int v = iOb.getob(); System.out.println("value: " + v); Gen<String> strOb = new Gen<String>("Generics Test"); strOb.showType(); String str = strOb.getob(); System.out.println("value: " + str); //iOb = strOb; Will be reported during compile time } } Type Arguements Output: Type of T is java.lang.Integer value: 88 Type of T is java.lang.String value: Generics Test Java 1.6 Syntax: Gen<Integer> iOb = new Gen<Integer>(88); Java 1.7 Syntax: Gen<Integer> iOb = new Gen(88); Value 88 and "Generics Test" are Constructor arguments. Generic Classes don't infer types from constructor arguments.    Introduced in JDK1.5 Classes, Class methods and Interfaces can be generic. Generics Work Only with Objects. Gen<int> iOb = new Gen<int>(53); // Error, can't use primitive type Value 53 is autoboxed and object appearance is obtained. Gen<int> iOb = new Gen<Integer>(new Integer(88)); Gen<int> iOb = new Gen<int>(53); 3
  4. 4. Manu M,manumanjunatha.mm@gmail.com   Java professional rarely write generics ,but extensively uses generics from libraries. We can discard the generic support given by generic classes. Which we do for adding dissimilar data int some collection classes (those which allow dissimilar data.). class Gen<T> { T ob; Gen(T o) { ob = o; } T getob() { return ob; } void showType() { System.out.println("Type of T is " + ob.getClass().getName()); } } class GenDemo { public static void main(String args[]) { Gen iOb = new Gen(88); //neglecting generic support iOb.showType(); int v = (Integer) iOb.getob(); //type casting is required System.out.println("value: " + v); } } Create a raw-type Gen object and give it a Integer value. Type parameter Naming Convention Usually type parameter names are single, uppercase letters to make it easily distinguishable from java variables. The most commonly used type parameter names are:  E – Element (used extensively by the Java Collections Framework, for example ArrayList, Set etc.)  K – Key (Used in Map)  N – Number  T – Type  V – Value (Used in Map)  S,U,V etc. – 2nd, 3rd, 4th types A Generic Class with Two Type Parameters class TwoGen<T, V> { T ob1; V ob2; TwoGen(T o1, V o2) { ob1 = o1; ob2 = o2; } void showTypes() { System.out.println("Type of T is " + ob1.getClass().getName()); System.out.println("Type of V is " + ob2.getClass().getName()); } T getob1() { return ob1; } V getob2() { return ob2; } } class GenDemo { public static void main(String args[]) { 4
  5. 5. Manu M,manumanjunatha.mm@gmail.com TwoGen<Integer, String> tgObj = new TwoGen<Integer, String>(88, "Generics"); tgObj.showTypes(); int v = tgObj.getob1(); System.out.println("value: " + v); String str = tgObj.getob2(); System.out.println("value: " + str); } } Ouput: Type of T is java.lang.Integer Type of V is java.lang.String value: 88 value: Generics The General Form of a Generic Class As above program we can have more than one type parameter. The generics syntax shown in the preceding examples can be generalized. Here is the syntax for declaring a generic class: class class-name<type-param-list> { // ... Here is the syntax for declaring a reference to a generic class: class-name<type-arg-list> var-name = new class-name<type-arg-list>(cons-arg-list); Generic classes may not be direct or indirect subclass of Throwable class Gen<T> extends Throwable{ } Error The catch mechanism only works with non generic types Bounded Types class class class class A A{} B extends A{} C extends B{} Gen<T extends A>{ void methGen() {} B } public class BoundedTypes { public static void main(String[] args) { Gen<A> obj1 =new Gen<>(); obj1.methGen(); Gen<B> obj2 =new Gen<>(); obj2.methGen(); Gen<C> obj3 =new Gen<>(); obj3.methGen(); //Gen<Integer> obj4 =new Gen<>(); //obj4.methGen(); } } Type Parameter class Gen<T extends A> class Gen<T extends B> class Gen<T extends C>   C Error Type Arguements A and sub classes of A (A,B,C,D) B and sub classes of B (B,C,D) C and sub classes of C (C Only) Type arguments can be direct/indirect subclasses of Upper Bound. To set Upper Bound Syntax is <Type Parameter extends superclass> Upper Bound A B C 5
  6. 6. Manu M,manumanjunatha.mm@gmail.com  Bound Can be o Class (only one class at a time) o Interface, can be one or more. o Combination of class and interface.(Only one class at a time) When a bound includes an interface type, only type arguments that implement that interface are legal. When specifying a bound that has a class and an interface, or multiple interfaces, use the & operator to connect them. For example, class Gen<T extends MyClass & MyInterface> { // ... Here, T is bounded by a class called MyClass and an interface called MyInterface. Thus, any type argument passed to T must be a subclass of MyClass and implement MyInterface. Type Parameter Type Arguements class Gen<T extends A>{ T val; Gen(T val){ this.val=val; } } Gen<A> obj1 =new Gen<>(new A()); Gen<B> obj2 =new Gen<>(new B()); Gen<C> obj3 =new Gen<>(new C()); Upper Bound A class Gen<T extends B>{ T val; Gen(T val){ this.val=val; } } Gen<B> obj2 =new Gen<>(new B()); Gen<C> obj3 =new Gen<>(new C()); B class Gen<T extends C>{ T val; Gen(T val){ this.val=val; } } Gen<C> obj3 =new Gen<>(new C()); C Advantage of using Bounded Types. Calculate sum of elements of a numeric array. Array can be of any numeric data type like byte, short, int, long, float, double. Calculate the sum of double version of elements. Without Bounded Types With Bounded Types class Stats<T> { T[] nums; Stats(T[] o) { nums = o; } double average() { double sum = 0.0; for(int i=0; i < nums.length; i++) sum += nums[i].doubleValue(); return sum / nums.length; } } class Stats<T extends Number> { T[] nums; Stats(T[] o) { nums = o; } double average() { double sum = 0.0; for(int i=0; i < nums.length; i++) sum += nums[i].doubleValue(); return sum / nums.length; } } Gives Error In Stats, the average( ) method attempts to obtain the double version of each number in the nums array by calling doubleValue( ). Because all numeric classes, such as Integer and Double, are subclasses of Number, and Number defines the doubleValue( ) method, this method is available to all numeric wrapper classes. The trouble is that the 6
  7. 7. Manu M,manumanjunatha.mm@gmail.com 7 compiler has no way to know that you are intending to create Stats objects using only numeric types. Thus, when we try to compile Stats, an error is reported that indicates that the doubleValue( ) method is unknown. To solve this problem, we need some way to tell the compiler that we intend to pass only numeric types to T. Furthermore, we need some way to ensure that only numeric types are actually passed. To handle such situations, Java provides bounded types. What if Generic classes are used as parameters in methods? Consider the following code class A{} class B extends A{} class C extends B{} class Gen<T>{ } class D { void methD(Gen<?> ref) {System.out.println("HellO"); } } public class BoundedTypes { public static void main(String[] args) { Gen<A> obj1 =new Gen<>(); Gen<B> obj2 =new Gen<>(); Gen<C> obj3 =new Gen<>(); Gen<Integer> obj4 =new Gen<>(); D d= new D(); d.methD(obj1); } } Type Parameter Type Arguements method parameter method Arguements Gen<T > Any Objects void methD(Gen<?> ref) d.methD(obj1); d.methD(obj2); d.methD(obj3); d.methD(obj4); void methD(Gen<A> ref) void methD(Gen<B> ref) d.methD(obj1); d.methD(obj2); d.methD(obj4); obj1,obj2,obj3 obj2,obj3 obj3 obj1 obj1,obj2 obj1,obj2,obj3 obj1,obj2,obj3 d.methD(obj1); d.methD(obj2); d.methD(obj3); obj1,obj2,obj3 obj2,obj3 obj3 obj1 obj1,obj2 obj1,obj2,obj3 obj2,obj3 d.methD(obj2); d.methD(obj3); obj2,obj3 Gen<A> obj1 =new Gen<>(new A()); Gen<B> obj2 =new Gen<>(new B()); Gen<C> obj3 =new Gen<>(new C()); Gen<Integer> obj4 =new Gen<>(); void methD(Gen<Integer> ref) void methD(Gen< ? extends A> ref) void methD(Gen<? extends B> ref) void methD(Gen<? extends c> ref) void methD(Gen< ? super A> ref) void methD(Gen< ? super B> ref) void methD(Gen< ? super C> ref) Gen<T extends A> A and sub classes of A (A,B,C) Gen<A> obj1 =new Gen<>(new A()); Gen<B> obj2 =new Gen<>(new B()); Gen<C> obj3 =new Gen<>(new C()); void void void void methD(Gen<?> methD(Gen<A> methD(Gen<B> methD(Gen<C> ref ref) ref) ref) void methD(Gen< ? extends A> ref) void methD(Gen<? extends B> ref) void methD(Gen<? extends c> ref) void methD(Gen< ? super A> ref) void methD(Gen< ? super B> ref) void methD(Gen< ? super C> ref) Gen<T extends B> B and sub classes of B (B,C) Gen<B> obj2 =new Gen<>(new B()); Gen<C> obj3 =new Gen<>(new C()); void methD(Gen<?> ref void methD(Gen<B> ref) void methD(Gen<C> ref) void methD(Gen<? extends B> ref)
  8. 8. Manu M,manumanjunatha.mm@gmail.com void methD(Gen<? extends C> ref) void methD(Gen< ? super B> ref) void methD(Gen< ? super C> ref) Gen<T extends B> C and sub classes of C(Only C) Gen<C> obj3 =new Gen<>(new C()); void methD(Gen<?> ref void methD(Gen<? extends C> ref) void methD(Gen< ? super C> ref) obj3 obj2 obj2,obj3 obj3 obj3 obj3 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. public class GenericMethodDemo{ public static < E > void printArray(E[] elements) { for ( E element : elements){ System.out.print(element+" " ); } System.out.println(); } public static void main( String args[] ) { Integer[] intArray = { 10, 20, 30, 40, 50 }; Character[] charArray = {'A','d','i','T','e','m','p' }; System.out.println( "Printing Integer Array" ); printArray( intArray ); System.out.println( "Printing Character Array" ); printArray( charArray ); } } Output: Printing Integer Array 10 20 30 40 50 Printing Character Array A d i T e m p Erasure An important constraint that governed the way that generics were added to Java was the need for compatibility with previous versions of Java. Simply put, generic code had to be compatible with preexisting, non-generic code. Thus, any changes to the syntax of the Java language, or to the JVM, had to avoid breaking older code. The way Java implements generics while satisfying this constraint is through the use of erasure. In general, here is how erasure works. When your Java code is compiled, all generic type information is removed (erased). This means replacing type parameters with their bound type, which is Object if no explicit bound is specified, and then applying the appropriate casts (as determined by the type arguments) to maintain type compatibility with the types specified by the type arguments. The compiler also enforces this type compatibility. This approach to generics means that no type parameters exist at run time. They are simply a source-code mechanism. This mechanism of erasing all details about generic after compilation is known as type erasing. 8
  9. 9. Manu M,manumanjunatha.mm@gmail.com 9

×