Java反射使用总结

声明:原创文章,转载请注明出处。http://www.jianshu.com/p/b4757a970b26

一、概述

反射:指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。也就是可以获取正在运行的Java对象。

反射作为Java中一个强大的工具,不仅可以很方便创建灵活的代码,而且对一些其他第三方代码可以进行增强。
其主要功能主要有:
1、可以判断运行时对象所属的类
2、可以判断运行时对象所拥有的成员属性和方法
3、生成动态代理

光看概念有些晦涩,我们先说一个简单的应用反射的例子:

public class Item {
    private String id;
    private String name;
    private double price;

    public Item(String id, String name, double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public String getId() {   return id; }
    public String getName() {  return name; }
    public double getPrice() { return price; }
}

上面这部分代码不管出于什么目的,其成员属性只在new对象时接收,其他情况一律修改不了。我们可以通过反射来修改类的私有属性。

public static void main(String[] args) throws Exception {
     Item item = new Item("1", "a", 1.0);
     Field field = item.getClass().getDeclaredField("id");
     field.setAccessible(true);
     field.set(item, "2");
     System.out.println(item.getId());  // 2
    }

运行可以发现,我们已经把其对象的id值更新到了2。

二、具体功能实现

1、获取类并创建其对象:反射中获取类通常有三种方法

Class clz1 = Class.forName("java.lang.String"); // 1.通过包和类名
Class clz2 = String.class;  // 2.直接通过类名

String str = new String();
Class clz3 = str.getClass(); // 3.根据对象(运行时类)

clz1.newInstance();
clz2.newInstance();
其他方法名 含义
getEnclosingClass() 返回底层类的立即封闭类
getDeclaredClasses() 返回 Class 对象的一个数组,这些对象反映声明为此 Class 对象所表示的类的成员的所有类和接口
getDeclaringClass() 如果此 Class 对象所表示的类或接口是另一个类的成员,则返回的 Class 对象表示该对象的声明类

2、获取类的属性

方法名 含义
getFields() 获取类的所有public属性,包括其父类
getField() 获取某一个属性
getDeclaredFields() 获取类的所有声明的字段,不包括父类
getDeclaredField() 获取某一个属性

3、获取类的方法

方法名 含义
getMethods() 获取类的所有public方法,包括其父类
getMethod() 获取某一个方法
getDeclaredMethods() 获取类的所有声明的方法,不包括父类
getDeclaredMethod() 获取某一个方法
getConstructors() 获取访问权限是public的所有构造方法
getConstructor() 获取某一个构造方法
getDeclaredConstructors() 获取类的所有构造方法
getConstructors() 获取某一个构造方法

4、总结

  • 反射里的Class, Field, Method, Constructor必须结合对象使用,除非是静态的。
  • 获取非public对象须用类似getDeclaredMethod()而不是getMethod()。
  • Field和Method都能设置accessible(true),之后能访问到私有权限。

三、一个简单的例子

下面是一个Person类,其中有两个私有属性id和name;拥有一个构造方法和一个私有方法print;

  • 还有一个public内部类BaseInfo:含有两个私有属性nation和bloodType;拥有一个构造方法和一个私有方法print;
  • 还有一个private内部类FamilyInfo:含有两个私有属性nativePlace和address,拥有一个构造方法和一个私有方法print。

由于FamilyInfo为私有的,因此为了可以初始化其属性,在Person中添加了一个私有属性,并在构造方法中对其进行了初始化。

public class Person {
    private String id;
    private String name;

    private FamilyInfo familyInfo;

    public Person(String id, String name) {
        this.id = id;
        this.name = name;
        this.familyInfo = this.new FamilyInfo("beijing", "beijing");
    }

    private void print() {
        System.out.println("Person{id=" + id + ", name=" + name + "}");
    }

    public class BaseInfo {
        private String nation;
        private String bloodType;

        public BaseInfo(String nation, String bloodType) {
            this.nation = nation;
            this.bloodType = bloodType;
        }

        private void print() {
            System.out.println("BaseInfo{nation=" + nation + ", bloodType=" + bloodType + "}");
        }
    }

    private class FamilyInfo {
        private String nativePlace; // 籍贯
        private String address;     // 住址

        private FamilyInfo(String nativePlace, String address) {
            this.nativePlace = nativePlace;
            this.address = address;
        }
        private void print() {
            System.out.println("FamilyInfo{nativePlace=" + nativePlace + ", address=" + address + "}");
        }
    }
}

下面的Main方法中,初始化了Person类,通过一个getFiledFromPerson()方法打印出其私有属性、私有方法、内部类私有属性及方法。

public class Main {

    private static void getFiledFromPerson(Person person, Person.BaseInfo baseInfo) {
        try {
            // 获取外部类的私有属性
            Field idField = person.getClass().getDeclaredField("id");
            idField.setAccessible(true);
            String id = (String) idField.get(person);
            System.out.println("id:" + id);

            Field familyInfoField = person.getClass().getDeclaredField("familyInfo");
            familyInfoField.setAccessible(true);
            Object familyInfo = familyInfoField.get(person);

            // 获取外部类的私有方法
            Method printPersonMethod = person.getClass().getDeclaredMethod("print");
            printPersonMethod.setAccessible(true);
            printPersonMethod.invoke(person);

            // 获取内部类的私有属性
            Class baseInfoClz = Class.forName("demo.Person$BaseInfo");
            Field nationField = baseInfoClz.getDeclaredField("nation");
            nationField.setAccessible(true);
            String nation = (String) nationField.get(baseInfo);
            System.out.println("nation:" + nation);

            Class familyInfoClz = Class.forName("demo.Person$FamilyInfo");
            Field field = familyInfoClz.getDeclaredField("address");
            field.setAccessible(true);
            String address = (String) field.get(familyInfo);
            System.out.println("address:" + address);

            // 获取内部类的私有方法
            Method printBaseInfoMethod = baseInfoClz.getDeclaredMethod("print");
            printBaseInfoMethod.setAccessible(true);
            printBaseInfoMethod.invoke(baseInfo);

            Method printFamilyInfoMethod = familyInfoClz.getDeclaredMethod("print");
            printFamilyInfoMethod.setAccessible(true);
            printFamilyInfoMethod.invoke(familyInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Person person = new Person("1001", "John"); // 初始化Person以及默认FamilyInfo
        Person.BaseInfo baseInfo = person.new BaseInfo("han", "A"); // 初始化BaseInfo
        getFiledFromPerson(person, baseInfo);
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够...
    java部落阅读 175评论 0 0
  • 20- 枚举,枚举原始值,枚举相关值,switch提取枚举关联值 Swift枚举: Swift中的枚举比OC中的枚...
    iOS_恒仔阅读 2,337评论 1 6
  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 2,733评论 0 11
  • 今天是开学第二天,学生生活一直是我所期盼的,但真正回归它时,似乎并没有在我的预设中迅速步入正轨。 ...
    妙妙是魔女阅读 248评论 0 0
  • 2016.Jun.28~新做的美甲,闪粉很漂亮。微距。 2016.Jun.29~绿色好心情,给大家养养眼!微距上的...
    不优雅熊猫阅读 329评论 2 1