Java反射使用总结

声明:原创文章,转载请注明出处。//www.greatytc.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);
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容

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