Java反射机制

来源:互联网 发布:淘宝卖家骂人怎么投诉 编辑:程序博客网 时间:2024/06/03 23:44
前言:由于最近有换工作的打算,所以顺便整理了一下之前记得笔记,我觉得可能会对大家有用的笔记会陆续贴出来。温故而知新,同时也送给需要的朋友,有不对的地方欢迎指正。

一. 什么是反射机制?
我按照字面的理解先解释一下,反射是对已经存在事物的一种响应。在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/

直接从Evernote粘过来的,有点乱。


0 0
原创粉丝点击