反射

一、什么是反射

Java 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”。

反射用在 Java 身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的 classes。反射(Reflection)机制是 JAVA 成为动态语言的一个关键特性。

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。(Reflection)

二、面向对象扩展

前面讲的面向对象的概念中有类和对象的概念。类是用来描述对象的,对象是类的实例。

类描述的是其对象所共有的属性和方法。

根据面向对象的核心思想,Java将一切都看做是对象(everything is an object)

那么,类是不是也可以看做是一种对象?这种对象由谁来描述?这种对象共有的属性和方法是什么?

三、实现反射的核心类和对象

Java API中的Class类是用来实现反射的最重要的功能类。

类的字节码文件(*.class)是实现反射的核心对象。

Class就是用来描述所有的字节码文件,将字节码文件当做是对象。通过操作字节码文件对象来获得该类中的属性、方法、构造等信息。

四、Java反射的功能

在运行中动态获取对象及其类的信息。

--可以获取正在运行中的类的属性信息。

--可以获取正在运行中的类的方法信息。

--可以获取正在运行中的类的构造信息。

--可以获取正在运行中的类的访问修饰符。

主要有:Class对象,类名,修饰符,包信息,父类,实现的接口,构造器,方法,属性,注解。

五、实现反射的一些类

java.lang.Class            该类的对象为一份字节码文件(.class)

java.lang.reflect.Field       该类描述相关类的属性信息

java.lang.reflect.Method    该类描述相关类的方法信息

java.lang.reflect.Constructor 该类描述相关类的构造器信息

java.lang.reflect.Modifier    该类描述相关类的访问修饰符信息

Array类   提供了动态创建数组,以及访问数组的元素的静态方法。

六、三种获取字节码对象的方式

1. 对象名.getClass()

2. Class.forName(类全限定名字符串)

3. 类型名.class

七、获取类信息的方法

1. 获取类的构造器

Class类的方法:

getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此                                               Class 对象所表示的类的指定公共构造方法。

getConstructors() 返回一个包含某些 Constructor 对象的数组,这些对象反映此                                                  Class 对象所表示的类的所有公共构造方法。

getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该                                             对象反映此 Class 对象所表示的类或接口的指定构造方法。

getDeclaredConstructors()  返回 Constructor 对象的一个数组,这些对象反映此                                                  Class 对象表示的类声明的所有构造方法。

Constructor类的方法:

setAccessible(boolean flag)  将此对象的 accessible 标志设置为指示的布尔值。

可以改变该对象的访问权限。

newInstance(Object... initargs)  使用此 Constructor 对象表示的构造方法来创建该                             构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

2. 获取访问修饰符

Class类的方法:

getModifiers() 返回此类或接口以整数编码的 Java 语言修饰符。

Modifier类的方法:

toString(int mod)  返回描述指定修饰符中的访问修饰符标志的字符串。

isXXXXX(int mod)  如果整数参数包括XXXXX修饰符,则返回 true,否则返回 false。

3. 获取类的属性

Class类的方法:

getField(String name)  返回一个 Field 对象,它反映此 Class 对象所表示的类或接                                             口的指定公共成员字段。

getFields()  返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所                             表示的类或接口的所有可访问公共字段。

getDeclaredField(String name)  返回一个 Field 对象,该对象反映此 Class 对象所                                                                表示的类或接口的指定已声明字段。

getDeclaredFields()  返回 Field 对象的一个数组,这些对象反映此 Class 对象所表                                             示的类或接口所声明的所有字段。

Field类的方法:

setAccessible(boolean flag)  将此对象的 accessible 标志设置为指示的布尔值。

可以改变该对象的访问权限。

getXXXX(Object o)  获取参数对象中XXXX类型或另一个通过扩展转换可以转换为                                      XXXX类型的基本类型的静态或实例字段的值。

setXXXX(Object o, XXXX x) 将字段的值设置为指定对象上的一个XXXX型的值。

4. 获取类的方法

Class类的方法:

getMethod(String name, Class<?>... parameterTypes)  返回一个 Method 对象,它反                                    映此 Class 对象所表示的类或接口的指定公共成员方法。

getMethods()  返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对                                    象所表示的类或接口(包括那些由该类或接口声明的以及从超类                                           和超接口继承的那些的类或接口)的公共成员方法。

getDeclaredMethod(String name, Class<?>... parameterTypes)  返回一个 Method 对                             象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。

getDeclaredMethods()  返回 Method 对象的一个数组,这些对象反映此 Class 对                                               象表示的类或接口声明的所有方法,包括公共、保护、默认                                                    (包)访问和私有方法,但不包括继承的方法。

Method类的方法:

setAccessible(boolean flag)  将此对象的 accessible 标志设置为指示的布尔值。

可以改变该对象的访问权限。

getParameterTypes()  按照声明顺序返回 Class 对象的数组,这些对象描述了此                                                  Method 对象所表示的方法的形参类型。

getReturnType()  返回一个 Class 对象,该对象描述了此 Method 对象所表示的方                                    法的正式返回类型。

invoke(Object obj, Object... args) 对带有指定参数的指定对象调用由此 Method 对                                                                象表示的底层方法。

5.实现的接口

可以通过如下方式获取指定类所实现的接口集合:

Class[] interfaces= c.getInterfaces();

因为接口可以实现多继承,所以返回一个数组,得到的数组仅仅包括当前类所实现的接口,不包括父类。

6. 获得父类:

Class sc=c.getSuperclass();

仅仅是父类,但是可以通过父类继续获得父类的父类,直到Object。

7.注解:

你可以通过如下方式访问一个类的注解:

Annotation[] annotations=c.getAnnotations();

8.包信息

Package package=c.getPackage();

可以获得关于包的所有信息,例如包名,编译的版本号。

属性,构造方法,访问修饰符的例子:

package com.auuzee.reflect;

import static org.junit.Assert.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;

import org.junit.Test;

public class TestReflect {

    @Test
    public void TestAAA() {
        System.out.println("AAA");
    }

    @Test
    public void TestGetUser() {
        User user = new User(1, "拉里佩奇", 10, '男');
        System.out.println(user.getName());
    }

    @Test
    public void GetUserByReflect() {
        // 方法一:通过 对象.getClass()获得Class对象,通过getName()获得类名
        User user = new User();
        Class<User> c1 = (Class<User>) user.getClass();
        System.out.println("c1: " + c1.getName());
        System.out.println("c1: " + c1.hashCode());
        // 方法二:通过类型.class
        Class<User> c2 = (Class<User>) User.class;
        System.out.println("c2: " + c2.getName());
        System.out.println("c2: " + c2.hashCode());
        // 方法三:Class.forName(类的全限定名称字符串)
        Class<User> c3;
        try {
            c3 = (Class<User>) Class.forName("com.hpe.reflect.User");
            System.out.println("c3: " + c3.getName());
            System.out.println("c3: " + c3.hashCode());
        } catch (ClassNotFoundException e) {

            e.printStackTrace();
        }
    }

    @Test
    public void testGetConstructor() {
        Class<User> c1 = (Class<User>) User.class;
        // 获取有参构造
        try {
            Constructor cs1 = c1.getConstructor(int.class, String.class, double.class, char.class);
            System.out.println("访问修饰符是: " + Modifier.toString(cs1.getModifiers()) + " " + cs1.getName());
            try {
                User u1 = (User) cs1.newInstance(1, "张仲谋", 10, '男');
                System.out.println(u1.getName());
            } catch (InstantiationException e) {

                e.printStackTrace();
            } catch (IllegalAccessException e) {

                e.printStackTrace();
            } catch (IllegalArgumentException e) {

                e.printStackTrace();
            } catch (InvocationTargetException e) {

                e.printStackTrace();
            }

        } catch (NoSuchMethodException e) {

            e.printStackTrace();
        } catch (SecurityException e) {

            e.printStackTrace();
        }

        // 获得User类的无参构造器对象
        try {
            Constructor cs2 = c1.getConstructor(null);
            System.out.println("访问修饰符是: " + Modifier.toString(cs2.getModifiers()) + " " + cs2.getName());
            try {
                User u2 = (User) cs2.newInstance(null);
                u2.setName("刘若英");
                System.out.println(u2.getName());
            } catch (InstantiationException e) {

                e.printStackTrace();
            } catch (IllegalAccessException e) {

                e.printStackTrace();
            } catch (IllegalArgumentException e) {

                e.printStackTrace();
            } catch (InvocationTargetException e) {

                e.printStackTrace();
            }
        } catch (NoSuchMethodException e) {

            e.printStackTrace();
        } catch (SecurityException e) {

            e.printStackTrace();
        }
        // 获得User类的私有构造器对象

        try {
            Constructor<User> cs3 = c1.getDeclaredConstructor(int.class, String.class);
            System.out.println("获取私有构造方法" + Modifier.toString(cs3.getModifiers()));
            cs3.setAccessible(true);
            try {
                User u3 = cs3.newInstance(10, "周瑜");

                System.out.println("us的名字:" + u3.getName());
            } catch (InstantiationException e) {

                e.printStackTrace();
            } catch (IllegalAccessException e) {

                e.printStackTrace();
            } catch (IllegalArgumentException e) {

                e.printStackTrace();
            } catch (InvocationTargetException e) {

                e.printStackTrace();
            }

        } catch (NoSuchMethodException e) {

            e.printStackTrace();
        } catch (SecurityException e) {

            e.printStackTrace();
        }

    }

    @Test
    public void getFieldByReflect() {
        Class<User> c1 = (Class<User>) User.class;
        try {
            // 获得User类的属性
            // Field f1 = c1.getField("name");
            Field f1 = c1.getDeclaredField("name");
            f1.setAccessible(true);
            try {
                Constructor<User> cs1 = c1.getConstructor(null);
                User u1 = (User) cs1.newInstance(null);
                f1.set(u1, "李四");
                System.out.println(f1.get(u1));
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (NoSuchFieldException e) {

            e.printStackTrace();
        } catch (SecurityException e) {

            e.printStackTrace();
        }
    }
}

User:

package com.auuzee.reflect;

public class User {
    private int id;
    private String name;
    private double money;
    private char sex;

    public User() {
        super();
    }

    private User(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    public User(int id, String name, double money, char sex) {
        super();
        this.id = id;
        this.name = name;
        this.money = money;
        this.sex = sex;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

}

Java中反射的理解的更多相关文章

  1. Java中hashcode的理解

    Java中hashcode的理解 原文链接http://blog.csdn.net/chinayuan/article/details/3345559 怎样理解hashCode的作用: 以 java. ...

  2. Java中反射的三种常用方式

    Java中反射的三种常用方式 package com.xiaohao.test; public class Test{ public static void main(String[] args) t ...

  3. java中反射学习整理

    转载请注明:http://blog.csdn.net/j903829182/article/details/38405735 反射主要是指程序能够訪问.检測和改动它本身的状态或行为的一种能力. jav ...

  4. 谈谈我对Java中CallBack的理解

    谈谈我对Java中CallBack的理解 http://www.cnblogs.com/codingmyworld/archive/2011/07/22/2113514.html CallBack是回 ...

  5. Java中反射的实现方式

    所谓反射,是指在运行时状态中,获取类中的属性和方法,以及调用其中的方法的一种机制.这种机制的作用在于获取运行时才知道的类(Class)及其中的属性(Field).方法(Method)以及调用其中的方法 ...

  6. 沉淀再出发:关于java中的AQS理解

    沉淀再出发:关于java中的AQS理解 一.前言 在java中有很多锁结构都继承自AQS(AbstractQueuedSynchronizer)这个抽象类如果我们仔细了解可以发现AQS的作用是非常大的 ...

  7. java中ThrealLocal的理解

    目录 java中threadlocal的理解 一.threadlocal的生命周期和ThreadLocalMap的生命周期 二.ThreadLocal的作用 三.threadlocal示例 四.Inh ...

  8. java中threadlocal的理解

    [TOC] #java中threadlocal的理解##一.threadlocal的生命周期和ThreadLocalMap的生命周期可以吧TreadLocal看做是一个map来使用,只不过这个map是 ...

  9. 简单模拟Java中反射的应用场景

    有人说Java是一门静态语言.那么何为静态语言,动态语言又是什么? 1.动态语言 是一类在运行时可以改变其结构的语言:例如新的函数.对象.甚至代码可以 被引进,已有的函数可以被删除或是其他结构上的变化 ...

随机推荐

  1. Red hat 6.4下面的qt安装

    运行环境:Red hat 6.4 去官网下载qt5.2并且安装 当启动的时候会出现如下错误 核心载入失败: /opt/Qt5.2.0/Tools/QtCreator/lib/qtcreator/plu ...

  2. 封装ios静态库碰到的一些问题(三)

    静态库封装好以后,就存在一个问题,静态库,模拟器的静态库何真机的静态库是分开的,那么能够合并,答案是肯定的,但是必须我们手工在终端工具下执行命令合并 lipo -create Release-ipho ...

  3. The Singleton pattern

    作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 单例模式的结构 单例模式的特点: 单例类只能有一个实例. 单例类必须自己创建自己的唯一 ...

  4. linux环境下安装mongodb

    最近有用到mongodb,顺便找到了以前的指南,顺便写一篇随笔,以后或许有用到的地方. 第一步:下载mongodb的linux版本,mongodb-linux-x86_64-3.2.4.tgz(去官网 ...

  5. 大文件下载控件(down2)-示例更新-Xproer.HttpDownloader

    版权所有 2009-2016 荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/down2/i ...

  6. [UE4]AnimDynamics简介

    AnimDynamics简介 Author:Jia Zhipeng AnimDynamics是UE4.11 Preview 5测试版本发布的AnimationBlueprint中的新节点.功能是通过简 ...

  7. JAVA设计模式--抽象工厂模式

    抽象工厂设计模式 1.系统中有多个产品族,而系统一次只可能消费其中一族产品2.同属于同一个产品族的产品以其使用.来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):抽象工厂角色: 这是工厂方法模式的 ...

  8. andriod studio

    初衷:使用andriod的webview调用html页面,生成app. AVD注意细节: RAM : 1G VM heap:228MB Graphics:software - GLES 2.0 存在的 ...

  9. java多线程(精华版)

    在 Java 程序中使用多线程要比在 C 或 C++ 中容易得多,这是因为 Java 编程语言提供了语言级的支持.本文通过简单的编程示例来说明 Java 程序中的多线程是多么直观.读完本文以后,用户应 ...

  10. IOS 跳转至AppStore的两种方式

    //第一种方法 直接跳转 id+编号 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms-apps: ...