use*_*820 11 java generics factory
我有一个通用接口处理程序
public interface Handler<T> {
void handle(T obj);
}
Run Code Online (Sandbox Code Playgroud)
我可以有这个接口的n个实现.假设我现在有以下2个实现.一个处理String对象,另一个处理Date
public class StringHandler implements Handler<String> {
@Override
public void handle(String str) {
System.out.println(str);
}
}
public class DateHandler implements Handler<Date> {
@Override
public void handle(Date date) {
System.out.println(date);
}
}
Run Code Online (Sandbox Code Playgroud)
我想编写一个工厂,它将根据类类型返回处理程序实例.像这样的东西:
class HandlerFactory {
public <T> Handler<T> getHandler(Class<T> clazz) {
if (clazz == String.class) return new StringHandler();
if (clazz == Date.class) return new DateHandler();
}
}
Run Code Online (Sandbox Code Playgroud)
我在这个工厂得到以下错误:
类型不匹配:无法转换
StringHandler为Handler<T>
如何解决这个问题?
简单的解决方案
你可以节省您的映射Class<T> -> Handler<T>中Map.就像是:
Map<Class<T>, Handler<T>> registry = new HashMap<>();
public void registerHandler(Class<T> dataType, Class<? extends Handler> handlerType) {
registry.put(dataType, handlerType);
}
public <T> Handler<T> getHandler(Class<T> clazz) {
return registry.get(clazz).newInstance();
}
Run Code Online (Sandbox Code Playgroud)
在某些地方,初始化处理程序(可能在工厂本身):
factory.registerHandler(String.class, StringHandler.class);
factory.registerHandler(Date.class, DateHandler.class);
Run Code Online (Sandbox Code Playgroud)
在另一个地方,您创建并使用它们:
Handler<String> stringhandler = factory.getHandler(String.class);
Handler<Date> dateHandler = factory.getHandler(Date.class);
Run Code Online (Sandbox Code Playgroud)
更复杂的解决方案
您可以使用反射"扫描"类,而不是手动注册映射Class<T> -> Handler<T>,使用反射进行操作.
for (Class<? extends Handler> handlerType : getHandlerClasses()) {
Type[] implementedInterfaces = handlerType.getGenericInterfaces();
ParameterizedType eventHandlerInterface = (ParameterizedType) implementedInterfaces[0];
Type[] types = eventHandlerInterface.getActualTypeArguments();
Class dataType = (Class) types[0]; // <--String or Date, in your case
factory.registerHandler(dataType, handlerType);
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以像上面一样创建和使用它们:
Handler<String> stringhandler = factory.getHandler(String.class);
Handler<Date> dateHandler = factory.getHandler(Date.class);
Run Code Online (Sandbox Code Playgroud)
要实现getHandlerClasses(),请查看此内容以扫描您的所有类jar.对于每个班级,您必须检查它是否是Handler:
if (Handler.class.isAssignableFrom(scanningClazz) //implements Handler
&& scanningClazz.getName() != Handler.class.getName()) //it is not Handler.class itself
{
//is a handler!
}
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你!
您的问题是编译器无法跳转到结果类型正确的事实。
为了帮助编译器,您可以让工厂委托构造。尽管这看起来很奇怪且笨拙,但它确实能够正确维护类型安全,而无需做出诸如强制转换或使用?或原始类型之类的牺牲。
public interface Handler<T> {
void handle(T obj);
}
public static class StringHandler implements Handler<String> {
@Override
public void handle(String str) {
System.out.println(str);
}
}
public static class DateHandler implements Handler<Date> {
@Override
public void handle(Date date) {
System.out.println(date);
}
}
static class HandlerFactory {
enum ValidHandler {
String {
@Override
Handler<String> make() {
return new StringHandler();
}
},
Date {
@Override
Handler<Date> make() {
return new DateHandler();
}
};
abstract <T> Handler<T> make();
}
public <T> Handler<T> getHandler(Class<T> clazz) {
if (clazz == String.class) {
return ValidHandler.String.make();
}
if (clazz == Date.class) {
return ValidHandler.Date.make();
}
return null;
}
}
public void test() {
HandlerFactory factory = new HandlerFactory();
Handler<String> stringHandler = factory.getHandler(String.class);
Handler<Date> dateHandler = factory.getHandler(Date.class);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9614 次 |
| 最近记录: |