Cómo usar Class en Java?
Hay una buena discusión de los genéricos y lo que realmente hacen detrás de escena en esta pregunta, por lo que todos sabemos que Vector<int[]>
es un vector de matrices enteras, y HashTable<String, Person>
es una tabla de cuyas claves son cadenas y valores Person
s.
Sin embargo, lo que me impacta es el uso de Class<>
.
Se supone que la clase java Class
también debe tomar un nombre de plantilla, (o eso me dice el subrayado amarillo en eclipse). No entiendo qué debería poner ahí. Todo el punto de el objeto Class
es cuando usted no tiene completamente la información sobre un objeto, para la reflexión y tal. ¿Por qué me hace especificar qué clase tendrá el objeto Class
? Claramente no lo sé, o no estaría usando el objeto Class
, usaría el específico.
10 answers
Usando la versión generificada de class Class le permite, entre otras cosas, escribir cosas como
Class<? extends Collection> someCollectionClass = someMethod();
Y luego puede estar seguro de que el objeto de Clase que recibe se extiende Collection
, y una instancia de esta clase será (al menos) una Colección.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-20 10:31:25
Todo lo que sabemos es "Todas las instancias de una clase any comparten el mismo java.lang.Objeto de clase de ese tipo de clase "
E. g)
Student a = new Student();
Student b = new Student();
Entonces a.getClass() == b.getClass()
es verdad.
Ahora asume
Teacher t = new Teacher();
Sin genéricos lo siguiente es posible.
Class studentClassRef = t.getClass();
Pero esto está mal ahora ..?
E. g) public void printStudentClassInfo(Class studentClassRef) {}
se puede llamar con Teacher.class
Esto se puede evitar usando genéricos.
Class<Student> studentClassRef = t.getClass(); //Compilation error.
Ahora, ¿qué es T ?? T es parámetros de tipo (también llamados tipo variables); delimitado por corchetes angulares ( ), sigue el nombre de la clase.
T es solo un símbolo, como un nombre de variable (puede ser cualquier nombre) declarado durante la escritura del archivo de clase. Más tarde que T será sustituido por
nombre de clase válido durante la inicialización (HashMap<String> map = new HashMap<String>();
)
Ej) class name<T1, T2, ..., Tn>
Así que Class<T>
representa un objeto de clase de tipo de clase específico 'T
'.
Asuma que sus métodos de clase tienen que trabajar con parámetros de tipo desconocidos como abajo
/**
* Generic version of the Car class.
* @param <T> the type of the value
*/
public class Car<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
Aquí T se puede usar como String
tipo como CarName
O T se puede utilizar como Integer
tipo como ModelNumber ,
O T se puede utilizar como Object
tipo como instancia válida del coche.
Ahora aquí lo anterior es el POJO simple que se puede usar de manera diferente en tiempo de ejecución.
Las colecciones e. g) List, Set, Hashmap son los mejores ejemplos que funcionarán con diferentes objetos según la declaración de T, pero una vez que declaramos T como cadena
e.g) HashMap<String> map = new HashMap<String>();
Entonces solo aceptará objetos de instancia de Clase String.
Métodos Genéricos
Los métodos genéricos son métodos que introducen sus propios parámetros de tipo. Esto es similar a declarar un tipo genérico, pero el ámbito del parámetro type está limitado al método donde se declara. Se permiten métodos genéricos estáticos y no estáticos, así como constructores de clases genéricos.
La sintaxis para un método genérico incluye un parámetro de tipo, inside angle y aparece antes del tipo de retorno del método. Para métodos genéricos, la sección parámetro tipo debe aparecer antes del tipo de retorno del método.
class Util {
// Generic static method
public static <K, V, Z, Y> boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
class Pair<K, V> {
private K key;
private V value;
}
Aquí <K, V, Z, Y>
es la declaración de tipos utilizados en los argumentos del método que deben antes del tipo de retorno que es boolean
aquí.
A continuación; la declaración de tipo <T>
no es necesaria a nivel de método, puesto que ya se ha declarado a nivel de clase.
class MyClass<T> {
private T myMethod(T a){
return a;
}
}
Pero a continuación está mal como parámetros de tipo de nivel de clase K, V, Z e Y no se pueden usar en un contexto estático (aquí el método estático).
class Util <K, V, Z, Y>{
// Generic static method
public static boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
OTROS ESCENARIOS VÁLIDOS SON
class MyClass<T> {
//Type declaration <T> already done at class level
private T myMethod(T a){
return a;
}
//<T> is overriding the T declared at Class level;
//So There is no ClassCastException though a is not the type of T declared at MyClass<T>.
private <T> T myMethod1(Object a){
return (T) a;
}
//Runtime ClassCastException will be thrown if a is not the type T (MyClass<T>).
private T myMethod1(Object a){
return (T) a;
}
// No ClassCastException
// MyClass<String> obj= new MyClass<String>();
// obj.myMethod2(Integer.valueOf("1"));
// Since type T is redefined at this method level.
private <T> T myMethod2(T a){
return a;
}
// No ClassCastException for the below
// MyClass<String> o= new MyClass<String>();
// o.myMethod3(Integer.valueOf("1").getClass())
// Since <T> is undefined within this method;
// And MyClass<T> don't have impact here
private <T> T myMethod3(Class a){
return (T) a;
}
// ClassCastException for o.myMethod3(Integer.valueOf("1").getClass())
// Should be o.myMethod3(String.valueOf("1").getClass())
private T myMethod3(Class a){
return (T) a;
}
// Class<T> a :: a is Class object of type T
//<T> is overriding of class level type declaration;
private <T> Class<T> myMethod4(Class<T> a){
return a;
}
}
Y finalmente el método estático siempre necesita una declaración explícita <T>
; No derivará del nivel de clase Class<T>
. Esto se debe a que el nivel de clase T está vinculado con la instancia.
Léase también Restricciones a los medicamentos genéricos
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-15 14:18:59
De la Documentación de Java:
[...] Más sorprendentemente, la clase Clase ha sido generificada. Los literales de clase ahora funcionan como tokens de tipo, proporcionando información de tipo tanto en tiempo de ejecución como en tiempo de compilación. Esto permite un estilo de fábricas estáticas ejemplificado por el método getAnnotation en la nueva interfaz AnnotatedElement:
<T extends Annotation> T getAnnotation(Class<T> annotationType);
Este es un método genérico. Infiere el valor de su parámetro de tipo T de su argumento, y devuelve una instancia apropiada de T, como lo ilustra el siguiente fragmento:
Author a = Othello.class.getAnnotation(Author.class);
Antes de los genéricos, habría tenido que emitir el resultado al Autor. Tampoco habría tenido forma de hacer que el compilador comprobara que el parámetro real representaba una subclase de Anotación. [...]
Bueno, nunca tuve que usar este tipo de cosas. ¿Alguien?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-03 23:26:09
He encontrado class<T>
útil cuando creo búsquedas de registro de servicios. Por ejemplo,
<T> T getService(Class<T> serviceClass)
{
...
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-20 21:52:48
Como señalan otras respuestas, hay muchas y buenas razones por las que este class
se hizo genérico. Sin embargo, hay muchas veces que no tiene ninguna forma de saber el tipo genérico para usar con Class<T>
. En estos casos, simplemente puede ignorar las advertencias de eclipse amarillas o puede usar Class<?>
... Así es como lo hago;)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-20 17:53:39
Siguiendo la respuesta de @Kire Haglin, se puede ver otro ejemplo de métodos genéricos en la documentación de para JAXB unmarshalling :
public <T> T unmarshal( Class<T> docClass, InputStream inputStream )
throws JAXBException {
String packageName = docClass.getPackage().getName();
JAXBContext jc = JAXBContext.newInstance( packageName );
Unmarshaller u = jc.createUnmarshaller();
JAXBElement<T> doc = (JAXBElement<T>)u.unmarshal( inputStream );
return doc.getValue();
}
Esto permite a unmarshal
devolver un documento de un tipo de árbol de contenido JAXB arbitrario.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-07 16:29:53
A menudo desea usar comodines con Class
. Por ejemplo, Class<? extends JComponent>
, le permitiría especificar que la clase es una subclase de JComponent
. Si has recuperado la instancia Class
de Class.forName
, entonces puedes usar Class.asSubclass
para hacer el cast antes de intentar, por ejemplo, construir una instancia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-20 17:47:13
Solo para agregar otro ejemplo, la versión genérica de Class (Class<T>
) permite escribir funciones genéricas como la siguiente.
public static <T extends Enum<T>>Optional<T> optionalFromString(
@NotNull Class<T> clazz,
String name
) {
return Optional<T> opt = Optional.ofNullable(name)
.map(String::trim)
.filter(StringUtils::isNotBlank)
.map(String::toUpperCase)
.flatMap(n -> {
try {
return Optional.of(Enum.valueOf(clazz, n));
} catch (Exception e) {
return Optional.empty();
}
});
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-10 08:13:15
Es confuso al principio. Pero ayuda en las siguientes situaciones:
class SomeAction implements Action {
}
// Later in the code.
Class<Action> actionClass = Class.forName("SomeAction");
Action action = actionClass.newInstance();
// Notice you get an Action instance, there was no need to cast.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-02 12:25:39
Simplemente use la clase beef:
public <T> T beefmarshal( Class<beef> beefClass, InputBeef inputBeef )
throws JAXBException {
String packageName = docClass.getPackage().getBeef();
JAXBContext beef = JAXBContext.newInstance( packageName );
Unmarshaller u = beef.createBeef();
JAXBElement<T> doc = (JAXBElement<T>)u.beefmarshal( inputBeef );
return doc.getBeef();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-29 19:17:22