-1

I have learned that in compile time generics we use changes to most specific type. so what is the benefit of generics?

for example in this code:

int a=1;
double b = 2.1;
printArray(a,b);
public static <E> void printArray(E first , E second);

in compile time E changes to Number (because the specific parent of int and double is Number)

so what is the benefit of generics when we can write Number instead of E in here?

someone
  • 71
  • 6
  • If you used Number, you wouldn't be able to print two Strings, for example. But yes, this specific method doesn't make much sense, and should simply take two Objects as argument. – JB Nizet Jun 24 '18 at 17:53
  • what about in general we can always take objects as argument – someone Jun 24 '18 at 17:54
  • No, you can't. Sometimes the method is only meaningful for a certain type (E extends Foo, for example). And most of the time, a generic method is needed to be able to return a generic type. Try implementing a method that takes two elements and returns a list containing both of them, for example. – JB Nizet Jun 24 '18 at 17:57
  • If you use `Object`, you loose type safety. Imagine a `List intList`. You know that there will only will be integers inside this list. But if you have a `List intList` or `List intList`, you **hope** that there are only `Integer`s in the list. Also, you have to cast every `get(...)` form the list. – Turing85 Jun 24 '18 at 17:58
  • But `Objects` aren't the same as a specific type `E`. if you had a method `printArray(Object first, Object second);` then you could pass in a `String` as the first, and an `Integer` as the second when that might not be what you really want. Read up on generics, [here's a start](https://stackoverflow.com/questions/7815528/what-are-generics-in-java). – xtratic Jun 24 '18 at 17:58
  • @xtratic you could pass a String and an Integer to a printArray(E first, E second) method, too. – JB Nizet Jun 24 '18 at 18:00
  • Possible duplicate of [What are Generics in Java?](https://stackoverflow.com/questions/7815528/what-are-generics-in-java) – xtratic Jun 24 '18 at 18:01
  • `printArray("A", 10);`. – Boris the Spider Jun 24 '18 at 18:03
  • @JBNizet making `E == ? extends Object` if you don't care that the arguments are a specific type, but if you do care then you could do something like `public static void printArray(E first , E second);` to be sure that all arguments are `Number`s. – xtratic Jun 24 '18 at 18:08
  • Your method signature is very similar to that of a "generic" version of JUnit's assertEquals. [This question](https://stackoverflow.com/q/38787083/3788176) asks why assertEquals isn't declared like that. – Andy Turner Jun 24 '18 at 18:19

1 Answers1

2

The purpose of generics is not related to the fact that the generic parameter will be inferred to be the most specific type. The purpose of generic methods is to allow you to write a method that can work with any type and at the same time, maintain type safety.

Your printArray method can not only take Number as arguments, but also String, SomeClass, Object and all sorts of reference types.

At this point you might ask "can't we just write Object as the parameter types?" Sure with the type being Object, the parameter will not only accept all reference types, but the primitives will also be accepted and boxed! So in this specific case, you don't necessarily have to use a generic method.

However, there are times when generic methods shine.

One of these occasions is when the methods work with generic types. For example, this is Optional.ofNullable:

public static <T> Optional<T> ofNullable(T value) {
    return value == null ? empty() : of(value);
}

It creates a Nullable<T> depending on whether the parameter is null. If this were not generic, it would have to return Optional<Object>. Every time you want to call get or orElse, you need to cast the result to the type you want. If you made a mistake in one of the casts, a ClassCastException might be thrown at runtime. But with generics, the compiler checks the types for you!

Here's another example:

public static <T> T first(List<T> list) { return list.get(0); }

Without generics, you would have to use the raw type List and return an Object. This again creates the problems of casting and reduced type safety.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • You may care to mention that OP's method signature allows one to avoid "cross-contamination" of values: the only things you can assign to `first` and `second` are the values of `first` and `second`, or `null`; you couldn't, for example, assign an arbitrary object. Honestly, I have never found a use for that. But it is a theoretical benefit. – Andy Turner Jun 24 '18 at 18:15
  • @AndyTurner Edited. – Sweeper Jun 24 '18 at 18:20