title: use generics to replace specific class type
body: <p>Currently, I have three classes, <code>Apple</code>, <code>Grape</code>, <code>Banana</code>, and I created a converter class (can convert a string to list) for each of them. Then I realized all those converter classes are basically the same except they take different class types. 
  The example of <code>AppleConverter.java</code></p>
  
  <pre><code>  public class AppleConverter extends StrutsTypeConverter {
  
    @SuppressWarnings("rawtypes")
    @Override
    public Object convertFromString(Map context, String[] values, Class toClass) {
  
      final List&lt;Apple&gt; appleList = new ArrayList&lt;&gt;();
      try {
        for (String appleString : values) {
            Apple apple = Apple.valueOf(appleString);
            appleList.add(apple);
        }
      }
      catch (IllegalArgumentException e) {
        throw new TypeConversionException(e);
      }
      return appleList;
    }
  
    @SuppressWarnings("rawtypes")
    @Override
    public String convertToString(Map context, Object o) {
      if (o == null) {
        return null;
      }
      if (o instanceof List&lt;?&gt;) {
        List&lt;Apple&gt; list = (List&lt;Apple&gt;) o;
        String appleString = list
          .stream()
          .map(e -&gt; String.valueOf(e))
          .collect(Collectors.joining(","));
        return appleString;
      }
      throw new TypeConversionException("wrong");
    }
  </code></pre>
  
  <p>Basically, <code>GrapdeConverter.java</code> and <code>BananaConverter.java</code> are the same as <code>AppleConverter.java</code> except they take different class types. 
  So I tried to create a generic class then those converter classes can inherit it.<br>
  My generic class code: </p>
  
  <pre><code>    public class FruitConverter&lt;T&gt; extends StrutsTypeConverter {
  
  
    @SuppressWarnings("rawtypes")
    @Override
    public Object convertFromString(Map context, String[] values, Class toClass) {
      if (ArrayUtils.isEmpty(values)) {
        return null;
      }
      final List&lt;T&gt; objs = new ArrayList&lt;&gt;();
      try {
        for (String objStr : values) {
  
             Object obj = toClass.getDeclaredMethod("valueOf", String.class).invoke(null, objStr);
  
            objs.add(obj);
          }
        }
      }
      catch (IllegalArgumentException e) {
        throw new TypeConversionException(e);
      }
      return objs;
    }
  
    @SuppressWarnings("rawtypes")
    @Override
    public String convertToString(Map context, Object o) {
      if (o == null) {
        return null;
      }
      if (o instanceof List&lt;?&gt;) {
        List&lt;?&gt; list = (List&lt;?&gt;) o;
        String fruitString = list
          .stream()
          .map(e -&gt; String.valueOf(e))
          .collect(Collectors.joining(","));
        return fruitString;
      }
      throw new TypeConversionException("object is not a list of objs");
    }
  }
  </code></pre>
  
  <p>When I called <code>T obj = T.valueOf(objStr);</code>, it throws an error <code>can not resolve method valueOf</code>.
  May anyone tell me how to apply generics correctly in this case.</p>