Java反射使用总结

来源:互联网 发布:cf易语言源码大全 编辑:程序博客网 时间:2024/05/17 22:03

一、概述

反射:指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。也就是可以获取正在运行的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);    }}