Java中的反射机制
来源:互联网 发布:平面设计软件分类 编辑:程序博客网 时间:2024/06/11 15:02
Java中的反射机制
JAVA反射机制是在运行状态中,对于任意一个类 (class文件),都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
动态获取类中信息,就是java反射 。可以理解为对类的解剖。要想要对字节码文件进行解剖,必须要有字节码文件对象.那么如何获取字节码文件对象呢?
获取字节码文件(.class文件)的三种方式:
1.Object类中的getClass()方法,想要用这种方法必须明确具体的类,并且创建对象,相对麻烦。
package cn.ruicai.bean;public class Person { private int age; private String name; public Person(String name,int age) { super(); this.age = age; this.name = name; System.out.println("Person param run..."+this.name+":"+this.age); } public Person() { super(); System.out.println("person run"); } public void show(){ System.out.println(name+"...show run..."+age); } private void privateMethod(){ System.out.println(" method run "); } public void paramMethod(String str,int num){ System.out.println("paramMethod run....."+str+":"+num); } public static void staticMethod(){ System.out.println(" static method run......"); }}Person p=new Person();Class clazz=p.getClass();//取得字节码文件
2.任何数据类型都具备一个静态的属性.class来获取其对应的Class对象。相对简单,但是还是要明确用到类中的静态成员,还是不够扩展
Class clazz=Person.class;
3.只要通过给定的类的 字符串名称就可以获取该类,更为扩展。可是用Class类中的方法完成。该方法就是forName.这种方式只要有名称即可,更为方便,扩展性更强。
String className="cn.ruicai.bean.Person"; //包.类名称Class clazz=Class.forName(className);
获取Class对象中的构造函数
早期,在new的时候,先根据被new的类的名称找寻该类的字节码文件,并加载进内存,创建该字节码文件对象,并接着创建该字节文件的对应的Person对象
cn.ruicai.bean.Person p = new cn.ruicai.bean.Person(); Person p=new Person();
现在通过反射,在Class类中的forName()方法中,传入包.类名称,得到该类的class对象,通过该对象调用newInstance()方法即可实例化新的对象。
String name = "cn.ruicai.bean.Person";Class clazz = Class.forName(name);Object obj = clazz.newInstance();
注意:以上这种方法,只适合于,类中有无参构造的类。如果类中没有无参构造,就通过字节码文件对象,可以取得该类的构造函数:使用getConstructor(paramterTypes)方法
String name = "cn.ruicai.bean.Person";Class clazz=Class.forName(name);Constructor constructor = clazz.getConstructor(String.class,int.class);Object obj = constructor.newInstance("小明",38); //获取字节码文件中的字段String name="cn.itcast.bean.Person";Class clazz=Class.forName(name);Field field=null; //clazz.getField();注意:此方法只能获取非私有字段field=clazz.getDeclaredField("age");//只会取本类的字段,包括私有的//对私有字段的访问权限取消。暴力访问field.setAccessible(true);Object obj=clazz.newInstance();//通过clazz实例一个对象field.set(obj,89);Object o=field.get(obj); //取得字段的值,必需要传入一个对象, //获取字节码文件中的方法String name="cn.itcast.bean.Person";Class clazz=Class.forName(name);Method[] methods=clazz.getMethods(); //取得所有的公共的方法,返回的是Method数组//取得无参函数Method method=clazz.getMethod("show",null);//获取指定方法,传入方法名,对应方法无参则传null//取得方法后要想调用,则要创建一个对象,创建对象则要取得构造函数,这里取得有参数构造,方便属性输出Constructor cons=clazz.getConstructor(String.class,int.class);Object obj=cons.newInstance("小明",22);//通过obj这个对象,调用method 方法,invoke()方法里面传入对象和参数,无参则传nullmethod.invoke(obj,null); //取得有参函数String name="cn.itcast.bean.Person";Class clazz=Class.forName(name);Method method=clazz.getMethod("paramMethod",String.class,int.class);Object obj=clazz.newInstance(); //调用次方法则通过类中的无参构造实例化一个对象method.invoke(obj,"小强",20);//调用方法,并传入相应的参数
利用反射增强程序扩展性应用
电脑开机后,主板运行,主板里可以插各种扩展性的卡,如果有声卡,则声卡打开,然后关闭,如果有网卡,则网卡打开然后关闭
1.主板类
public class MainBoard { public void run(){ System.out.println("主板运行"); } public void usePCI(PCI p){ if(p!=null){ p.open(); p.close(); } }}
2.PCI扩展接口类
public interface PCI{ public void open(); public void close();}
3.声卡类
public class SoundCard implements PCI { @Override public void open() { System.out.println("声卡打开。。。。"); } @Override public void close() { System.out.println("声卡关闭"); }}
4.网卡类
public class NetCard implements PCI { @Override public void open() { System.out.println("网卡打开"); } @Override public void close() { System.out.println("网卡关闭"); }}
5.创建pci.properties配置文件:在项目工程右键,新建文件,取名为pci.properties
pci1=com.ruicai.test.SoundCardpci2=com.ruicai.test.NetCard //包.类名称
6.main类
public class Test { public static void main(String[] args) throws Exception { MainBoard mb=new MainBoard(); mb.run(); File file=new File("pci.properties"); //创建配置文件 Properties pro=new Properties(); //创建属性 InputStream is=new FileInputStream(file);//创建输入流读取文件 pro.load(is); //通过输入流加载配置文件 for(int i=0;i<pro.size();i++){ String name=pro.getProperty("pci"+(i+1)); //通过名字取得property Class clazz=Class.forName(name); PCI pci=(PCI)clazz.newInstance(); mb.usePCI(pci); } is.close(); }}
如果后期,pci接口上还有其他扩展性的功能,只需写好该功能的类,然后在配置文件pci.properties中写入类名,就可以了,已写好的代码不需要做任何修改,很好的符合了开闭原则。
- Java中的反射机制
- JAVA中的反射机制
- Java中的反射机制
- java中的反射机制
- JAVA中的反射机制
- Java中的反射机制
- Java中的反射机制
- java中的反射机制
- java中的反射机制
- Java中的反射机制
- java中的反射机制
- JAVA中的反射机制
- java中的反射机制
- Java中的反射机制
- java中的反射机制
- Java中的反射机制
- Java中的反射机制
- java中的反射机制
- 课堂练习三
- MySQL删除没有主键的表中的重复记录,只保留一条记录
- 点击按钮发送短信方法,这里只介绍一种(TP框架)
- 全网友遇到的Mac安装Scrapy框架所有问题
- 数据库相关操作
- Java中的反射机制
- iOS 基本设备信息查询
- krpano360全景 教程
- Leetcode题解-17. Letter Combinations of a Phone Number
- 常用正则表达式收集
- Java爬虫,信息抓取的实现
- 课堂练习四
- 记录一下第一个向ElasticSearch中添加数据的方法
- UIMenuController 显示不出来的原因