Java学习总结-反射
2016-07-26 17:23
519 查看
1、反射的概念。
是Java语言提供的一种机制,并不是所有语言都具备;反射可以实现在.java文件编译时,可以不明确类的具体类型,而在.class文件运行再去检查和明确这个类。
2、反射的原理。
首先要了解一下java程序的运行步骤,源(.java)文件经过javac.exe编译后生成二进制(.class)文件,编译主要工作就是语法检查,然后通过java.exe去执行二进制文件,这时jvm会通过类加载器把二进制文件装入方法区,同时在堆中会创建一个描述这个类的对象,类型为java.lang.Class(注意是大写)。这个类描述的内容无非是装载类的基本属性:
class Class{
名称(类名)
字段(成员变量)
构造函数
一般函数(成员函数)
}
通过这个类可以获取到字节码文件的所有信息,而反射的就是依赖的这个字节码文件对象。
也许你有疑问,获取这些信息能干什么呢?
1. 有了构造函数,你可以创建这个类的新的实例(对象)。
2. 可以返回字段值。
3. 执行一般函数等。
所有的工作都可以做,跟你拿到这个类的源代码是同样的效果。下面的工作就是怎么获取一个类的二进制文件的对象。
3、获取Class对象的三种方式
1、 通过Object类提供的getClass()方法。
2、 通过所有类都具备的静态属性.class。
3、 通过java.lang.Class的forName
(String
className)方法(重点)。
packageitcast.reflect.demo; publicclass ReflectDemo { public static void main(String[] args)throws Exception{ //getClassObject_1() //getClassObject_2() getClassObject_3(); } /* *1、Object类的getClass()方法。必须要明确具体的类,并创建对象 */ public static void getClassObject_1(){ Person p = new Person(); Class clazz = p.getClass(); Person p1 = new Person(); Class clazz1 = p1.getClass(); System.out.println(clazz ==clazz1); } /* *2、任何数据类型都具备一个静态属性.class来获取起对应的class对象 */ public static void getClassObject_2(){ Class clazz = Person.class; Class clazz1 = Person.class; System.out.println(clazz ==clazz1); } /* *3、通过java.lang.Class类的forName,根据类名的字符串形式,获取该类的二进制文件对象,这种方式只需名称即可,扩展性更强。 */ public static void getClassObject_3()throws Exception{ String name ="itcast.reflect.demo.Person"; Class clazz =Class.forName(name); System.out.println(clazz); } }
packageitcast.reflect.demo; publicclass Person { private int age; private String name; public Person(String name,int age){ super(); this.age = age; this.name = name; System.out.println("Personparam run..."+this.name+":"+this.age); } public Person(){ super(); System.out.println("personrun"); } public void show(){ System.out.println(name+"...showrun..."+age); } private void privateMethod(){ System.out.println("privateMethodrun"); } public void paraMethod(String str,intnum){ System.out.println("paraMethodrun...."+str+":"+num); } public static void staticMethod(){ System.out.println("staticmethod run...."); } }
4、获取构造函数(创建实例)
1、 如果是构建一个无参的实例,通过Class调用newInstance()方法。
2、 如果是构建一个有参数的实例,通过Class的getConstructor
(Class
<?>... parameterTypes)方法,根据传入的参数列表的类型去返回对象的构造函数对象,然后再调用newInstance(Object... initargs)方法创建实例。
packageitcast.reflect.demo; importjava.lang.reflect.*; publicclass ReflectDemo2 { public static void main(String[] args)throws Exception { createNewObject_2(); } public static void createNewObject()throws Exception{ //早期:new时候,先根据被new的名称找寻该类的字节码文件,并加载进内存, //并创建该自己吗文件对象,并接着创建该字节文件的对应的Person对象 //itcast.bean.Person p = newcn.itcast.bean.Person(); //现在: String name ="itcast.reflect.demo.Person"; //找寻该名称类文件,并加载进内存,并产生Class对象 Class clazz =Class.forName(name); //如何产生该类的对象呢 Object obj =clazz.newInstance(); } public static void createNewObject_2()throws Exception{ /* * 当获取指定名称对应类中的所体现的对象是 * 而该对象初始化不适用空参数构造该怎么办呢 * 既然是通过指定的构造函数进行初始化,所以应该先获取该构造函数。 * 通过字节码文件对象就可以获得,指定的:getConstructor(Class<?>...parameterTypes) 全部:getConstructors() 全部(包含私有):getDeclareConstrunctors() * */ String name ="itcast.reflect.demo.Person"; Class<?> clazz =Class.forName(name); //获取到了指定的构造函数对象 Constructor constructor =clazz.getConstructor(String.class,int.class); //通过该构造器对象的newInstance方法进行对象的初始化 Object obj =constructor.newInstance("小强",23); } }
5、返回Class中字段
公有的字段,通过Class的getField(String
name)
,根据字段名去获取。
私有的,通过Class的getDeclaredField
(String
name)
获取,又叫暴力获取。
以上返回Field对象,其中该对象的set
(Object
obj,Object
value)
方法可以修改对象中值。
packageitcast.reflect.demo; importjava.lang.reflect.*; publicclass ReflectDemo3 { public static void main(String[] args)throws Exception { getFieldDemo(); } public static void getFieldDemo()throws Exception { Class<?> clazz =Class.forName("itcast.reflect.demo.Person"); //私有成员变量无法获取 //Field field=clazz.getField("age"); //暴力获取私有成员变量 Field field =clazz.getDeclaredField("age"); //获取指定参数的构造函数 Constructor constructor =clazz.getConstructor(String.class,int.class); //调用构造的函数传入参数,创建实例 Object obj = constructor.newInstance("小强",23); //get(Object obj)返回指定对象上Field表示字段的值 //私有成员不能获取,通过SetAccessible()设置 field.setAccessible(true); field.set(obj,89); Object value =field.get(obj); System.out.println(value); } }
6、 获取Class中方法
通过Class的getMethods()获取所有的公共方法,包括父类的。
通过Class的getDeclaredMethods
()
获取本类的方法,包括私有。
通过Class的getDeclaredMethod
(String
name,Class
<?>... parameterTypes)获取单个方法,name表示函数名,parameterTypes表示参数。
以后返回Method对象,通过invoke
(Object
obj,Object
... args)
,传入对象和参数值,执行该方法。
package itcast.reflect.demo; import java.lang.reflect.*; public class ReflectDemo4 { public static void main(String[] args) throws Exception { getMethodDemo_2(); } /* * 获取指定Class中的公共函数 */ public static void getMethodDemo() throws Exception { Class clazz =Class.forName("itcast.reflect.demo.Person"); Method[] methods = clazz.getMethods();//获取的都是公有的方法 methods = clazz.getDeclaredMethods();//获取本类的所有方法 for(Method method : methods){ System.out.println(method); } } public static void getMethodDemo_2() throws Exception { Class<?> clazz = Class.forName("itcast.reflect.demo.Person"); Method method =clazz.getMethod("staticMethod",null); //Constructor constructor =clazz.getConstructor(String.class,int.class); //Object obj =constructor.newInstance("小强",23); method.invoke(null,null); } }
7、 反射的应用
通过读取配置文件,获取加载的类文件对象,然后动态执行程序,编码程序的修改。packageitcast.reflect.test; importjava.lang.reflect.*; importjava.io.*; importjava.util.*; publicclass ReflectTest { public static void main(String[] args)throws Exception { Mainboard mb = newMainboard(); mb.run(); //每次添加一个设备都需要修改代码传递一个新创建的对象 //mb.usePCI(new SoundCard()); //能不能不修改代码就可以完成这个动作 //不用new来完成,而是值获取起class文件。 File configFile = newFile("pci.properties"); Properties prop = newProperties(); FileInputStream fis = newFileInputStream(configFile); prop.load(fis); for(intx=0;x<prop.size();x++){ String pciName =prop.getProperty("pci"+(x+1)); Class clazz =Class.forName(pciName); Object obj =clazz.newInstance(); PCI p =(PCI)clazz.newInstance(); mb.usePCI(p); } fis.close(); } }
packageitcast.reflect.test; //importitcast.reflect.test.PCI; publicclass Mainboard { public void run() { System.out.println("mainborad run..."); } /*public void useSound(SoundCard c){ c.open(); c.close(); }*/ public void usePCI(PCI p){ if(p!=null){ p.open(); p.close(); } } }
packageitcast.reflect.test; publicinterface PCI { public void open(); public void close(); } packageitcast.reflect.test; publicclass SoundCard implements PCI { public void open() { System.out.println("soundopen"); } public void close() { System.out.println("soundclose"); } }
packageitcast.reflect.test; publicclass NetCard implements PCI { public void open() { System.out.println("netopen"); } public void close() { System.out.println("netclose"); } }
文件名:pci.properties:
pci1=itcast.reflect.test.SoundCard pci2=itcast.reflect.test.NetCard
相关文章推荐
- 基于Java代码实现证书生成
- java中反射
- RxJava入门——概念篇
- javaIO(二)
- Spring IOC原理解读 面试必读
- JAVA笔记之RandomAccessFile
- No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK
- JAVA中复制数组的五种方法
- Java获取package下所有的class对象(普通文件包和Jar文件包)
- [Java基础笔记]服务器/客户端交互部分
- <%@ include file=” ”%> ——最简洁易懂的解释
- Eclipse对web项目打war包并且关联java项目
- Java序列化学习导图
- [kafka] 005_kafka_Java_API
- Java 集合体系详解——List体系有序集合
- Head First Java笔记(九)
- Java配置环境变量
- [Java基础笔记]JDBC初步
- java中用集合编写简单的学生信息管理系统
- java正则表达学习