美文网首页
Java 反射机制

Java 反射机制

作者: nxiangbo | 来源:发表于2018-08-10 20:17 被阅读0次

本篇文章,翻译自Java Reflection Tutorial

什么是反射?为什么要使用反射?如何用它?

什么是反射

在JVM中,当一个程序需要在运行时修改或者检测应用运行的行为时,则需要使用反射。反射的概念容易和自我检查(introspection)相混淆。wiki上关于反射与自我检查的定义如下,

  1. 自我检查(introspection):能够在运行时检测对象类型属性.
  2. 反射(reflection):能够在运行时检测修改对象的结构行为.

从上述定义可知,自我检查是反射的子集。有些语言是支持自我检查,但是不支持反射, 例如C++。

java反射机制

自我检查的例子:instanceof操作检查对象是否属于某个类。

    if(obj instanceof Dog){
        Dog d = (Dog)obj;
        d.bark();
    }

反射的例子:Class.forName()方法返回与给定的类名的类关联的Class对象。forName方法可以使得这个类实例化。

    // with reflection
    Class<?> c = Class.forName("classpath.and.classname");
    Object dog = c.newInstance();
    Method m = c.getDeclaredMethod("bark", new Class<?>[0]);
    m.invoke(dog);

在Java中,反射的功能要比自我检查多,因为自我检查不能修改对象的结构。

为什么需要反射

反射有以下用途:

  • 在运行时,检查对象所属的类
  • 在运行时,构造一个类的对象
  • 在运行时,检查一个类的域和方法
  • 在运行时,调用类的任何方法
  • 改变构造器、方法和域的访问标志
  • 等等...

反射是框架的基本方法。
例如, JUnit使用反射区查找含有@Test注解的方法,并且在运行单元测试时,调用这些方法。
对于web框架,产品开发者定义他们自己的接口和类的实现,并且将这些接口和类放入配置文件。使用反射,可以快速的,动态的初始化这些类。
例如,Spring使用这样的bean配置文件,

    <bean id="someID" class="com.programcreek.Foo">
        <property name="someField" value="someValue" />
    </bean>

当Spring上下文处理这个<bean>元素时,它将使用Class.forName(String className)和”com.programcreek.Foo“字符串作为参数去实例化这个类。然后,它将再次使用反射,get属性的值和set属性的值。

这种机制也被用于Servlet 框架中。

    <servlet>
        <servlet-name>someServlet</servlet-name>
        <servlet-class>com.programcreek.WhyReflectionServlet</servlet-class>
    <servlet>

如何使用反射

例1:获取对象的类名。

    package myreflection;
    import java.lang.reflect.Method;
     
    public class ReflectionHelloWorld {
        public static void main(String[] args){
            Foo f = new Foo();
            System.out.println(f.getClass().getName());         
        }
    }
     
    class Foo {
        public void print() {
            System.out.println("abc");
        }
    }

输出

    myreflection.Foo

例2:调用未知类型对象的方法
对于下面的例子,考虑对象的类型是未知的。通过使用反射,这段代码可以使用这个对象,并且如果这个对象有名为“print”的方法,那么就调用print()方法。

    package myreflection;
    import java.lang.reflect.Method;
     
    public class ReflectionHelloWorld {
        public static void main(String[] args){
            Foo f = new Foo();
     
            Method method;
            try {
                method = f.getClass().getMethod("print", new Class<?>[0]);
                method.invoke(f);
            } catch (Exception e) {
                e.printStackTrace();
            }           
        }
    }
     
    class Foo {
        public void print() {
            System.out.println("abc");
        }
    }

输出:

    abc

例3:从Class实例中创建对象

    package myreflection;
 
    public class ReflectionHelloWorld {
        public static void main(String[] args){
            //create instance of "Class"
            Class<?> c = null;
            try{
                c=Class.forName("myreflection.Foo");
            }catch(Exception e){
                e.printStackTrace();
            }
     
            //create instance of "Foo"
            Foo f = null;
     
            try {
                f = (Foo) c.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }   
     
            f.print();
        }
    }
     
    class Foo {
        public void print() {
            System.out.println("abc");
        }
    }

例4:获取构造方法,并且创建实例

    package myreflection;
 
    import java.lang.reflect.Constructor;
     
    public class ReflectionHelloWorld {
        public static void main(String[] args){
            //create instance of "Class"
            Class<?> c = null;
            try{
                c=Class.forName("myreflection.Foo");
            }catch(Exception e){
                e.printStackTrace();
            }
     
            //create instance of "Foo"
            Foo f1 = null;
            Foo f2 = null;
     
            //get all constructors
            Constructor<?> cons[] = c.getConstructors();
     
            try {
                f1 = (Foo) cons[0].newInstance();
                f2 = (Foo) cons[1].newInstance("abc");
            } catch (Exception e) {
                e.printStackTrace();
            }   
     
            f1.print();
            f2.print();
        }
    }
     
    class Foo {
        String s; 
     
        public Foo(){}
     
        public Foo(String s){
            this.s=s;
        }
     
        public void print() {
            System.out.println(s);
        }
    }

输出:

    null
    abc

此外,你可以使用Class实例去获得该类实现的接口,父类,声明的域等等。

例5:通过反射,改变数组的大小

    package myreflection;
     
    import java.lang.reflect.Array;
     
    public class ReflectionHelloWorld {
        public static void main(String[] args) {
            int[] intArray = { 1, 2, 3, 4, 5 };
            int[] newIntArray = (int[]) changeArraySize(intArray, 10);
            print(newIntArray);
     
            String[] atr = { "a", "b", "c", "d", "e" };
            String[] str1 = (String[]) changeArraySize(atr, 10);
            print(str1);
        }
     
        // change array size
        public static Object changeArraySize(Object obj, int len) {
            Class<?> arr = obj.getClass().getComponentType();
            Object newArray = Array.newInstance(arr, len);
     
            //do array copy
            int co = Array.getLength(obj);
            System.arraycopy(obj, 0, newArray, 0, co);
            return newArray;
        }
     
        // print
        public static void print(Object obj) {
            Class<?> c = obj.getClass();
            if (!c.isArray()) {
                return;
            }
     
            System.out.println("\nArray length: " + Array.getLength(obj));
     
            for (int i = 0; i < Array.getLength(obj); i++) {
                System.out.print(Array.get(obj, i) + " ");
            }
        }
    }

输出:

    Array length: 10
    1 2 3 4 5 0 0 0 0 0 
    Array length: 10
    a b c d e null null null null null 

总结

上面代码展示了Java反射的一小部分使用方法,更详细的介绍,参考这里

相关文章

  • Java反射机制入门

    Java反射机制入门 一、什么是反射 JAVA反射机制(The JAVA reflection mechanism...

  • 反射之一

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • 反射之二

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • Java基础之反射

    Java基础之—反射(非常重要)Java中反射机制详解Java进阶之reflection(反射机制)——反射概念与...

  • 反射之三

    总结内容源自以下文章 粗浅看java反射机制 反射机制应用实践 谈谈java反射机制 Java Reflectio...

  • java反射机制

    java的反射机制 1 JAVA的反射机制是什么?反射机制能做什么?反射机制的优点与缺点2 认识 Class...

  • Java中反射的用途

    Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在。灵活掌握Java反射机制,对大家以后学习框...

  • Chapter 13 . 反射机制

    阅读原文 Chapter 13 . 反射机制 13.1 Java反射机制研究及应用 Java Reflection...

  • 详解Java反射机制(Reflection)

    详解Java反射机制(Reflection) 反射机制的作用 JAVA反射机制是在运行状态中,对于任意一个类,都能...

  • Java 反射机制

    [1]. java反射详解[2]. Java Reflection(反射机制)详解[3]. 深入理解Java类型...

网友评论

      本文标题:Java 反射机制

      本文链接:https://www.haomeiwen.com/subject/cuilbftx.html