zoukankan      html  css  js  c++  java
  • [Java] Java反射

    首先推荐三个十分有趣的网站:

    http://www.programcreek.com/simple-java/

    http://tutorials.jenkov.com/

    http://www.meetup.com/

    Java Reflection makes it possible to inspect classes, interfaces, fields and methods at runtime, without knowing the names of the classes, methods etc. at compile time. It is also possible to instantiate new objects, invoke methods and get/set field values using reflection.

    Classes

    From the classes you can obtain information about: 

    在做任何操作前,你必须获取java.lang.Class对象。Java中所有类型,包括基础类型,数组,都有关联的class对象。获取class的方式

    1)如果在编译时知道类名: MyClass.class

    2) 如果编译时不知道类名但是在运行时能获取字符串: Class.forName("...'')    //如果在classpath中找不到,会抛出ClassNotFoundException

    Class Name

    String className = aClass.getName();   // 获取类全名,包括包名
    String className = aClass.getSimpleName();  //不包括包名

    Class Modifiers

    可以通过class对象访问类的修饰符,修饰符有:public,private,static等等。

    int modifiers = aClass.getModifiers(); // int 类型
    Modifier.isAbstract(int modifiers); //通过Modifier.XXX查看

    Package Name

    Package package = aClass.getPackage();

    通过Package对象可以访问package的信息。

    Superclass

    Class superclass = aClass.getSuperclass();

    superclass对象是一个class对象。

    实现接口

    Class[] interfaces = aClass.getInterfaces();

    如果要获得类实现的所有接口,必须得递归的遍历父节点对象

    Constructors

    获取constructor对象:

    Constructor[] constructors = aClass.getConstructors();  //获得所有public
     constructors
    
    Constructor constructor = aClass.getConstructor(new Class[]{String.class}); // 获取带一个String类型参数的public constructor
    
    //如果找不到匹配的constructor,会抛出NoSuchMethodException

    获取constructor参数: 

    Class[] parameterTypes = constructor.getParameterTypes();

    实例化constructor: 

    MyObject myObject = (MyObject)constructor.newInstance("constructor-arg1");

    Methods

    只访问public方法:

      Class.getMethod(String name, Class[] parameterTypes) and Class.getMethods() 只返回 public methods。比如:

    Method method = aClass.getMethod("doSomething", new Class[]{String.class}); 
    
    //get method that takes a String as argument
    Method method = MyObject.class.getMethod("doSomething", String.class);
    Object returnValue = method.invoke(myObject, "parameter-value1"); //如果是static方法,myObject换成null

    访问private方法:

      调用 Class.getDeclaredMethod(String name, Class[] parameterTypes) or Class.getDeclaredMethods()方法。比如:

    PrivateObject privateObject = new PrivateObject("The Private Value");
    
    Method privateStringMethod = PrivateObject.class.
            getDeclaredMethod("getPrivateString", null);
    
    privateStringMethod.setAccessible(true);
    
    String returnValue = (String)
            privateStringMethod.invoke(privateObject, null);

    By calling Method.setAcessible(true) you turn off the access checks for this particular Method instance, for reflection only.

    Fields

    访问public fields:

      调用 Class.getField(String name) 和 Class.getFields()方法只返回public fields。

    访问private fields

      需要调用 Class.getDeclaredField(String name) or Class.getDeclaredFields()方法。例如:

    PrivateObject privateObject = new PrivateObject("The Private Value");
    
    Field privateStringField = PrivateObject.class.
                getDeclaredField("privateString");
    
    privateStringField.setAccessible(true);
    
    String fieldValue = (String) privateStringField.get(privateObject);

    By calling Field.setAcessible(true) you turn off the access checks for this particular Field instance, for reflection only.

    Annotations

    Annotation[] annotations = aClass.getAnnotations();

    注解是Java 5引入的新feature,是一种插入java代码中的comment或元数据。注解可以在编译期被与编译工具处理,或者在运行时被Java反射处理。

    比如:类 TheClass 有注解 @MyAnnotation 。注解的定义类似interfaces。The @ in front of the interface marks it as an annotation。

    @MyAnnotation(name="someName",  value = "Hello World")
    public class TheClass {
    }
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    
    public @interface MyAnnotation {
        public String name();
        public String value();
    }

    上面的注解定义中有两个指令(directives) :

      @Retention(RetentionPolicy.RUNTIME) means that the annotation can be accessed via reflection at runtime. If you do not set this directive, the annotation will not be preserved at runtime, and thus not available via reflection.

      @Target(ElementType.TYPE) means that the annotation can only be used ontop of types (classes and interfaces typically). You can also specify METHOD or FIELD, or you can leave the target out alltogether so the annotation can be used for both classes, methods and fields.

    Generics

    许多论坛文章说java泛型信息在编译时会被抹掉,但是这并不完全正确。运行java泛型的情况大致可以分成两类:

    1. Declaring a class/interface as being parameterizable.
    2. Using a parameterizable class.

    我们可以获取泛型函数的返回类型,参数类型,fields类型

    Arrays

    Working with arrays via Java Reflection is done using the java.lang.reflect.Array class.

    创建Arrayint[] intArray = (int[]) Array.newInstance(int.class, 3);

    访问Array: This is done via theArray.get(...) and Array.set(...) methods.

    获取Array的class对象

    Class stringArrayClass = String[].class; 
    Class intArray = Class.forName("[I"); //用于基本类型数组,类似 "I" 这种简写方式只适用于数组情况
    Class stringArrayClass = Class.forName("[Ljava.lang.String;");  //用于object数组

    动态代理*

    You create dynamic proxies using the Proxy.newProxyInstance() method. The newProxyInstance()methods takes 3 parameters:

    1. The ClassLoader that is to "load" the dynamic proxy class.
    2. An array of interfaces to implement.
    3. An InvocationHandler to forward all methods calls on the proxy to.

    例如:

    InvocationHandler handler = new MyInvocationHandler();
    MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
                                MyInterface.class.getClassLoader(),
                                new Class[] { MyInterface.class },
                                handler);

    Class Loading & reloading*

    All classes in a Java application are loaded using some subclass of java.lang.ClassLoader

    动态class加载:动态加载类很容易,我们只需要获得一个 ClassLoader 然后调用 loadClass()方法

    public class MainClass {
    
      public static void main(String[] args){
    
        ClassLoader classLoader = MainClass.class.getClassLoader();
    
        try {
            Class aClass = classLoader.loadClass("com.jenkov.MyClass");
            System.out.println("aClass.getName() = " + aClass.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    动态class重加载:重加载比较复杂点,因为java加载一个类会检查类是否被加载。使用java buildin classLoader不可能实现重载。要实现这点,必须自己实现classloader。

    TODO

    
    


  • 相关阅读:
    pythondjango框架电商项目用户模块开发_20191117
    pythondjango项目基础haystack&whoosh&jieba_20191124
    django项目总结_20191128
    pythondjango框架电商项目商品模块开发_20191124
    pythondjango框架电商项目购物车模块开发_20191125
    pythondjango框架电商项目首页开发_20191122
    pythondjangofastdfs+Nginx的安装和配置_20191122
    git基本操作长期维护
    pythondjango项目Linux系统建立django项目_20191117
    django框架基础框架介绍长期维护
  • 原文地址:https://www.cnblogs.com/qingwen/p/5213548.html
Copyright © 2011-2022 走看看