• Post Reply Bookmark Topic Watch Topic
  • New Topic

Question about generic method  RSS feed

 
Winston Liek
Ranch Hand
Posts: 194
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Accdg to docs.oracle:
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.


Sorry but I can't understand what it says. Does it mean:
1. The method is only exclusively to be used for the declared argument parameter? For example given a generic method:

public static <String, Integer> boolean method(Pair<K, V> p1) {}

I could only invoke the method if Pair argument parameter is <String, Integer>?

2. Or, it will return a <String, Integer> value?
 
Rico Felix
Ranch Hand
Posts: 411
5
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Liek wrote:
Sorry but I can't understand what it says. Does it mean:
1. The method is only exclusively to be used for the declared argument parameter? For example given a generic method:

public static <String, Integer> boolean method(Pair<K, V> p1) {}

I could only invoke the method if Pair argument parameter is <String, Integer>?

2. Or, it will return a <String, Integer> value?


Actually generics don't work like that and your code will run into some problems with the compiler.


Here is some code that demonstrates the use of generics with a method that accepts a Map with key and value pairs of any type and converts its values to a list:



The method getListFromMapValues accepts a Map of type Map<K, ? extends V> and returns a list of type List<V>, and does so for any type <K, V>. This is indicated by writing <K, V> at the beginning of the method signature, which declares <K, V> as new type variables. A method which declares type variables in this way is called a generic method. The scope of the type variables <K, V> is local to the method itself. It may appear in the method signature and the method body, but not outside the method. The compiler infers the types by the values passed in as in the demonstration code above bounding <K, V> to <String, Integer> respectively on that specific invocation of the method based on the types in the HashMap that was passed in as an argument. This types of method declaration generalizes the code allowing it to be flexible as it can work with a plethora of types. I personally see this mechanism fit as a replacement for method overloading in some situations.
 
Winston Liek
Ranch Hand
Posts: 194
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thanks for your explanation.

Based on your example code, I could only invoke getListFromMapValues if and only if I passed an argument on the method with <K, V> as type parameter?

For example, if I change:

with:


I would get a compilation error from main method since the argument passed is <String, Integer> and in the generic method it is <Integer, Integer>? Is that correct?

I'm really confused
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Liek wrote:For example, if I change:...

But this is precisely what you don't do. The whole point of generics is that it can be used with all sorts of types, so there's no point in changing them.
public static <K, V> List<V> getListFromMapValues(Map<K, ? extends V> map)
says:
"The method takes a Map with a key type of K and returns a List of type V, either of which can be ANY Java class.
Since V might have subclasses, and the Map's values will be used to populate the List, the value type of the Map must be either V itself, OR a type that extends V."

There is no idea of "changing" method declarations, what you do is call the method according to the rules it specifies.
So if you have two Maps:
Map<String, Number> map1 = new HashMap<String, Number>(); and
Map<String, Integer> map2 = new HashMap<String, Integer>();

the following calls:
List<Number> list1 = getListFromMapValues(map1);,
List<Number> list2 = getListFromMapValues(map2); and
List<Integer> list3 = getListFromMapValues(map2);
are legal, but:
List<Integer> list4 = getListFromMapValues(map1);
is not.

This is because map1 is a Map<String, Number>, but list4 is a List<Integer>, which means that for that call, V == Integer. But the map's value type is Number, which is NOT a subclass of Integer.

Hope it helps. Generics can be quite tough to get your head around to begin with and, from time to time, I still have to go back to the tutorials.

Winston
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!