2011-06-01 16 views
7

Creé una clase de NotificationManager, que permite registrar un oyente genérico en un servicio de notificación genérico. En la clase NotificationManager Tengo un método genérico para registrar un oyente con un servicio:Java: ¿Cómo se exige que un parámetro de tipo de clase sea el mismo que el genérico especificado en un método genérico?

public static <E> void registerNotify(Class<E> type, INotificationListener<E> listener) { 
    @SuppressWarnings("unchecked") 
    INotificationService<E> service = (INotificationService<E>) NotificationServiceFactory.get(type); 
    service.registerNotificationListener(listener); 
} 

Así, para algunos INotificationListener de un tipo particular me gustaría obligar al usuario, cuando se llama a este método, para especificar el mismo tipo que el oyente. El tipo se asigna a todos los INotificationListeners del mismo tipo, sin embargo, este método no impone lo que estoy tratando de hacer cumplir. Por ejemplo, podría llamar:

INotificationListener<Location> locationListener = this; 
NotificationManager.registerNotify(String.class, locationListener); 

y el código compila bien. Lo que pensé que esto haría cumplir es el siguiente:

INotificationListener<Location> locationListener = this; 
NotificationManager.registerNotify(Location.class, locationListener); 

¿Alguna idea sobre cómo lograr esto?


Actualización:

Lo siento por la confusión, lo anterior de hecho funciona. El método en la misma clase que no funciona en realidad es la siguiente:

public static <E> void broadcastNotify(Class<E> type, E data) 
    { 
     @SuppressWarnings("unchecked") 
     INotificationService<E> service = (INotificationService<E>) NotificationServiceFactory.get(type); 
     service.notifyListeners(data); 
    } 

Y llamando a:

Location location = new Location(); 
NotificationManager.broadcastNotify(Object.class, location); 

no causa un error de compilación, que es lo que me gustaría que hiciera.

+0

¿Cuál es el tipo de devolución declarada de 'NotificationServiceFactory # get()'? –

+0

Es INotificationService . La fábrica tiene un mapa que asigna nombres de clase a INotificationServices. Supongo que probablemente debería ser INotificationService , pero ¿cómo me aseguro de que el usuario obtenga un error de compilación cuando pasan la clase incorrecta en el método registerNotify? –

+1

No estoy seguro, pero acabo de obtener el error de compilación deseado cuando intento pasar 'String.class' (Eclipse Helios SR2). ¿Realmente está ejecutando el código que cree que está ejecutando? ¿O estás usando javac o un IDE diferente? – BalusC

Respuesta

1

Me di cuenta de esto. He cambiado la firma de:

public static <E> void broadcastNotify(Class<E> type, E data) 

a:

public static <E> void broadcastNotify(Class<E> type, INotification<E> data) 

donde INotification es alguna de las interfaces que envuelve los datos que estoy tratando de volver en la notificación. Esto exige que el tipo de clase debe coincidir exactamente con el tipo de notificación para que el mapa subyacente que mapea las notificaciones envíe los mensajes a los oyentes registrados correctamente sin preocuparse del error del programador.

0

Una forma de evitar el problema es utilizar la reflexión y obtener el tipo de la propia clase. Esto evitará la necesidad de proporcionar el mismo tipo dos veces. Solo proporcionará una advertencia si se usa un tipo no genérico.

Puede obtener el tipo genérico de la interfaz para la clase de implementación.

+0

Elegí no seguir esta ruta debido a la legibilidad. Si una clase registra y anula el registro de un grupo de diferentes tipos de oyentes usando 'this' como parámetro de escucha, es difícil decir para qué se registra/anula el registro de las notificaciones. –

+0

Está registrando/anulando el registro de los tipos de notificación que acepta. Solo tendrías que mirar la implementación. Pero estoy de acuerdo en que es mejor hacer lo que cree que es más claro, y menos probable que resulte en un error. –

0

ubicación es un objeto - Creo que se convierte en:

public static <Object> void broadcastNotify(Class<Object> type, Object data) 

recordar en java todos los objetos heredan del objeto.

+0

Lo sé, pero me gustaría exigir que sea exactamente la misma clase porque debajo tengo un mapa, que asigna la clase a los oyentes de esa clase, por lo que si alguien se registra con registerNotify (Location.class, this), pero una broadcast se escribe como broadcastNotify (Object.class, location) los oyentes no recibirán el mensaje. –

Cuestiones relacionadas