美文网首页
Java反射使用总结

Java反射使用总结

作者: 唐影若凡 | 来源:发表于2017-03-06 10:31 被阅读0次

声明:原创文章,转载请注明出处。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反射

    简单总结下什么是Java反射,怎么使用。 Java反射机制 反射就是指JVM运行期,获取指定类所有的属性和方法的一...

  • Java 反射 使用总结

    反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够...

  • Java 反射使用总结

  • Java反射使用总结

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

  • Java反射使用总结

    Java反射总结 1.反射机制的定义 1.1定义 Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类...

  • java反射使用总结

    反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够...

  • 反射之一

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • 反射之二

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • 反射之三

    总结内容源自以下文章 粗浅看java反射机制 反射机制应用实践 谈谈java反射机制 Java Reflectio...

  • Android Kotlin 反射使用 (null receiv

    最近在使用Kotlin反射遇到些问题,总结一下:报错:java.lang.NullPointerException...

网友评论

      本文标题:Java反射使用总结

      本文链接:https://www.haomeiwen.com/subject/jkfdwttx.html