Java反射
2015-07-17 13:45
633 查看
1、Class类
Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class。
得到各个字节码对应对应的实例对象(Class类型)的方法有三种:
(a)类名.class,例如:System.class
(b)对象.getClass(),例如:new Date().getClass();
(c)Class.forName("类名"),例如:Class.forName("java.util.Date");
2、 反射的概念
反射就是把Java类中的各种成分映射成相应的Java类。例如,一个Java类中用一个Class类对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机、变速箱等等也是一个类。表示Java类的Class类显然要提供一系列的方法,来获得其中的变量、方法,构造方法、修饰符、包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。
3、 构造方法的反射应用Constructor类
Constructor类代表某个类中的一个构造方法。
得到某个类所有构造方法:Constructor[] cons=Class.forName("java.lang.String").getConstructors();
得到某一个构造方法:Constructor con=Class.forName("java.lang.String").getConstructor(StringBuffer.class);//getConstructor()这里要用到类型
创建实例对象:
通常方式 String str=new String(new StringBuffer("abc"));
反射方式: String str=(String)con.newInstance(new StringBuffer("abc"));
Class.newInstance()方法:
示例:String str=(String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象,用缓存机制来保存默认构造方法的实例对象。
4、 成员变量的反射Field类
Field类代表某个类中的一个成员变量,示例如下:
5、 成员方法的反射Method类
Method类代表某个类中的一个成员方法。
启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射调用main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,但是按照jdk1.4的语法,数组中的每一个元素对应一个参数,因为要兼容1.4的语法,会把数组打散成若干个单独的参数,因此使用代码 mainMethod.invoke(null,new String[]{"XXX"})会出现参数类型不对问题。
解决办法如下面代码所示:
7、 数组的反射
a、具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象
b、代表数组的Class实例对象的getSuperclass()方法返回的父类为Object类对应的Class
c、基本类型的一维数组可以看作是Object的子类对象使用,但不可以当作Object[]类型使用;
非基本类型的一维数组,可以当作Object类型使用,也可以当作Object[]类型使用
Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class。
得到各个字节码对应对应的实例对象(Class类型)的方法有三种:
(a)类名.class,例如:System.class
(b)对象.getClass(),例如:new Date().getClass();
(c)Class.forName("类名"),例如:Class.forName("java.util.Date");
String str1="abc"; Class cls1=str1.getClass(); Class cls2=String.class; Class cls3=Class.forName("java.lang.String"); System.out.println(cls1==cls2);//true System.out.println(cls1==cls3);//true System.out.println(int.class==Integer.class);//false System.out.println(int.class==Integer.TYPE);//true System.out.println(int.class.isPrimitive());//true 基本数据类型的Class实例对象可以用Class.isPrimitive()方法来判断 System.out.println(int[].class.isArray());//true 数组类型的Class实例对象可以用Class.isArray()方法来判断总之,只要是在源程序中出现的类型,都有格子的Class实例对象,例如 int[],void。
2、 反射的概念
反射就是把Java类中的各种成分映射成相应的Java类。例如,一个Java类中用一个Class类对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机、变速箱等等也是一个类。表示Java类的Class类显然要提供一系列的方法,来获得其中的变量、方法,构造方法、修饰符、包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor、Package等等。
3、 构造方法的反射应用Constructor类
Constructor类代表某个类中的一个构造方法。
得到某个类所有构造方法:Constructor[] cons=Class.forName("java.lang.String").getConstructors();
得到某一个构造方法:Constructor con=Class.forName("java.lang.String").getConstructor(StringBuffer.class);//getConstructor()这里要用到类型
创建实例对象:
通常方式 String str=new String(new StringBuffer("abc"));
反射方式: String str=(String)con.newInstance(new StringBuffer("abc"));
Class.newInstance()方法:
示例:String str=(String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象,用缓存机制来保存默认构造方法的实例对象。
4、 成员变量的反射Field类
Field类代表某个类中的一个成员变量,示例如下:
class ReflectPoint{ private int x; public int y; public String str1="abc"; private String str2="basketball"; public String str3="zrf"; ReflectPoint(int x,int y){ this.x=x; this.y=y; } @Override public String toString() { return "ReflectPoint [str1=" + str1 + ", str2=" + str2 + ", str3=" + str3 + "]"; } } class ReflectTest{ public static void main(String[] args){ ReflectPoint pt1=new Reflectpoint(3,5); Field fy=pt1.getClass().getField("y"); //fy不代表对象上的变量,而是类上的变量,对于不同的对象其y的值都不同,要用fy去取某个对象上对应的值 System.out.println(fy.get(pt1));//5 //Field fx=pt1.getClass().getField("x");//这句会抛出异常,因为x是私有的,不会让别的类看到 //如果想得到其中的私有成员变量,可以这样操作 Field fx=pt1.getClass().getDeclaredField("x");//此时fx还不能被操作,只是让我们看到有这个成员变量 fx.setAccessible(true); System.out.println(fx.get(pt1));//3 暴力反射 Field[] fields=pt1.getClass().getFields();//不能得到私有成员变量 if(fields!=null){ for(Field f:fields){ if(f.getType()==String.class){ try { f.set(pt1,((String)f.get(pt1)).replace('b', 'a')); } catch (IllegalArgumentException | IllegalAccessException e) { System.out.println("getFields()能看到私有成员变量!"); } } } } System.out.println(pt1); } }
5、 成员方法的反射Method类
Method类代表某个类中的一个成员方法。
String str="abc"; Method methodCharAt=String.class.getMethod("charAt",int.class); System.out.println(methodCharAt.invoke(str,1));//b 若为静态方法,invoke方法第一个参数设为null6、 用反射方式执行某个类的main方法
启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射调用main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,但是按照jdk1.4的语法,数组中的每一个元素对应一个参数,因为要兼容1.4的语法,会把数组打散成若干个单独的参数,因此使用代码 mainMethod.invoke(null,new String[]{"XXX"})会出现参数类型不对问题。
解决办法如下面代码所示:
Class clazz=Class.forName(args[0]); Method mainMethod=clazz.getMethod("main",String[].class); mainMethod.invoke(null,new Object[]{new String[]{"xxx","111"}}); mainMethod.invoke(null,(Object)new String[]{"xxx","111"});//编译器会做特殊处理,不把参数当数组看待,所以不会把参数拆散成若干个参数
7、 数组的反射
a、具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象
b、代表数组的Class实例对象的getSuperclass()方法返回的父类为Object类对应的Class
c、基本类型的一维数组可以看作是Object的子类对象使用,但不可以当作Object[]类型使用;
非基本类型的一维数组,可以当作Object类型使用,也可以当作Object[]类型使用
相关文章推荐
- 黑马程序员——JDK1.5新特性、单例设计模式
- java学习之static关键字(上)
- Java Persistence with Hibernate
- 关于eclipse的汉化方法
- 典型的Java Web程序包含的内容
- Spring MVC遭遇checkbox的问题解决方案
- JAVA学习第四天
- Springmvc+mybatis+maven查询分页完美封装版
- eclipse怎样自动排版
- Java 一行代码初始化ArrayList
- Spring和MyBatis环境整合
- Spring 整合Mybatis实例
- 为eclipse配置黑色背景
- Java基础——集合框架(二)
- eclipse快捷键-超实用
- HashMap存储数据赋值javabean简单示例
- Java中static的用法归纳
- Myeclipse集成Maven(图文说明)
- Java通过SMS短信平台实现发短信功能
- JAVA IO学习总结