创建一个Person类

 package com.qianfeng.test;

public class Person {

	private String name;

	public String getName() {
		return name;
	}

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

	public Person() {
		super();
	}

	public Person(String name) {
		super();
		this.name = name;
	}

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

	//非静态无参
	public void play(){
		System.out.println("play");
	}

	//非静态有参
	public void run(String number){
		System.out.println("run:"+number);
	}

	//静态有参
	public  static void show(String apple,int age){
		System.out.println("show:"+apple+" age:"+age);
	}

}

获取字节码文件对象的3种方式

package com.qianfeng.test;

/*
 * 反射:动态的获取类的字节码文件对象,并对其成员进行抽象。
 *
 * 想做的:就是通过字节码文件将对象直接创建普通的对象。
 *
 * 1.获取字节码文件对象
 * 2.>通过字节码文件对象获取具体的实例对象
 * 	 >获取具体的构造方法(通过从构造方法中抽象出来的类Constructor)
 * 3.获取具体的属性并给属性赋值(通过从属性中抽象出来的类Field实现)
 * 4.获取具体的方法,并调用方法(通过从方法中抽象出来的类Method实现)
 *
 *
 * 首先:1.获取字节码文件对象
 * a:通过Object提供的getClass方法得到字节码文件对象
 * 	缺点:首先要有一个对象  XXXXX
 * b:每种数据类型都有一个class属性,通过他也可以获取当前的字节码文件对象
 * 	缺点:首先要知道这个类的名字 XXXX
 * c:Class提供的方法forName(字符串)	字符串的构成:包名+类名
 * 	优点:只需要提供一个当前类的字符串形式
 *
 * 注意:字符串表示的类在工作的时候必须保证对应的是一个真正的类,否则报异常ClassNotFoundException
 *
 */
public class Demo1 {

	public static void main(String[] args) throws Exception{

//		 * a:通过Object提供的getClass方法得到字节码文件对象
		fun1();
//		 * b:每种数据类型都有一个class属性,通过他也可以获取当前的字节码文件对象
		fun2();
//		 * c:Class提供的方法forName(字符串)	字符串的构成:包名+类名
		fun3();

	}

//	 * a:通过Object提供的getClass方法得到字节码文件对象
	public static void fun1(){
		Person person = new Person("bingbing");
		Class class1 = person.getClass();
		Person person1 = new Person("bingbing");
		Class class2 = person.getClass();
		System.out.println(class1 == class2);//说明一个类只对应一个字节码文件对象

	}


//	 * b:每种数据类型都有一个class属性,通过他也可以获取当前的字节码文件对象
	public static void fun2(){
		Class class1 = Person.class;
		System.out.println(class1);
	}


//	 * c:Class提供的方法forName(字符串)	字符串的构成:包名+类名
	public static void fun3() throws ClassNotFoundException{
		Class class1 = Class.forName("com.qianfeng.test.Person");
		System.out.println(class1);
	}

}

获取具体的实例对象和构造方法

package com.qianfeng.test;

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

/*
 * 2.>通过字节码文件对象获取具体的实例对象
 * 	 >获取具体的构造方法(通过从构造方法中抽象出来的类Constructor)
 */
public class Demo2 {

	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {

		//通过普通的方式创建对象
		Person person = new Person("bingbing");

		//通过反射--绕过new
		Class class1 = Class.forName("com.qianfeng.test.Person");
		//通过无参的构造方法
		fun1(class1);
		//通过有参的构造方法
		fun2(class1);

	}

	//通过无参的构造方法
	public static void fun1(Class class1) throws InstantiationException, IllegalAccessException{
		//创建实例对象
		//相当于在newInstance方法的内部调用了无参的构造方法
		Object person = class1.newInstance();
		//向下转型
		Person person2 = (Person)person;
		person2.setName("bingbing");
		System.out.println(person2.getName());
	}

	//通过有参的构造方法
	public static void fun2(Class class1) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		//这里的参数是实际的构造方法的参数字节码文件对象
		Constructor constructor = class1.getConstructor(String.class);
		//调用方法
		Object person = constructor.newInstance("bingbing");//给定的实际参数
		System.out.println(person);

	}

}

获取具体的属性并赋值

package com.qianfeng.test;

import java.lang.reflect.Field;

/*
 * 3.获取具体的属性并给属性赋值(通过从属性中抽象出来的类Field实现)
 */
public class Demo3 {

	public static void main(String[] args) throws Exception {

		//通过普通的方式
//		Person person = new Person();
//		person.setName("bingbing");

		//通过反射
		//1.获取字节码对象
		Class class1 = Class.forName("com.qianfeng.test.Person");
		//2.调用Field的方法得到对应的属性
		//参数就是那个实际属性
		//注意:getField方法在获取属性的时候,必须保证属性存在,还要保证name的权限够大--public
		//Field field1 = class1.getField("name");

		//当属性是私有的,可以通过下面的设置临时更改属性的权限,完成属性的获取。
		Field field1 = class1.getDeclaredField("name");
		field1.setAccessible(true);

		//3.给当前的属性指定一个具体的实例对象
		Object person1 = class1.newInstance();
		//4.将field指定给person1
		//第一个参数是field1对应的具体的实例对象,第二个参数是赋的具体的值
		field1.set(person1, "bingbing");//person.name="bingbing"
		System.out.println(field1.get(person1));


		//再次进行实例对象的创建并绑定属性并赋值
		//3.给当前的属性指定一个具体的实例对象
		Object person2 = class1.newInstance();
		//4.将field指定给person1
		//第一个参数是field1对应的具体的实例对象,第二个参数是赋的具体的值
		field1.set(person2, "chenchen");//person.name="bingbing"
		System.out.println(field1.get(person2));

	}
}

获取具体的方法

package com.qianfeng.test;

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

/*
 * 4.获取具体的方法,并调用方法(通过从方法中抽象出来的类Method实现)
 */
public class Demo4 {

	public static void main(String[] args) throws Exception {

		//调用普通的方法
//		Person person = new Person();
//		person.run("123");

		//使用反射
		//1.获取字节码对象
		Class class1 = Class.forName("com.qianfeng.test.Person");
		//2.调用非静态的无参方法
		fun1(class1);
		//3.调用非静态的有参方法
		fun2(class1);
		//4.调用静态的有参方法
		fun3(class1);


	}

	//2.调用非静态的无参方法
	public static void fun1(Class class1) throws Exception{
		//第一个参数:对应的方法的具体名字  第二个参数:具体方法参数的字节码文件对象
		Method method = class1.getMethod("play");

		//创建实例对象
		Constructor constructor = class1.getConstructor(String.class);
		Object person = constructor.newInstance("bingbing");

		//调用方法
		//第一个参数:给当前的指定的具体对象  第二个参数:方法的具体参数
		method.invoke(person);
	}

	//3.调用非静态的有参方法
	public static void fun2(Class class1) throws Exception{
		//第一个参数:对应的方法的具体名字  第二个参数:具体方法参数的字节码文件对象
		Method method = class1.getMethod("run",String.class);

		//创建实例对象
		Constructor constructor = class1.getConstructor(String.class);
		Object person = constructor.newInstance("bingbing");

		//调用方法
		//第一个参数:给当前的指定的具体对象  第二个参数:方法的具体参数
		method.invoke(person,"123");
	}


	//4.调用静态的有参方法
	public static void fun3(Class class1) throws Exception{
		//第一个参数:对应的方法的具体名字  第二个参数:具体方法参数的字节码文件对象
		//注意:所有数据类型都有自己的字节码文件对象
		Method method = class1.getMethod("show",String.class,int.class);

		//调用方法
		//第一个参数:给当前的指定的具体对象  第二个参数:方法的具体参数
		method.invoke(null,"苹果",222);
	}

}


10-06 17:20