Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a generic method and how is <T> bound in this case? [duplicate]

Tags:

java

generics

Preface: I understand generics and how they're declared at the class level (e.g. class MyClass<T>) but I've never seen it declared at the level of a static method, and without any explicit bindings (e.g. class MySubclass<String> extends MyClass).

I found this code snippet in an app I'm working on (I didn't write this part). I've never seen a method declared this way. <T> is not defined anywhere else in the class. Intent.getExtras().get() returns an Object which may actually be a String, Boolean ...etc.

private static <T> T getItemExtra(final Intent intent, final String extraName) {
    T item = null;

    if(intent != null && intent.getExtras() != null) {
        item = (T) intent.getExtras().get(extraName);
    }

    return item;
}

Sample usage:

String s1 = getItemExtra(someIntent, "some_string_extra");
Uri u1 = getItemExtra(someIntent, "some_uri_extra");

How does the JVM know what type to use for <T>? (Yes this method compiles and executes successfully).

like image 814
Barry Fruitman Avatar asked Nov 12 '15 02:11

Barry Fruitman


People also ask

What are generics method?

Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter's scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.

Why do we use T in generics?

Yes, the angle-brackets with one (or more) types is the syntax for generics. The T (to confirm, can be any identifier) serves as the placeholder for(in effect, is replaced by) the supplied type.

How are bounds used with generics?

Whenever you want to restrict the type parameter to subtypes of a particular class you can use the bounded type parameter. If you just specify a type (class) as bounded parameter, only sub types of that particular class are accepted by the current generic class. These are known as bounded-types in generics in Java.

What is the difference between T and in Java generics?

Well there's no difference between the first two - they're just using different names for the type parameter ( E or T ).


1 Answers

How does the JVM know what type to use for <T>?

The basic answer is, it doesn't. In Java, generic types are used by the type checker at compile time, but are removed from the program when the program actually runs. So for instance, the cast to T in item = (T) intent.getExtras().get(extraName) doesn't actually do anything at runtime: it's effectively a cast to Object, always, regardless of what type the caller expects T to be. (This is different from a cast to a normal type like String, where the program will fail with an exception immediately if you try to cast the wrong thing.)

The fact that you can cast to T without a check is a loophole in Java's type system that can cause weird class-cast exceptions. For instance, if you say

String s = getItemExtra(...); 
s.toLowerCase();

but getItemExtra doesn't return a string, then you'll get an exception on the second line telling you that s isn't a string, even though there's no cast on that line. For that reason, when the Java compiler sees a cast to T it will generate an unchecked-cast warning, telling you that it can't check that your typecast was legal and you might run into problems like this.

like image 132
jacobm Avatar answered Sep 20 '22 20:09

jacobm