2009-04-13 17 views
311

Quiero tener un objeto de clase, pero quiero forzar cualquier clase que representa para extender la clase A y B. implementar la interfazJava Generics comodines Con múltiples clases

que puedo hacer:

Class<? extends ClassA> 

O bien:

Class<? extends InterfaceB> 

pero no puedo hacer las dos cosas. ¿Hay alguna forma de hacer esto?

Respuesta

502

En realidad, usted puede haga lo que quiera. Si desea proporcionar múltiples interfaces o una clase más interfaces, tiene que tener su comodín ser algo como esto:

<T extends ClassA & InterfaceB> 

Véase el Generics Tutorial en sun.com, específicamente la sección Bounded Type Parameters, en la parte inferior de la página . De hecho, puede enumerar más de una interfaz si lo desea, utilizando & InterfaceName para cada uno que necesite.

Esto puede complicarse arbitrariamente. Para demostrar, consulte la declaración de JavaDoc Collections#max, que (envuelto en dos líneas) es:

public static <T extends Object & Comparable<? super T>> T 
              max(Collection<? extends T> coll) 

qué tan complicado? Como se dijo en las preguntas frecuentes de Java Generics: To preserve binary compatibility.

Parece que esto no funciona para la declaración de variables, pero funciona al poner un límite genérico en una clase. Por lo tanto, para hacer lo que quieras, es posible que tengas que saltar unos pocos aros. Pero puedes hacerlo. Se puede hacer algo como esto, poniendo un límite genérico en su clase y luego:

class classB { } 
interface interfaceC { } 

public class MyClass<T extends classB & interfaceC> { 
    Class<T> variable; 
} 

para obtener variable que tiene la restricción que desea. Para obtener más información y ejemplos, consulte la página 3 de Generics in Java 5.0. Tenga en cuenta que en <T extends B & C>, el nombre de clase debe ser lo primero, y las interfaces siguen. Y, por supuesto, solo puede enumerar una sola clase.

+0

¿Pero por qué tengo que lanzar el objeto a T al devolverlo? –

+0

@BernhardV: Debe proporcionar más información antes de que pueda responderla. ¿En qué situación necesitas lanzar? – Eddie

+79

Esto es útil. Vale la pena mencionar que la clase _debería ser lo primero, no se puede decir ''. – EricS

11

No puede hacerlo con parámetros de tipo "anónimo" (es decir, comodines que usan ?), pero puede hacerlo con parámetros de tipo "con nombre". Simplemente declare el parámetro de tipo en el método o nivel de clase.

import java.util.List; 
interface A{} 
interface B{} 
public class Test<E extends B & A, T extends List<E>> { 
    T t; 
} 
+0

¿Por qué no se permiten comodines? es decir, no veo por qué esto no debería ser válido: ArrayList ; Y luego, si sacaste un elemento de la lista, puedes asignarlo a una variable de tipo ClassA o de tipo InterfaceB – Mark

+0

¡Reemplazar el comodín con una variable es una gran técnica! Pero no siempre funciona. Por ejemplo, Java no permite nombres de tipo variables en los tipos de valor de anotación, mientras que sí permite comodines. – sigpwned