java反射机制

一、概念

所谓反射就是通过类的“.class”文件去获得该类的属性、方法以供使用。

二、好处

这样做的好处是什么呢?

1.灵活、强大;只要知道类的全名就能使用它的任意属性、任意方法(包括私有的)。

2.节省内存;如果使用频繁,通过反射机制不用去大量的实例化对象,而永远用的只是同一个对象,这个功能类似于设计模式中的单例模式。

三、使用方法

前提:假设我们有一个Person类代码如下:

package com.test;

public class Person {
	private String name;
	int age;
	public String address;

	public Person() {
	}

	private Person(String name) {
		this.name = name;
	}

	Person(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public Person(String name, int age, String address) {
		this.name = name;
		this.age = age;
		this.address = address;
	}

	public void show() {
		System.out.println("show");
	}

	public void method(String s) {
		System.out.println("method " + s);
	}

	public String getString(String s, int i) {
		return s + "---" + i;
	}

	private void function() {
		System.out.println("function");
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", address=" + address
				+ "]";
	}

}

下面我们要通过反射机制来获取Person类的所有属性和所有方法并使用。对于反射机制来说也就是以下几种类型:

  成员变量 Field
  构造方法 Constructor
  成员方法 Method

步骤1:

首先必须得到.class文件对象;有以下3种方式,在开发中用第3种的居多

// 方式1
Person p = new Person();
Class c = p.getClass();
// 方式2
Class c2 = Person.class;
// 方式3
Class c3 = Class.forName("com.test.Person");


(1)通过反射获取构造方法并使用

所有公共构造方法:public Constructor[] getConstructors():

所有构造方法:  public Constructor[] getDeclaredConstructors():
获取单个构造方法 public Constructor<T> getConstructor(Class<?>... parameterTypes)

// 参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象

public T newInstance(Object... initargs)
使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

示例1:获取构造方法:

package com.test;

import java.lang.reflect.Constructor;

public class ReflectDemo {

	public static void main(String[] args) throws Exception {
		
		// 获取字节码文件对象
		Class c = Class.forName("com.test.Person");
		//获取所有构造方法
	 	Constructor[] cons = c.getDeclaredConstructors();
		for (Constructor con : cons) {
			System.out.println(con);
		}
		//获取单个构造方法:
		
		//无参数构造器
		Constructor con1 = c.getConstructor();// 返回的是构造方法对象

		// 获取带参构造方法对象
		Constructor con2 = c.getConstructor(String.class, int.class,String.class);
		// 通过带参构造方法对象创建对象
		Object obj = con2.newInstance("林四川", 27, "北京");
		System.out.println(obj);
			
		// 获取私有构造方法对象
		Constructor con3 = c.getDeclaredConstructor(String.class);

		// 用该私有构造方法创建对象
		con3.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。
		Object obj3 = con3.newInstance("杨万里");
		System.out.println(obj3);
		

	}

}
输出结果:

---------------------------------------------------------------------------------------------

private com.test.Person(java.lang.String)
com.test.Person(java.lang.String,int)
public com.test.Person(java.lang.String,int,java.lang.String)
public com.test.Person()
Person [name=林四川, age=27, address=北京]
Person [name=杨万里, age=0, address=null]

----------------------------------------------------------------------------------------------

示例2:获取成员变量并使用

package com.test;

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

/*
 * 通过反射获取成员变量并使用
 */
public class ReflectDemo2 {
	public static void main(String[] args) throws Exception {
		// 获取字节码文件对象
		Class c = Class.forName("com.test.Person");

		// 获取所有的成员变量
		 Field[] fields = c.getFields();
		 Field[] fields2 = c.getDeclaredFields();
		 for (Field field : fields2) {
		 System.out.println(field);
		 }

		// 通过无参构造方法创建对象
		Constructor con = c.getConstructor();
		Object obj = con.newInstance();
		System.out.println(obj);

		// 获取单个的成员变量
		// 获取address并对其赋值
		Field addressField = c.getField("address");
		addressField.set(obj, "旧金山"); // 给obj对象的addressField字段设置值为"北京"
		System.out.println(obj);

		// 获取name并对其赋值
		Field nameField = c.getDeclaredField("name");
		nameField.setAccessible(true);
		nameField.set(obj, "Tom");
		System.out.println(obj);

		// 获取age并对其赋值
		Field ageField = c.getDeclaredField("age");
		ageField.setAccessible(true);
		ageField.set(obj, 27);
		System.out.println(obj);
	}
}

输出 :

----------------------------------------------------------------------------------------------

private java.lang.String com.test.Person.name
int com.test.Person.age
public java.lang.String com.test.Person.address
Person [name=null, age=0, address=null]
Person [name=null, age=0, address=旧金山]
Person [name=Tom, age=0, address=旧金山]
Person [name=Tom, age=27, address=旧金山]

----------------------------------------------------------------------------------------------

示例3:获取所有方法并使用

package com.test;

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

public class ReflectDemo4 {
	public static void main(String[] args) throws Exception {
		// 获取字节码文件对象
		Class c = Class.forName("com.test.Person");

		// 获取所有的方法
		 Method[] methods = c.getMethods(); // 获取自己的包括父亲的公共方法
		 Method[] methods2 = c.getDeclaredMethods(); // 获取自己的所有的方法
		 for (Method method : methods2) {
		 System.out.println(method);
		 }

		Constructor con = c.getConstructor();
		Object obj = con.newInstance();

		// 获取单个方法并使用
		Method m1 = c.getMethod("show");
		m1.invoke(obj); // 调用obj对象的m1方法

		System.out.println("----------");
		Method m2 = c.getMethod("method", String.class);
		m2.invoke(obj, "hello");
		System.out.println("----------");

		Method m3 = c.getMethod("getString", String.class, int.class);
		Object objString = m3.invoke(obj, "hello", 100);
		System.out.println(objString);
		System.out.println("----------");

		// private void function()
		Method m4 = c.getDeclaredMethod("function");
		m4.setAccessible(true);
		m4.invoke(obj);
	}
}

输出:

------------------------------------------------------------------------------------------------

public java.lang.String com.test.Person.toString()
public java.lang.String com.test.Person.getString(java.lang.String,int)
public void com.test.Person.show()
public void com.test.Person.method(java.lang.String)
private void com.test.Person.function()
show
----------
method hello
----------
hello---100
----------
function

------------------------------------------------------------------------------------------------


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值