java反射机制

反射类Person:

package entity;

public class Person {
	
	private String name;
	private int age;
	
	
	public Person(String name, int age) {
		
		this.name = name;
		this.age = age;
		System.out.println(name+"    param cons run    "+age);
	}
	
	public Person() {
		
		System.out.println("cons run");
	}
	
	public void method1(){
		
		System.out.println("method1 run");
	}
	public void method2(String name,int age){
		
		System.out.println(name+"  method2 run  "+age);
	}
	
	public static void method3(){
		
		System.out.println("method3 run");
	}
	public static void method4(String name,int age){
		
		System.out.println(name+"  method4 run   "+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;
	}
	

}

package reflect;

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

import entity.Person;


/*
 * java反射机制,是在运行状态中,对于任意一个类(class文件)
 * 都能知道这个类的所有属性和方法;
 * 这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制
 * 
 * 要想对字节码文件进行解剖,必须要有字节码文件的对象
 * 获取字节码的方式:
 * 1、Object类中的getClass()方法
 * 2、通过任何数据类型都具备的静态属性.class获取
 * 3、通过Class类的.forName()方法,只要具备类的字符串名字即可(推荐)
 * 
 * 通过getDeclaredXxxs()方法拿到本类中定义的所有的成员,
 * 通过getXxxs()方法也可以拿到父类中的成员,不过private的成员不能拿到
 */
public class ReflectDemo {
	
	public static void main(String[] args) throws Exception {
		
		// Class clazz = ReflectDemo.getClass("entity.Person");
		// System.out.println(clazz)

		// Person person = (Person)
		// ReflectDemo.createNewObject("entity.Person");
		// person.method1();
			
		//Constructor constructor = ReflectDemo.getConstructor("entity.Person");
		//constructor.newInstance("zhangsan",23);
		
		//Method method = ReflectDemo.getNoParamMethod("entity.Person");
		//Person person = (Person) ReflectDemo.createNewObject("entity.Person");
		//method.invoke(person, null);
		
		//Method method = ReflectDemo.getParamMethod("entity.Person");
		//Person person = (Person) ReflectDemo.createNewObject("entity.Person");
		//method.invoke(person,"wangcai",23);
		
		//Method method = ReflectDemo.getStaticNoParamMethod("entity.Person");
		//method.invoke(null,null);
		
		//Method method = ReflectDemo.getStaticMethod("entity.Person");
		//method.invoke(null,"xiaoqiang",23);
		
		Field field = ReflectDemo.getField("entity.Person");
		field.setAccessible(true);//取消字段的访问权限,暴力反射
		Person person = (Person) ReflectDemo.createNewObject("entity.Person");
		field.set(person, "xingshi");
		System.out.println(person.getName());
		
	}
	
	public static Class getClass(String className){
		/*
		 * 用Class.forName()获取字节码对象时,代表类名的字符串需要带完整的包名
		 */
		Class clazz = null;
		try {
			clazz = Class.forName(className);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			System.out.println("ClassNotFound");
		}
		return clazz;
	}
	
	public static Object createNewObject(String className){
		/*
		 * A a = new A();JVM根据类名从classpath中找到对应的字节码文件,
		 * 并将其加载到内存中,然后生成字节码对象,再通过这个字节码对象
		 * 创建该类的对象
		 * 
		 * Class clazz = Class.forName(className);JVM通过给定的字符串
		 * 形式的类名从classpath中找到对应的字节码文件,然后生成字节码
		 * 对象返回回来
		 */
		Class clazz = null;
		Object obj = null;
		try {
			clazz = Class.forName(className);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			System.out.println("ClassNotFound");
		}
		try {
			/*
			 * 通过类的字节码生成类的对象,这个方法调用的是
			 * 空参构造方法---空参构造方法---空参构造方法
			 */
			obj = clazz.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return obj;
		
	}

	public static Constructor getConstructor(String className) throws Exception{
		/*
		 * 如果类中没有无参的构造方法,那么就不能用createNewObject这种方式创建对象
		 * 而要获取到类中的其他构造方法
		 */
		Class clazz = getClass(className);
		//根据提供的参数来获取相应的构造方法
		Constructor constructor = clazz.getConstructor(String.class,int.class);
		return constructor;
	}
	
	public static Method getNoParamMethod(String className) throws Exception{
		//根据提供的参数来获取相应的空参普通方法
		Class clazz = getClass(className);
		Method method = clazz.getMethod("method1", null);
		return method;
		
	}
	public static Method getParamMethod(String className) throws Exception{
		//根据提供的参数来获取相应的普通方法
		Class clazz = getClass(className);
		Method method = clazz.getMethod("method2",String.class,int.class);
		return method;
		
	}
	public static Method getStaticNoParamMethod(String className) throws Exception{
		//根据提供的参数来获取相应的空参静态方法
		Class clazz = getClass(className);
		Method method = clazz.getMethod("method3",null);
		return method;
		
	}
	public static Method getStaticMethod(String className) throws Exception{
		//根据提供的参数来获取相应的静态方法
		Class clazz = getClass(className);
		Method method = clazz.getMethod("method4",String.class,int.class);
		return method;
		
	}
	public static Field getField(String className) throws Exception{
		//根据提供的参数来获取相应的成员变量
		Class clazz = getClass(className);
		//getDeclaredField,只要在类中有声明,都可以反射
		Field field = clazz.getDeclaredField("name");
		return field;
		
	}

}

反射机制的好处:

Computer类:

package computer;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;

import pci.PCI;

public class Computer {
	/*
	 * 使用“接口+配置文件”提高程序的可扩展性,只需要按照接口定义的规则来
	 * 设计类,并把类的相关信息配置到配置文件中,不用修改源码就可以使用程
	 * 序的扩展功能
	 */

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

		MainBoard mb = new MainBoard();
		mb.run();

		SAXBuilder builder = new SAXBuilder();
		FileInputStream file = new FileInputStream("src/pci/pci.xml");
		Document document = builder.build(file);// 获得文档对象
		Element root = document.getRootElement();// 获得根节点
		List<Element> list = root.getChildren();
		for (Element e : list) {
			String pciName = e.getChildText("class");
			//System.out.println(e.getAttributeValue("name"));
			//System.out.println(e.getChildText("class"));
			Class clazz = Class.forName(pciName);
			PCI pci = (PCI) clazz.newInstance();
			pci.open();
			pci.close();
		}
		file.close();
	}

}

MainBoard类:

package computer;

public class MainBoard {
	
	public void run(){
		
		System.out.println("MainBoard run.....");
	}
}

对外提供的PCI接口:PCI.java

package pci;

public interface PCI {

	public void open();
	public void close();
}

对外提供的配置文件:pci.xml

<pcis>
	<pci name="pci1">
		<class>pci.SoundCard</class>
	</pci>
	<pci name="pci2">
		<class>pci.NetCard</class>
	</pci>
</pcis>

应用扩展类:SoundCard.java

package pci;


public class SoundCard implements PCI {

	@Override
	public void close() {

		System.out.println("SoundCard close.....");
	}

	@Override
	public void open() {
		System.out.println("SoundCard open.....");

	}

}

应用扩展类:NetCard.java

package pci;

public class NetCard implements PCI {

	@Override
	public void close() {
		System.out.println("NetCard close....");

	}

	@Override
	public void open() {
		System.out.println("NetCard open....");

	}

}

最开始计算只有主板运行,但是提供了一个PCI接口和一个配置文件,想装声卡的时候只需要按照PCI接口的标准来实现声卡,并把声卡的相关信息写到配置文件中,即使是不修改computer的代码,也可以直接使用声卡,再添加网卡或者其他的设备也一样,这样无论添加多少设备,都不用改动已经写好的计算机的代码,这样程序的扩展性就大大的提高了。也就是说“接口+配置文件”,通过反射可以大大的提高程序的可扩展性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值