Using Java, is it possible to use an unlimited type of a wildcard type as an argument to a method, and then check and apply it to a parameterized type?

If I use unlimited lookup types for two collections (each collection will have a different type ) as arguments to the method:

private void doAssertion(List<?> testList, List<?> generatedList) 

Inside this method, can I first check the type of objects in these collections, and then pass the collection to a parameterized type? It just smells bad and I get a warning without warning.

 if (testList.get(0) instanceof X) { List<X> xList = (List<X>) testList; // call methods specific to X for each object } else if (testList.get(0) instanceof Y){ List<Y> yList = (List<Y>) testList; // call methods specific to Y for each object } 

Part of my problem is that I have no way to touch the code that defines the classes X or Y. Otherwise, I know that I can implement them for a common interface and use a parameter of a limited type. I cannot overload assertEqual because both methods have the same erase.

In my case, X and Y will always be child classes of other classes, and I don’t modify objects at all by simply calling the get() methods of the objects.

+4
source share
6 answers

A warning:

 List<?> 

means list of unknown type. You can get () from this list, but you cannot add () to it except null.

If you need to add elements, it is best to use a non-generic version and check the type as you suggested. The result will be the same.

 private void doAssertion(List testList, List generatedList){ if (testList.get(0) instanceof X) { List<X> xList = (List<X>) testList; // call methods specific to X for each object } else if (testList.get(0) instanceof Y){ List<Y> yList = (List<Y>) testList; // call methods specific to Y for each object } } 

Also make sure the lists are not empty before executing (testList.get (0) instanceof X)

0
source

No, you should not do this. Take for example:

 List<Integer> myIntList = ...; if (myIntList.get(0) instanceof Number) { List<Number> myNumberList = (List<Number>)myIntList; myNumberList.put(Double.valueOf(100)); // BAD! } 

General arguments can optionally be replaced in sub / superclass hierarchies.

+4
source

You can declare several methods with specific types of X and Y:

  private void doAssertion(List<X> testList, List<X> generatedList, X x) { // call methods specific to X for each object } private void doAssertion(List<Y> testList, List<Y> generatedList, Y y) { // call methods specific to Y for each object } 

The third parameter is simply used simply to prompt the method.

+2
source

private <T, U> void doAssertion(List<T> testList, List<U> generatedList);

+1
source

In my case, X and Y will always be child classes of other classes, and I don’t modify objects at all, just by calling get () methods.

If the above statement is true, then are these getXX () methods the parent class. If so, why don't you do:

 private void doAssertion(List<? extends SomeFoo> testList, List<? extends SomeFoo> generatedList) 

Assuming SomeFoo has the functions you want, I can call it with any subclass of SomeFoo.

+1
source

Afaik, in C # there is no concept of Unbound Wild Card types. If so, this is good, since I think that with UnboundWildCardTypes (or not?) You can only use what can be done: - c below:

 private static void demoUnboundedWildcardType(List<?> aList, List<?> anotherList, Object obj){ //aList.add(""); You can't do this because at compile time capture is ? and not string. aList.contains(""); // you can only methods that don't take a generic type. Set<?> gs = (Set<?>) obj; // But must do this and not Set<?> gs = (Set) obj; aka don't use raw types } 
0
source

All Articles