如何解决Java泛型和类层次结构
| 我遇到这种情况,我尝试创建一个示例,并想看看是否有任何优雅的方法来修复它。 假设我有一些可显示的接口,并实现了类:Person和Car,并且我声明了通用的Converter类,如下所示:public interface Converter<T extends displayable> {
boolean canConvert(displayable o);
String convert(T o);
T decode(String s);
boolean canRevert(String s);
}
假设我有这个实现
public class CarConverter implements Converter<Car> { ... }
和
public class PersonConverter implements Converter<Person> { ... }
现在,在我的使用中,我有一个displayable列表和一个转换器列表,我想转换和还原displayable:
List<displayable> ds = new ArrayList<displayable>();
ds.add(new Person(\"ma\",12));
ds.add(new Person(\"fa\",43));
ds.add(new Car());
ds.add(new Car());
ds.add(new Person(\"Sol\",58));
List<Converter>cs = new ArrayList<Converter>();
cs.add(new CarConverter());
cs.add(new PersonConverter());
ArrayList<String> displays = new ArrayList<String>();
for(displayable d:ds) {
for(Converter c:cs) {
if(c.canConvert(d)) {
displays.add(c.convert(d));
break;
}
}
}
List<displayable> ret = new ArrayList<displayable>();
for(String display : displays) {
for(Converter c:cs) {
if(c.canRevert(display)) {
displayable d = c.decode(display);
ret.add(d);
}
}
}
令人讨厌的一点是,我不得不声明一个Converter列表,从而失去了泛型。
List<Converter>
如果尝试声明,则会收到语法错误
List<Convert<displayable>>
然后我收到很多警告。
解决方法
您可以这样做,您只需要对列表声明进行一些更改:
List<Converter<? extends Displayable>> list = ...
这将为您工作。这里要记住的关键是,您不能依赖嵌套类型参数中的继承,需要使用extends
声明扩展名。
如果您有8个实例,则只能将9个实例添加到该列表中,而不能将10个实例添加到该列表中。
, 看起来转换器只是在制作可显示内容的字符串表示形式。如果是这种情况,我认为您真正想做的就是为每个Displayable重写toString()方法,并为每个参数提供一个以显示字符串作为参数的构造函数。然后,您不必担心为Displayable的每个实现实现单独的Converter。所以一个人看起来像:
public class Person implements Displayable {
public Person(String display) {
// Make a Person from a display
}
public String toString() {
// Make a display from a person
}
...
}
, 这可能很la脚,但是在这种情况下您根本不需要泛型。由于您已经使用canConvert和canRevert,因此不需要其他编译时类型检查。
我快速修复的代码:
public static void main(String[] args) {
List<Displayable> ds = new ArrayList<Displayable>();
ds.add(new Person(\"ma\",12));
ds.add(new Person(\"fa\",43));
ds.add(new Car());
ds.add(new Car());
ds.add(new Person(\"Sol\",58));
ArrayList<Converter> cs = new ArrayList<Converter>();
cs.add(new CarConverter());
cs.add(new PersonConverter());
ArrayList<String> displays = new ArrayList<String>();
for (Displayable d : ds) {
for (Converter c : cs) {
if (c.canConvert(d)) {
displays.add(c.convert(d));
break;
}
}
}
List<Displayable> ret = new ArrayList<Displayable>();
for (String display : displays) {
for (Converter c : cs) {
if (c.canRevert(display)) {
Displayable d = c.decode(display);
ret.add(d);
}
}
}
}
。
public class CarConverter implements Converter {
@Override
public boolean canConvert(Displayable o) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean canRevert(String s) {
// TODO Auto-generated method stub
return false;
}
@Override
public String convert(Displayable o) {
// TODO Auto-generated method stub
return null;
}
@Override
public Car decode(String s) {
// TODO Auto-generated method stub
return null;
}
}
。
打包转换
public interface Converter {
boolean canConvert(Displayable o);
String convert(Displayable o);
Displayable decode(String s);
boolean canRevert(String s);
}
还是我缺少的仿制药有什么优势?
一个更漂亮的解决方案是将转换器代码包含在Displayable类中。如果每种类型只有一个转换器,那就更好了。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。