Java基础总结之反射

Java反射机制:是在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法;对于任何一个对象都能够调用它的任何一个方法说着属性;这种动态获取的信息以及动态调用的对象的方法的功能成为Java语言的反射机制。

那么,如果想解刨一个类的话,首先就要获取到该类的字节码文件对象:获取方法有如下三种:

package h.l.reflect;

public class ReflectDemo1 {

	public static void main(String[] args) throws ClassNotFoundException {
		// 方式一:Object类的getClass()方法得到
		Person p = new Person();
		Class<? extends Person> c = p.getClass();
		// 方式二:数据类型的静态属性class
		Class<Person> c2 = Person.class;
		System.out.println(c == c2);
		// 方式三:Class中的静态方法forName
		Class<?> c3 = Class.forName("h.l.reflect.Person");
		System.out.println(c == c3);
	}
}

提示:开发中尝试用第三种:因为第三种的参数是一个字符串,而不是一个具体的类名。这样我们就可以把这样的字符串配置到配置文件中。

得到Class字节码文件对象后怎么使用呢?Class类中提供了三种方法供我们分别对变量、构造函数、成员函数进行操作。

在学习响应操作前,先定义一个Person类:

public class Person {

	private String name;
	int age;
	public String address;

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

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

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

	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}

	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 + "]";
	}

}

(1)获取构造方法,实例化对象:

API提供了如下获取方法:

public Constructor<?>[] getConstructors()//拿到所有的公共构造方法

public Constructor<?>[] getDeclaredConstructors()//拿到所有的构造方法,包括私有构造

public Constructor<T> getConstructor(类<?>... parameterTypes)//获取单个构造方法(所有公共构造方法中的单个)

public Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)//获取单个构造方法(所有构造方法中的单个,包括私有构造)

简单的使用如下:

import java.lang.reflect.Constructor;

public class ReflectDemo1 {

	public static void main(String[] args) throws Exception {
		// 得到Person类的字节码文件对象
		Class<?> c = Class.forName("h.l.reflect.Person");
		// 得到Person类的所有公共构造函数
		Constructor<?>[] cons = c.getConstructors();
		for (Constructor<?> con : cons) {
			System.out.println(con);
		}
		System.out.println("--------------");
		// 得到Person类的所有构造函数,包括私有
		Constructor<?>[] cons2 = c.getDeclaredConstructors();
		for (Constructor<?> con : cons2) {
			System.out.println(con);
		}
		System.out.println("--------------");
		// 得到Person类public构造函数(无参)实例化
		Constructor<?> con = c.getConstructor();
		Object obj = con.newInstance();
		Person p = (Person) obj;
		p.show();
		System.out.println(p);
		System.out.println("--------------");
		// 得到Person类public构造函数(带参)实例化
		Constructor<?> con2 = c.getConstructor(String.class, int.class, String.class);
		Object obj2 = con2.newInstance("Is-Me-HL", 22, "UJS");
		Person p2 = (Person) obj2;
		p.show();
		System.out.println(p2);
		System.out.println("--------------");
		// 得到Person类的private构造函数(带参)实例化
		Constructor<?> con3 = c.getDeclaredConstructor(String.class);
		con3.setAccessible(true);// 设置可访问,值为true时,则指示反射的对象在使用是应该取消Java语言访问检查
		Object obj3 = con3.newInstance("Is-Me-HL");
		Person p3 = (Person) obj3;
		p3.show();
		System.out.println(p3);
	}
}

控制台打印信息为:

public h.l.reflect.Person()
public h.l.reflect.Person(java.lang.String,int,java.lang.String)
--------------
public h.l.reflect.Person()
h.l.reflect.Person(java.lang.String,int)
private h.l.reflect.Person(java.lang.String)
public h.l.reflect.Person(java.lang.String,int,java.lang.String)
--------------
show
Person [name=null, age=0, address=null]
--------------
show
Person [name=Is-Me-HL, age=22, address=UJS]
--------------
show
Person [name=Is-Me-HL, age=0, address=null]

由上面的程序对应相应的控制台结果,四个获取构造函数的方法及类的实例化应该能大致掌握。需要注意一下两点:获取私有构造要使用带Declare的函数获取,在获取到私有函数实例化的时候要记得调用setAccessible()函数,让其避开Java的语言访问检查。

(2)获取成员变量、赋值:

API提供了如下方法获取成员变量:

getFields()获取所有的公共成员变量

getDeclaredFields()获取所有的成员变量
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("h.l.reflect.Person");
		Field[] field = c.getDeclaredFields();
		for (Field f : field) {
			System.out.println(f);
		}
		Constructor<?> con = c.getConstructor();
		Object obj = con.newInstance();
		// 给obj对象的address public变量赋值
		Field addressField = c.getField("address");
		addressField.set(obj, "UJS");
		// 给obj对象的name private变量赋值
		Field nameField = c.getDeclaredField("name");
		nameField.setAccessible(true);
		nameField.set(obj, "Is-Me-HL");
		// 给obj对象的age default变量赋值
		Field ageField = c.getDeclaredField("age");
		ageField.setAccessible(true);
		ageField.set(obj, 22);
		System.out.println(obj);
	}
}
private java.lang.String h.l.reflect.Person.name
int h.l.reflect.Person.age
public java.lang.String h.l.reflect.Person.address
Person [name=Is-Me-HL, age=22, address=UJS]

上述代码是对变量的简单使用。主要注意的还是两点:一:获取非public变量记得使用的是带Declare的方法,二:获取到后要对对象进行操作记得先关闭Java语言检查。

(3)获取成员方法:

API提供了如下的方法供使用:

Method [] methods=c.getMethods();//获取自己的包括父类的公共方法

Method []methods=c.getDeclaredMethods();//获取自己类里面的所有方法
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ReflectDemo3 {
	public static void main(String[] args) throws Exception {
		Class<?> c = Class.forName("h.l.reflect.Person");
		Method[] method = c.getMethods();
		for (Method m : method) {
			System.out.println(m);
		}
		System.out.println("--------------");
		// 创建对象
		Constructor<?> con = c.getConstructor();
		Object obj = con.newInstance();
		// 得到public成员方法对象,调用
		Method m = c.getMethod("show");
		m.invoke(obj);
		System.out.println("--------------");
		// 得到private成员方法(无参)对象,调用
		Method m2 = c.getDeclaredMethod("function");
		m2.setAccessible(true);
		m2.invoke(obj);
		System.out.println("--------------");
		// 得到private成员方法(带参)对象,调用
		Method m3 = c.getDeclaredMethod("getString", String.class, int.class);
		m3.setAccessible(true);
		System.out.println(m3.invoke(obj, "Is-Me-HL", 22));

	}
}
public java.lang.String h.l.reflect.Person.toString()
public java.lang.String h.l.reflect.Person.getString(java.lang.String,int)
public void h.l.reflect.Person.method(java.lang.String)
public void h.l.reflect.Person.show()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
--------------
show
--------------
function
--------------
Is-Me-HL---22

一个小例子:在ArrayList<Integer>集合中添加字符串:

import java.lang.reflect.Method;
import java.util.ArrayList;

/*
 * 实现ArrayList<Integer>中存储字符串数据
 */
public class ReflectDemo4 {
	public static void main(String[] args) throws Exception, SecurityException {
		ArrayList<Integer> list = new ArrayList<>();
		Class<?> c = list.getClass();
		Method m = c.getMethod("add", Object.class);
		m.invoke(list, "hello");
		m.invoke(list, "world");
		System.out.println(list);
	}
}
//执行结果
[hello, world]

注:以上文章仅是个人学习过程总结,若有不当之处,望不吝赐教。

猜你喜欢

转载自blog.csdn.net/m0_37265215/article/details/81910454