Java反射机制

一. 什么是反射机制?
什么是反射?以镜子为例,一束光照射到镜子上,会有反射行为发生,所以反射是对已经存在事物的一种响应。在Java中就是在运行状态下,可以动态的获取某个类或对象的方法和属性。
二. 反射可以做什么?
  • 动态的构造类
  • 动态的调用对象的方法,包括判断对象的属性,例如是不是数组等
  • 动态代理
三. 如何实例化Class对象?
     有三种实例化Class对象的方式:
  1. Class<?> clazz = Class.forName("包路径+类名")。以下为Class类源码,它有两个构造函数,第一个是常用的。
@CallerSensitive
  public static Class<?> forName(String paramString)
    throws ClassNotFoundException
  {
    Class localClass = Reflection.getCallerClass();
    return forName0(paramString, true, ClassLoader.getClassLoader(localClass), localClass);
  }

  @CallerSensitive
  public static Class<?> forName(String paramString, boolean paramBoolean, ClassLoader paramClassLoader)
    throws ClassNotFoundException
  {
    Class localClass = null;
    SecurityManager localSecurityManager = System.getSecurityManager();
    if (localSecurityManager != null)
    {
      localClass = Reflection.getCallerClass();
      if (VM.isSystemDomainLoader(paramClassLoader))
      {
        ClassLoader localClassLoader = ClassLoader.getClassLoader(localClass);
        if (!VM.isSystemDomainLoader(localClassLoader)) {
          localSecurityManager.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
        }
      }
    }
    return forName0(paramString, paramBoolean, paramClassLoader, localClass);
  }


  1. Class<?> clazz = 对象名.getClass();
  2. Class<?> clazz = 类名.class;
四. Class类主要包含哪些方法?
  1. getName():返回包名+类名 
  2. getFields()/getDeclaredFields():返回public/全部属性
  3. getMethods()/getDeclaredMethods() :返回public/全部方法
  4. getConstructors()/getConstructor(Class<?>... paramVarArgs) :返回public/特种参数类型的构造方法
  5. getSuperclass():返回父类
  6. isArray():是否数组
  7. isInterface():是否接口
  8. isPrimitive():是否原始类型(boolean、char、byte、short、int、long、float、double)
  9. newInstance():返回一个对象,该对象由不带参数的构造方法创建。注意于Class.forName("")的区别,Class.forName("")返回的是类。
      ...  
五. 怎么用?
  • 通过反射修改属性
          直接看例子:
public class TestReflectForField {
      //私有属性
      private String testField = null;

      public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("com.tddy.reflect.TestReflect");
        Object object = clazz.newInstance();
        //getDeclaredField获取指定属性,如果不清楚它有什么属性,可以用getDeclaredFields()获取所有属性
        Field field = clazz.getDeclaredField("testField");
        field.setAccessible(true);
        field.set(object, "change field!");
        System.out.println(field.get(object));
    }

      public String getTestField() {
            return testField;
      }
      public void setTestField(String testField) {
            this.testField = testField;
      }
}


  • 通过反射调用方法
     直接看例子:

public class TestReflectMethod {
      public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("com.tddy.reflect.TestReflectMethod");
        Object object = clazz.newInstance();
        //获取"method1()"方法,如果不知道有什么方法,可以通过getDeclaredMethods()获取所有方法
        Method method = clazz.getMethod("method1");
        //执行
        method.invoke(object);
        /*
         * 跟上面相同,只需要注意参数
        method = clazz.getMethod("method2", String.class);
        method.invoke(clazz.newInstance(), "TestReflectMethod");
        */
    }

    public void method1() {
        System.out.println("called method1");
    }

    public void method2(String str) {
        System.out.println("called method2 and the str = " + str);
    }
}
六. java.lang.reflect包轻解读
在JDK中,反射所用的类和接口主要有Field, Method, Constructor, Array, Modifier,Proxy, InvocationHandler等,除核心类Class位于java.lang包中,其他常用类或接口都位于java.lang.reflect包(jre/rt.jar),有兴趣可以去阅读一下源码,这里只是简单的解释一下这些类或接口分别能干什么。
  1. Field类:getFields()/getDeclaredFields()返回Field数组。
  2. Method类:getMethods()/getDeclaredMethods()返回Method数组
  3. Constructor类:getConstructors()/getConstructor(Class<?>... paramVarArgs)返回Constructor<?>[]数组
  4. Array类:数组的反射涉及到同维数组和不同维数组。同类型元素的同维数组,他们的Class相同,他们有共同的父类Object。原始类型数组(需要转换成对应的包装类)不能直接转换为Object类型数组。
  5. Modifier类:类、变量或方法的修饰符,修饰符集被表示为整数。以下为Modifier类源码:
  public static final int PUBLIC = 1;
  public static final int PRIVATE = 2;
  public static final int PROTECTED = 4;
  public static final int STATIC = 8;
  public static final int FINAL = 16;
  public static final int SYNCHRONIZED = 32;
  public static final int VOLATILE = 64;
  public static final int TRANSIENT = 128;
  public static final int NATIVE = 256;
  public static final int INTERFACE = 512;
  public static final int ABSTRACT = 1024;
  public static final int STRICT = 2048;
  static final int BRIDGE = 64;
  static final int VARARGS = 128;
  static final int SYNTHETIC = 4096;
  static final int ANNOTATION = 8192;
  static final int ENUM = 16384;
  static final int MANDATED = 32768;
  private static final int CLASS_MODIFIERS = 3103;
  private static final int INTERFACE_MODIFIERS = 3087;
  private static final int CONSTRUCTOR_MODIFIERS = 7;
  private static final int METHOD_MODIFIERS = 3391;
  private static final int FIELD_MODIFIERS = 223;
  private static final int PARAMETER_MODIFIERS = 16;
  static final int ACCESS_MODIFIERS = 7;
以下为动态代理:
  1. Proxy类和InvocationHandler接口
     关于动态代理,实际工作中可能用到的比较少,但是如果你使用框架,例如Spring, SpringMVC等,它的一个主要思想是AOP和IOC,其中AOP就是Java的动态代理机制。
     分享2篇文章供大家参考:
  1. http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/
  2. http://www.cnblogs.com/xiaoluo501395377/p/3383130.html
七. Java类加载器
     Java中默认的类加载器是AppClassLoader,它可以加载classpath下指定的类,在读取配置文件时经常使用。
      深入了解类加载器请参考:   https://www.ibm.com/developerworks/cn/java/j-lo-classloader/




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值