要在参数化类型中使用的类和泛型类型转换

时间:2013-11-21 11:54:58

标签: java generics reflection

我有两个循环,我正在尝试重构为单个方法。循环通知不同类型的侦听器,并将它们声明为通用。我以为我可以做一些反思,但我似乎无法理解它。

这是我的消息类和监听器接口:

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()));
    }
}

1 个答案:

答案 0 :(得分: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);
    }
});