Java Language introduzione


Esempio

Nozioni di base

L'API Reflection consente di controllare la struttura della classe del codice in fase di esecuzione e di richiamare il codice in modo dinamico. Questo è molto potente, ma è anche pericoloso poiché il compilatore non è in grado di determinare staticamente se le invocazioni dinamiche sono valide.

Un semplice esempio potrebbe essere quello di ottenere i costruttori e i metodi pubblici di una determinata classe:

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

// This is a object representing the String class (not an instance of String!)
Class<String> clazz = String.class;

Constructor<?>[] constructors = clazz.getConstructors(); // returns all public constructors of String
Method[] methods = clazz.getMethods(); // returns all public methods from String and parents

Con questa informazione è possibile istanziare l'oggetto e chiamare dinamicamente diversi metodi.

Riflessione e tipi generici

Le informazioni di tipo generico sono disponibili per:

  • parametri del metodo, usando getGenericParameterTypes() .
  • metodo restituisce i tipi, usando getGenericReturnType() .
  • campi pubblici , usando getGenericType .

L'esempio seguente mostra come estrarre le informazioni di tipo generico in tutti e tre i casi:

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

public class GenericTest {

    public static void main(final String[] args) throws Exception {
        final Method method = GenericTest.class.getMethod("testMethod", Map.class);
        final Field field = GenericTest.class.getField("testField");

        System.out.println("Method parameter:");
        final Type parameterType = method.getGenericParameterTypes()[0];
        displayGenericType(parameterType, "\t");

        System.out.println("Method return type:");
        final Type returnType = method.getGenericReturnType();
        displayGenericType(returnType, "\t");

        System.out.println("Field type:");
        final Type fieldType = field.getGenericType();
        displayGenericType(fieldType, "\t");

    }

    private static void displayGenericType(final Type type, final String prefix) {
        System.out.println(prefix + type.getTypeName());
        if (type instanceof ParameterizedType) {
            for (final Type subtype : ((ParameterizedType) type).getActualTypeArguments()) {
                displayGenericType(subtype, prefix + "\t");
            }
        }

    }

    public Map<String, Map<Integer, List<String>>> testField;

    public List<Number> testMethod(final Map<String, Double> arg) {
        return null;
    }

}

Ciò risulta nell'output seguente:

Method parameter:
    java.util.Map<java.lang.String, java.lang.Double>
        java.lang.String
        java.lang.Double
Method return type:
    java.util.List<java.lang.Number>
        java.lang.Number
Field type:
    java.util.Map<java.lang.String, java.util.Map<java.lang.Integer, java.util.List<java.lang.String>>>
        java.lang.String
        java.util.Map<java.lang.Integer, java.util.List<java.lang.String>>
            java.lang.Integer
            java.util.List<java.lang.String>
                java.lang.String