简体   繁体   中英

using getter with java generic method argument

I have a method that takes a generic parameter type. The scenario I have is this method will be called with different parameter types.

class something{
    public void someMethod(){
        List<A> listA = ....; //Class A have a field String Id;
        List<B> listB = ....; //Class B haave a field String Id;

        testMethod(listA);
        testMethod(listB);
    }

    private <T> void testMethod( List<T> list ){
            for( T event : list ){
                //TODO (something like): event.getId();
            }
        }
}

In the above code all the parameters will be be a List<someObjectType> . All the object types have a common field and need to use the getter to fetch its value. Now since the method definition is generic, how do I achieve this?

Have A and B implement a common interface that has a method getID :

interface SomeInterface {
    String getID();
}

then you could have:

private <T extends SomeInterface> void testMethod(List<T> list) {
    for (T event : list) {
        // now you can use `event.getID()` here
    }
}

This cannot be done. You can't handle two different lists with incompatible interfaces the same way in your method, unless you do something with instanceof , ie

public void testMethod(List<? extends Object> list) {
  if(list.get(0) == null) return;
  if(list.get(0) instanceof A) {
    // Do the A stuff
  } else {
    // Do the B stuff
  }
}

There is no point in creating such a generic method without bounded type. Since T isn't bounded to any type, you can't use specific interface on the objects inside the list. So if you want testMethod to get list of objects of any type, you should use List<?> instead.

Define your method like this with T extending your common class/interface BaseType :

private <T extends BaseType> void testMethod( List<T> list ){
   for( T event : list ){
       //TODO (something like): event.getId();
   }
}

Example:

public void someMethod() {
    List<Integer> listA = Arrays.asList( new Integer[] {1, 4, 9} );
    List<Double> listB = Arrays.asList( new Double[] {1.5, 4.2, 9.3} );;
    testMethod(listA);
    testMethod(listB);
}

private <T extends Number> void testMethod( List<T> list ){
    for( T event : list ) {
        // Note intValue() method is being called here which is provided
        // in the base class Number that is being extended by T
        System.out.println(event.intValue());
    }
}   

As other answers said, you need to bound the type parameter by some interface. But for what you're using it for, you don't actually need to have a T :

private void testMethod(List<? extends SomeInterface> list) {
    for (SomeInterface event : list) {
        // now you can use `event.getID()` here
    }
}

I don't know if i really understand what you want. But if you know, you will store for example Strings into your List and want to use the toUpperCase() method, how about just casting it?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM