笔记:反射

反射库提供了大量操作Java代码的工具集,以便编写能够通道操作Java代码的程序,能够分析类能力的程序称为反射(reflective)。

  1. Class

    在程序运行期间,Java运行时系统始终为所有的对象维护一个称为运行时的类型标识,这个信息跟踪着每个对象所属的类,虚拟机利用运行时类型信息选择相应的方法执行,可以通过专门的类来访问这些信息,保存这些信息的类被称为
    Class,Object
    类的getClass方法将返回一个Class类型的实例,示例代码如下:

    ??????public static
    void
    main( String[] args )

    ????????{

    ????????????????String str = "测试号";

    ????????????????Class stringClassObj = str.getClass();

    ????????????????
    ?

    ????????????????System.out.println("Str Class is "+stringClassObj.getName());

    ????????}

    可以调用静态方法
    forName
    获得类名对应得Class对象,示例代码如下:

    String className = "java.util.Date";

    Class cl = Class.forName(className);

    虚拟机为每个类型管理一个Class对象,因此可以利用
    ==
    运算符实现两个类对象得比较操作,还可以使用
    newInstance
    方法调用默认的构造函数初始化新创建的对象,示例代码如下:

    if(stringClassObj.getClass() == String.getClass()){

    ????...

    }

    ?
    ?

    String className = "java.util.Date";

    Object m = Class.forName(className).newInstance();

    如果没有默认的构造函数,则调用类对象的
    newInstance
    会抛出异常,如果希望调用构造函数来创建实例,则必须使用
    Constructor类的
    newInstance
    方法。

  2. 利用反射分析类的能力

    在Java的
    java.lang.reflect包中有三个类
    Field、Method和Constructor类,分别用于描述类的域、方法和构造器,三个类都有一个叫做getName的方法,用来返回项目的名称。Field类有一个getType方法,用来返回描述域所属类型的Class对象;Method

    Constructor类有能够报告参数类型的方法,Method类还有一个可以报告返回类型的方法,这三个类都有getModifiers的方法,返回一个整数值,用不同的位开关描述public

    static
    这样的修饰符,通过
    Modifier类的
    isPublic、isPrivate

    isFinal 来判断方法的修饰符。

    Class类中的
    getFields、getMethods和getConstructors
    方法分别返回类提供的
    public
    域、方法和构造器;getDeclareFields、getDeclareMethods

    getDeclaredConstructors
    方法将分别返回类中声明的全部域、方法和构造器,其中包括私有、保护成员,但不包括超类(基类)的成员,示例代码如下:

    public class App {

    ????public static
    void
    main(String[] args) {

    ????????Class clazz = Double.class;

    ????????Field[] fields = clazz.getFields();

    ????????Method[] methods = clazz.getMethods();

    ????????String clazzDeclare = BuildClassCode(clazz);

    ????????System.out.println(clazzDeclare);

    ????????System.out.println("{");

    ????????for (Field f : fields) {

    ????????????System.out.println(" " + BuildFieldCode(f));

    ????????}

    ?
    ?

    ????????System.out.println("");

    ????????for (Method m : methods) {

    ????????????System.out.println(" " + BuildMethodCode(m));

    ????????}

    ????????System.out.println("}");

    ????}

    ?
    ?

    ????/**

    ???? * 构建类源码

    ???? * @param clazz

    ???? * @return

    ???? */

    ????protected static <T> String BuildClassCode(Class<T> clazz) {

    ????????StringBuilder sb = new
    StringBuilder();

    ????????
    int modifiers = clazz.getModifiers();

    ?????????sb.append(Modifier.toString(modifiers) + " ");

    ?????????sb.append(clazz.getSimpleName() + " ");

    ????????
    ?

    ?????????Class superClass = clazz.getSuperclass();

    ?????????if (superClass != null && superClass != Object.class) {

    ?????????????sb.append("extends " + superClass.getSimpleName());

    ?????????}

    ????????
    ?

    ?????????Class[] superInterfaces = clazz.getInterfaces();

    ?????????if (superInterfaces != null && superInterfaces.length > 0) {

    ?????????????sb.append(" implements ");

    ????????
    ?

    ?????????????for (int j = 0; j < superInterfaces.length; j++) {

    ?????????????????sb.append(superInterfaces[j].getName());

    ????????
    ?

    ?????????????????if (j != superInterfaces.length - 1) {

    ?????????????????????sb.append(", ");

    ?????????????????}

    ?????????????}

    ?????????}????????

    ???????????????return sb.toString();

    ????}

    ?
    ?

    ????/**

    ???? * 构建公共字段域代码

    ???? * @param field

    ???? * @return

    ???? */

    ????protected static String BuildFieldCode(Field field) {

    ????????StringBuilder sb = new
    StringBuilder();

    ?
    ?

    ????????int mod = field.getModifiers();

    ????????sb.append(Modifier.toString(mod) + " ");

    ????????sb.append(field.getType().getSimpleName() + " " + field.getName() + ";");

    ?
    ?

    ????????return sb.toString();

    ????}

    ?
    ?

    ????/**

    ???? * 构建公共方法代码

    ???? * @param method

    ???? * @return

    ???? */

    ????protected static String BuildMethodCode(Method method) {

    ????????StringBuilder sb = new
    StringBuilder();

    ?
    ?

    ????????int mod = method.getModifiers();

    ????????sb.append(Modifier.toString(mod) + " ");

    ????????sb.append(method.getReturnType().getSimpleName() + " " + method.getName());

    ????????sb.append("(");

    ????????Class[] parameterTypes = method.getParameterTypes();

    ????????for (int i = 0; i < parameterTypes.length; i++) {

    ????????????Class c = parameterTypes[i];

    ????????????sb.append(c.getName());

    ?
    ?

    ????????????if (i != parameterTypes.length - 1) {

    ????????????????sb.append(", ");

    ????????????}

    ????????}

    ????????sb.append(")");

    ?
    ?

    ????????return sb.toString();

    ????}

    }

  3. 在运行时使用反射分析对象

    查看对象域的关键方法是Field类中的get方法,如果 f 是一个Field类型的对象,obj是某个包含 f 域的类对象,f.get(obj)将返回一个对象,其值为obj域的当前值,如果访问的时私有域,get方法的调用将抛出一个 IllegalAccessException 异常,反射机制默认行为受限与Java的访问控制,如果需要覆盖Java的访问控制,可以调用Field、Method和Constructor对象的setAccessible方法,示例代码如下:

    ????????Employee em = new
    Employee();

    ????????em.setName("lixue");

    ????????em.setYear(1982);

    ????????em.setMonth(12);

    ????????em.setDay(7);

    ????????
    ?

    ????????Field nameField = em.getClass().getDeclaredField("name");

    ????????// 覆盖访问控制,允许访问私有字段域

    ????????nameField.setAccessible(true);

    ????????
    ?

    ????????Object val = nameField.get(em);

    ????????System.out.println("Employee name is "+val);

  4. 使用反射编写泛型数组代码

    可以使用Array类的newInstance方法构造新数组,调用他必须提供二个参数,一个时数组的元素类型,一个是数组的长度,示例代码如下:

    Object newArray = Array.newInstance(componentType,newLength);

  5. 调用任意方法

    在Method类中有一个invoke方法,他允许调用包装在当前Method对象中的方法,invoke的方法签名是:

    Object invoke(Object obj,Object... args)

    第一个参数是隐式参数,其余的对象提供了显示参数,对于静态方法,第一个参数可以被忽略,可以设置为
    null,示例代码如下:

    ????????Method getNameMethod = em.getClass().getDeclaredMethod("getName", null);

    ????????String nameValue = (String) getNameMethod.invoke(em);

    ????????System.out.println("Employee name is "+nameValue);

    ?
    ?

?
?

时间: 2024-12-21 00:04:24

笔记:反射的相关文章

java笔记--反射机制之基础总结与详解

一.反射之实例化Class类的5种方式: java的数据类型可以分为两类,即引用类型和原始类型(即基本数据类型). 对于每种类型的对象,java虚拟机会实例化不可变的java.lang.Class对象. 它提供了在运行时检查对象属性的方法,这些属性包括它的成员和类型信息. 更重要的是Class对象是所有反射API的入口. Class类是泛型类,可以使用@SuppressWarnings("unchecked")忽略泛型或者使用Class<V>类型. 获得Class对象的5种

java笔记--反射进阶之总结与详解

一.反射进阶之动态设置类的私有域 "封装"是Java的三大特性之一,为了能更好保证其封装性,我们往往需要将域设置成私有的, 然后通过提供相对应的set和get方法来操作这个域.但是我们仍然可以用java的反射机制来 修改类的私有域,由于修改类的私有域会破坏Java"封装"的特性,故请慎重操作. 主要技术:     Field类提供有关类或接口的单个字段的信息,以及对它的动态访问权限.     访问的字段可能是一个类(静态)字段或实例字段.             常

Python 学习笔记 - 反射

Python里面反射指的是可以通过字符串在对象里面(比如一个模块)去操作(查找,删除,判断)一个成员(比如这个模块里面的函数). 比如目前所学的知识,我们需要在模块s1.py中调用一个函数f1,我们需要导入s1.py,然后才能执行f1() import s1 s1.f1() 如果一个大型软件有几百上千个函数需要调用,那么这样写起来会很累.一个简单的方法是反射. 比如一个简单的例子,从index里面调用commons commons.py #!/usr/bin/env python # -*- c

11-java学习笔记-反射

1.反射的应用场景 一.概述 反射技术: Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 二.应用场景 一个已经可以使用的应用程序,因为程序已经做好可以运行使用,不能再进行代码的加入了.而当后期我们新的功能加入程序时,该怎么做呢?就如我们的电脑一样,后期我们可能会鼠标.键盘等,所以电脑给我们预留了usb接口,只要符合这个接口规则的设备

Java学习笔记——反射

反射就是把Java类中的各种成分映射成相应的java类. Class类-->java程序中的各个java类属于同一事物,描述这类事物的Java类名就是Class. Class.forName的作用:返回类的字节码,返回的方式有两种,一种是这个类曾被加载过,则直接从JVM中返回字节码,另一种是JVM中没用这个类的字节码,得用类加载器先将字节码加载到JVM中,然后返回字节码. 得到类的字节码的三种方式1.类名.class2.对象.getClass();3.Class.forName("完整类名

Java基础笔记-反射及应用

反射: 动态获取字节码文件对象(Person.class),并对其成员进行运行. 动态获取字节码文件对象的方式: 1:任何一个对象都是由字节码文件对象创建的,所以任何一个对象都可以得到自己的字节码文件对象 那么这个功能应该定义在Object中,所以使用 getClass() 需要先new对象 2:每种数据类型都有一个 静态的class 属性,通过该属性可以得到字节码文件对象 不需要new对象,但是需要Person类存在 3:Class类提供了一个静态的forName(String str)方法

C#学习笔记 ----反射

自定义特性允许把自定义元数据与程序元素关联起来 .NET Framework允许用户定义自己的特性 编译器不能识别,但是特性应用于程序元素时,可以在编译好的程序集中用作元数据 示例: public string SocialSecurityNumber { get{ //etc. 特性类本身用一个特性 ----System.AttributeUsage特性来标记 AttributeUsage主要用于标识自定义特性可以应用到哪些类型的程序元素上 这些信息由它的第一个参数给出,该参数必选,类型是枚举

Java学习笔记--反射

待完成 http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html http://coolszy.iteye.com/blog/569846 http://www.cnblogs.com/octobershiner/archive/2012/03/18/2404751.html package com.ev

JDK动态代理和CGLIB动态代理

转载自http://www.itzhai.com/java-dong-tai-dai-li-zhi-jdk-dong-tai-dai-li-he-cglib-dong-tai-dai-li-mian-xiang-qie-mian-bian-cheng-aop-yuan-li.html 静态代理 静态代理相对来说比较简单,无非就是聚合+多态: 参考:设计模式笔记 – Proxy 代理模式 (Design Pattern) 动态代理 我们知道,通过使用代理,可以在被代理的类的方法的前后添加一些处理方

Java系列笔记(2) - Java RTTI和反射机制

目录 前言 传统的RTTI 反射 反射的实现方式 反射的性能 反射与设计模式 前言 并不是所有的Class都能在编译时明确,因此在某些情况下需要在运行时再发现和确定类型信息(比如:基于构建编程,),这就是RTTI(Runtime Type Information,运行时类型信息). 在java中,有两种RTTI的方式,一种是传统的,即假设在编译时已经知道了所有的类型:还有一种,是利用反射机制,在运行时再尝试确定类型信息. 本文主要讲反射方式实现的RTTI,建议在阅读本文之前,先了解类的加载机制(