目前,我有三个类Apple
,Grape
,Banana
,我为每个类创建了一个转换器类(可以将字符串转换为列表)。然后我意识到所有这些转换器类基本相同,只是它们采用不同的类类型。
AppleConverter.java
public class AppleConverter extends StrutsTypeConverter {
@SuppressWarnings("rawtypes")
@Override
public Object convertFromString(Map context, String[] values, Class toClass) {
final List<Apple> appleList = new ArrayList<>();
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<?>) {
List<Apple> list = (List<Apple>) o;
String appleString = list
.stream()
.map(e -> String.valueOf(e))
.collect(Collectors.joining(","));
return appleString;
}
throw new TypeConversionException("wrong");
}
基本上,GrapdeConverter.java
和BananaConverter.java
与AppleConverter.java
相同,只是它们采用不同的类类型。
所以我尝试创建一个泛型类,然后那些转换器类可以继承它
我的通用类代码:
public class FruitConverter<T> extends StrutsTypeConverter {
@SuppressWarnings("rawtypes")
@Override
public Object convertFromString(Map context, String[] values, Class toClass) {
if (ArrayUtils.isEmpty(values)) {
return null;
}
final List<T> objs = new ArrayList<>();
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<?>) {
List<?> list = (List<?>) o;
String fruitString = list
.stream()
.map(e -> String.valueOf(e))
.collect(Collectors.joining(","));
return fruitString;
}
throw new TypeConversionException("object is not a list of objs");
}
}
当我拨打T obj = T.valueOf(objStr);
时,会抛出错误can not resolve method valueOf
。
在这种情况下,任何人都可以告诉我如何正确应用泛型。
答案 0 :(得分:1)
你不能在这些表达中使用T
,我怀疑你甚至需要泛型来完成这项任务。
快速而肮脏的推广方法是使用反射,而不是T obj = T.valueOf(objStr);
使用此:
Object obj = toClass.getDeclaredMethod("valueOf", String.class).invoke(null, objStr);
然后你就可以对所有这样的对象使用相同的功能了。
另一种方法是使用结构,但它需要更多的代码。
答案 1 :(得分:1)
发生编译错误是因为Java的泛型是用type erasure实现的。在这种情况下,T.valueOf
被视为与您尝试Object.valueOf
时相同,即它不知道要搜索valueOf
方法的哪些类,除了Object
。
您可以使用方法引用将该方法作为函数传递,如以下示例所示:
import java.util.function.Function;
class FruitConverter<T> {
private final Function<String, T> valueOf;
FruitConverter(Function<String, T> valueOf) {
this.valueOf = valueOf;
}
// ...
}
class AppleConverter extends FruitConverter<Apple> {
AppleConverter() {
super(Apple::valueOf);
}
}
然后,当您想要调用方法时,可以使用this.valueOf.apply(...)
。
另见https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html。