java 反射分析

来源:互联网 发布:威纶通触摸屏编程软件 编辑:程序博客网 时间:2024/05/22 03:23

java反射的基础-Class类
java程序中的各个java类,属于同一类事物,可以用一个类来描述这类事物,这个类的名字就是Class。
Class类描述了java类的名称、访问属性、类所属的包名、字段名称的列表、方法名称的列表等。
Class对象代表了某个java类的字节码文件,将硬盘中存储的类字节码文件加载到内存有3种方法:
1. 类名.class,如Class clazz1=Person.class
2. 对象.getClass(),如Class clazz2=new Person().getClass()
3. Class.forName("类名")
如Class clazz3=Class.forName("cn.itcast.Person"),必须是完整类名(加包路径),该方法会抛ClassNotFoundException异常。

Jvm只会加载一份字节码文件到内存,同一个程序中用3种不同方法获取同一个类的字节码文件得到的Class对象是同一个。

九个预定义的Class实例对象
8种基本数据类型(byte,short,int,long,char,float,double,boolean)和void也都有Class类对象,如int.class, void.class.

反射(Reflect)
反射就是把java类中的各种成分映射成相应的java类。
一个java类的组成部分:成员变量、方法、构造函数、包信息等都可以用一个个java类来表示,分别是Field、Method、Contructor、Package等,都是java.lang.reflect包中的类。
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,这些实例对象可调用Class类的方法得到,得到这些实例对象后可通过架构思想创建java类对象,使得对象中的方法。

下面通过代码演示java类中构造函数、方法和成员变量的反射方式:

import java.lang.reflect.*;
class Point{
private int x;
private int y;
public int h;
Point(int x, int y){
this.x=x;
this.y=y;
}
private Point(int x,int y, int h){
this.x=x;
this.y=y;
this.h=h;
}
private void show(){
System.out.println("x...."+x+" , "+"y...."+y);
}
}
public class ReflectDemo2{
public static void main(String[] args) throws Exception
{
String str1="wus";
//反射String类的一个带参数的构造函数
Constructor con1=String.class.getConstructor(StringBuffer.class);
//通过Constructor对象的newInstance()方法创建String对象,newInstance()方法中需传递对应参数,返回Object对象,使用返回值时需强制转换。
String str2=(String)con1.newInstance(new StringBuffer("can"));
System.out.println(str2.charAt(2));
//暴力反射Point类中的私有构造函数
Constructor con2=Point.class.getDeclaredConstructor(int.class,int.class,int.class);
//上面得到的con2所代表的构造函数仍是私有的,使用前需要强制公开其权限。
con2.setAccessible(true);
Point p1=(Point)con2.newInstance(6,7,8);

//反射String类中的charAt()方法
Method methodCharAt=String.class.getMethod("charAt",int.class);
//使用Method对象的invoke()函数执行str1的charAt()方法,这是jdk1.5中invoke()调用方式。
System.out.println(methodCharAt.invoke(str1,1));
//jdk1.4中invoke()函数调用方式
System.out.println(methodCharAt.invoke(str1, new Object[]{2}));
//暴力反射Point类中的无参私有方法,下面的null也可以不写
Method methodShow=Point.class.getDeclaredMethod("show",null);
methodShow.setAccessible(true);
methodShow.invoke(p1);

//调用Class对象的getField()方法得反射Point类中的一个公有成员变量x.
Field fieldh=p1.getClass().getField("h");
//调用Field对象的get()方法,传入具体对象,获取该对象中成员变量x的值。
System.out.println(fieldh.get(p1));
//暴力反射成员变量y
Field fieldy=p1.getClass().getDeclaredField("y");
fieldy.setAccessible(true);
System.out.println(fieldy.get(p1));
}
}
注解:
1. 通过Class对象的getConstructor()、getMethod()等方法反射类的构造函数、成员方法时,会抛出NoSuchMethodException和SecurityException,getField()等方法会抛出NoSuchFieldException和SecurityException。
2. newInstance()、invoke()和get()方法抛出IllegalAccessException和IllegalArgumentException,setAccessible()会抛出SecurityException异常。
3. 私有权限的构造函数和成员必须使用getDeclaredXXX()方法来反射,否则会报错,反射后使用前必须公开其权限。
4. Class类中也有newInstance()方法,是先反射出类的无参构造函数,再创建实例,因此使用该方法时,类中必须有无参构造函数。
5. 静态成员的反射,得到静态成员的Method或Field对象后,再调用invoke()或get()时,不用传递具体的对象参数,用null即可。
0 0
原创粉丝点击