Troubles with generics while trying to call a method
我正在尝试为我的Java应用程序开发一个静态验证方法。我正在使用带有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public enum ValidationType { TAX_CODE(null); // FIXME private final DataValidator<?> validator; private ValidationType(DataValidator<?> validator) { this.validator = validator; } } public static <T> void validate(T data, ValidationType dataType) { dataType.validator.validate(data); } private static abstract class DataValidator<T> { public abstract Class<T> getType(); public abstract void validate(T data); } |
在使用Eclipse进行编辑时,调用validate方法时出错(行
伊柯丽斯说:
The method validate(capture#3-of ?) in the type ValidationUtil.DataValidator is not applicable for the arguments (T)
我不能理解梅萨加。如果可能,如何修复或修改代码以使其正常工作?
提前感谢您的意见和建议。
您会得到这个错误,因为您使用的是通用通配符,并且您的代码不是类型安全的。
一种解决方案是不使用通用通配符。
问题是复杂的,因为在EDCOX1 17中有这样的事实,枚举不能有类型参数(至少,还没有——这可能成为Java未来版本中的一个特性)。例如,这是不允许的:
1 2 3 4 5 6 7 | public enum ValidationType<T> { // Not valid Java! (at least not in Java 8) TAX_CODE(null); // FIXME private final DataValidator<T> validator; // etc. } |
您可以改为使用一个带有常量的类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public final class ValidationType<T> { public static final ValidationType<String> TAX_CODE = new ValidationType<>(...); public static final ValidationType<Integer> SOMETHING = new ValidationType<>(...); public static final ValidationType<Double> ANOTHER = new ValidationType<>(...); private final DataValidator<T> validator; private ValidationType(DataValidator<T> validator) { this.validator = validator; } public DataValidator<T> getValidator() { return validator; } } |
枚举中的字段
但是,您可以通过为具有正确签名的字段创建一个访问器方法来解决这个问题:
1 2 3 | public <T> DataValidator<T> getValidator() { return (DataValidator<T>)validator; } |
您将需要在这里强制转换,因为您假定在
换言之,系统将无法阻止你做一些愚蠢的事情,比如:
1 | TAX_CODE.getValidator().validate(new HashMap<>()); |
不会检查
这是调整后的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public enum ValidationType { TAX_CODE(null); // FIXME private final DataValidator<?> validator; private ValidationType(DataValidator<?> validator) { this.validator = validator; } public <T> DataValidator<T> getValidator() { return (DataValidator<T>)validator; } } public static <T> void validate(T data, ValidationType dataType) { dataType.getValidator().validate(data); } private static abstract class DataValidator<T> { public abstract Class<T> getType(); public abstract void validate(T data); } |
更新
重写提案:
如果您将
1 2 3 | public static class Validators { public static final DataValidator<String> TAX_CODE_VALIDATOR = ...; } |
用途:
1 | Validators.TAX_CODE_VALIDATOR.validate("12345"); |