1

I don't understand the difference between these two code snippets.

What's the role of T extends List in the first example? Can I interpret it as "a method named see that you can pass List type or subtype of List to"? If yes, why not just use method 2?

1.

public <T extends List> void see(T n) {}

2.

public void see(List n) {}
1
  • “why don't I just use method 2?” In this special case: good question. Method 1 does not make much sense here. Commented Sep 12, 2013 at 13:08

2 Answers 2

3

In this example, I don't think it is useful.

But in this one :

public <T extends MyClass> T[] toArray(List<T> n) {
   ...
}

It gives you some type checking (I reused T in the return type).

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
//I gave a List<Integer> so it returns a Integer[]. No need to cast ! 
Integer[] myArray = toArray(list);

Whereas in this case :

//I don't know the generic type of the list so I return a Object[]
public Object[] toArray(List n) {
   ...
}

You will need to cast the result.

Note : To answer your question, here <T extends MyClass> only restrict the type of T to a subclass of MyClass.

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

1 Comment

It would make also sense if it was : public <T extends MyClass> List<T> toArray(List<T> n). It is more clear, that generics make sense mainly when they used incollections.
1

"Bounded generic types" are normally used, to allow the parameter-types or return-types of a method/ or methods within a class to be inter-related.

Considering your example 1):

public <T extends List> void see(T n) {}

The generic type is bounded to be a subtype of List, so at the JVM level the compiled (raw) code & signature will be equivalent to example 2).

There are some subtle semantic differences in how "generic" and "raw" types are treated by the compiler, however. Conversion between "raw" and "generic" types typically a warning, as do unchecked generic type operations.

For code using generics properly, declaring List would (I understand) be preferable. Since there is no inter-relation between method parameters, the second style would be simpler.

My suggestion:

public void see (List<?> items) {}

The style in 1) makes more sense for inter-related parameters/ or result types. A couple of separate examples, showing more typical use:

public <T>  List<T> getChildren (T parent);
public <T>  List<T> listItems (T list1, T item2);
public <T extends List<?>>  T combineLists (T list1, T list2);

It is probably more common to declare T as the item parameter, and genericize collections on that, than to declare T as a "collection type".

Comments

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.