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 Persons. 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.

Author: Community, 2009-01-20

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.

 110
Author: Yuval,
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

 136
Author: Kanagavelu Sugumar,
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?

 30
Author: raupach,
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)
{
    ...
}
 8
Author: Kire Haglin,
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;)

 5
Author: bruno conde,
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.

 3
Author: Stew,
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.

 2
Author: Tom Hawtin - tackline,
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();
                }
            });
}
 0
Author: zeronone,
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.
 -2
Author: fastcodejava,
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();
}
 -5
Author: yaa,
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