1

I was reading up on generics in Java here and here, and while I understand the point of having them, I'm having a little trouble understanding the header of a generic Java method. I'm used to:

public returnType methodName(parameters){body}

What keeps confusing me is the specification of a generic method declaration:

public *genericType* returnType methodName(parameters){body}

or

public static <T> void fromArrayToCollection(Collection<T> c) {}

What is this type declaration (<T> between static and void) affecting? Is it just outlining the type that the method parameters can be?

6
  • 2
    It means "This method has a generic type parameter referred to as T" Commented Jan 15, 2016 at 16:26
  • @khelwood Why doesn't the existence of Collection<T> in the signature implicitly have that same meaning? Commented Jan 15, 2016 at 16:27
  • 1
    It lets you add a generic type parameter to just that method, as opposed to declaring it at the class level. Commented Jan 15, 2016 at 16:27
  • Didnt even see void there : / Commented Jan 15, 2016 at 16:28
  • 2
    @Matt Because there is nothing (other than convention) which says that you name type variables like T. For example, you could write void foo(Collection<String> strs) { String bar = ""; } (which compiles), but you could also write <String> void foo(Collection<String> strs) { String bar = ""; } which does not, since String is a type variable, not java.util.String. Similarly, if it were inferrable that T might mean a type variable, there is no way of knowing whether you mean that or some class which you forgot to import, T. Commented Jan 15, 2016 at 16:35

2 Answers 2

4

The <T> between static and void in this case means "There is a generic type parameter being referred to as T in this method."

Compare case 1:

class Foo<T> {
     public void doFoo(Collection<T> items) ...
}

with case 2:

class Foo {
    public <T> void doFoo(Collection<T> items) ...
}

and case 3:

class Foo {
    public void doFoo(Collection<T> items) ...
}

In the first case, T is a generic type for the whole class, so if you call doFoo, the <T> in the collection you pass in needs to be the same T as the generic type of the instance of Foo<T>.

In the second case, T is a generic type existing only in the method doFoo.

In case 3, T must be an actual type, because there is no declaration that it is a generic type parameter.

Sign up to request clarification or add additional context in comments.

Comments

2

The <T> declared as return type references the <T> declared in the parameter. That way you know that if you feed your method a collection of Strings, you'll get a String as a result.

So in conclusion, a generic type give you the ability to reference in your code a type without having to specify it yet.

2 Comments

The types within the generic body are actually only known at compile time (rather than runtime), thanks to type erasure
@augray "fixed" it, but it seems clunky. I'll see if I can find a better way to express it. Thanks for remining me generics were specified during compilation

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.