`

Java反射教程

    博客分类:
  • java
 
阅读更多

什么是反射?反射有什么用处?

1. 什么是反射?

“反射(Reflection)能够让运行于JVM中的程序检测和修改运行时的行为。”这个概念常常会和内省(Introspection)混淆,以下是这两个术语在Wikipedia中的解释:

  1. 内省用于在运行时检测某个对象的类型和其包含的属性;
  2. 反射用于在运行时检测和修改某个对象的结构及其行为。

从它们的定义可以看出,内省是反射的一个子集。有些语言支持内省,但并不支持反射,如C++。

内省示例:instanceof 运算符用于检测某个对象是否属于特定的类。

1
2
3
4
if (obj instanceof Dog) {
    Dog d = (Dog) obj;
    d.bark();
}

反射示例:Class.forName()方法可以通过类或接口的名称(一个字符串或完全限定名)来获取对应的Class对象。forName方法会触发类的初始化。

1
2
3
4
5
// 使用反射
Class<?> c = Class.forName("classpath.and.classname");
Object dog = c.newInstance();
Method m = c.getDeclaredMethod("bark", new Class<?>[0]);
m.invoke(dog);

在Java中,反射更接近于内省,因为你无法改变一个对象的结构。虽然一些API可以用来修改方法和属性的可见性,但并不能修改结构。

2. 我们为何需要反射?

反射能够让我们:

  • 在运行时检测对象的类型;
  • 动态构造某个类的对象;
  • 检测类的属性和方法;
  • 任意调用对象的方法;
  • 修改构造函数、方法、属性的可见性;
  • 以及其他。

反射是框架中常用的方法。

例如,JUnit通过反射来遍历包含 @Test 注解的方法,并在运行单元测试时调用它们。(这个连接中包含了一些JUnit的使用案例)

对于Web框架,开发人员在配置文件中定义他们对各种接口和类的实现。通过反射机制,框架能够快速地动态初始化所需要的类。

例如,Spring框架使用如下的配置文件:

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

当Spring容器处理<bean>元素时,会使用Class.forName("com.programcreek.Foo")来初始化这个类,并再次使用反射获取<property>元素对应的setter方法,为对象的属性赋值。

Servlet也会使用相同的机制:

1
2
3
4
<servlet>
    <servlet-name>someServlet</servlet-name>
    <servlet-class>com.programcreek.WhyReflectionServlet</servlet-class>
<servlet>

3. 如何使用反射?

让我们通过几个典型的案例来学习如何使用反射。

示例1:获取对象的类型名称。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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");
    }
}

输出:

1
myreflection.Foo

示例2:调用未知对象的方法。

在下列代码中,设想对象的类型是未知的。通过反射,我们可以判断它是否包含print方法,并调用它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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");
    }
}

输出:

1
abc

示例3:创建对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package myreflection;
 
public class ReflectionHelloWorld {
    public static void main(String[] args){
        // 创建Class实例
        Class<?> c = null;
        try{
            c=Class.forName("myreflection.Foo");
        }catch(Exception e){
            e.printStackTrace();
        }
 
        // 创建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:获取构造函数,并创建对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package myreflection;
 
import java.lang.reflect.Constructor;
 
public class ReflectionHelloWorld {
    public static void main(String[] args){
        // 创建Class实例
        Class<?> c = null;
        try{
            c=Class.forName("myreflection.Foo");
        }catch(Exception e){
            e.printStackTrace();
        }
 
        // 创建Foo实例
        Foo f1 = null;
        Foo f2 = null;
 
        // 获取所有的构造函数
        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);
    }
}

输出:

1
2
null
abc

此外,你可以通过Class实例来获取该类实现的接口、父类、声明的属性等。

示例5:通过反射来修改数组的大小。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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);
    }
 
    // 修改数组的大小
    public static Object changeArraySize(Object obj, int len) {
        Class<?> arr = obj.getClass().getComponentType();
        Object newArray = Array.newInstance(arr, len);
 
        // 复制数组
        int co = Array.getLength(obj);
        System.arraycopy(obj, 0, newArray, 0, co);
        return newArray;
    }
 
    // 打印
    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) + " ");
        }
    }
}

输出:

1
2
3
4
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反射机制很小一部分的功能。如果你觉得意犹未尽,可以前去阅读官方文档

参考资料:

  1. http://en.wikipedia.org/wiki/Reflection_(computer_programming)
  2. http://docs.oracle.com/javase/tutorial/reflect/
分享到:
评论

相关推荐

    JAVA反射教程有代码

    本教程将深入探讨Java反射的基本概念和实践应用。 1. **Java反射基础** - **Class对象**:每个类在Java运行时都有一个对应的Class对象,可以通过`Class.forName()`或对象的`getClass()`方法获取。 - **构造器**:...

    完整版 Java高级教程 Java语言程序设计 第5章 Java反射(共9页).ppt

    完整版 Java高级教程 Java语言程序设计 第5章 Java反射(共9页).ppt 完整版 Java高级教程 Java语言程序设计 第6章 常用设计模式(共25页).ppt 完整版 Java高级教程 Java语言程序设计 第7章 Java注解(共10页).ppt...

    JAVA反射详细讲解

    Java反射详解 在Java编程语言中,反射是一个强大的工具,它允许程序在运行时检查类、接口、字段和方法的信息,甚至能够在运行时创建和访问这些对象。这种能力使得Java成为一种动态语言,增强了代码的灵活性和可扩展...

    java教程ppt,讲述了java reflect.,对大家应该很有帮助

    Java反射机制是Java编程语言中的一...本Java反射教程的PPT将详细介绍这些概念,并通过实例演示如何使用反射,对于学习和理解Java反射机制将大有裨益。请参考`java_base10_reflect.ppt`来深入学习这一强大而复杂的主题。

    Java 反射-动态代理

    Java反射和动态代理是Java编程中的重要特性,它们在实现高度灵活...在提供的压缩包文件"JavaReflect"中,可能包含了关于Java反射和动态代理的示例代码和教程,通过学习和实践这些内容,你可以更深入地掌握这两种技术。

    Java-Java反射与泛型教程

    Java 反射与泛型教程 资源为视频教程资源 希望对你的 Java 学习有所帮助。

    Java反射机制视频教程

    这个"Java反射机制视频教程"可能是为了帮助开发者深入理解这一概念,尽管描述中提到视频质量可能不尽如人意。在Java中,反射主要用在以下场景: 1. **动态加载类**:在程序运行时,根据用户输入或特定条件动态加载...

    Java反射总结:入门进阶到使用

    未经允许禁止转载,转载请联系作者。 目录 一 反射(Reflect)初识 二 反射的基本使用和常用API 2.1 基本使用 2.2 反射获取一个对象的步骤 2.3 反射常用API 2.3.1 获取反射中的Class对象 ...4.1 Java反射机制的起源

    java反射入门

    Java反射是Java语言的一个重要特性,它允许程序在运行时检查和操作类、接口、对象等的内部结构。反射机制使得代码能够动态地获取类的信息并调用其方法,增加了程序的灵活性和可扩展性。以下将详细介绍Java反射中的几...

    java反射机制教程

    Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、对象等的内部信息,包括但不限于类名、方法名、参数类型等。这一机制的核心在于Class类,它代表了Java运行时的类信息。通过...

    2020老杜最新Java零基础进阶视频教程-反射机制课件

    本Java视频教程适合有一定编程语言基础的学员观看,在本Java视频教程中讲解了Java面向对象、异常、数组、常用类、集合、IO流、线程、反射机制。该视频教程基于Java13进行讲解,Java13是目前Java最新版本。视频中讲师...

    JAVA反射,一定要学的

    这是一个小型的JAVA反射学习教程,权威啊 学习它可以让你更轻松处理复杂问题

    Java SE编程入门教程 java反射机制(共16页).pptx

    Java SE编程入门教程 java反射机制(共16页).pptx Java SE编程入门教程 java泛型(共11页).pptx Java SE编程入门教程 java封装继承多态(共56页).pptx Java SE编程入门教程 java集合(共38页).pptx Java SE编程...

    java基础教程ppt

    这份"java基础教程ppt"提供了一个全面的学习资源,帮助初学者掌握Java编程的基本概念和语法。 在Java的基础教程中,通常会包含以下几个核心知识点: 1. **Java简介**:介绍Java的历史、特点以及其在软件开发中的...

    java反射机制图文教程

    java反射机制

    完整版 Java高级教程 Java语言程序设计 全套PPT课件资源集合 共9个章节 含各类辅导资料.rar

    完整版 Java高级教程 Java语言程序设计 第5章 Java反射(共9页).ppt 完整版 Java高级教程 Java语言程序设计 第6章 常用设计模式(共25页).ppt 完整版 Java高级教程 Java语言程序设计 第7章 Java注解(共10页).ppt...

    java反射机制讲解

    Java反射机制是Java语言提供的一种强大的能力,它允许我们在运行时检查类的信息并动态地创建和操作对象。这种机制使得程序具有更高的灵活性和扩展性,尤其是在框架开发中有着广泛的应用。 首先,我们要理解反射的...

    完整版 Java高级教程 Java语言程序设计 第7章 Java注解(共10页).ppt

    完整版 Java高级教程 Java语言程序设计 第5章 Java反射(共9页).ppt 完整版 Java高级教程 Java语言程序设计 第6章 常用设计模式(共25页).ppt 完整版 Java高级教程 Java语言程序设计 第7章 Java注解(共10页).ppt...

    完整版 Java高级教程 Java语言程序设计 第4章 Java泛型(共10页).ppt

    完整版 Java高级教程 Java语言程序设计 第5章 Java反射(共9页).ppt 完整版 Java高级教程 Java语言程序设计 第6章 常用设计模式(共25页).ppt 完整版 Java高级教程 Java语言程序设计 第7章 Java注解(共10页).ppt...

Global site tag (gtag.js) - Google Analytics