java反射总结

反射概述
      JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一一个方法和属性;

      这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。要想解剖一个类,必须先要获取到该类的字节码文件对象。

      而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象。 

三种方式

      a:Object类的getClass( )方法,判断两个对象是否是同一个字节码文件

      b:静态属性class,锁对象

      c:Class类中静态方法forName() ,读取配置文件

 

public class Reflect {
	/**
	 * @param args
	 * @throws ClassNotFoundException 
	 */
	public static void main(String[] args) throws ClassNotFoundException {
		Class clazz1 = Class.forName("Person");
		Class clazz2 = Person.class;
		Person p = new Person();
		Class clazz3 = p.getClass();
		System.out.println(clazz1 == clazz2);
		System.out.println(clazz2 == clazz3);
	}
}
class Person {
	private String name;
	private int age;
	public Person() {
		super();
		
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (this.getClass() != obj.getClass())		//判断调用对象和传入对象的字节码文件是否是同一个字节码文件
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}

输出:

true
true

Class.forName()读取配置文件举例:

import java.io.BufferedReader;
import java.io.FileReader;

public class Test {

	public static void main(String[] args) throws Exception {
		Juicer j = new Juicer();									
		//j.run(new Apple());
		//j.run(new Orange());
		BufferedReader br = new BufferedReader(new FileReader("config.properties"));
		Class clazz = Class.forName(br.readLine());					//获取该类的字节码文件
		Fruit f = (Fruit) clazz.newInstance();						//创建实例对象
		j.run(f);
		
	}
}
interface Fruit {
	public void squeeze();
}
class Apple implements Fruit {
	public void squeeze() {
		System.out.println("榨出一杯苹果汁");
	}
}

class Orange implements Fruit {
	public void squeeze() {
		System.out.println("榨出一杯橘子汁");
	}
}

class Juicer {
	/*public void run(Apple a) {
		a.squeeze();
	}
	
	public void run(Orange o) {
		o.squeeze();
	}*/
	
	public void run(Fruit f) {
		f.squeeze();
	}
}

config.properties配置文件里面写对应要读取的类名就可以了

通过构造函数创建对象:

import java.lang.reflect.Constructor;

public class Test {

	/**
	 * Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数,
	 * 就不能这样创建了,可以调用Class类的getConstructor
	 * (String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance
	 * 方法创建对象
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		Class clazz = Class.forName("Person");
		//Person p = (Person) clazz.newInstance();				通过无参构造创建对象
		//System.out.println(p);
		Constructor c = clazz.getConstructor(String.class,int.class);	//获取有参构造
		Person p = (Person) c.newInstance("张三",23);						//通过有参构造创建对象
		System.out.println(p);
	}

}
class Person {
	private String name;
	private int age;
// 	public Person() {
// 		super();
		
// 	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (this.getClass() != obj.getClass())		//判断调用对象和传入对象的字节码文件是否是同一个字节码文件
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}

输出:

Person [name=张三, age=23]

Field(获取字段):

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

public class Test {

	/**
	 * Class.getField(String)方法可以获取类中的指定字段(可见的),
	 * 如果是私有的可以用getDeclaedField("name")方法获取,通过set(obj, "李四")方法可以设置指定对象上该字段的值,
	 * 如果是私有的需要先调用setAccessible(true)设置访问权限,用获取的指定的字段调用get(obj)可以获取指定对象中该字段的值
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		Class clazz = Class.forName("Person");
		Constructor c = clazz.getConstructor(String.class,int.class);	//获取有参构造
		Person p = (Person) c.newInstance("张三",23);						//通过有参构造创建对象
		
		//Field f = clazz.getField("name");								//获取姓名字段
		//f.set(p, "李四");												//修改姓名的值
		Field f = clazz.getDeclaredField("name");						//暴力反射获取字段
		f.setAccessible(true);											//去除私有权限
		f.set(p, "李四");	
		
		System.out.println(p);
	}

}

class Person {
	private String name;
	private int age;
// 	public Person() {
// 		super();
		
// 	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (this.getClass() != obj.getClass())		//判断调用对象和传入对象的字节码文件是否是同一个字节码文件
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}

输出:

Person [name=李四, age=23]

Method(获取方法):

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

public class Test {

	/**
	 * Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String,
	 * Class...)方法可以获取类中的指定方法,调用invoke(Object,
	 * Object...)可以调用该方法,Class.getMethod("A") invoke(obj)
	 * Class.getMethod("A",int.class) invoke(obj,10)
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		Class clazz = Class.forName("Person");
		Constructor c = clazz.getConstructor(String.class,int.class);	//获取有参构造
		Person p = (Person) c.newInstance("张三",23);						//通过有参构造创建对象
		
		Method m = clazz.getMethod("A");								//获取A方法
		m.invoke(p);
		
		Method m2 = clazz.getMethod("A", int.class);					//获取有参的A方法
		m2.invoke(p, 10);
	}

}


class Person {
	private String name;
	private int age;
// 	public Person() {
// 		super();
		
// 	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (this.getClass() != obj.getClass())		//判断调用对象和传入对象的字节码文件是否是同一个字节码文件
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	public void A()
	{
	    System.out.println("A题");
	}
	public void A(int num)
	{
	    System.out.println("A出"+num+"题");
	}
}

输出:

A题
A出10题

反射越过泛型检查:

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

public class Test {
	/**
	 * @param args
	 * ArrayList的一个对象,在这个集合中添加一个字符串数据
	 * 泛型只在编译期有效,在运行期会被擦除掉
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		ArrayList list = new ArrayList<>();
		list.add(111);
		list.add(222);
		Class clazz = Class.forName("java.util.ArrayList");				//获取字节码对象
		Method m = clazz.getMethod("add", Object.class);				//获取add方法
		m.invoke(list, "abc");
		System.out.println(list);
	}
}

输出:

[111, 222, abc]

修改对象属性值:

import java.lang.reflect.Field;

public class Tool {
	//此方法可将obj对象中名为propertyName的属性的值设置为value。
	public void setProperty(Object obj, String propertyName, Object value) throws Exception {
		Class clazz = obj.getClass();					//获取字节码对象
		Field f = clazz.getDeclaredField(propertyName);	//暴力反射获取字段
		f.setAccessible(true);							//去除权限
		f.set(obj, value);
	}
}

 

你可能感兴趣的:(java,Java学习之路)