En Java, me gustaría tener algo como:
class Clazz<T> {
static void doIt(T object) {
// ...
}
}
Pero consigo
No se puede hacer una referencia estática al tipo T no estático
No entiendo los genéricos más allá de los usos básicos y, por lo tanto, no tiene mucho sentido. No ayuda que no haya podido encontrar mucha información en Internet sobre el tema.
¿Podría alguien aclarar si tal uso es posible, de manera similar? Además, ¿por qué fracasó mi intento original?
fuente
Java no sabe qué
T
es hasta que crea una instancia de un tipo.Tal vez pueda ejecutar métodos estáticos llamando,
Clazz<T>.doit(something)
pero parece que no puede.La otra forma de manejar las cosas es poner el parámetro de tipo en el método mismo:
lo que no te da la restricción correcta en U, pero es mejor que nada ...
fuente
Me encontré con este mismo problema. Encontré mi respuesta descargando el código fuente
Collections.sort
en el marco de Java. La respuesta que usé fue poner el<T>
genérico en el método, no en la definición de la clase.Entonces esto funcionó:
Por supuesto, después de leer las respuestas anteriores, me di cuenta de que esta sería una alternativa aceptable sin usar una clase genérica:
fuente
T extends XXX
sintaxis.Comparable
. Intenta en su<T extends Comparable<? super T>>
lugar.Es posible hacer lo que quiera usando la sintaxis para métodos genéricos al declarar su
doIt()
método (observe la adición de<T>
entrestatic
yvoid
en la firma del método dedoIt()
):Obtuve el editor Eclipse para aceptar el código anterior sin el
Cannot make a static reference to the non-static type T
error y luego lo expandí al siguiente programa de trabajo (completo con referencias culturales algo apropiadas para la edad):Lo que imprime estas líneas en la consola cuando lo ejecuto:
fuente
<T>
enmascara al primero de la misma manera que enclass C { int x; C(int x) { ... } }
el parámetrox
enmascara el campox
.static <E extends SomeClass> E foo(E input){return input;}
para todos y cada uno de los métodos cuando me gustaría hacer algo comostatic <E extends SomeClass>; //static generic type defined only once and reused
static E foo(E input){return input;}
static E bar(E input){return input;}
//...etc...
Creo que esta sintaxis aún no se ha mencionado (en el caso de que desee un método sin argumentos):
Y la llamada:
Espero que esto ayude a alguien.
fuente
<String>
porque simplemente infiere el argumento de tipo porque lo asigna a una variable. Si no lo asigna, simplemente infiereObject
.Se menciona correctamente en el error: no se puede hacer una referencia estática a T. tipo no estática La razón es el parámetro de tipo
T
puede ser sustituido por cualquiera de los argumentos por ejemplo, tipoClazz<String>
oClazz<integer>
etc, pero los campos estáticos / métodos son compartidos por todos los no -objetos estáticos de la clase.El siguiente extracto se toma del documento :
Como acertadamente señaló Chris en su respuesta , debe usar el parámetro type con el método y no con la clase en este caso. Puedes escribirlo como:
fuente
Algo como lo siguiente te acercaría
EDITAR: ejemplo actualizado con más detalles
fuente
Cuando especifica un tipo genérico para su clase, JVM sabe que solo tiene una instancia de su clase, no una definición. Cada definición solo tiene un tipo parametrizado.
Los genéricos funcionan como plantillas en C ++, por lo que primero debe crear una instancia de su clase, luego usar la función con el tipo que se especifica.
fuente
Clazz<int>::doIt( 5 )
)También para decirlo en términos simples, ocurre debido a la propiedad "Erasure" de los genéricos. Lo que significa que aunque definimos
ArrayList<Integer>
yArrayList<String>
, en el momento de la compilación, permanece como dos tipos concretos diferentes, pero en el tiempo de ejecución la JVM borra los tipos genéricos y crea solo una clase ArrayList en lugar de dos clases. Entonces, cuando definimos un método de tipo estático o cualquier cosa para un genérico, es compartido por todas las instancias de ese genérico, en mi ejemplo es compartido por ambosArrayList<Integer>
y.ArrayList<String>
Es por eso que obtiene el error. Un parámetro de tipo genérico de una clase no es Permitido en un contexto estático!fuente
@BD en Rivenhill: Dado que esta vieja pregunta ha recibido una atención renovada el año pasado, sigamos un poco, solo por el bien de la discusión. El cuerpo de su
doIt
método no hace nadaT
específico. Aquí está:Por lo tanto, puede descartar por completo todas las variables de tipo y solo codificar
Okay. Pero volvamos más cerca del problema original. La primera variable de tipo en la declaración de clase es redundante. Solo se necesita el segundo en el método. Aquí vamos de nuevo, pero aún no es la respuesta final:
Sin embargo, es demasiado alboroto por nada, ya que la siguiente versión funciona de la misma manera. Todo lo que necesita es el tipo de interfaz en el parámetro del método. No hay variables de tipo a la vista en ningún lado. ¿Era realmente ese el problema original?
fuente
Dado que las variables estáticas son compartidas por todas las instancias de la clase. Por ejemplo, si tiene el siguiente código
T está disponible solo después de crear una instancia. Pero los métodos estáticos se pueden usar incluso antes de que haya instancias disponibles. Por lo tanto, no se puede hacer referencia a los parámetros de tipo genérico dentro de los métodos y variables estáticos
fuente