java反射

Java反射API详解

一:获得Class对象

获取Class对象的三种方式
Class类和一般类不同,不能通过new来实例对象,它的实例对象就是类在内存中的字节码,所以Class类的实例过程就是类获取字节码的过程。

1、调用某个类的 class 属性获取 Class 对象
    如:Date.class 会返回 Date 类对应的 Class对象(其实就是得到一个类的一份字节码文件);
2、使用 Class 类的 forName(String className)静态方法,className 表示全限定名
    如:Class.forName("java.lang.String")
3、调用某个对象的 getClass()方法。该方法属于 Object 类
    如:new Date().getClass();

九个预定义Class实例对象:八个基本数据类型,void

Class<?> in1 = int.class;  //int
Class<?> in2 = Integer.class;  //class java.lang.Integer
//包装类都有一个常量TYPE,用来表示其基本数据类型的字节码
Class<?> in3 = Integer.TYPE;  //int

System.out.println(in3 == in1);//true
System.out.println(in3 == in2);//false

//数组类型的 Class 实例对象:
Class<String[]> s = String[].class;
Class<int[]> i = int[].class;

二:利用 Class 对象获取类的属性信息

Class clazz = Class.forName("java.lang.String");
System.out.println(clazz.getPackage());     //包名package java.lang, Java Platform API Specification, version 1.7
System.out.println(clazz.getName());        //全限定名java.lang.String
System.out.println(clazz.getSimpleName());  //类的简称String
System.out.println(clazz.getSuperclass());  //父类class java.lang.Object
System.out.println(clazz.getInterfaces());  //接口数组[Ljava.lang.Class;@4a0b1298
for (Class cla : clazz.getInterfaces()) {  
    System.out.println(cla);
    //interface java.io.Serializable  
    //interface java.lang.Comparable
    //interface java.lang.CharSequence
}

三:利用 Class 对象获取构造方法 Constructor

Constructor<T> getConstructor(Class<?>... parameterTypes)
根据构造函数的参数,返回一个具体的具有public属性的构造函数;
如:Constructor constructor = String.class.getConstructor(StringBuffer.class);
    String str = (String)constructor.newInstance(new StringBuffer("abc"));

Constructor<?>[] getConstructors()
返回所有具有public属性的构造函数数组;
如:Constructor[] constructors = Class.forName("java.lang.String").getConstructors();

Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性,和访问权限无关);

Constructor<?>[] getDeclaredConstructors()
返回该类中所有的构造函数数组(不分public和非public属性,和访问权限无关);

四:利用 Class 对象获取成员方法 Method

Method getMethod(String name, Class<?> ... parameterTypes)
根据方法名和参数,返回该 Class 对象表示类和其父类的指定的 public 方法;
如:Method charAt = String.class.getMethod(“charAt”,int.class)Method[] getMethods():
返回该 Class 对象表示类和其父类的所有 public 方法;

Method getDeclaredMethod(String name, Class<?>... parameterTypes)
根据方法名和参数,返回该 Class 对象表示类的指定的方法。和访问权限无关,但不包括继承的方法;

Method[] getDeclaredMethods(): 
获得类所有的方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法;

五:利用 Class 对象获取成员变量 Field

Field getField(String name)  
根据变量名,返回一个具体的具有public属性的成员变量

Field[] getFields()  
返回具有public属性的成员变量的数组

Field getDeclaredField(String name) 
根据变量名,返回一个成员变量(不分public和非public属性,和访问权限无关)

Field[] getDelcaredFields() 
返回所有成员变量组成的数组(不分public和非public属性,和访问权限无关)

例:获取和更改某个对象的私有字段

Class<Student> clz = Student.class;
Student stu = clz.newInstance("Tom",22);  //创建Student的实例对象

Field f1 = clz.getDeclaredField("name");  //获取Student类的name变量
f1.setAccessible(true);  //将name设置成可访问的
Object obj = f1.get(stu);  //从stu对象上获取name属性的值
f1.set(stu, "Jim");  //修改stu对象的name属性值为Jim

Field f2 = clz.getDeclaredField("age");  //获取Student类的name变量
f2.setAccessible(true);  //将age设置成可访问的
int age = f2.getInt(stu);  //从stu对象上获取age属性的值
f2.set(stu, 21);  //修改stu对象的age属性值为21

六:利用 Class 对象获取泛型信息

Class<Student> clz = Student.class;

Field f = clz.getDeclaredField("map");  //获取Student类的map变量

// Class<?> getType() 返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。
Class cl = f.getType();  //interface java.util.Map

//Type getGenericType() 返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型(包含泛型的类型)。
Type t = f.getGenericType();  //java.util.Map<java.lang.String, java.lang.Integer>

//Type这个类里面没有任何方法,所以需要调用子类的方法,大类型转到小类型,需要强转!
ParameterizedType pt = (ParameterizedType)t;

/**
* Type[] getActualTypeArguments()
    返回泛型参数类型
* Type getOwnerType()
    返回 Type 对象,表示此类型是其成员之一的类型。
* Type getRawType()
    返回被泛型限制的变量的类型
*/
t = pt.getRawType();  //interface java.util.Map
Type[] ts = pt.getActualTypeArguments();
for (Type type : ts) {
    System.out.println(type);
    //class java.lang.String
    //class java.lang.Integer
}

七:利用 Class 对象获取注解信息

//自定义注解类
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface MyAnnotation {
    int value();
}

//使用注解类
public class MyBean {

    @MyAnnotation(20)
    private int value;

    @Override
    public String toString() {
        return String.valueOf(value);
    }
}

//反射注解
public static void main(String[] args) {
       try {
           Field field = MyBean.class.getDeclaredField("value");//获取变量value
           field.setAccessible(true);//将value设置成可访问的
           if(field.isAnnotationPresent(MyAnnotation.class)){//判断成员变量是否有注解

               MyAnnotation myAnnotation = field.getAnnotation(MyAnnotation.class);//获取定义在成员变量中的注解MyAnnotation
               int value = myAnnotation.value();//获取定义在MyBean的MyAnnotation里面value属性值
               System.out.println(value);//20

               Class<MyBean> clz = MyBean.class;
               MyBean myBean = clz.newInstance();  //创建MyBean实例对象

               field.setInt(myBean, value);//将注解的值20可以赋给成员变量
               System.out.println(myBean);//验证结果20
           }
       } catch (Exception e) {
           e.printStackTrace();
       };
   }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值