Chapter 16 Summary

16.1 Reflection

JAVA reflection mechanism is that in the running state, for any class, you can know all the properties and methods of this class; for any object, you can call any of its A method and attribute; this dynamically obtained information and the function of dynamically calling the object's method are called the reflection mechanism of the Java language

16.1.1 Accessing constructors

 

Get the construction method through reflection
 1. Get the construction method:
  1). Batch method:
public Constructor[] getConstructors(): All "public" constructors
            public Constructor[] getDeclaredConstructors(): Get all constructors (including private, protected, default, public)
     
  2). Get a single method and call:
public Constructor getConstructor(Class... parameterTypes): Get a single "public" constructor Method:
public Constructor getDeclaredConstructor(Class... parameterTypes): Get "a certain constructor" which can be private, protected, default, or public;

package com.mr;
public class Demo1 {
    String s;
    int i, i2, i3;
    private Demo1() {
    }
    protected Demo1(String s, int i) {
        this.s = s;
        this.i = i;
    }
    public Demo1(String... strings) throws NumberFormatException {
        if (0 < strings.length)
           i = Integer.valueOf(strings[0]);
        if (1 < strings.length)
           i2 = Integer.valueOf(strings[1]);
        if (2 < strings.length)
           i3 = Integer.valueOf(strings[2]);
    }
    
    public void print() {
        // TODO Auto-generated method stub
        System.out.println("s=" + s);
        System.out.println("i=" + i);
        System.out.println("i2=" + i2);
        System.out.println("i3=" + i3);
    }
}

 

import java.lang.reflect.Constructor;
import com.mr.Demo1;
 
public class ConstructorDemo1 {
	public static void main(String[] args) {
		Demo1 d1 = new Demo1("10", "20", "30");
		Class<? extends Demo1> demoClass = d1.getClass();
		// 获得所有构造方法
		Constructor[] declaredConstructors = demoClass.getDeclaredConstructors();
		for (int i = 0; i < declaredConstructors.length; i++) { // 遍历构造方法
			Constructor<?> constructor = declaredConstructors[i];
			System.out.println("查看是否允许带有可变数量的参数:" + constructor.isVarArgs());
			System.out.println("该构造方法的入口参数类型依次为:");
			Class[] parameterTypes = constructor.getParameterTypes(); // 获取所有参数类型
			for (int j = 0; j < parameterTypes.length; j++) {
				System.out.println(" " + parameterTypes[j]);
			}
			System.out.println("该构造方法可能抛出的异常类型为:");
			// 获得所有可能抛出的异常信息类型
			Class[] exceptionTypes = constructor.getExceptionTypes();
			for (int j = 0; j < exceptionTypes.length; j++) {
				System.out.println(" " + exceptionTypes[j]);
			}
			Demo1 d2 = null;
			try { // 如果该成员变量的访问权限为private,则抛出异常,即不允许访问
				if (i == 2) // 通过执行默认没有参数的构造方法创建对象
					d2 = (Demo1) constructor.newInstance();
				else if (i == 1)
					// 通过执行具有两个参数的构造方法创建对象
					d2 = (Demo1) constructor.newInstance("7", 5);
				else { // 通过执行具有可变数量参数的构造方法创建对象
					Object[] parameters = new Object[] { new String[] { "100", "200", "300" } };
					d2 = (Demo1) constructor.newInstance(parameters);
				}
			} catch (Exception e) {
				System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法");
				constructor.setAccessible(true); // 设置为允许访问
			}
			if (d2 != null) {
				d2.print();
				System.out.println();
			}
		}
 
	}
}
//例题16.1

 

Access member variables 

 
package com.mr;
 
public class Demo2 {
	int i;
	public float f;
	protected boolean b;
	private String s;
}
//例题16.2

 

import java.lang.reflect.Field;
import com.mr.Demo2;
 
public class FieldDemo {
	public static void main(String[] args) {
		Demo2 example = new Demo2();
		Class exampleC = example.getClass();
		// 获得所有成员变量
		Field[] declaredFields = exampleC.getDeclaredFields();
		for (int i = 0; i < declaredFields.length; i++) { // 遍历成员变量
			Field field = declaredFields[i];
			System.out.println("名称为:" + field.getName()); // 获得成员变量名称
			Class fieldType = field.getType(); // 获得成员变量类型
			System.out.println("类型为:" + fieldType);
			boolean isTurn = true;
			while (isTurn) {
				// 如果该成员变量的访问权限为private,则抛出异常,即不允许访问
				try {
					isTurn = false;
					// 获得成员变量值
					System.out.println("修改前的值为:" + field.get(example));
					if (fieldType.equals(int.class)) { // 判断成员变量的类型是否为int型
						System.out.println("利用方法setInt()修改成员变量的值");
						field.setInt(example, 168); // 为int型成员变量赋值
					} else if (fieldType.equals(float.class)) { // 判断成员变量的类型是否为float型
						System.out.println("利用方法setFloat()修改成员变量的值");
						field.setFloat(example, 99.9F); // 为float型成员变量赋值
						// 判断成员变量的类型是否为boolean型
					} else if (fieldType.equals(boolean.class)) {
						System.out.println("利用方法setBoolean()修改成员变量的值");
						field.setBoolean(example, true); // 为boolean型成员变量赋值
					} else {
						System.out.println("利用方法set()修改成员变量的值");
						field.set(example, "MWQ"); // 可以为各种类型的成员变量赋值
					}
					// 获得成员变量值
					System.out.println("修改后的值为:" + field.get(example));
				} catch (Exception e) {
					System.out.println("在设置成员变量值时抛出异常," + "下面执行setAccessible()方法!");
					field.setAccessible(true); // 设置为允许访问
					isTurn = true;
				}
			}
			System.out.println();
		}
	}
}
 
//例题16.2

Access member methods 

package com.mr;

public class Demo2 {

int i;

public float f;

protected boolean b;

private String s;

}

//例题16.2

 

import java.lang.reflect.Field;
import com.mr.Demo2;
 
public class FieldDemo {
    public static void main(String[] args) {
        Demo2 example = new Demo2();
        Class exampleC = example.getClass();
        // 获得所有成员变量
        Field[] declaredFields = exampleC.getDeclaredFields();
        for (int i = 0; i < declaredFields.length; i++) { // 遍历成员变量
            Field field = declaredFields[i];
            System.out.println("名称为:" + field.getName()); // 获得成员变量名称
            Class fieldType = field.getType(); // 获得成员变量类型
            System.out.println("类型为:" + fieldType);
            boolean isTurn = true;
            while (isTurn) {
                // 如果该成员变量的访问权限为private,则抛出异常,即不允许访问
                try {
                    isTurn = false;
                    // 获得成员变量值
                    System.out.println("修改前的值为:" + field.get(example));
                    if (fieldType.equals(int.class)) { // 判断成员变量的类型是否为int型
                        System.out.println("利用方法setInt()修改成员变量的值");
                        field.setInt(example, 168); // 为int型成员变量赋值
                    } else if (fieldType.equals(float.class)) { // 判断成员变量的类型是否为float型
                        System.out.println("利用方法setFloat()修改成员变量的值");
                        field.setFloat(example, 99.9F); // 为float型成员变量赋值
                        // 判断成员变量的类型是否为boolean型
                    } else if (fieldType.equals(boolean.class)) {
                        System.out.println("利用方法setBoolean()修改成员变量的值");
                        field.setBoolean(example, true); // 为boolean型成员变量赋值
                    } else {
                        System.out.println("利用方法set()修改成员变量的值");
                        field.set(example, "MWQ"); // 可以为各种类型的成员变量赋值
                    }
                    // 获得成员变量值
                    System.out.println("修改后的值为:" + field.get(example));
                } catch (Exception e) {
                    System.out.println("在设置成员变量值时抛出异常," + "下面执行setAccessible()方法!");
                    field.setAccessible(true); // 设置为允许访问
                    isTurn = true;
                }
            }
            System.out.println();
        }
    }
}
//例题16.2

Access member methods

package com.mr;
 
public class Demo3 {
    static void staticMethod() {
        System.out.println("执行staticMethod()方法");
    }
 
    public int publicMethod(int i) {
        System.out.println("执行publicMethod()方法");
        return i * 100;
    }
 
    protected int protectedMethod(String s, int i) throws NumberFormatException {
        System.out.println("执行protectedMethod()方法");
        return Integer.valueOf(s) + i;
    }
 
    private String privateMethod(String... strings) {
        System.out.println("执行privateMethod()方法");
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < strings.length; i++) {
            stringBuffer.append(strings[i]);
        }
        return stringBuffer.toString();
    }
}
//例题16.3

 

import java.lang.reflect.*;
 
import com.mr.Demo3;
 
public class MethondDemo {
    public static void main(String[] args) {
        Demo3 demo = new Demo3();
        Class demoClass = demo.getClass();
        // 获得所有方法
        Method[] declaredMethods = demoClass.getDeclaredMethods();
        for (int i = 0; i < declaredMethods.length; i++) {
            Method method = declaredMethods[i]; // 遍历方法
            System.out.println("名称为:" + method.getName()); // 获得方法名称
            System.out.println("是否允许带有可变数量的参数:" + method.isVarArgs());
            System.out.println("入口参数类型依次为:");
            // 获得所有参数类型
            Class[] parameterTypes = method.getParameterTypes();
            for (int j = 0; j < parameterTypes.length; j++) {
                System.out.println(" " + parameterTypes[j]);
            }
            // 获得方法返回值类型
            System.out.println("返回值类型为:" + method.getReturnType());
            System.out.println("可能抛出的异常类型有:");
            // 获得方法可能抛出的所有异常类型
            Class[] exceptionTypes = method.getExceptionTypes();
            for (int j = 0; j < exceptionTypes.length; j++) {
                System.out.println(" " + exceptionTypes[j]);
            }
            boolean isTurn = true;
            while (isTurn) {
                try {// 如果该方法的访问权限为private,则抛出异常,即不允许访问
                    isTurn = false;
                    if ("staticMethod".equals(method.getName()))
                        method.invoke(demo); // 执行没有入口参数的方法
                    else if ("publicMethod".equals(method.getName()))
                        System.out.println("返回值为:" + method.invoke(demo, 168)); // 执行方法
                    else if ("protectedMethod".equals(method.getName()))
                        System.out.println("返回值为:" + method.invoke(demo, "7", 5)); // 执行方法
                    else if ("privateMethod".equals(method.getName())) {
                        Object[] parameters = new Object[] { new String[] { "M", "W", "Q" } }; // 定义二维数组
                        System.out.println("返回值为:" + method.invoke(demo, parameters));
                    }
                } catch (Exception e) {
                    System.out.println("在执行方法时抛出异常," + "下面执行setAccessible()方法!");
                    method.setAccessible(true); // 设置为允许访问
                    isTurn = true;
                }
            }
            System.out.println();
        }
    }
}
//例题16.3

16.2Annotation annotation function


1. Define the Annotation annotation function
Define the Annotation type to contain multiple members

public @interface NoMemberAnnotation{String describe();Class type();

}

Available member types: String, Class, primitive, enumerated and annotation

When defining an Annotation type, you can use @Target to set the type of program element that the Annotation type is applicable to.
 

 

Create custom annotations

First define an Annotation type @Constructor_Annotation used to annotate the constructor method. The valid range is to load the Annotation into the JVM at runtime. The complete code is as follows:

 

 
import java.lang.annotation.*;
 
@Target(ElementType.CONSTRUCTOR)
// 用于构造方法
@Retention(RetentionPolicy.RUNTIME)
// 在运行时加载Annotation到JVM中
public @interface Constructor_Annotation {
	String value() default "默认构造方法"; // 定义一个具有默认值的String型成员
}

Then define an Annotation type @Field_Method_Parameter_Annotation used to annotate fields, methods and parameters. The valid range is to load Annotation into the JVM at runtime.

import java.lang.annotation.*;
 
// 用于字段、方法和参数
@Target( { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
// 在运行时加载Annotation到JVM中
public @interface Field_Method_Parameter_Annotation {
	String describe(); // 定义一个没有默认值的String型成员
	
	Class type() default void.class; // 定义一个具有默认值的Class型成员
}

Finally, write a Record class, in which the previously defined Annotation types @Constructor_Annotation= and @Field_Method_Parmeter_Annotation are used to annotate constructors, fields, methods and parameters. The complete code is as follows:

public class Record {
	@Field_Method_Parameter_Annotation(describe = "编号", type = int.class)
	// 注释字段
	int id;
	@Field_Method_Parameter_Annotation(describe = "姓名", type = String.class)
	String name;
 
	@Constructor_Annotation()
	// 采用默认值注释构造方法
	public Record() {
	}
 
	@Constructor_Annotation("立即初始化构造方法")
	// 注释构造方法
	public Record(@Field_Method_Parameter_Annotation(describe = "编号", type = int.class) int id,
			@Field_Method_Parameter_Annotation(describe = "姓名", type = String.class) String name) {
		this.id = id;
		this.name = name;
	}
 
	@Field_Method_Parameter_Annotation(describe = "获得编号", type = int.class)
	// 注释方法
	public int getId() {
		return id;
	}
 
	@Field_Method_Parameter_Annotation(describe = "设置编号")
	// 成员type采用默认值注释方法
	public void setId(
			// 注释方法的参数
			@Field_Method_Parameter_Annotation(describe = "编号", type = int.class) int id) {
		this.id = id;
	}
 
	@Field_Method_Parameter_Annotation(describe = "获得姓名", type = String.class)
	public String getName() {
		return name;
	}
 
	@Field_Method_Parameter_Annotation(describe = "设置姓名")
	public void setName(@Field_Method_Parameter_Annotation(describe = "姓名", type = String.class) String name) {
		this.name = name;
	}
}

2. Access Annotaiton information 
If @Retention is set to RetentionPolicy.RUNTIME when defining the Annotaiton type, then the relevant Annotaiton information can be obtained through reflection when running the program. Such as obtaining Annotaiton information of constructors, fields and methods.

The Constructor class, Field class and Method class all inherit the AccessibleObject class, and three methods about Annotaiton are defined in the AccessibleObject class. Among them, the method isAnnotaitonPresent(Class<? extends Annotaiton>annotaitonClass) is used to check whether the Annotaiton of the specified type has been added. If so, it returns true, otherwise it returns false; the method getAnnotaiton(Class<T>annotaitonClass) is used to obtain the Annotaiton of the specified type. , if it exists, return the corresponding object, otherwise return null; the method getAnnotaiton() is used to obtain all Annotaiton, this method will return an Annotaiton array.

The method getParameterAnnotaitons() is also defined in the Constructor class and Method class, which is used to obtain the Annotaiton added for all parameters. It will be returned as a two-dimensional array of Annotaiton type, and the order in the array is the same as the order declared. If there are no parameters, an array of length 0 is returned; if there are parameters without annotaiton added, a nested array of length 0 will be used as the placeholder.
 

import java.lang.annotation.*;
import java.lang.reflect.*;
 
public class AnnotationTest {
 
    public static void main(String[] args) {
        Class recordC = null;
        try {
            recordC = Class.forName("Record");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
 
        System.out.println("------ 构造方法的描述如下 ------");
        Constructor[] declaredConstructors = recordC.getDeclaredConstructors(); // 获得所有构造方法
        for (int i = 0; i < declaredConstructors.length; i++) {
            Constructor constructor = declaredConstructors[i]; // 遍历构造方法
            // 查看是否具有指定类型的注释
            if (constructor.isAnnotationPresent(Constructor_Annotation.class)) {
                // 获得指定类型的注释
                Constructor_Annotation ca = (Constructor_Annotation) constructor
                        .getAnnotation(Constructor_Annotation.class);
                System.out.println(ca.value()); // 获得注释信息
            }
            Annotation[][] parameterAnnotations = constructor.getParameterAnnotations(); // 获得参数的注释
            for (int j = 0; j < parameterAnnotations.length; j++) {
                // 获得指定参数注释的长度
                int length = parameterAnnotations[j].length;
                if (length == 0) // 如果长度为0则表示没有为该参数添加注释
                    System.out.println("    未添加Annotation的参数");
                else
                    for (int k = 0; k < length; k++) {
                        // 获得参数的注释
                        Field_Method_Parameter_Annotation pa = (Field_Method_Parameter_Annotation) parameterAnnotations[j][k];
                        System.out.print("    " + pa.describe()); // 获得参数描述
                        System.out.println("    " + pa.type()); // 获得参数类型
                    }
            }
            System.out.println();
        }
 
        System.out.println();
 
        System.out.println("-------- 字段的描述如下 --------");
 
        Field[] declaredFields = recordC.getDeclaredFields(); // 获得所有字段
        for (int i = 0; i < declaredFields.length; i++) {
            Field field = declaredFields[i]; // 遍历字段
            // 查看是否具有指定类型的注释
            if (field.isAnnotationPresent(Field_Method_Parameter_Annotation.class)) {
                // 获得指定类型的注释
                Field_Method_Parameter_Annotation fa = field.getAnnotation(Field_Method_Parameter_Annotation.class);
                System.out.print("    " + fa.describe()); // 获得字段的描述
                System.out.println("    " + fa.type()); // 获得字段的类型
            }
        }
 
        System.out.println();
 
        System.out.println("-------- 方法的描述如下 --------");
 
        Method[] methods = recordC.getDeclaredMethods(); // 获得所有方法
        for (int i = 0; i < methods.length; i++) {
            Method method = methods[i]; // 遍历方法
            // 查看是否具有指定类型的注释
            if (method.isAnnotationPresent(Field_Method_Parameter_Annotation.class)) {
                // 获得指定类型的注释
                Field_Method_Parameter_Annotation ma = method.getAnnotation(Field_Method_Parameter_Annotation.class);
                System.out.println(ma.describe()); // 获得方法的描述
                System.out.println(ma.type()); // 获得方法的返回值类型
            }
            Annotation[][] parameterAnnotations = method.getParameterAnnotations(); // 获得参数的注释
            for (int j = 0; j < parameterAnnotations.length; j++) {
                int length = parameterAnnotations[j].length; // 获得指定参数注释的长度
                if (length == 0) // 如果长度为0表示没有为该参数添加注释
                    System.out.println("    未添加Annotation的参数");
                else
                    for (int k = 0; k < length; k++) {
                        // 获得指定类型的注释
                        Field_Method_Parameter_Annotation pa = (Field_Method_Parameter_Annotation) parameterAnnotations[j][k];
                        System.out.print("    " + pa.describe()); // 获得参数的描述
                        System.out.println("    " + pa.type()); // 获得参数的类型
                    }
            }
            System.out.println();
        }
    }
}
public class Record {
    @Field_Method_Parameter_Annotation(describe = "编号", type = int.class)
    // 注释字段
    int id;
    @Field_Method_Parameter_Annotation(describe = "姓名", type = String.class)
    String name;
 
    @Constructor_Annotation()
    // 采用默认值注释构造方法
    public Record() {
    }
 
    @Constructor_Annotation("立即初始化构造方法")
    // 注释构造方法
    public Record(@Field_Method_Parameter_Annotation(describe = "编号", type = int.class) int id,
            @Field_Method_Parameter_Annotation(describe = "姓名", type = String.class) String name) {
        this.id = id;
        this.name = name;
    }
 
    @Field_Method_Parameter_Annotation(describe = "获得编号", type = int.class)
    // 注释方法
    public int getId() {
        return id;
    }
 
    @Field_Method_Parameter_Annotation(describe = "设置编号")
    // 成员type采用默认值注释方法
    public void setId(
            // 注释方法的参数
            @Field_Method_Parameter_Annotation(describe = "编号", type = int.class) int id) {
        this.id = id;
    }
 
    @Field_Method_Parameter_Annotation(describe = "获得姓名", type = String.class)
    public String getName() {
        return name;
    }
 
    @Field_Method_Parameter_Annotation(describe = "设置姓名")
    public void setName(@Field_Method_Parameter_Annotation(describe = "姓名", type = String.class) String name) {
        this.name = name;
    }
}  

 16.3 Built-in annotations

@Override introduction: It can only be used on constructors and member variables to modify a method.

@SuppressWarnings function: Suppress compiler warnings scope classes, member properties, member methods

@Deprecated function: The identifier is obsolete 

Guess you like

Origin blog.csdn.net/Leonie1/article/details/134026012