反射
来源:互联网 发布:java基础常见面试题 编辑:程序博客网 时间:2024/06/07 14:37
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
反射
Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class
对比提问:众多的人用一个什么类表示?众多的Java类用一个什么类表示?
人 Person java类 Class
对比提问:Person类代表人,它的实例对象就是张三,李四这样一个个具体的人,Class类代表Java类,它的各个事例对象又分别对应 什么呢?
对应各个类的字节码,如Person类的字节码,ArrayList类的字节码等等
一个类被类加载器加载进入内存中,占用了一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码不同,所以它们在内存 中的内容是不同的
这一个个空间可分别用一个个的对象来表示,这些对象显然具有相同的类型。
如何得到各个字节码对象的事例对象(Class类型)
1、类名.class,如:System.class
2、对象.getClass(),如:new Date().getClass()
3、Class.forName("类名");,如:Class.forName("java.lang.String");
九个预定义Class实例对象:
八个基本数据类型(boolean,char,byte,short,int,lang,float,double)
数组类型的Class实例对象:
class.isArray()
总之,只要在源程序中出现的类型,都有各自的Class实例对象,如:int[],void
如:
- package cn.itcast.day1;
- public class ReflectTest {
- /**
- * @param args
- */
- public static void main(String[] args)throws Exception {
- // TODO Auto-generated method stub
- String str1 = "abc";
- Class cla1 = str1.getClass();
- Class cla2 = String.class;
- Class cla3 = Class.forName("java.lang.String");
- //验证三种方法是不是同一份字节码,答案都是true
- System.out.println(cla1==cla2);
- System.out.println(cla1==cla3);
- System.out.println(cla1.isPrimitive());//判断是否是一个基本数据类型
- System.out.println(int.class==Integer.class);//int和Integer是不同类型,各自有自己的字节码
- System.out.println(int.class==Integer.TYPE);//TYPE用来表示所包装的那份基本类型的字节码
- //数组出现的类型也有自己的字节码,用isArray()判断
- System.out.println(int[].class.isPrimitive());
- System.out.println(int[].class.isArray());
- }
- }
反射概念:就是把JAVA类中的各种成分映射成相应的JAVA类。
如:一个java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的JAVA类来表示,就像汽车是一个类,汽车的发动机,变速箱等等也是一个个类。表示java类的Class类显然就是提供一系列方法,来获得其中的变量,方法和构造方 法,修饰符,包等等信息,这个信息就是用相应类的事例对象来表示,它们是Field、Method、Constructor、Package等等。
Constructor类:
1、概述:Constructor代表某个类的构造方法。
2、获取构造方法:
1、如何得到某个类的所有构造方法(如得到String类的所有构造方法):
Constructor[] cons = Class.forName(“java.lang.String”).getConstructors();
2、获取某一个构造方法:
Constructor con =String.class.getConstructor(StringBuffer.class); ①
3、创建实例对象:
1、通常方式:String str = new String(new StringBuffer (”abc”));
2、反射方式:String str = (String)con.newInstance(new StringBuffer(“abc”)); ②
调用获得的方法时要用到上面相同类型的实例对象,即两个StringBuffer()要对应相等。
NewInstance():构造出一个实例对象,每调用一次就构造一个对象。
注意:上面的两个地方①②都要用到StringBuffer,这必须是一致的。
第①个是指定要带StringBuffer参数类型的构造方法,即所需使用的是含StringBuffer类型的构造方法。
第②个是用这个构造方法创建对象,要传入的参数类型必须是StringBuffer。
4、Class.newInstance():创建一个对象,不带参数的构造方法。
Field类:
概述:Field类代表成员变量(字段)的反射。
如:
- public class ReflectPoint {
- private int x;
- public int y;
- public String toString(){
- return str1+";" + str2 + ";" + str3;
- }
- }
- public class FieldTest(){
- ReflectPoint pt1 = new ReflectPoint(3,5);
- //fieldX和fieldY并不是对象身上的变量,而是类上的
- //要用它去取某个对象上的对应的值,传入什么对象,就取相应对象的值。
- Field fieldY = pt1.getClass().getField("y");
- System.out.println(fieldY.get(pt1));
- //获取私有的成员变量
- Field fieldX = pt1.getClass().getDeclaredField("x");
- fieldX.setAccessible(true);
- System.out.println(fieldX.get(pt1));
- }
Method类:
1、概述:Method类代表某个类中的一个成员方法。调用某个对象身上的方法,要先得到方法,再针对某个对象调用。
2、专家模式:谁调用这个数据,就是谁在调用它的专家。
如人关门。调用者:是门调用管的动作,对象是门,因为门知道如何执行关的动作,通过门轴之类的细节实现。指挥者:是人在指挥门做 关的动作,只是给门发出了关的信号,让门执行。
总结:变量使用方法,是方法本身知道如何实现执行的过程,也就是“方法对象”调用方法,才执行了方法的每个细节的。
3、获取某个类中的某个方法:(如String str = ”abc”)
1、通常方式:str.charAt(1)
2、反射方式:
Method charAtMethod = Class.forName(“java.lang.String”).getMethod(“charAt”,int.class);
charAtMethod.invoke(str,1);
说明:如果传递给Method对象的invoke()方法的第一个参数为null,说明Method对象对应的是一个静态方法
4、用反射方式执行某个main方法:
首先要明确为何要用反射:在写源程序时,并不知道使用者传入的类名是什么,但是虽然传入的类名不知道,而知道的是这个类中 的方法有main这个方法,所以可以通过反射的方式,通过使用者传入的类名(可定义字符串型变量作为传入类名的入口,通过这个 变量代表类名),内部通过传入的类名获取其main方法,然后执行相应的内容。
如:
- //Method类演示
- private static void methodTest(String [] args) throws Exception {
- String str1 = "abc";
- //一般方法:
- System.out.println(str1.charAt(1));
- //反射方法 :
- Method methodCharAt =
- Class.forName("java.lang.String").getMethod("charAt",int.class);
- System.out.println(methodCharAt.invoke(str1,1));
- //用反射方式执行某个main方法
- //一般方式:
- Test.main(new String[]{"111","222","333"});
- System.out.println("-------");
- //反射方式:
- String startingClassName = args[0];
- Method methodMain =
- Class.forName(startingClassName).getMethod("main",String[].class);
- //方案一:强制转换为超类Object,不用拆包
- methodMain.invoke(null,(Object)new String[]{"111","222","333"});
- //方案二:将数组打包,编译器拆包后就是一个String[]类型的整体
- methodMain.invoke(null,new Object[]{new String[]{"111","222","333"}});
- }
- //定义一个测试类
- class Test{
- public static void main(String [] args){
- for(String arg : args){
- System.out.println(arg);
- }
- }
- }
数组的反射:
具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象(此处比较与值无关)。
代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。
基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又 可以当做Object[]类型使用。
Arrays.asList()方法处理int[]和String[]时的差异。
Array工具类用于完成对数组的反射操作。
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 反射
- 双系统如何正确的删除Ubuntu
- PhoneGap(Cordova)之js调用本地native的方法 2
- 基于梯度调整的矩不变自动阈值图像分割算法
- Linux初始RAM磁盘介绍
- iOS中使用blend改变图片颜色
- 反射
- hive中的order by+sort by+distribute by+cluster by
- 关于json的一些误解
- UML建模工具Trufun Plato的下载及安装为Eclipse的插件
- jqGrid方法
- NDK入门(环境搭建与demo编写)
- php导出excl
- WPF之路——DataGrid学习
- grub启动顺序更改