(二)利用反射机制实例化类,获取和修改变量,获取和调用方法和构造方法

上一篇文章初步认识了Java反射机制的基本概念,本文将进一步探究 Java 反射机制的作用。

综述:

获取类之后,可以调用赋值其成员变量,可以调用成员方法,构造方法。对于使用private 修饰的变量、方法和构造方法,需要调用 .setAccessible(true)

直接上代码,一个普通的类,然后待会使用反射机制实例化对象,获取普通常量,普通方法,构造方法,静态方法,静态常量

 

public class Demo4 {
	public Demo4() {
		System.out.println("私有化的无参构造函数被实例化");
	}
	
	private Demo4(String name) {
		System.out.println("public 修饰的有参构造函数被调用:"+name);
	}
	
	private String str1="1";
	
	public String str2="2";
	String str3="3";
	
	
	public void method(String name){
		System.out.println("调用类的方法,输入参数为:"+name);
	}
	
	private void method2(String name){
		System.out.println("调用类的方法,输入参数为:"+name);
	}

	public static String str4="4";
	private static void method3(String name,String msg,int a,Integer b){
		System.out.println("name="+name+";msg="+msg+";a="+a+";b="+b);
	}

}

测试代码

 

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.junit.Test;

/**
 * Java 反射机制
 * 实例化类,修改变量值,调用成员方法
 * @author wj
 *
 */
public class Demo4Test {
	
	@Test
	public void test7(){
		System.out.println("综述:获取类之后,可以调用赋值其成员变量,可以调用成员方法,构造方法。对于使用private 修饰的变量、方法和构造方法,需要调用 .setAccessible(true)");
	}
	
	
	/**
	 * 私有化的构造函数被实例化
	 * public 修饰的无参构造函数 方法有三种 http://blog.csdn.net/bestcxx/article/details/79134315
	 * Class.forName("demo3.Demo3Class1")
	 * Demo3Class1.class
	 * demo31.getClass()
	 */
	@Test
	public void test6(){
		Class obj=Demo4.class;
		Constructor c;//无参构造函数
		Constructor c2;//有参构造函数
		try {
			//获取无参的构造函数
			c = obj.getDeclaredConstructor();
			
			//调用构造函数
			c.newInstance();
			
			//---------------------------------------------
			
			//获取有参构造函数
			c2=obj.getDeclaredConstructor(String.class);
			
			//允许反射调用 private 的构造函数
			c2.setAccessible(true);
			
			//调用构造函数
			c2.newInstance("123");
			
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}
	
	/**
	 * Java 反射机制 调用 静态方法
	 * 静态方法本身即代表已被实例化的对象
	 * method.invoke(method, 传入参数)
	 */
	@Test
	public void test5(){
		Class obj=Demo4.class;
		
		try {
			Method method=obj.getDeclaredMethod("method3", String.class,String.class,int.class,Integer.class);
			method.setAccessible(true);
			System.out.println("method.invoke(method, \"1\",\"2\",3,4)=调用静态方法");
			method.invoke(method, "1","2",3,4);
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 *反射机制 获取 静态变量 
	 *直接以自己为对象进行取值和赋值
	 *field.get(field)
	 *field.set(field, "123")
	 */
	@Test
	public void test4(){
		Class obj=Demo4.class;
		
		try {
			Field field=obj.getDeclaredField("str4");
			field.setAccessible(true);	
			System.out.println("field.get(field)=获取静态变量,field 即表示自身和已被实例化的类"+field.get(field));
			field.set(field, "123");
			System.out.println("field.set(field, \"123\")=给静态变量赋值,field 即表示自身和已被实例化的类"+field.get(field));
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 运用反射机制调用方法
	 */
	@Test 
	public void test3(){
		Class obj=Demo4.class;
		
		try {
			//获得方法
			Method method=obj.getDeclaredMethod("method2", String.class);
			
			//获取一个对象
			Object demo4= obj.newInstance();
			
			//允许反射方法调用 private 修饰的方法
			method.setAccessible(true);
			
			//反射 调用 方法,并传入参数
			method.invoke(demo4, "name2");
			
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 反射机制 修改 非 public 修饰的变量,比如private、默认、protected
	 * Field field=obj.getDeclaredField("str1");//如果获取的是 非public 修饰的变量,需要使用 DeclaredField
	 * field.setAccessible(true);//允许通过反射机制获取和修改 private 修饰的变量
	 * 
	 */
	@Test
	public void test2(){
		Class obj=Demo4.class;
		try {
			//获得变量,如果获取的是 非public 修饰的变量,需要使用 DeclaredField
			Field field=obj.getDeclaredField("str1");
			
			//用反射机制获取一个对象
			Object demo4=obj.newInstance();//这里并没有转化为具体的类的对象
		
			//使用反射机制将 获取的成员变量 赋给 demo4 并且赋新值
			field.setAccessible(true);//允许通过反射机制获取和修改 private 修饰的变量
			
			//输出 demo4 中 变量 field 的变量值
			System.out.println(field.get(demo4));
			
			//将 demo4 中 变量 field 的值修改为 "aaa"
			field.set(demo4, "aaa");
			
			//验证值被修改
			System.out.println(field.get(demo4));
			
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * 反射机制 修改 public 修饰的变量,将结果赋给指定对象
	 */
	@Test
	public void test1(){
		Class obj=Demo4.class;
		try {
			Field field=obj.getField("str2");
			
			//用反射机制获取一个对象
			Demo4 demo4=(Demo4) obj.newInstance();
			System.out.println(demo4.str2);
			
			//使用反射机制将 获取的成员变量 赋给 demo4 并且赋新值
			field.set(demo4, "aaa");
			
			//验证值被修改
			System.out.println(demo4.str2);
			
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	
	/**
	 * 反射机制 实例化对象
	 * 输出成员常量,调用成员方法
	 */
	@Test
	public void test(){
		System.out.println("obj.newInstance()=实例化一个 obj类型的对象,可以输出成员常量,调用成员方法");
		Class obj=Demo4.class;
		try {
			Demo4 demo4=(Demo4) obj.newInstance();
			System.out.println(demo4.str2);
			
			demo4.method("Jecket");
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println();
	}
}

运行结果

 

obj.newInstance()=实例化一个 obj类型的对象,可以输出成员常量,调用成员方法
私有化的无参构造函数被实例化
2
调用类的方法,输入参数为:Jecket

私有化的无参构造函数被实例化
2
aaa
私有化的无参构造函数被实例化
1
aaa
私有化的无参构造函数被实例化
调用类的方法,输入参数为:name2
field.get(field)=获取静态变量,field 即表示自身和已被实例化的类4
field.set(field, "123")=给静态变量赋值,field 即表示自身和已被实例化的类123
method.invoke(method, "1","2",3,4)=调用静态方法
name=1;msg=2;a=3;b=4
私有化的无参构造函数被实例化
public 修饰的有参构造函数被调用:123
综述:获取类之后,可以调用赋值其成员变量,可以调用成员方法,构造方法。对于使用private 修饰的变量、方法和构造方法,需要调用 .setAccessible(true)

 

 

 

 

 

 

 

 

你可能感兴趣的:(Java,反射机制)