——Java中反射机制09
2015-07-11 08:34
567 查看
一、类的加载:
原理理解:
当使用某个类的时候,如果该类还没有被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
a、
加载:
就是指将class文件读入到内存,并创建一个Class对象
任何类被使用时系统都会建立一个Class对象
b、
连接:
验证 : 是否有正确的内部结果,并和其他类协调一致。
准备: 负责为类的静态成员分配内存,并配置默认初始化值。
解析: 将类的二进制数据中的符号引用替换为直接的引用。
c、
初始化 :
类初始化时机:
1.访问类的实例
2.访问类的静态变量,或者为静态变量赋值,
3.调用类的静态方法
4.调用反射方式来强制创建某个类或者接口对应的
5. Java.lang.Class对象。
6. 初始化某个类的子类
7. 直接使用java.exe命令来运行某个主类。
二、类加载器:
将.class文件加载到内存中,并生成对应的Class对象
分为三种:
BootstrapClassLoader 根类加载器:
(引导类加载器)负责java核心类加载,
如System,String等,在JDK中JRE的lib目录下rt.jar文件中
Extension ClassLoader扩展类加载器:
负责JRE的扩展目录中Jar包的加载
在JDK中JRE的lib目录下ext目录
SystemClassLoader 系统类加载器:
负责在JVM启动时加载来自java命令的class文件
以及classpath环境变量所指定的jar包和类路径
三、什么是反射?
1、原理理解:
能够知道任意一个类的所有属性和方法,且能调用它的任意一个方法和属性,
这种动态获取的信息以及动态调用对象的方法的功能称为java语音的反射机制。
要解剖一个类,首先要获取到类的每一个字节码文件对应的Class类型的对象,
其中用的是Class类中的方法:
成员变量 Field
构造方法 Constructor
成员方法 Method
2、获取class文件对象的方式:
三种方式:
a.
Person p = new Person();
Class c1 = p.getClass();
b.
Class c2 = Person.class;
c.
Class c3 = Class.forName(“myReflect.Person”);
PS.
c1 == c2 true
c2 == c3 true
1和2都运用于日常(2较方便),3常用于项目开发,
3中的全路径通常通过配置文件中存储的路径,因为容易出错。
3、Constructor
获取构造方法:
1)得到这个类的所有构造方法:如得到上面示例中Person类的所有构造方法
Constructor[] cons = Class.forName(“myReflect.Person”).getConstructors();
2)获取某一个构造方法:
Constructor con=Person.class.getConstructor(String.class,int.class);
括号中是参数的字节码文件对象。
4、Field
获取类中一个成员变量
FieldgetField(String
s);//只能获取公有和父类中公有
FieldgetDeclaredField(String s);//获取该类中任意成员变量,包括私有
setAccessible(ture);
//如果是私有字段,要先将该私有字段进行取消权限检查的能力。也称暴力访问。
set(Objectobj, Object value);//将指定对象变量上此Field对象表示的字段设置为指定的新值。
Object get(Objectobj);//返回指定对象上Field表示的字段的值。
5、Method
调用某个对象身上的方法,要先得到方法,再针对某个对象调用。
Method[] getMethods();//只获取公共和父类中的方法。
Method[] getDeclaredMethods();//获取本类中包含私有。
Method getMethod("方法名",参数.class(如果是空参可以写null));
Object invoke(Objectobj ,参数);//调用方法
如果方法是静态,invoke方法中的对象参数可以为null。
6、案例演示:
案例1:
案例2:
创建老师对象:
创建学生对象:
配置文件:
反射调用:
当配置路径设为学生时结果为:
案例演示3:
在ArrayList<Integer> list = new ArrayList<Integer>();
在这个泛型为Integer的ArrayList中存放一个String类型的对象。
美好的一天!
原理理解:
当使用某个类的时候,如果该类还没有被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
a、
加载:
就是指将class文件读入到内存,并创建一个Class对象
任何类被使用时系统都会建立一个Class对象
b、
连接:
验证 : 是否有正确的内部结果,并和其他类协调一致。
准备: 负责为类的静态成员分配内存,并配置默认初始化值。
解析: 将类的二进制数据中的符号引用替换为直接的引用。
c、
初始化 :
类初始化时机:
1.访问类的实例
2.访问类的静态变量,或者为静态变量赋值,
3.调用类的静态方法
4.调用反射方式来强制创建某个类或者接口对应的
5. Java.lang.Class对象。
6. 初始化某个类的子类
7. 直接使用java.exe命令来运行某个主类。
二、类加载器:
将.class文件加载到内存中,并生成对应的Class对象
分为三种:
BootstrapClassLoader 根类加载器:
(引导类加载器)负责java核心类加载,
如System,String等,在JDK中JRE的lib目录下rt.jar文件中
Extension ClassLoader扩展类加载器:
负责JRE的扩展目录中Jar包的加载
在JDK中JRE的lib目录下ext目录
SystemClassLoader 系统类加载器:
负责在JVM启动时加载来自java命令的class文件
以及classpath环境变量所指定的jar包和类路径
三、什么是反射?
1、原理理解:
能够知道任意一个类的所有属性和方法,且能调用它的任意一个方法和属性,
这种动态获取的信息以及动态调用对象的方法的功能称为java语音的反射机制。
要解剖一个类,首先要获取到类的每一个字节码文件对应的Class类型的对象,
其中用的是Class类中的方法:
成员变量 Field
构造方法 Constructor
成员方法 Method
2、获取class文件对象的方式:
三种方式:
a.
Person p = new Person();
Class c1 = p.getClass();
b.
Class c2 = Person.class;
c.
Class c3 = Class.forName(“myReflect.Person”);
PS.
c1 == c2 true
c2 == c3 true
1和2都运用于日常(2较方便),3常用于项目开发,
3中的全路径通常通过配置文件中存储的路径,因为容易出错。
3、Constructor
获取构造方法:
1)得到这个类的所有构造方法:如得到上面示例中Person类的所有构造方法
Constructor[] cons = Class.forName(“myReflect.Person”).getConstructors();
2)获取某一个构造方法:
Constructor con=Person.class.getConstructor(String.class,int.class);
括号中是参数的字节码文件对象。
4、Field
获取类中一个成员变量
FieldgetField(String
s);//只能获取公有和父类中公有
FieldgetDeclaredField(String s);//获取该类中任意成员变量,包括私有
setAccessible(ture);
//如果是私有字段,要先将该私有字段进行取消权限检查的能力。也称暴力访问。
set(Objectobj, Object value);//将指定对象变量上此Field对象表示的字段设置为指定的新值。
Object get(Objectobj);//返回指定对象上Field表示的字段的值。
5、Method
调用某个对象身上的方法,要先得到方法,再针对某个对象调用。
Method[] getMethods();//只获取公共和父类中的方法。
Method[] getDeclaredMethods();//获取本类中包含私有。
Method getMethod("方法名",参数.class(如果是空参可以写null));
Object invoke(Objectobj ,参数);//调用方法
如果方法是静态,invoke方法中的对象参数可以为null。
6、案例演示:
案例1:
<span style="font-size:14px;">package myDemo; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class ClassDemo { @SuppressWarnings({ "rawtypes", "unused" }) public static void main(String[] args) throws Exception { //Class c = Person.class; //获取字节码文件对象 Class c = Class.forName("myDemo.Person"); //获取私有构造方法对象 //Constructor[] cons = c.getConstructors();获取所以的公共构造方法 //Constructor[] cons = c.getDeclaredConstructors();获取所以的构造方法 Constructor con = c.getDeclaredConstructor(); //用私有构造方法创建对象 Object obj = con.newInstance(); //con.setAccessible(true);暴力访问,设置为true则指反射的对象在使用时取消java语言访问检查。 //第一个参数表示方法名,第二个参数表示的是方法的参数的class类型。 Method method = c.getMethod("method_1",String.class); //String s = (String)method.invoke(obj,"zzz"); //调用obj的method方法,给方法参数赋值为“zzz”; Object objString = method.invoke(obj,"zzz"); System.out.println(objString); } }</span><span style="font-size:18px;"> </span>
案例2:
创建老师对象:
package myDemo; public class Teacher { public void love(){ System.out.println("爱校长。"); } }
创建学生对象:
package myDemo; public class Student { public void love(){ System.out.println("爱学习。"); } }
配置文件:
反射调用:
package myDemo; import java.io.FileReader; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Properties; public class ReflectDemo { public static void main(String[] args) throws Exception { //读取配置文件 FileReader fis = new FileReader("class.txt"); Properties pop = new Properties(); //导入配置文件信息 pop.load(fis); //获取配置文件中的路径 String className = pop.getProperty("className"); String classMethod = pop.getProperty("classMethod"); Class c = Class.forName(className); //通过配置路径获取对象的字节码对象 //获取构造方法对象 Constructor con = c.getConstructor(); //用构造方法创建对象 Object obj = con.newInstance(); //获取方法LOVE Method m = c.getMethod("love"); m.invoke(obj);//调用方法 } }<strong> </strong>
当配置路径设为学生时结果为:
案例演示3:
在ArrayList<Integer> list = new ArrayList<Integer>();
在这个泛型为Integer的ArrayList中存放一个String类型的对象。
<span style="font-size:14px;">/** * */ package myTestDir; import java.lang.reflect.Method; import java.util.ArrayList; /** * @author LinP *第三题:ArrayList<Integer> list = new ArrayList<Integer>(); * * 在这个泛型为Integer的ArrayList中存放一个String类型的对象。 */ public class Test3 { /** * @param args * @throws Exception * @throws NoSuchMethodException */ public static void main(String[] args) throws Exception { // 创建集合对象 ArrayList<Integer> list = new ArrayList<Integer>(); //获取list的字节码文件 Class c = list.getClass();//集合ArrayLiset中的class文件对象 //用Method类调用c中的Method方法。 Method method = c.getMethod("add",Object.class); method.invoke(list, "hello");//调用list的add方法,传入的值是hello System.out.println(list); } }</span><span style="font-size:18px;"><strong> </strong></span>
美好的一天!
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories