文档章节

JAVA基础之反射

克温s
 克温s
发布于 2015/11/12 23:14
字数 898
阅读 14
收藏 0

反射库提供了一个非常丰富且精心设计的工具集。

能够分析类能力的程序叫反射,反射机制可以用来:

1)在运行中分析类的能力

2)在运行中查看对象,例如,编写一个toString方法供所有类使用

3)实现通用的数组操作代码

4)利用Method对象,这个对象很像C++中的函数指针。

使用它的人员主要是工具构造者。

1,Class类,java.lang.Class

在程序运行期间,Java运行时系统始终为所有对象维护一个被称为运行时的类型标识,这个信息可以跟踪每个对象所属的类,JVM利用运行时类型信息选择相应的方法执行。

可以通过专门的Java类访问这些信息,保存这些信息的类被称为Class。(Class保存对象运行时的类信息)

Date d = new Date();
Class cls = d.getClass();
System.out.println(cls.getName());

Class cls = Class.forName("java.util.Date");
Object obj = cls.newInstance();//创建一个对象,newInstance调用默信构造,没有则报错
forName只有在ClassName是类名或接口名时才能够执行。

2,Throwable是Exception的超类;

3,利用反射分析类的能力:

    java.lang.reflect包中有三个类Field,Method,Constructor分别用于描述类的域、方法、构造器。

    getName用来方法名称,

    Field的getType用来返回Class的类型,

    getModifiers返回Method、Constructor的访问修饰符,如:public private final,将返回整数。

    Class类中的getFields、getMethods、getConstructors方法将分别返回类提供的public的,域、方法、构造器数组和超类的。getDeclared*会返回所有的域、方法、构造,但不返回超类的。

public static void main(String[] args) {
    String name;
    if (args.length > 0) name = args[0];
    else {
        Scanner in = new Scanner(System.in);
        System.out.print("Enter class name (e.g.java.util.Date):");
        name = in.next();
    }
    try {
        //用类名产生一个运行时的类型
        Class cls = Class.forName(name);
        //父类的运行时类型
        Class supercls = cls.getSuperclass();
        //修饰符
        String modifiers = Modifier.toString(cls.getModifiers());
        if (modifiers.length() > 0) System.out.print(modifiers + " ");
        System.out.print("class " + name);
        if (supercls != null && supercls != Object.class)
            System.out.print(" extends " + supercls.getName());
        System.out.print("\n{\n");

    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    System.exit(0);
}

/**
 * 打印构造
 *
 * @param cls
 */
public static void printConstructors(Class cls) {
    Constructor[] constructors = cls.getDeclaredConstructors();
    for (Constructor c : constructors) {
        //构造方法名
        String name = c.getName();
        System.out.print("   ");
        //修饰符
        String modifiers = Modifier.toString(c.getModifiers());
        if (modifiers.length() > 0) System.out.print(modifiers + " ");
        System.out.print(name + " (");
        //参数类型
        Class[] paramTypes = c.getParameterTypes();
        for (int j = 0; j < paramTypes.length; j++) {
            if (j > 0) System.out.print(", ");
            System.out.print(paramTypes[j].getName());
        }
        System.out.println(");");
    }
}

public static void printMethods(Class cls) {
    Method[] methods = cls.getDeclaredMethods();
    for (Method m : methods) {
        Class retTeype = m.getReturnType();
        String name = retTeype.getName();
        System.out.print("   ");
        String modifiers = Modifier.toString(m.getModifiers());
        if (modifiers.length() > 0) System.out.print(modifiers + " ");
        System.out.print(retTeype.getName() + " " + name + "(");
        Class[] paramTypes = m.getParameterTypes();
        for (int j = 0; j < paramTypes.length; j++) {
            if (j > 0) System.out.print(", ");
            System.out.print(paramTypes[j].getName());
        }
        System.out.print(");");
    }
}

public static void printFields(Class cls) {
    Field[] fields = cls.getFields();
    for (Field f : fields) {
        Class type = f.getType();
        String name = type.getName();
        System.out.print("   ");
        String modifiers = Modifier.toString(f.getModifiers());
        if (modifiers.length() > 0) System.out.print(modifiers + " ");
        System.out.print(type.getName() + " " + name + ";");
    }
}

4,运行时获得,设置对象域值;反射可以访问私有域的值,设置accessible,false情况下遵循java安全控制修饰符的限定。

Employee harry = new Employee("test", 9000, new Date());
//获取运行时对象
Class cls = harry.getClass();
try {
    //获得运行时对象的域(数据)
    Field f = cls.getDeclaredField("name");
    //设置访问控制,如果不设置将受制于java的访问控制,下面就无法访问name私有域
    f.setAccessible(true);
    //获得运行时对象中域的值
    Object obj = f.get(harry);
    //设置值
    f.set(harry, "new name");
} catch (NoSuchFieldException e) {
    e.printStackTrace();
} catch (IllegalAccessException e1) {
    e1.printStackTrace();
}

5,调用任意方法,f.invoke()

    Method f = Employee.class.getMethod("getSalary", double.class);

    建议尽量少使用Method回调方法:

    1)getMethod,invoke()容易导致参数性错误;

    2)invoke调用较正常调用效率缓慢;

    3)invoke的参数,返回值都必须是Object,容易导致类型转换错误,而编译器如果错误过检查机会,只有在运行时才会出错。



© 著作权归作者所有

克温s
粉丝 2
博文 52
码字总数 19221
作品 0
东城
项目经理
私信 提问
黑马程序员--JDK1.5新特性(二)

----------------------android培训、java培训、期待与您交流!---------------------- Java反射机制定义: Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性、方法...

长平狐
2013/07/01
62
0
JVM之动态方法调用:invokedynamic

在本文的前面的姊妹篇中,介绍了Java方法调用的5种操作码中的4种。它们是Java 8和Java 9中方法调用的标准字节码形式。 于是第五个操作码invokedynamic便进入了我们的视线。简单来说,Java 7中...

01/19
0
0
好程序员大数据视频教程从零基础入门到精通

好程序员大数据视频教程从零基础入门到精通,学习大数据技术的必经之路是什么?是Hadoop吗?当然不是!如果想要踏入大数据的门槛,一个必须的条件就是我们的编程基础。熟练掌握一门编程语言是对大...

好程序员IT
04/03
27
0
【Java学习路线】新手该如何一步步的学习 Java

新手该如何一步步的学习 Java? 如果真的想学Java,最好要循序渐进,有章有法的学习它! 今天小慕就不说一些学习方法和技巧了,直接来谈每个阶段要学习的内容。 首先,给大家分享一张以 企业...

Eddie_yang
2018/11/15
2.4K
0
从 java bean 的内省到 dbutils 的应用

java bean 内省的基础 java bean 的内省,其实可以算是反射的一种基础应用,关于 java 的反射,无非就是获得对应的类、属性、方法、修饰符等的应用,对于 java 的反射探讨,可以点击参考 ja...

peiquan
2018/07/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

家庭作业——苗钰婷

2 编写一个程序,发出一声警报,然后打印下面的文本: Startled by the sudden sound, Sally shouted, "By the Great Pumpkin, what was that! #include<stdio.h>int main(){......

OSC_Okruuv
9分钟前
1
0
经典系统设计面试题解析:如何设计TinyURL(一)

原文链接: https://www.educative.io/courses/grokking-the-system-design-interview/m2ygV4E81AR 编者注:本文以一道经典的系统设计面试题:《如何设计TinyURL》的参考答案和解析为例,帮助...

APEMESH
10分钟前
1
0
2.面向对象设计原则(7条)

开闭原则 开闭原则的含义是:当应用的需求改变时,在不修改软件实体的源代码或者二进制代码的前提下,可以扩展模块的功能,使其满足新的需求。 实现方法 可以通过“抽象约束、封装变化”来实...

Eappo_Geng
12分钟前
1
0
8086汇编基础 debug P命令 一步完成loop循环

    IDE : Masm for Windows 集成实验环境 2015     OS : Windows 10 x64 typesetting : Markdown    blog : my.oschina.net/zhichengjiu    gitee : gitee.com/zhichengjiu   ......

志成就
16分钟前
1
0
使用nodeJS实现前端项目自动化之项目构建和文件合并

本文转载于:专业的前端网站➜使用nodeJS实现前端项目自动化之项目构建和文件合并 前面的话   一般地,我们使用构建工具来完成项目的自动化操作。本文主要介绍如何使用nodeJS来实现简单的项...

前端老手
30分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部