Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any reason to use generics in Java?

Tags:

java

generics

Perhaps I'm missing the point but coming from a C# background, I can't see any reason to use Java's generics...

In C# I've got a method which takes a string and deserializes it into an object...

public static Deserialize<T>(string source) {
    // Use reflection to examine T and determine
    // which properties I should be reading from
    // the string. Create an instance of T, 
    // populate the properties and return it
}

which I can call as follows: x.Deserialize<AnyClass>("String representation of AnyClass");

Type erasure seems to make this impossible in Java?

My next most common usage of generics is storing things in lists but since I can't do List<int> and have to box to use List<Integer>, it seems like pointless overhead boxing/unboxing when I could just use int[].

So... Is the only real use for generics to do things like

List<MyClass> MyClassList = new List<MyClass>

and get some compile-time type checking? If so, it seems pretty redundant given that the variable name makes it clear what the type should be (at least as long as I'm using sensible naming conventions).

I can't help but feel I'm missing something...

like image 537
Basic Avatar asked Dec 05 '22 23:12

Basic


2 Answers

Well, if you don't use generics, you get to cast each time. You would have to:

// if raw List
MyClass c = (MyClass) myClassList.get(0);
// if List<MyClass>
MyClass c = myClassList.get(0);

for instance.

Yes, generics are erased at runtime, yes, they are here to enforce type safety at compile time only; however there is still runtime type erasure when you use bounds. Example:

public <E extends RuntimeException> E get(final Class<E> c,
    final Throwable t)
{
    try {
        return (E) getHandle(c).invokeExact(t);
    } catch (Error | RuntimeException e) {
        throw e;
    } catch (Throwable oops) {
        final RuntimeException exception = new IllegalStateException(oops);
        exception.addSuppressed(t);
        throw exception;
    }
}

The E here has a runtime type erasure; it extends RuntimeException. Therefore the cast is to RuntimeException, not Object.

See the javadoc of Collections.max() for another interesting example of runtime type erasure (hint: why does it define T extends Object & Comparable<? super T> instead of T extends Comparable<? super T>?)

like image 143
fge Avatar answered Dec 17 '22 11:12

fge


From the Java Docs :

Why Use Generics?

In a nutshell, generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. Much like the more familiar formal parameters used in method declarations, type parameters provide a way for you to re-use the same code with different inputs. The difference is that the inputs to formal parameters are values, while the inputs to type parameters are types.

Code that uses generics has many benefits over non-generic code:

  • Stronger type checks at compile time. A Java compiler applies strong type checking to generic code and issues errors if the code violates type safety. Fixing compile-time errors is easier than fixing runtime errors, which can be difficult to find.

  • Elimination of casts. The following code snippet without generics requires casting:

    List list = new ArrayList();
    list.add("hello");
    String s = (String) list.get(0);
    

    When re-written to use generics, the code does not require casting:

    List<String> list = new ArrayList<String>();
    list.add("hello");
    String s = list.get(0); // no cast
    
  • Enabling programmers to implement generic algorithms. By using generics, programmers can implement generic algorithms that work on collections of different types, can be customized, and are type safe and easier to read.

like image 23
Rockstar Avatar answered Dec 17 '22 10:12

Rockstar