0

I have implemented a java method with the following signature:

public <T> T getItemValue(String itemName, Class<T> itemType)  {
...
}

This allows a client to call the method in the following way to get for example a value of the type String or Integer:

String s = itemCol.getItemValue("_name", String.class);
int i = itemCol.getItemValue("_count", Integer.class);

This kind of method signature is also used by the Config interface of the new microprofile Config 1.3 API.

My question is how - or if - I can call the method with a Type of List of Types like List<String> to get for example a List of String objects. I was not able to formulate the client call. I tried something like this:

List<String> list = itemCol.getItemValue("_count", List<String.class>);

but this seems not to be the correct syntax.

EDITED:

As a result of the responses below I decided to add a separate method to get a List of a specific type.

public <T> List<T> getItemValueList(String itemName, Class<T> itemType) {
        ...
}

With this additional method signature a client can decide weather to get a single value or a list of a specific type.

Ralph
  • 3,451
  • 6
  • 36
  • 62
  • 1
    `List.class` does not work because of type erasure. https://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens – killjoy Aug 20 '18 at 20:09
  • This is correct, just with a warning. Java does not have ```List.class```, only ```List.class```, so there is an unsafe type conversion warning. – zhh Aug 20 '18 at 20:12
  • Would it than be a solution to add a second method like this `public List getItemValueList(String itemName, Class itemType)` which allows the client to call like this `List slist = itemCol.getItemValueList("txtname", String.class);` ? Do you find this solution better? – Ralph Aug 20 '18 at 20:57
  • If you have control over the data, you may want to use arrays instead of Lists. `String[].class` is completely valid and will not generate any warnings. – VGR Aug 20 '18 at 23:34
  • As the List interface is important to the client code, I now added a separate method. See my edited question. Thanks for the help. – Ralph Aug 21 '18 at 06:39

2 Answers2

5

Type Parameters are erased, they don't exist at runtime. There is no such thing as List<String> at runtime, there is only List.

So, the correct way to express a reflective proxy for List<String> is … you can't. You can only express a reflective proxy for List, the same way you do for any other class: List.class.

Jörg W Mittag
  • 337,159
  • 71
  • 413
  • 614
  • But how would the client code than look like? `List list = itemCol.getItemValue("_count", List.class)` ?? - How can my implementation know that the returned list should contain only String elements? – Ralph Aug 20 '18 at 20:46
  • It can't. The type is erased. It doesn't exist at runtime. That's what "type erasure" means. The type is gone. – Jörg W Mittag Aug 20 '18 at 22:47
  • thanks for the clarification. I added a new separate method. See my edited question. – Ralph Aug 21 '18 at 06:38
4

Not with List<String.class>, no. You need to use a TypeToken to get that sort of generic information. You also need to change your code to work with Type instead of Class.

Kayaman
  • 67,952
  • 3
  • 69
  • 110