Chapter 16 Reflection and Annotation

 

Table of contents

16.1 Reflection

1. Use the getClass() method

2. Use the .class attribute

3. Use the forname method of the class class

16.1.2 Accessing member variables

16.2 Annotation annotation function

16.2.1 Define Annotation type

16.2.2 Access Annotation information

 


16.1 Reflection

1.class class

2. Get the construction method

3. Get member attributes

4. Get member method

annotation

1. Built-in annotations

2. Reflection annotations

Three ways to create Class objects

1. Use the getClass() method

object str = new object();

class c = str.getClass()
 

  Demo1 d1 = new Demo1();
        Class c1 = d1.getClass();

2. Use the .class attribute

class c = object.class

Class c2 = Demo1.class;

3. Use the forname method of the class class

class c = class.forname("full path")

 Class c3 = Class.forName("com.mr.Demo1");

 

Create a class and the package will be created automatically

As we all know, all Java classes inherit the Object class, and a getClassO method is defined in the Object class, which returns

Returns an object of type Class. For example the following code:

JTextField textField = new JTextFieldO);   //创建 JTextField 对象
 
Class textFieldC = textField.getClass();  //获取Class对象

Using the object textFieldC of the Class class, you can access the description information of the textField object used to return the object. Can access

The main descriptive information is shown in Table 16.1

16.1.1 Accessing constructors 
When a constructor is accessed through the following set of methods, an object or array of type Constructor will be returned. Each Constructor object represents a constructor method, and the corresponding constructor method can be manipulated using the Constructor object:

getConstructors()
getConstructor(Class<?>...parameterTypes)
getDeclaredConstructors()
getDeclaredConstructor(Class<?>..parameterTypes)
If you are accessing the specified constructor, you need to access it according to the type of the entry parameter of the constructor. For example, accessing a constructor whose entry parameter types are String and int can be achieved in the following two ways:
 

objeciClass.getDeclaredConstructor(String.class, int.class);

objectClass.getDeclaredConstructor(new Classil { String.class, int.class });

 The common methods provided in the Constructor class are shown in Table 16.2.

 Common parsing methods in the Modifier class are as follows:

 

For example, determine whether the constructor represented by the object constructor is modified by private, and obtain the constructor in the form of a string

Typical code for all modifiers of a method is as follows:

int modifiers = constructor.getModifiers();
 
boolean isEmbellishByPrivate = Modifier.isPrivate(modifiers);
 
String embelishment = Modifier.toString(modifiers);

 Example 16.1

 
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);
	}
}
//例题16.1
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

The running results are as follows:

16.1.2 Accessing member variables

When accessing member variables through the following set of methods, an object or array of Field type will be returned. Each Field object represents a member variable, and the corresponding member variable can be manipulated using the Ficld object:

getFields()
getField(String name)
getDeclaredFields()
getDeclaredField(String name) a>
If you are accessing a specified member variable, you can access it through the name of the member variable. For example, to access a member variable named birthday, the access method is as follows:
 

object. getDeclaredField("birthday");

 The common methods provided in the Field class are shown in Table 16.4.

Example 16.2

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

The running results are as follows:

16.2 Annotation annotation function

This feature can be used in the declaration of classes, constructors, member variables, member methods, parameters, etc. This function will not affect the running of the program, but will affect auxiliary tools such as compiler warnings.

16.2.1 Define Annotation type

Built-in annotations:

@Override: Limit overriding of parent class method scope member methods
@SuppressWarnings: Suppress compiler warnings about scope classes, member properties, member methods
@Deprecated: Marks obsolete scope classes, member properties, and member methods
When defining the Annotation type, the interface keyword used to define the interface also needs to be used, but it needs to be in the interface key Add an "@" symbol before the word, that is, the keyword defining the Annotation type is @interface. The implicit meaning of this keyword is that it inherits the java.lang.annotation.Annotation interface. For example, the following code defines an Annotation type:
 

public @interface NoMemberAnnotation{

}

The Annotation type @NoMemberAnnotation defined above does not contain any members. Such Annotation type is called marker annotation. The following code defines an Annotation type that contains only one member:

public @interface OneMemberAnnotation {

String value();

}

 

String: member type. Available member types are String, Class, primitive, enumerated, and annotation, as well as arrays of the listed types
value: member name. If the defined Annotation type contains only one member, the member name is usually named value
The following code defines an Annotation type containing multiple members:

public @interface MoreMemberAnnotation {

String describe();

Class type();

}

When defining members for an Annotation type, you can also set default values ​​for the members. For example, the following code defines an Annotation

A default value is set for the member when typed:

public @interface DefaultValueAnnotation

String describe() default "<Default value>";

Class type() default void.class;

}

When defining the Annotation type, you can also set the type of program element that the Annotation type is applicable to through the Annotation type @Target. If @Target is not set, it applies to all program elements. The enumeration constants in the enumeration class ElementType are used to set @Targer, as shown in Table 16.6

The valid range of Amnotation can be set through the Amotaion type @Retenion. The enumeration constants in the enumeration class RetentioPolicy are used to set @Rctention, as shown in Table 16.7. If @Retention is not set, the valid range of Annotation is the range represented by the enumeration constant CLASS

Example 16.4

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

Finally, write a Record class in which the previously defined Annotation types @Constructor_Annotation and

@Field Method Parameter_Annotation annotates 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;
	}
}

16.2.2 Access Annotation information

Example 16.5

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();
		}
	}
}
//例题16.5

The running results are as follows:

 

Guess you like

Origin blog.csdn.net/2301_76549195/article/details/134227775