Home  >  Article  >  Java  >  Example analysis of Java reflection

Example analysis of Java reflection

WBOY
WBOYforward
2023-04-29 21:10:051202browse
    ##1. Class class and Java reflection

    Class textFieldC=tetxField.getClass(); //tetxField is a JTextField class object

    The main description of reflection accessibility

    Example analysis of Java reflection

    1. Access the constructor method

    Each Constructor object represents a constructor method, using the Constructor object The corresponding construction method can be manipulated.

    • getConstructors() //Get public

    • ##getConstructor(Class>... parameterTypes)

      //Get the specified public

    • getDeclaredConstructors()

      //Get all

    • getDeclaredConstructor(Class>... parameterTypes)

      //Get the specified method

    • Create the Demo1 class, declare String type member variables and 3 int type member variables, and Provides 3 construction methods.
    package bao;
     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[0]);
    			}
    			if(2<strings.length) {
    				i3=Integer.valueOf(strings[0]);
    			}
    		}
     		public  void print() {
    			System.out.println("s="+s);
    			System.out.println("i="+i);
    			System.out.println("i2="+i2);
    			System.out.println("i3="+i3);
    		}
     }

    Write the Main class to perform reflective access to all constructors of Demo1 in this class, and output information about whether the constructor allows a variable number of parameters, entry parameters, and exception types that may be thrown. .

    package bao;
     import java.lang.reflect.Constructor;
     public class Main {
    	public static void main(String[] args) {
    		Demo1 demo=new Demo1("10","20","30");
    		Class<? extends Demo1>demoC=demo.getClass();  
    		//获得所有构造方法
    		Constructor[] declaredConstryctors=demoC.getDeclaredConstructors();
    		for(int i=0;i<declaredConstryctors.length;i++) {
    			Constructor<?> constructor=declaredConstryctors[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 example2=null;
    			while(example2==null) {
    				try {           
    					if(i==2) {
    						example2=(Demo1)constructor.newInstance();
    				}else if(i==1) {
    					example2=(Demo1)constructor.newInstance("7",5);
    				}else {
    					Object[] parameters=new Object[] {new String[] {"100","200","300"}};
    					example2=(Demo1)constructor.newInstance(parameters);		
    				}	
    				}catch(Exception e){
    				System.out.println("在创建对象时抛出异常,下面执行setAccessible()方法");
    				constructor.setAccessible(true);     //设置允许访问
    				}
    			}
    			if(example2!=null) {
    				example2.print();
    				System.out.println();
    			}
    		}
     	}
    }
      /*输出结果:
     查看是否允许带有可变数量的参数:true
    该构造方法的入口参数类型依次为:
     class [Ljava.lang.String;
    该构造方法的入口可能抛出异常类型为:
     class java.lang.NumberFormatException
    s=null
    i=100
    i2=100
    i3=100
    查看是否允许带有可变数量的参数:false
    该构造方法的入口参数类型依次为:
     class java.lang.String
     int
    该构造方法的入口可能抛出异常类型为:
    s=7
    i=5
    i2=0
    i3=0
    查看是否允许带有可变数量的参数:false
    该构造方法的入口参数类型依次为:
    该构造方法的入口可能抛出异常类型为:
    在创建对象时抛出异常,下面执行setAccessible()方法
    s=null
    i=0
    i2=0
    i3=0
     */

    2. Access member variables

    Each Field object represents a member variable, and the corresponding member variable can be manipulated using the Field object.

      getFields()
    • getField(String name)
    • getDeclaredFields()
    • getDeclaredField(String name)
    • Create the Demo1 class and declare member variables of int, fioat, boolean and String types in sequence, and set different access rights.
    package bao;
     public class Demo1{
    	int i;
    	public float f;
    	protected boolean b;
    	private String s;
    }

    Access all member variables in the Demo1 class through reflection, and output the name and type information of the member variables.

    package bao;
     import java.lang.reflect.Field;
    public class Main {
    	public static void main(String[] args) {
    		Demo1 demo=new Demo1();
    		Class demoC=demo.getClass();
    		//获得所有成员变量
    		Field[] declaredField=demoC.getDeclaredFields();
    		for(int i=0;i<declaredField.length;i++) {
    			Field field=declaredField[i];
    			System.out.println("名称为:"+field.getName());   //获取成员变量名称
     			Class fieldType=field.getType();   ///获取成员变量类型
    			System.out.println("类型为:"+fieldType);
    			boolean isTurn=true;
    			while(isTurn) {
    				try {
    					isTurn=false;
    					System.out.println("修改前的值为:"+field.get(demo));
    					if(fieldType.equals(int.class)) {     //判断成员变量的类型是否为int类型
    						System.out.println("利用方法setInt()修改成员变量的值");
    						field.setInt(demo, 168);      //为int类型成员变量赋值
    					}else if(fieldType.equals(float.class)){     //判断成员变量的类型是否为float类型
    						System.out.println("利用方法 setFloat()修改成员变量的值");      
    						field.setFloat(demo, 99.9F);      //为float类型成员变量赋值
    					}else if(fieldType.equals(boolean.class)){      //判断成员变量的类型是否为boolean类型
    						System.out.println("利用方法 setBoolean()修改成员变量的值");
    						field.setBoolean(demo, true);      //为boolean类型成员变量赋值
    					}else {
    						System.out.println("利用方法 set()修改成员变量的值");
    						field.set(demo, "MWQ");            //可以为各种类型的成员变量赋值
    					}
    					//获得成员变量值
    					System.out.println("修改后的值为:"+field.get(demo));
    				}catch(Exception e) {
    					System.out.println("在设置成员变量值时抛出异常,"+"下面执行setAccesssible()方法!");
     					field.setAccessible(true);       //设置为允许访问
    					isTurn=true;
    				}
    			}
    			System.out.println();
    		}
    	}
    }

    /*Output result:
    The name is: i

    The type is: int
    The value before modification is: 0
    Use the method setInt() to modify the member variable The value
    The modified value is: 168
    The name is: f
    The type is: float
    The value before modification is: 0.0
    Use the method setFloat() to modify the value of the member variable
    The modified value is: 99.9
    The name is: b
    The type is: boolean
    The value before modification is: false
    Use the method setBoolean() to modify the value of the member variable
    After modification The value is: true
    The name is: s
    The type is: class java.lang.String
    An exception is thrown when setting the member variable value, execute the setAccesssible() method below!
    The value before modification is: null
    Use the method set() to modify the value of the member variable
    The modified value is: MWQ
    */

    3. Access Method

    Each Method object represents a method, and the corresponding method can be manipulated using the Method object.

      getMethods()
    • ##getMethod(String name, Class>... parameterTypes)
    • getDeclaredMethods()
    • getDeclaredMethod(String name, Class>... parameterTypes)
    • Create the Demo1 class, Write 4 typical methods.
    • package bao;
       public class Demo1{
          static void staitcMethod() {
          	System.out.println("执行staitcMethod()方法");
          }
          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<stringBuffer.length();i++) {
          		stringBuffer.append(strings[i]);
          	}
          	return stringBuffer.toString();
          }
       }
    Reflection accesses all methods in the Demm1 class, and outputs the method name, entry parameter type, return value type and other information

    package bao;
     import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    public class Main {
    	public static void main(String[] args) {
    	Demo1 demo = new Demo1();
    	Class demoC = demo.getClass();
    	// 获得所有方法
    	Method[] declaredMethods = demoC.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 {
    				isTurn = false;
    				if("staitcMethod".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 {
    					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();
    	}
    	}
    }

    /*Output result:

    Name is: publicMethod
    Whether a variable number of parameters is allowed: false

    The entry parameter types are:
    int
    The return value type is: int
    The exception types that may be thrown are:
    Execute the publicMethod() method
    The return value is: 16800
    The name is: staitcMethod
    Whether a variable number of parameters are allowed: false
    The entry parameter types are:
    Return The value type is: void
    The exception types that may be thrown are:
    Execute the staitcMethod() method
    The name is: protectedMethod
    Whether a variable number of parameters is allowed: false
    Entry parameters The types are:
    class java.lang.String
    int
    The return value type is: int
    The exception types that may be thrown are:
    class java.lang.NumberFormatException
    Execution protectedMethod() method
    The return value is: 12
    The name is: privateMethod
    Whether a variable number of parameters is allowed: true
    The entry parameter types are:
    class [Ljava.lang .String;
    The return value type is: class java.lang.String
    The exception types that may be thrown are:
    Exception is thrown when executing the method, execute the setAccessible() method below!
    Execute the privateMethod() method
    The return value is:
    */


    2. Use the Annotation function

    1. Define the Annotation type

    When defining the Annotation type, you also need to use the interface keyword used to define the interface, but you need to add an "@" symbol before the interface keyword, that is, the keyword defining the Annotation type is @interface. The implicit meaning of this keyword It means that it inherits the java.lang.annotation.Annotation interface.

    public @interface NoMemberAnnotation{

    String value();

    }

    ##@interface

    : Declare keywords.

    NoMemberAnnotation: Annotation name.

    String: member type.

    value: member name.

    Example analysis of Java reflection

    定义并使用Annotation类型

    ①定义Annotation类型@Constructor_Annotation的有效范围为运行时加载Annotation到JVM中。

    package annotationbao;
     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型成员
    }

    ②定义一个来注释字段、方法和参数的Annotation类型@Field_Method_Parameter_Annotation的有效范围为运行时加载Annotation到JVM中

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

    ③编写一个Record类,在该类中运用前面定义Annotation类型的@Constructor_Annotation和@Field_Method_Parameter_Annotation对构造方法、字段、方法和参数进行注释。

    package annotationbao;
     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 = "设置编号")
    	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、访问Annotation信息

    如果在定义Annotation类型时将@Retention设置为RetentionPolicy.RUNTIME,那么在运行程序时通过反射就可以获取到相关的Annotation信息,如获取构造方法、字段和方法的Annotation信息。

    联合以上的定义并使用Annotation类型,通过反射访问Record类中的Annotation信息。

    package annotationbao;
    import java.lang.annotation.*;
    import java.lang.reflect.*;
     public class Main_05 {
     	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();
    		}
     	}
    }

    /*输出结果:
    ------ 构造方法的描述如下 ------
    默认构造方法
    立即初始化构造方法
    编号 int
    姓名 class java.lang.String
    -------- 字段的描述如下 --------
    编号 int
    姓名 class java.lang.String
    -------- 方法的描述如下 --------
    获得姓名
    class java.lang.String
    设置姓名
    void
    姓名 class java.lang.String
    获得编号
    int
    设置编号
    void
    编号 int

    */

    The above is the detailed content of Example analysis of Java reflection. For more information, please follow other related articles on the PHP Chinese website!

    Statement:
    This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete