反射学习小结

反射学习笔记

反射:就是通过class文件对象,去使用该文件中的成员变量、构造方法、成员方法。

  • 如果想用反射,那么首先你必须得到class文件对象,其实就也就是得到Class类的对象
  • Class这个类就是用来装你的对象的字节码文件的对象

Class类:

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

获取class文件对象的方式:

  • A:Object类对象.getClass()方法

  • B:数据类型的静态属性class。

  • C:Class类中静态方法

    		public static Class forName(String className);
    

    一般我们使用第三种方式来获取,因为第三种是一个字符串,而不是一个具体的类名。这样我们就可以把这样的字符串配置到配置文件中。安全性。

例子:

	//方式一:Object类对象.getClass()方法
	Person p = new Person();
	Class class_p1 = p.getClass();
	String name = class_p1.getName();//类的权限定名
	System.out.println(name);

输出结果为:Test.Demo.Person

	//方式二:数据类型的静态属性class。
	Class class_p3 = Person.class;
	System.out.println(class_p3==class_p1);//true 因为字节码文件只有一个,所以是true。
	
	/*方式三:Class类中静态方法
	public static Class forName(String className)*/

	Class class_p4 = Class.forName("com.hwua.ReflectDemo.Person");
	System.out.println(class_p4==class_p3);    //结果为true

一、通过反射来使用某类的构造方法

 //获取构造方法
	 	/*
	 	 * public Constructor[] getConstructors():获得所有公共的构造方法 只会返回带有public所修饰的
	 	 * public Constructor[] getDeclaredConstructors():获得所有的构造方法
	 	 * */

例子如下:
首先得有个person类以下是person类

package Test.Demo;
public class Person {

private String name;
int age;
public String address;
public Person() {
}

Person(String name){
	this.name = name;
}
private Person(String name, int age, String address) {
	super();
	this.name = name;
	this.age = age;
	this.address = address;
}
public String getName() {
	return name;
}
private void setName(String name) {
	this.name = name;
}
public int getAge() {
	return age;
}
 void setAge(int age) {
	this.age = age;
}
public String getAddress() {
	return address;
}
public void setAddress(String address) {
	this.address = address;
}
@Override
public String toString() {
	return "Person [name=" + name + ", age=" + age + ", address=" + address + "]";
}	
}

下面是例子:

 Class cl = Class.forName("Test.Demo.Person");
 	 Constructor[] constructors = cl.getConstructors();//这里只返回public修饰的构造方法
 	 	 for (Constructor c : constructors) {
			System.out.println(c);  // 输出为public Test.Demo.Person()(这里只定义了一个public的构造方法)
	 }

 Constructor[] declaredConstructors = cl.getDeclaredConstructors();
		 for (Constructor cc : declaredConstructors) {
				 System.out.println(cc);
		}

这里输出的结果为:

private Test.Demo.Person(java.lang.String,int,java.lang.String)
Test.Demo.Person(java.lang.String)
public Test.Demo.Person()

获取单个的方法,并调用:
public Constructor getConstructor(Class… parameterTypes):获取单个的"公有的"构造方法:
public Constructor getDeclaredConstructor(Class… parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有的;
参数表示:你要获取的构造方法的构造参数个数以及数据类型的class字节码文件对象。

例子:

	Constructor con = cl.getDeclaredConstructor(String.class,int.class,String.class);//返回的是构造方法的对象
	con.setAccessible(true);//暴力破解,设置为true的时候,私有的东西就能访问了
	System.out.println(con);

输出结果为:

	privateTest.Demo.Person(java.lang.String,int,java.lang.String)

使用此Constructor对象表示的构造方法来创建该构造方法的声明类的实例,并使用指定的初始化参数进行初始化实例。

	Object newInstance = con.newInstance("张三",1,"中国");
	 Person p = (Person) newInstance;
	 System.out.println(p);

输出结果为:

	Person [name=张三, age=1, address=中国]

二、通过反射获取某类的成员变量并使用

例子如下:

Class cl = Class.forName("Test.Demo.Person");	

//获取所有的成员变量
//getFields()和getDeclaredFields();

Field[] fields = cl.getFields(); //获取所有公共字段
	for (Field field : fields) {
		System.out.println(field);
}

输出结果为:

public java.lang.String Test.Demo.Person.address

获取所有字段:

Field[] declaredFields = cl.getDeclaredFields();
	for (Field field : declaredFields) {
		System.out.println(field);
	}

输出结果为:

private java.lang.String Test.Demo.Person.name
int Test.Demo.Person.age
public java.lang.String Test.Demo.Person.address

三、获取单个的成员变量

	//比如:我要获取address并赋值
	Field field = cl.getField("address");
	//只是获得了变量,你要对变量进行赋值,那么你要考虑到给哪个对象的变量进行赋值
	field.set(obj, "北京");
	System.out.println(obj);

输出结果为:

	Person [name=null, age=0, address=北京]

四、通过反射获取某类的成员方法并使用

获取所有方法

	 获取公共:getMethods():获取自己的以及父类的公共方法
	 获取所有:getDeclaredMethods():获取自己的所有的方法

代码如下:

	Method[] methods = cl.getMethods();//这里得到得到的是所有公共的方法,包括自己的和父类的
	for (Method method : methods) {
		System.out.println(method);
	}

输出结果如下:

public java.lang.String Test.Demo.Person.toString()
public java.lang.String Test.Demo.Person.getAddress()
public java.lang.String Test.Demo.Person.getName()
public int Test.Demo.Person.getAge()
public void Test.Demo.Person.setAddress(java.lang.String)
//这是父类object类的方法
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()

获取自己的所有方法:

Method[] declaredMethods = cl.getDeclaredMethods();
	for (Method method : declaredMethods) {
		System.out.println(method);
	}

输出结果为:

public java.lang.String TestDemo.Person.toString()
public java.lang.String Test.Demo.Person.getAddress()
public java.lang.String Test.Demo.Person.getName()
private void Test.Demo.Person.setName(java.lang.String)
public int Test.Demo.Person.getAge()
public void Test.Demo.Person.setAddress(java.lang.String)
void Test.Demo.Person.setAge(int)

获取单一方法并执行

	Constructor con = cl.getConstructor();
	Object obj = con.newInstance();
	Method m = cl.getMethod("setAddress", String.class);
	m.invoke(obj, "北海");//第一参数是对象,第二参数是调用方法参数数据
Method method = cl.getMethod("toString");//得到toString()方法
	Object invoke = method.invoke(obj);
	System.out.println(invoke);
	System.out.println("------------------------");

Method declaredMethod = cl.getDeclaredMethod("setName", String.class);//获取私有的方法
	declaredMethod.setAccessible(true);//暴力破解反射
	declaredMethod.invoke(obj, "阿达");
	invoke = method.invoke(obj);
	System.out.println(invoke);

这两个代码的输出结果是:

	Person [name=null, age=0, address=北海]

Person [name=阿达, age=0, address=北海]

本章内容暂时补充到这。

你可能感兴趣的:(学习笔记)