反射类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的代码,也可以直接使用声卡,再添加网卡或者其他的设备也一样,这样无论添加多少设备,都不用改动已经写好的计算机的代码,这样程序的扩展性就大大的提高了。也就是说“接口+配置文件”,通过反射可以大大的提高程序的可扩展性。