透彻分析反射的基础_Class类
Class类:Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class
如何得到各个类的字节码,即Class类?
1、类名.class //直接使用类.class获得
2、对象.getClass()//通过对象调用其getClass方法
3、Class.forName(“java.util.Date”) //使用类加载器加载
Java原始基本类型:boolean, byte, char, short, int, long, float,double 和关键词 void同样都有Class类,通过.class可获得他们的类字节码
理解反射的概念
反射就是吧Java类中的各种成分映射成相应的Java类,例如一个Java类中用一个Class类的对象表示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,就想七成是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示Java的Class类显然要提供一系列的方法,来获得其中的变量、方法、构造方法,修饰符、包等信息,这些信息就是用相应的类的实例对象来表示,他们是Field、Method、Contructor、Package等等。
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示。
构造方法的反射应用
Constructor 类,各种类的构造方法的反射类。
Constructor 反射类对象的获得:
例:Constructor constructor=String.class.getConstructor(StringBuffer.class);
构造方法可以用于构造实例对象
String str=(String)constructor.newInstance(new StringBuffer("abc"));
Class本身也还有newInstance方法,可以直接调用,例如
String obj=(String)String.class.newInstance();
//类似于调用无参的构造方法。
成员变量的反射
Field 类,类中成员变量的反射类。
Field 对象的反射获得:
class Person
{
public String personname;
protected String personcity;
private String personadd;
public int personage;
public Person(String personname, String personcity, String personadd)
{
this.personname = personname;
this.personcity = personcity;
this.personadd = personadd;
this.personage=0;
}
}
......
//一下为Field反射类的应用部分
......
Person person=new Person("myname","mycity","myaddress");
Field fieldname=person.getClass.getField("personname");//基本方式获得public成员变量
Field fieldcity=person.getClass.getDeclaredField("personcity");//获得声明的成员变量
Field fieldadd=person.getClass.getDeclaredField("personadd");//获得声明的成员变量
//Field[] fields=person.getClass.getDeclaredFields();//获得声明的所有成员变量数组
System.out.println("personname:" + fieldname.get(person));//打印成员变量的值
System.out.println("personcity:" + fieldcity.get(person));//protect修饰变量可直接读取
personadd.setAccessible(true);//设置成员变量可访问,包括private成员变量(暴力反射)
System.out.println("personcity:" + fieldadd.get(person));//private成员必须设置访问权限setAccessible(true)后才可以访问
成员变量的修饰符public、protect、private对反射类有不同的权限要求,注意红色字体部分。
成员变量反射的综合案例
循环访问类示例对象的成员变量,并修改其变量值:
public class Java_Test //声明运行主体类
{
public Java_Test()
{
// TODO Auto-generated constructor stub
}
public static void main(String[] args) throws Exception
{
System.out.println("-------------------------------");
Person person=new Person("myname","mycity","myaddress");
System.out.println(person.toString()); //打印原始对象成员变量的值
System.out.println("-------------------------------");
chageFields(person); //调用方法访问并修改类成员变量的值
System.out.println(person.toString()); //打印修改后的成员变量值
System.out.println("-------------------------------");
}
public static void chageFields(Object obj) throws IllegalAccessException
{
String str;
Field[] fields=obj.getClass().getDeclaredFields(); //获得成员变量反射类对象数组
for(Field field:fields) //循环访问数组成员
{
field.setAccessible(true); //设置成员变量可访问(暴力反射)
if(field.getType()==String.class)
{
str=(String)field.get(obj); //读取成员变量的值
str=str.replace('_',' '); //修改
field.set(obj,str); //重新设置成员变量的值
}
}
}
}
class Person //声明要操作的类
{
public String personname;
protected String personcity;
private String personadd;
public int personage;
public Person(String personname, String personcity, String personadd)
{
this.personname = personname;
this.personcity = personcity;
this.personadd = personadd;
this.personage=0;
}
@Override //覆盖toString方法,显示成员变量的值
public String toString()
{
return "personname:" + personname +"\npersoncity:"+personcity + "\npersonadd:" + personadd;
}
}
成员方法的反射
Method 类,类中各个成员方法的反射类
成员方法的反射应用方法:先得到类字节码的方法,然后再指定在哪个对象上调用方法,最后进行调用。
例如:利用反射调用String类的charAt方法
String str=new String("abc")
Method methodCharAt=String.class.getMethod("charAt",int.class);
//注意参数类型及意义:类字节码class.getMethod(“方法名”,方法参数类型.class)
System.out.println(methodCharAt.invoke(str,1)); //方法对象.invoke(原对象,参数对象数组)
输出结果同直接调用对象方法,即:str.charAt(1)
*注意* 静态方法的反射调用可以写成:方法对象method.invoke(null,参数对象数组)
无参静态方法反射调用要写成:方法对象method.invoke(null,null)
JDK1.4版本注意参数类型构成:methodCharAt.invoke(str,new Object[]{1})
对接收数组参数的成员方法进行反射
示例:调用其他类的main方法 public static void main(String[] args)
String mainClassName=new String("MainClassName");
Method mainMethod=Class.forName(mainClassName).getMethod("main", String[].class);
mainMethod.invoke(null, new Object[]{new String[]{"Ling","Dong","Cao"}});
mainMethod.invoke(null, (Object)new String[]{"Ling","Dong","Cao"});
为兼容JDK1.4,invoke会将数组参数拆分为单个的元素来作为参数列表。在以上示例中如果直接使用数组作为参数,则会出现main方法参数个数错误:
//错误的写法:mainMethod.invoke(null,new String[]{"Ling","Dong","Cao"});
数组与Object的关系及其反射类型
1、具有相同维数和元素类型的数组属于统一个类型,即具有相同的Class实例对象
2、代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。
3、基本类型的一维数组可以被当做Object类型使用,不能当做Object[]类型使用,非基本类型的一维数组既可以当做Object类型使用,又可以当做Object[]类型使用。
示例:
int[] num1=new int[3];
int[] num2=new int[4];
int[][] num12=new int[3][4];
String[] str=new String[3];
下面说明各个对象的反射类的关系
num1.getClass()==num1.getClass()
num1.getClass()!=num12.getClass()
num1.getClass()!=str.getClass()
数组与Object的关系:
num1.getClass().getSuperClass().getName()==str.getClass().getSuperClass().getName()=="java.lang.Object"
Object objint1=num1;
Object objint12=num12;
Object objstr=str;
//Object[] objint=num1; //错误的写法,int基本类型不是Object
Object[] objint12=num12; //正确写法,因其成员为int[],为Object。
Object[] obj_str=str; //正确,因为String实例即为Object对象类型
Array.asList()方法处理int[]和String[]的差异。
int[] num=new int[]{1,2,3};
String[] str=new String[]{"aaa","bbb","ccc"};
System.out.println(Arrays.asList(num1)); //打印输出类似“[[I@c17164]”的字符
System.out.println(Arrays.asList(str)); //打印类似“[aaa, bbb, ccc]”的字符
数组的反射应用
打印传入对象,如果为单一对象,直接打印,如果为数组,则逐一打印数组元素(对数组对象的判断应用)
public void printObject(Object obj)
{
Class cla=obj.getClass();
if(cla.isArray())
{
int len=Array.getLength(obj);
for(int i=0;i<len;i++)
{
System.out.println(Array.get(obj,i));
}
}
else
{
System.out.println(obj);
}
}
分享到:
相关推荐
这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。其中LEAD/LEAD++ 、OpenC++ 、MetaXa和OpenJava等就是基于反射机制的语言。...
详细介绍反射的概念,并以C#为例子进行说明
反射是C#的一个重要概念,如何使用很重要,有必要抽时间好好学习一下!
反射本身并不是一个新概念,它可能会使我们联想到光学中的反射概念,尽管计算机科学赋予了反射概念新的含义,但是,从现象上来说,它们确实有某些相通之处,这些有助于我们的理解。在计算机科学领域,反射是指一类...
电磁波发生全反射现象的研究及应用,施鹄,郝宏刚,本文通过引入狭义全反射和平衡场等概念,对电磁波的全反射现象和光纤传输问题进行建模,深入分析了发生全反射时折射波(表面波)
对java泛型以及反射机制进行原理和应用上的讲解,帮助初学者对这两个概念进行更轻松的掌握
应用探测仪器,不与探测目标接触,从远处用把目标的电磁波特性记录下来,通过对信息的处理和分析研究,揭示出物体的特征、性质及其变化的综合性探测技术。 戈壁滩遥感影像 戈壁滩遥感影像 遥感的基本概念 遥感技术...
学习笔记整理,里面简单介绍了反射的概念及应用相关。
本文实例讲述了PHP进阶学习之反射基本概念与用法。分享给大家供大家参考,具体如下: 一、前言 Reflection(反射)是Java程序开发语言的特征之一,它允许运行中的Java程序对自身进行检查,或者说“自审”,并能直接...
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。
本书全面介绍了反射的概念及其相关应用技术,内容包括使用动态绑定的原因以及Reflection API支持它的方式;检测程序集类等元数据;自由加载程序集并创建对象和调用方法;利用反射修改对象数据;使用属性控制编译过程...
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和...这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。其中LEAD/LEAD++ 、OpenC++ 、MetaXa和OpenJava等就是基于反射机制的语言。...
介绍反射的概念及初步的应用,有实例.
代理(Proxy)可以拦截并改变 JS 引擎的底层操作,如数据读取、属性定义、函数构造等一系列操作。ES6 通过对这些底层内置...如果你对些代理&反射的概念比较困惑的话,可以直接看后面的应用示例,最后再重新看这些定义
对于任意一个对象,都能够调用它的任意一个方法,常见的应用如下 逆向代码 ,例如反编译 与注解相结合的框架 例如Retrofit 单纯的反射机制应用框架 例如EventBus 2.x 动态生成类框架 例如Gson Java高级程序设计实战...
一个关于反射的简单示例。可以从理解反射的概念开始,结合示例,分析反射的应用范围。很快就可以真正理解反射机制了。
一个VS 2005下执行成功的关于反射的例子。有助于提高学习反射的概念和应用!附带数据!
说到反射,实际上包含两个概念: 检视 introspection 判断类、方法是否存在,父子类关系,调用关系等,检视的函数文档 反射 Reflection 获取类里的方法、属性,注释等,反射类的文档 PHP官方文档写得很清晰了,...