我有一个通用接口Handler
public interface Handler<T> {
void handle(T obj);
}
我可以有该接口的n个实现。假设我目前有以下两种实现。一个处理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);
}
}
我想写一个工厂,它将根据类类型返回处理程序实例。像这样的东西:
class HandlerFactory {
public <T> Handler<T> getHandler(Class<T> clazz) {
if (clazz == String.class) return new StringHandler();
if (clazz == Date.class) return new DateHandler();
}
}
我在这家工厂遇到以下错误:
类型不匹配:无法从
StringHandler
转换为Handler<T>
如何解决此问题?
简单解决方案>]
您的问题是,编译器无法实现结果类型正确的事实。[]为了帮助编译器,您可以让工厂委托构造。尽管这看起来很奇怪并且毫无用处,但是它确实设法正确地保持了类型安全性,而没有牺牲例如强制转换或使用?
或原始类型。
class HandlerFactory {
public <T> Handler<T> getHandler(Class<T> clazz) {
if (clazz.equals(String.class)) return (Handler<T>) new StringHandler();
if (clazz.equals(Date.class)) return (Handler<T>) new DateHandler();
return null;
}
}
T
是通用的,编译器无法在编译时将其映射。同样,使用.equals
代替==
更安全。
另一方面,如示例所示,如果实现可以共享,则工厂自然运行:
public class Main {
static public interface Handler<T> {
void handle(T obj);
}
static public class PrintHandler<T> implements Handler<T> {
@Override
public void handle(T obj) {
System.out.println(obj);
}
}
static class HandlerFactory {
public static <T> Handler<T> getHandler() {
return new PrintHandler<T>();
}
}
public static void main(String[] args) {
Handler<String> stringHandler = HandlerFactory.getHandler();
Handler<Date> dateHandler = HandlerFactory.getHandler();
stringHandler.handle("TEST");
dateHandler.handle(new Date());
}
}
public Handler getHandler( Class clazz ){
if( clazz == String.class ) return new StringHandler();
if( clazz == Date.class ) return new DateHandler();
return null;
}
public static void main( String[] args ){
HandlerFactory handlerFactory = new HandlerFactory();
StringHandler handler = ( StringHandler )handlerFactory.getHandler( String.class );
handler.handle( "TEST" );
DateHandler handler2 = ( DateHandler )handlerFactory.getHandler( Date.class );
handler2.handle( new Date() );
}
输出:
public Handler<?> getHandler(Class<?> clazz) {
if (clazz == String.class)
return new StringHandler();
if (clazz == Date.class)
return new DateHandler();
return null;
}
public class HandlerFactory {
public Handler<?> getHandler(Class<?> clazz) {
if (clazz == String.class) {
return new StringHandler();
}
if (clazz == Date.class) {
return new DateHandler();
}
return null;
}
}