2013-11-21 38 views
1

我有两个循环,我试图重构成单个方法。循环通知不同类型的监听器,并将其声明为通用。我认为我可以通过一些反思来做到这一点,但我似乎无法摆脱困境。在参数化类型中使用的类和泛型类型转换

这里是我的邮件类和侦听器接口:

public class Message { 

    private RequestType type; // Enum 
    private String data; 
    ... 
} 

public interface IRequestListener<T> { 
    public void resultUpdated(T result); 
} 

这里是循环:

... 
// Notification is an Enum 
for (IRequestListener<?> listener : listeners) { 
    IRequestListener<Notification> notificationListener = 
     (IRequestListener<Notification>) listener; 

    notificationListener.resultUpdated(Notification.valueOf(message.getData())); 
} 

... 

for (IRequestListener<?> listener : listeners) { 
     IRequestListener<Integer> notificationListener = 
      (IRequestListener<Integer>) listener; 

     notificationListener.resultUpdated(Integer.valueOf(message.getData())); 
} 

这里是在解决我的铸造尝试这显然是错误的:

... 

notifyMessageListeners(Notification.class, essage) 

... 

notifyMessageListeners(Integer.class, message); 

... 

private void notifyMessageListeners(Class clazz, Message message) { 
    LinkedList<IRequestListener<?>> listeners = 
     requestListenerMap.get(message.getType()); 

    for (IRequestListener<?> listener : listeners) { 

     // How to solve this cast? 
     // Error: unknown class: 'clazz' 
     IRequestListener<clazz> notificationListener = 
      (IRequestListener<clazz>) listener; 

     // How to solve the valueOf? Need to cast to a class which has valueOf()? 
     // Error: cannot resolve method valueOf 
     notificationListener.resultUpdated(clazz.valueOf(message.getData())); 
    } 
} 

这是我在解决这个问题时的一般尝试,也是错误的:

private void notifyMessageListeners(Message message) { 

    LinkedList<IRequestListener<?>> listeners = 
     requestListenerMap.get(message.getType()); 

    for (IRequestListener<?> listener : listeners) { 
     // Causes error 
     // resultUpdated (<?>) in IRequestListener cannot be applied to (java.lang.String) 
     listener.resultUpdated(message.getData()); 
    } 
} 

我已经在SO上花了一些时间,并在文档中试图解决这个问题。似乎有很多关于泛型的文章,但是我找不到与我的具体用例有关的东西。

干杯。

编辑:

与接受的答案的帮助下解决了。

notifyMessageListeners(message, new IValueGetter<T>() { 
    public T getValue(String data) { 
     return (T) Notification.valueOf(data); 
    } 
}); 

private void notifyMessageListeners(Message message, IValueGetter<T> getter) { 
    LinkedList<IRequestListener<?>> listeners = 
     requestListenerMap.get(message.getType()); 
    for (IRequestListener<?> listener : listeners) { 
     IRequestListener<T> notificationListener = (IRequestListener<T>) listener; 
     notificationListener.resultUpdated(getter.getValue(message.getData())); 
    } 
} 

回答

2

这里是如何解决你的第一次尝试:

首先,定义一个接口调用valueOf(您可以通过使用反射避免这种情况,但我认为,一个“无反射”的方法是清洁剂)

interface ValueGetter<T> { 
    T getValue(String data); 
} 

此通用接口可以传递一段代码到notifyMessageListeners,以便该方法会给你回电话,以提取从字符串所需的值。

private void notifyMessageListeners(Message message, ValueGetter<T> getter) { 
    LinkedList<IRequestListener<?>> listeners = 
     requestListenerMap.get(message.getType()); 

    for (IRequestListener<?> listener : listeners) { 
     IRequestListener<T> notificationListener = 
      (IRequestListener<T>) listener; 
     notificationListener.resultUpdated(getter.getValue(message.getData())); 
    } 
} 

当你调用notifyMessageListeners,你需要传递的ValueGetter<T>一个实例,像这样:

notifyMessageListeners(message, new ValueGetter<T>() { 
    public T getValue(String data) { 
     return (T) Notification.valueOf(data); 
    } 
}); 

notifyMessageListeners(message, new ValueGetter<T>() { 
    public T getValue(String data) { 
     return (T) Integer.valueOf(data); 
    } 
}); 
+0

谢谢,看来几乎把我的工作状态。非常聪明。我已经删除了'Class'参数,因为它看起来不需要。我还为我的班级签名添加了''。但是,我收到了一个错误,'MyService 类型的notifyMessageListeners(Message,ValueGetter )方法不适用于参数(Message,new ValueGetter (){})''。任何有关可能出错的建议? – span

+0

想我可能已经解决了它。如果您认为这是正确的,请参阅后期编辑。 – span

+1

@rattmuff是的,这是正确的:因为'ValueGetter'与'Class '是同一类型'T'的参数化,所以不需要通过类。 – dasblinkenlight