Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this use of Generics not throw a runtime or compile time exception?

Tags:

java

generics

I've got a method in a class that has a return type specified by use of a generic.

public class SomeMain {

  public static void main(String[] args) {

    Foo<Integer> foo = new Foo<Integer>();
    System.out.println(foo.getFoo()); // Works, prints out "Foo"

  }

  public static class Foo<E>  {
    public E getFoo() {
      return (E) "Foo";
    }
  }
}

With the generic return type, I assumed the return in the above example would evaluate to:

return (Integer) "Foo";  // Inconvertible types !!!

Instead a String is returned and printed correctly.

I get a compilation error if I change the call to be:

String fooString = foo.getFoo(); // Compile error, incompatible types found
System.out.println(fooString);

What am I missing to help me understand what's going on here and why the original version didn't result in a compilation error.

like image 377
Ray Avatar asked Sep 22 '18 16:09

Ray


People also ask

Are generics runtime or compile time?

Generics are a facility of generic programming that were added to the Java programming language in 2004 within version J2SE 5.0. They were designed to extend Java's type system to allow "a type or method to operate on objects of various types while providing compile-time type safety".

Do generics prevent compile time errors?

Type Safety: Generics make errors to appear compile time than at run time (It's always better to know problems in your code at compile time rather than making your code fail at run time).

Are Java generics capable of preventing runtime error?

You can prevent such showstoppers if you use the generics feature introduced in J2SE 5. Using generics in your Java development can help you detect issues during compile time rather than being confronted by them at run time. This gives you greater control of the code and makes the syntax easy to follow.

What is the disadvantages of using generics?

The Cons of Generic DrugsMedicines can look different: Trademark laws prohibit a generic drug from looking exactly like its brand-name version, so if you've switched to a generic drug, its shape, color or size may be different from what you're accustomed to taking.


1 Answers

This is because overload resolution resolved your println call to println(Object), since there is no println(Integer).

Keep in mind that Java's generics are erased at runtime. And casts like (E) "Foo" are removed, and are moved to call site. Sometimes this is not necessary, so things are casted to the right type only when needed.

In other words, no casts are performed inside getFoo. The language spec supports this:

Section 5.5.2 Checked Casts and Unchecked Casts

  • The cast is a completely unchecked cast.

    No run-time action is performed for such a cast.

After erasure, getFoo returns Object. And that gets passed into println(Object), which is perfectly fine.

If I call this method and pass foo.getFoo, I will get an error:

static void f(Integer i) {
    System.out.println(i);
}
// ...
f(foo.getFoo()); // ClassCastException

because this time it needs to be casted.

like image 168
Sweeper Avatar answered Sep 22 '22 02:09

Sweeper