search
HomeJavajavaTutorialExample analysis of Java reflection

    ##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:亿速云. If there is any infringement, please contact admin@php.cn delete
    带你搞懂Java结构化数据处理开源库SPL带你搞懂Java结构化数据处理开源库SPLMay 24, 2022 pm 01:34 PM

    本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于结构化数据处理开源库SPL的相关问题,下面就一起来看一下java下理想的结构化数据处理类库,希望对大家有帮助。

    Java集合框架之PriorityQueue优先级队列Java集合框架之PriorityQueue优先级队列Jun 09, 2022 am 11:47 AM

    本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于PriorityQueue优先级队列的相关知识,Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的,下面一起来看一下,希望对大家有帮助。

    完全掌握Java锁(图文解析)完全掌握Java锁(图文解析)Jun 14, 2022 am 11:47 AM

    本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于java锁的相关问题,包括了独占锁、悲观锁、乐观锁、共享锁等等内容,下面一起来看一下,希望对大家有帮助。

    一起聊聊Java多线程之线程安全问题一起聊聊Java多线程之线程安全问题Apr 21, 2022 pm 06:17 PM

    本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于多线程的相关问题,包括了线程安装、线程加锁与线程不安全的原因、线程安全的标准类等等内容,希望对大家有帮助。

    Java基础归纳之枚举Java基础归纳之枚举May 26, 2022 am 11:50 AM

    本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于枚举的相关问题,包括了枚举的基本操作、集合类对枚举的支持等等内容,下面一起来看一下,希望对大家有帮助。

    详细解析Java的this和super关键字详细解析Java的this和super关键字Apr 30, 2022 am 09:00 AM

    本篇文章给大家带来了关于Java的相关知识,其中主要介绍了关于关键字中this和super的相关问题,以及他们的一些区别,下面一起来看一下,希望对大家有帮助。

    java中封装是什么java中封装是什么May 16, 2019 pm 06:08 PM

    封装是一种信息隐藏技术,是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法;封装可以被认为是一个保护屏障,防止指定类的代码和数据被外部类定义的代码随机访问。封装可以通过关键字private,protected和public实现。

    Java数据结构之AVL树详解Java数据结构之AVL树详解Jun 01, 2022 am 11:39 AM

    本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于平衡二叉树(AVL树)的相关知识,AVL树本质上是带了平衡功能的二叉查找树,下面一起来看一下,希望对大家有帮助。

    See all articles

    Hot AI Tools

    Undresser.AI Undress

    Undresser.AI Undress

    AI-powered app for creating realistic nude photos

    AI Clothes Remover

    AI Clothes Remover

    Online AI tool for removing clothes from photos.

    Undress AI Tool

    Undress AI Tool

    Undress images for free

    Clothoff.io

    Clothoff.io

    AI clothes remover

    AI Hentai Generator

    AI Hentai Generator

    Generate AI Hentai for free.

    Hot Tools

    SublimeText3 English version

    SublimeText3 English version

    Recommended: Win version, supports code prompts!

    SAP NetWeaver Server Adapter for Eclipse

    SAP NetWeaver Server Adapter for Eclipse

    Integrate Eclipse with SAP NetWeaver application server.

    WebStorm Mac version

    WebStorm Mac version

    Useful JavaScript development tools

    SublimeText3 Linux new version

    SublimeText3 Linux new version

    SublimeText3 Linux latest version

    MinGW - Minimalist GNU for Windows

    MinGW - Minimalist GNU for Windows

    This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.