Java Basic Course (26) - reflection

one type

  For each type of objects, Java virtual machine will instantiate an instance of an immutable class java.lang.Class. This example provides a method of run-time attributes acquired object, including its membership and type information. Class class also provides a way to create a new instance. Most importantly, it is the entrance to all the reflection API. The following describes the most commonly involves reflection operation class.

1. Obtain the Class object

Object .getClass ()

  If you want an object to obtain its corresponding Class object, the easiest way is to call getClass () method, which inherits from the Object class, so each object can call this method:

import java.util.HashSet;
import java.util.Set;
import static reflect.ReflectDemo.E.A;

public class ReflectDemo {
    static enum E {A, B}
    public static void main(String[] args) {
        Class c1 = "foo".getClass();
        Class c2 = A.getClass();
        byte[] bytes = new byte[1024];
        Class c3 = bytes.getClass();
        Set<String> s = new HashSet<>();
        Class c4 = s.getClass();
    }
}

.Class class name

  If the type is not available instance, the object may be acquired by Class "class name .class":

import java.util.Set;
import static reflect.ReflectDemo.E.A;

public class ReflectDemo {
    static enum E {A, B}
    public static void main(String[] args) {
        Class c1 = String.class;
        Class c2 = E.class;
        Class c3 = byte[].class;
        Class c4 = Set.class;
    }
}

  Note that, when you call the basic data types of variables getClass () method, will produce a compilation error, but can be used for basic data types ".class", for example:

boolean b = true;
Class c1 = b.getClass();             //编译错误

Class c2 = boolean.class;

Class.forName()

  If the fully qualified class name of the class is available, use the static method the forName Class Class instance class to obtain, for example:

Class c = Class.forName("com.maconn.ReflectDemo");

  If no fully qualified type name corresponding to the class, the method throws an exception ClassNotFound. In addition, this approach can not be used for basic data types, the following procedures will be thrown:

try {
    Class c = Class.forName("int");
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

Basic types of packaging TYPE field

  Each elementary data type, and have a packing void classes include a static field TYPE, primitive type value of this field is to be packaged. E.g:

Class c = Integer.TYPE;

2. Obtain information on classes

  A class may contain elements of the following modifications:

  • public, protected or private: access control class
  • abstract: limit class must be inherited
  • static: only for internal class. When you create a class object, without first creating an instance of the outer class.
  • final: limit class can not be inherited
  • strictfp: internal limiting class all floating point operations performed in strict accordance with the IEEE-754 specification.
  • Note: to provide some additional information or markings for the class.

Note: strictfp mean FP-strict, that is precisely the meaning floating-point. When the Java virtual machine floating-point operations, if not specified strictfp keyword, Java compiler and runtime environment in the expression of floating-point operations is to adopt a behavior similar to its own way to complete these operations, so as to obtain the results are often unable to satisfy you. Once strictfp used to declare a class, when the interface or the method, then the range of the declared Java compiler and the runtime environment to execute completely floating-point specification in accordance with the IEEE-754. So if you want your floating-point arithmetic is more accurate, but not because of inconsistent results from different hardware platforms performed it, then please use keyword strictfp. (Excerpt from "Java language keyword strictfp use" a text description link https://blog.csdn.net/redv/article/details/326444 ).

  By following a program to demonstrate some of the ways to obtain such information, the program prints out the information of the String class:

import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.List;

import static java.lang.System.out;

public class ClassDeclarationSpy {
    public static void main(String[] args) {
        try {
            Class c = String.class;
            out.format("Class:%n  %s%n%n", c.getCanonicalName());
            out.format("Modifiers:%n  %s%n%n",
                    Modifier.toString(c.getModifiers()));

            out.format("Type Parameters:%n");
            TypeVariable[] tv = c.getTypeParameters();
            if (tv.length != 0) {
                out.format("  ");
                for (TypeVariable t : tv)
                    out.format("%s ", t.getName());
                out.format("%n%n");
            } else {
                out.format("  -- No Type Parameters --%n%n");
            }

            out.format("Implemented Interfaces:%n");
            Type[] intfs = c.getGenericInterfaces();
            if (intfs.length != 0) {
                for (Type intf : intfs)
                    out.format("  %s%n", intf.toString());
                out.format("%n");
            } else {
                out.format("  -- No Implemented Interfaces --%n%n");
            }

            out.format("Inheritance Path:%n");
            List<Class> l = new ArrayList<Class>();
            printAncestor(c, l);
            if (l.size() != 0) {
                for (Class<?> cl : l)
                    out.format("  %s%n", cl.getCanonicalName());
                out.format("%n");
            } else {
                out.format("  -- No Super Classes --%n%n");
            }

            out.format("Annotations:%n");
            Annotation[] ann = c.getAnnotations();
            if (ann.length != 0) {
                for (Annotation a : ann)
                    out.format("  %s%n", a.toString());
                out.format("%n");
            } else {
                out.format("  -- No Annotations --%n%n");
            }
        } catch (ClassNotFoundException x) {
            x.printStackTrace();
        }
    }

    private static void printAncestor(Class<?> c, List<Class> l) {
        Class<?> ancestor = c.getSuperclass();
        if (ancestor != null) {
            l.add(ancestor);
            printAncestor(ancestor, l);
        }
    }
}

  Here is the output of the program:

Class:
  java.lang.String

Modifiers:
  public final

Type Parameters:
  -- No Type Parameters --

Implemented Interfaces:
  interface java.io.Serializable
  java.lang.Comparable<java.lang.String>
  interface java.lang.CharSequence
  interface java.lang.constant.Constable
  interface java.lang.constant.ConstantDesc

Inheritance Path:
  java.lang.Object

Annotations:
  -- No Annotations --

  It should be noted that not all the comments are available through reflection. Only those using a meta-annotation @Retention {RetentionPolicy.RUNTIME} comments will be retained until runtime.

3 members found

  Members of the class may be further acquired by the class objects that are obtained, for example, member variables, methods and constructors members. This section describes how to obtain these members in turn below.

Obtain the Domain

method description Inherited Members Private member
getDeclaredField​(String name) Securing such a declaration pursuant to name member variables Does not contain contain
getDeclaredFields() Gets all member variables declared in the class Does not contain contain
getField(String name) Gets the member variable by name contain Does not contain
getFields() Get all the member variables contain Does not contain

Acquisition method

method description Inherited Members Private member
getDeclaredMethod​(String name, Class<?>... parameterTypes) Based on the name and parameter types of methods to obtain the class declaration Does not contain contain
getDeclaredMethods() Gets all the methods declared in the class Does not contain contain
getMethod​(String name, Class<?>... parameterTypes) Members get method name and parameter types contain Does not contain
getMethod​s() Get all the member methods contain Does not contain

Gets constructor

method description Private member
getDeclaredConstructor​(Class<?>... parameterTypes) Gets the configuration parameters according to the type of contain
getDeclaredConstructors() Get all the constructors contain
getConstructor​(Class<?>... parameterTypes) Gets the configuration parameters according to the type of Does not contain
getConstructors() Get all the constructors Does not contain

II. Members

  Reflection API defines an interface that represents Member, Field, Method and Constructor class members have achieved this interface. In the previous section has already acquired three members of the methods are simple to understand, this section will be a member of the three methods are introduced.

1. Domain

  In the reflection API, to indicate the domain using the Field class object. Has been described above how to get through the Class object Field object, now let's talk about the content of the Field class.

Gets the type of field

  You may be acquired by the type of the current field and getType getGenericType Field class. The difference is, Class getType method returns the object, and the object is returned getGenericType type Type. Further, if a field is a generic type, the return type of the method can not getType field precisely, and can be returned getGenericType field of the generic type.

Type is an interface java.lang.reflect package, the interface represent all types of senior public interface, Class class is a class that implements Type interface. Type including the original type, parameter types, array types, type variables and primitives.

  The following example in order to print out the results for each domain and call getType getGenericType of:

import java.lang.reflect.Field;
import java.util.List;

public class FieldSpy<T> {
    public String name  = "Alice";
    public List<Integer> list;
    public T val;

    public static void main(String... args) {
        try {
            Class<?> c = FieldSpy.class;
            Field f1 = c.getField("name");
            System.out.println("Field name:");
            System.out.format("Type: %s%n", f1.getType());
            System.out.format("GenericType: %s%n", f1.getGenericType());
            Field f2 = c.getField("list");
            System.out.println("Field list:");
            System.out.format("Type: %s%n", f2.getType());
            System.out.format("GenericType: %s%n", f2.getGenericType());
            Field f3 = c.getField("val");
            System.out.println("Field val:");
            System.out.format("Type: %s%n", f3.getType());
            System.out.format("GenericType: %s%n", f3.getGenericType());
        } catch (NoSuchFieldException x) {
            x.printStackTrace();
        }
    }
}

  The above program produces the following output:

Field name:
Type: class java.lang.String
GenericType: class java.lang.String
Field list:
Type: interface java.util.List
GenericType: java.util.List<java.lang.Integer>
Field val:
Type: class java.lang.Object
GenericType: T

  Val field type is Object, this is because the compiler erases all information on generic type during compilation. In this case, the upper bound will be used in place of the variable type, in this case, is the Object.

Get the value

  Field current domain can obtain the value indicated on the specified object. If the field is a reference type, use get (Object obj) method, which returns an Object object; if the field is the basic data types, can be used getXxx (Object obj) method, Xxx as Boolean, Byte, Char, Double, Float, Int, Long, Short of one.
  The following procedures were acquired value foo and bar fields:

import java.lang.reflect.Field;

public class FieldDemo {
    private String foo;
    private int bar;

    public FieldDemo(String stringField, int intField) {
        this.foo = stringField;
        this.bar = intField;
    }

    public static void main(String[] args) {
        Class<?> c = FieldDemo.class;
        FieldDemo fieldDemo = new FieldDemo("foo", 1);
        try {
            Field stringField = c.getDeclaredField("foo");
            System.out.println(stringField.get(fieldDemo));
            Field intField = c.getDeclaredField("bar");
            System.out.println(intField.getInt(fieldDemo));
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

  You may also set the value of the field for the specified object. If the field is a reference type, use set (Object obj, Object value) method; if the field is the basic data types, can be used getXxx (Object obj, Xxx value) method, Xxx as Boolean, Byte, Char, Double, Float, Int, Long, Short of one. For example, the following code domain foo and bar above the field settings:

Field stringField = c.getDeclaredField("foo");
stringField.set(c, "fool");
Field intField = c.getDeclaredField("bar");
intField.set(c, 2);

For additional information

  • <T extends Annotation> T getAnnotation (
    Class <T> annotationClass) Returns the field type annotation.
  • <T extends Annotation> T []
    getAnnotationsByType (Class <T> annotationClass) Returns the specified types of notes, returns an array. This method can be used to obtain repeat annotation.
  • Class <?> GetDeclaringClass ()
    Returns the class of the field in the statement.
  • int getModifiers ()
    with a modifier returns the integer domain. This requires the use of an integer type decoding Modifier.
  • String getName ()
    Returns the name of the domain.
  • boolean isSynthetic ()
    if the compiler returns true field is automatically generated, otherwise it returns false.

2. Methods

  In the reflection API, using the Method class representation. Method The following is a description of some of the common methods of the class.

Methods of access to information

  • <T extends Annotation> T getAnnotation (
    Class <T> annotationClass) Returns the specified type of action in the annotation process.
  • Annotation [] getDeclaredAnnotations ()
    returns directly annotations on the process occurs.
  • Class <?> GetDeclaringClass ()
    Returns the class of the method declaration.
  • Type [] getGenericExceptionTypes ()
    Returns the exception thrown
  • Type [] getGenericParameterTypes ()
    Returns the type of the process parameters.
  • Class <?> GetReturnType ()
    Return value type of the method.
  • Type getGenericReturnType ()
    Returns the value of the method's return type. We can not accurately return to the use of the generic return type.
  • String getName ()
    Returns the name of the method.

Call the method

  The method can be invoked on the object by the invoke method specified in the Method class. Here is the signature of the invoke method:
    Object invoke (Object obj, Object ... args)

  The first parameter is the object to invoke the method, as the variable parameters of the method is the need to receive parameters. The following procedure to obtain a method and call it:

import java.lang.reflect.Method;

public class MethodInvokeDemo {
    public static void main(String[] args) {
        try {
            Method method = Foo.class.getMethod("bar", int.class, int.class);
            Foo foo = new Foo();
            method.invoke(foo, 1, 2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
class Foo {
    public void bar(int a, int b) {
        System.out.println(a + b);
    }
}

3. Constructor

  In the reflection API, a class to represent Constructor constructor. Since most of the methods Constructor class are similar and Method class, is not repeated here. Here configured mainly about how the class instance of the class by the Constructor.
  Constructor class newInstance (Object ... initargs) method can be used to create new instances. In fact, Class class also has a newInstance method, but it is recommended to create an instance of the class using the newInstance method Constructor, which has been marked as Deprecated, is not recommended, because:

  • Class.newInstance () can only call the class constructor with no arguments, while Constructor.newInstance (Object ... initargs) can call any class constructor.
  • The Class.newInstance () constructor must be visible in claim, and in some cases Constructor.newInstance () can be called private constructor.

  The following program creates an instance of the Person class by class newInstance Constructor:

import java.lang.reflect.Constructor;

public class NewInstanceDemo {
    public static void main(String[] args) {
        Class<Person> c = Person.class;
        try {
            Constructor<Person> constructor = c.getConstructor(String.class, int.class);
            Person p = constructor.newInstance("foo", 26);
            System.out.println(p);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{name=" + name + ", age=" + age + "}";
    }
}

  For members of the Field, Method and Constructor represented, the class if the current location does not have access to these members, you can not access these members go through reflection. In this case, you need to call setAccessible these members (boolean flag) manual method flag is set to true in order to continue access.

III. Arrays and enumeration

1. Array

  Array is a fixed number of elements of the same type of reference, these elements may be the type of basic data types, or a reference type. Reflection API provides access to an array type, create a new array methods to get and set the value of the element.

Recognition array

  If we refer to the calling .getClass array () method will return what? The following do an experiment:

public class ArrayDemo {
    public static void main(String[] args) {
        byte[] b = {1, 2, 3};
        Integer[] i = {4, 5, 6};
        String[] s = {"Hello", "World"};
        System.out.println(b.getClass());
        System.out.println(i.getClass());
        System.out.println(s.getClass());
    }
}

  The above program will output:

class [B
class [Ljava.lang.Integer;
class [Ljava.lang.String;

  General class is different, the type of the array are coupled in front of the left bracket ([). If it is a two-dimensional array, it will have two left bracket, and so on. If you are an array of basic data types, the right side of the square brackets is only one capital letter, the letter is the first letter of the corresponding basic types. If the reference type is the right brackets is then coupled with a capital letter L fully qualified class name of the array elements, and the semicolon at the end.
  Although an object may be determined based on the result getClass () Returns the array is not, but this is not intuitive. A Class class provides the isArray () method, can be directly determined by this method is not an object array type.

Creating an array

  Reflection API is used to represent an array Array class. By this class newInstance (<?> Class componentType, int length) method to quickly create an array:

public static Object createArray(Class<?> c, int length) {
    return Array.newInstance(c, length);
}

  The above method of creating an array and returns a reference to the array, the caller needs to be cast to the actual type of array is used, e.g. Integer [] according to the specified type and length.

Get and set values

  Array class provides many get and set methods. Wherein get (Object array, int index) used to obtain a reference value from the array type, the getXxx (Object array, int index) for acquiring the value from the basic data type array; set (Object array, int index, Object value) is used to assign an array of reference type, while setXxx (Object array, int index, Object value) to the basic data types used for array assignment. Below is an example:

public class ArrayAssignmentDemo {
    public static void main(String[] args) {
        int[] i = new int[2];
        String[] s = new String[2];
        Array.setInt(i, 0, 1);
        Array.set(s, 0, "Hello");
        System.out.println(Array.getInt(i, 0));
        System.out.println(Array.get(s, 0));
    }
}

2. Enumeration

  Reflection API provides the following enumerated specific method:

  • Class.isEnum ()
    If the class is an enumeration type, it returns true.
  • Class.getEnumConstants ()
    to return all the enumeration constants enumerated types in the order stated.
  • java.lang.reflect.Field.isEnumConstant ()
    if the field is an enumerated type, it returns true.

Guess you like

Origin www.cnblogs.com/maconn/p/10962092.html