Java的反射技术

Java的反射可以绕过访问权限,访问到类的非公有方法和成员,利用反射还可以访问内部类、匿名内部类的私有属性。
可能这点会引起安全性的讨论,但反射的使用帮助解决很多复杂的问题。
其运行时的类型检查,动态调用,代理的实现等等,为我们的程序带来了很大的灵活性,很多底层的功能和框架都会使用反射。

实体类
package cn.moving.reflect;

import java.io.InputStream;
import java.util.List;

public class Person {
	private String name = "maomao";
	private int password;
	private static int age = 23;
	private static final Person instance = new Person();

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getPassword() {
		return password;
	}

	public void setPassword(int password) {
		this.password = password;
	}

	public static int getAge() {
		return age;
	}

	public static void setAge(int age) {
		Person.age = age;
	}

	private Person() {
		System.out.println("person");
	}

	public static Person getInstance() {
		return Person.instance;
	}

	public Person(String name) {
		this.name = name;
		System.out.println("person name");
	}

	public Person(String name, int age) {
		System.out.println("姓名:" + name + "年龄:" + age);
	}

	public Person(int age) {
		System.out.println("age");
	}

	public Person(List list) {
		System.out.println("list");
	}

	public void play(String name, int age) {
		System.out.println("姓名:" + name + "年龄:" + age + "正在玩");
	}

	public Class[] aa(String name, int[] password) {
		return new Class[] { String.class };
	}

	private void bb(InputStream is) {
		System.out.println(is);
	}

	public static void cc(int num) {
		System.out.println(num);
	}

	public static void main(String args[]) {
		for (String s : args) {
			System.out.println(s);

		}
	}

}
反射字段
package cn.moving.reflect;

import java.lang.reflect.Field;

import org.junit.Test;

public class ReflectField {

	/**
	 * 反射类的字段
	 * @throws Exception
	 * @throws SecurityException
	 */
	// 解剖(=反射)private String name = "maomao";
	// 私有字段
	@Test
	public void reflectName() throws SecurityException, Exception {
		Class clazz = Class.forName("cn.moving.reflect.Person");
		Field f = clazz.getDeclaredField("name");
		f.setAccessible(true);
		Person p = new Person("haha");
		Object value = f.get(p);
		Class type = f.getType();
		System.out.println(type);
		if (type.equals(String.class)) {
			String name_value = (String) value;
			System.out.println(name_value);
		}
		f.set(p, "LanWenTao");
		System.out.println(f.get(p));
	}
	@Test
	// private static int age = 23;静态私有的属性
	public void reflectAge() throws Exception {
		Class clazz = Class.forName("cn.moving.reflect.Person");
		Field f = clazz.getDeclaredField("age");
		f.setAccessible(true);
		System.out.println(f.get(null));;
	}

}
反射构造方法
package cn.moving.reflect;

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

import org.junit.Test;

public class ReflectConstructor {

	/**
	 * 反射构造方法
	 * 
	 * @throws ClassNotFoundException
	 * @throws InvocationTargetException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws IllegalArgumentException
	 */

	@Test
	public void reflectNoArgumentConstrustor() throws Exception {
		Class clazz = Class.forName("cn.moving.reflect.Person");
		Constructor[] cons = clazz.getDeclaredConstructors();
		Constructor c = null;
		for (Constructor con : cons) {
			con.setAccessible(true);
			c = con;
		}
		Person p = (Person) c.newInstance(null);
		System.out.println(p.getName());
	}

	@Test
	public void reflectConstructor() throws Exception {
		Class clazz = Class.forName("cn.moving.reflect.Person");
		Constructor c = clazz.getConstructor(String.class, int.class);
		Person p = (Person) c.newInstance("XiaoMing", 22);
		System.out.println(p.getName());// ???????????
	}
}
反射普通方法
package cn.moving.reflect;

import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;

import org.junit.Test;

public class reflectMethod {

	/**
	 * 反射普通方法
	 */
	// public void play(String name, int age)
	@Test
	public void reflectPlay() throws Exception {
		Class clazz = Class.forName("cn.moving.reflect.Person");
		Method method = clazz.getMethod("play", String.class, int.class);
		Person p = new Person("ZhangSan",22);
		method.invoke(p, "sdfdsf",44);
	}
	//public Class[] aa(String name, int[] password)
	@Test
	public void reflectClass() throws Exception{
		Class clazz = Class.forName("cn.moving.reflect.Person");
		Method method = clazz.getMethod("aa", String.class,int[].class);
		Person p = Person.getInstance();
		Class[] cs =(Class[]) method.invoke(p, "ZhangSan",new int[]{12,332,4,23,4});
		System.out.println(cs[0]);
		System.out.println(p.getName());
	} 
	
	@Test
	//private void bb(InputStream is)
	public void reflectbb() throws Exception{
		Class clazz = Class.forName("cn.moving.reflect.Person");
		Method method  = clazz.getDeclaredMethod("bb", InputStream.class);
		method.setAccessible(true);
		Person p = Person.getInstance();
		method.invoke(p, new FileInputStream("c:\\1.txt"));
	}
	
	@Test
	//public static void cc(int num)
	public void reflectcc() throws Exception{
		Class clazz = Class.forName("cn.moving.reflect.Person");
		Method method  = clazz.getMethod("cc",int.class);
		method.invoke(null,34535);//静态不传对象也可以
	}
}
反射main方法

main()的参数是一个字符串数组,通过反射方式来调用时,以什么样的形式invoke()传递参数呢?
按JDK5即以后的语法,整个数组是一个参数,而按JDK1.4的语法,数组中的每个元素对应一个参数。

@Test
//public static void main(String agrs[])
public void reflectMain()throws Exception{
	Class clazz = Class.forName("cn.moving.reflect.Person");
	Method method  = clazz.getMethod("main", String[].class);
	// 在JDK1.4中正确,JDK5及以后会报异常
	method.invoke(null,new String[]{"123","456"});
	// JDK5及以后版本正确的使用方式
	method.invoke(null,(Object)new String[]{"abc","xyz"});
	method.invoke(null,new Object[]{new String[]{"xxx","yyy"}});
}

所以,在JDK5以后,使用反射给main()传递参数时,不能直接传一个String[],会出现java.lang.IllegalArgumentException: wrong number of arguments异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值