Java反射机制详解

来源:互联网 发布:爱情电影推荐知乎 编辑:程序博客网 时间:2024/06/05 15:41

1. 反射机制是什么

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

2. 反射机制能做什么

反射机制主要提供了以下功能: 

  • 在运行时判断任意一个对象所属的类;

  • 在运行时构造任意一个类的对象;

  • 在运行时判断任意一个类所具有的成员变量和方法;

  • 在运行时调用任意一个对象的方法;

  • 生成动态代理。

3. 反射机制的相关API

通过一个对象获得完整的包名和类名

package net.xsoftlab.baike;

public class TestReflect {

    public static void main(String[] args) throws Exception {

        TestReflect testReflect = new TestReflect();

        System.out.println(testReflect.getClass().getName());

        // 结果 net.xsoftlab.baike.TestReflect

    }

}

实例化Class类对象

package net.xsoftlab.baike;

public class TestReflect {

    public static void main(String[] args) throws Exception {

        Class<?> class1 = null;

        Class<?> class2 = null;

        Class<?> class3 = null;

        // 一般采用这种形式

        class1 = Class.forName("net.xsoftlab.baike.TestReflect");

        class2 = new TestReflect().getClass();

        class3 = TestReflect.class;

        System.out.println("类名称   " + class1.getName());

        System.out.println("类名称   " + class2.getName());

        System.out.println("类名称   " + class3.getName());

    }

}

获取一个对象的父类与实现的接口

package net.xsoftlab.baike;

import java.io.Serializable;

public class TestReflect implements Serializable {

    private static final long serialVersionUID = -2862585049955236662L;

    public static void main(String[] args) throws Exception {

        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");

        // 取得父类

        Class<?> parentClass = clazz.getSuperclass();

        System.out.println("clazz的父类为:" + parentClass.getName());

        // clazz的父类为: java.lang.Object

        // 获取所有的接口

        Class<?> intes[] = clazz.getInterfaces();

        System.out.println("clazz实现的接口有:");

        for (int i = 0; i < intes.length; i++) {

            System.out.println((i + 1) + ":" + intes[i].getName());

        }

        // clazz实现的接口有:

        // 1:java.io.Serializable

    }

}

获取某个类中的全部构造函数 - 详见下例

通过反射机制实例化一个类的对象

package net.xsoftlab.baike;

import java.lang.reflect.Constructor;

public class TestReflect {

    public static void main(String[] args) throws Exception {

        Class<?> class1 = null;

        class1 = Class.forName("net.xsoftlab.baike.User");

        // 第一种方法,实例化默认构造方法,调用set赋值

        User user = (User) class1.newInstance();

        user.setAge(20);

        user.setName("Rollen");

        System.out.println(user);

        // 结果 User [age=20, name=Rollen]

        // 第二种方法 取得全部的构造函数 使用构造函数赋值

        Constructor<?> cons[] = class1.getConstructors();

        // 查看每个构造方法需要的参数

        for (int i = 0; i < cons.length; i++) {

            Class<?> clazzs[] = cons[i].getParameterTypes();

            System.out.print("cons[" + i + "] (");

            for (int j = 0; j < clazzs.length; j++) {

                if (j == clazzs.length - 1)

                    System.out.print(clazzs[j].getName());

                else

                    System.out.print(clazzs[j].getName() + ",");

            }

            System.out.println(")");

        }

        // 结果

        // cons[0] (java.lang.String)

        // cons[1] (int,java.lang.String)

        // cons[2] ()

        user = (User) cons[0].newInstance("Rollen");

        System.out.println(user);

        // 结果 User [age=0, name=Rollen]

        user = (User) cons[1].newInstance(20, "Rollen");

        System.out.println(user);

        // 结果 User [age=20, name=Rollen]

    }

}

class User {

    private int age;

    private String name;

    public User() {

        super();

    }

    public User(String name) {

        super();

        this.name = name;

    }

    public User(int age, String name) {

        super();

        this.age = age;

        this.name = name;

    }

    public int getAge() {

        return age;

    }

    public void setAge(int age) {

        this.age = age;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    @Override

    public String toString() {

        return "User [age=" + age + ", name=" + name + "]";

    }

}

获取某个类的全部属性

package net.xsoftlab.baike;

import java.io.Serializable;

import java.lang.reflect.Field;

import java.lang.reflect.Modifier;

public class TestReflect implements Serializable {

    private static final long serialVersionUID = -2862585049955236662L;

    public static void main(String[] args) throws Exception {

        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");

        System.out.println("===============本类属性===============");

        // 取得本类的全部属性

        Field[] field = clazz.getDeclaredFields();

        for (int i = 0; i < field.length; i++) {

            // 权限修饰符

            int mo = field[i].getModifiers();

            String priv = Modifier.toString(mo);

            // 属性类型

            Class<?> type = field[i].getType();

            System.out.println(priv + " " + type.getName() + " " + field[i].getName() + ";");

        }

         

        System.out.println("==========实现的接口或者父类的属性==========");

        // 取得实现的接口或者父类的属性

        Field[] filed1 = clazz.getFields();

        for (int j = 0; j < filed1.length; j++) {

            // 权限修饰符

            int mo = filed1[j].getModifiers();

            String priv = Modifier.toString(mo);

            // 属性类型

            Class<?> type = filed1[j].getType();

            System.out.println(priv + " " + type.getName() + " " + filed1[j].getName() + ";");

        }

    }

}

获取某个类的全部方法

package net.xsoftlab.baike;

import java.io.Serializable;

import java.lang.reflect.Method;

import java.lang.reflect.Modifier;

public class TestReflect implements Serializable {

    private static final long serialVersionUID = -2862585049955236662L;

    public static void main(String[] args) throws Exception {

        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");

        Method method[] = clazz.getMethods();

        for (int i = 0; i < method.length; ++i) {

            Class<?> returnType = method[i].getReturnType();

            Class<?> para[] = method[i].getParameterTypes();

            int temp = method[i].getModifiers();

            System.out.print(Modifier.toString(temp) + " ");

            System.out.print(returnType.getName() + "  ");

            System.out.print(method[i].getName() + " ");

            System.out.print("(");

            for (int j = 0; j < para.length; ++j) {

                System.out.print(para[j].getName() + " " + "arg" + j);

                if (j < para.length - 1) {

                    System.out.print(",");

                }

            }

            Class<?> exce[] = method[i].getExceptionTypes();

            if (exce.length > 0) {

                System.out.print(") throws ");

                for (int k = 0; k < exce.length; ++k) {

                    System.out.print(exce[k].getName() + " ");

                    if (k < exce.length - 1) {

                        System.out.print(",");

                    }

                }

            } else {

                System.out.print(")");

            }

            System.out.println();

        }

    }

}

通过反射机制调用某个类的方法

package net.xsoftlab.baike;

import java.lang.reflect.Method;

public class TestReflect {

    public static void main(String[] args) throws Exception {

        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");

        // 调用TestReflect类中的reflect1方法

        Method method = clazz.getMethod("reflect1");

        method.invoke(clazz.newInstance());

        // Java 反射机制 - 调用某个类的方法1.

        // 调用TestReflect的reflect2方法

        method = clazz.getMethod("reflect2", int.class, String.class);

        method.invoke(clazz.newInstance(), 20, "张三");

        // Java 反射机制 - 调用某个类的方法2.

        // age -> 20. name -> 张三

    }

    public void reflect1() {

        System.out.println("Java 反射机制 - 调用某个类的方法1.");

    }

    public void reflect2(int age, String name) {

        System.out.println("Java 反射机制 - 调用某个类的方法2.");

        System.out.println("age -> " + age + ". name -> " + name);

    }

}

通过反射机制操作某个类的属性

package net.xsoftlab.baike;

import java.lang.reflect.Field;

public class TestReflect {

    private String proprety = null;

    public static void main(String[] args) throws Exception {

        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");

        Object obj = clazz.newInstance();

        // 可以直接对 private 的属性赋值

        Field field = clazz.getDeclaredField("proprety");

        field.setAccessible(true);

        field.set(obj, "Java反射机制");

        System.out.println(field.get(obj));

    }

}

反射机制的动态代理

// 获取类加载器的方法

TestReflect testReflect = new TestReflect();

        System.out.println("类加载器  " + testReflect.getClass().getClassLoader().getClass().getName());

package net.xsoftlab.baike;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

//定义项目接口

interface Subject {

    public String say(String name, int age);

}

// 定义真实项目

class RealSubject implements Subject {

    public String say(String name, int age) {

        return name + "  " + age;

    }

}

class MyInvocationHandler implements InvocationHandler {

    private Object obj = null;

    public Object bind(Object obj) {

        this.obj = obj;

        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);

    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Object temp = method.invoke(this.obj, args);

        return temp;

    }

}

/**

 * 在java中有三种类类加载器。

 * 

 * 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。

 * 

 * 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jrelibext目录中的类

 * 

 * 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。

 * 

 * 如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。

 * 

 * @author xsoftlab.net

 * 

 */

public class TestReflect {

    public static void main(String[] args) throws Exception {

        MyInvocationHandler demo = new MyInvocationHandler();

        Subject sub = (Subject) demo.bind(new RealSubject());

        String info = sub.say("Rollen", 20);

        System.out.println(info);

    }

}

4. 反射机制的应用实例

在泛型为Integer的ArrayList中存放一个String类型的对象。

package net.xsoftlab.baike;

import java.lang.reflect.Method;

import java.util.ArrayList;

public class TestReflect {

    public static void main(String[] args) throws Exception {

        ArrayList<Integer> list = new ArrayList<Integer>();

        Method method = list.getClass().getMethod("add", Object.class);

        method.invoke(list, "Java反射机制实例。");

        System.out.println(list.get(0));

    }

}

通过反射取得并修改数组的信息

package net.xsoftlab.baike;

import java.lang.reflect.Array;

public class TestReflect {

    public static void main(String[] args) throws Exception {

        int[] temp = { 1, 2, 3, 4, 5 };

        Class<?> demo = temp.getClass().getComponentType();

        System.out.println("数组类型: " + demo.getName());

        System.out.println("数组长度  " + Array.getLength(temp));

        System.out.println("数组的第一个元素: " + Array.get(temp, 0));

        Array.set(temp, 0, 100);

        System.out.println("修改之后数组第一个元素为: " + Array.get(temp, 0));

    }

}

通过反射机制修改数组的大小

package net.xsoftlab.baike;

import java.lang.reflect.Array;

public class TestReflect {

    public static void main(String[] args) throws Exception {

        int[] temp = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

        int[] newTemp = (int[]) arrayInc(temp, 15);

        print(newTemp);

        String[] atr = { "a", "b", "c" };

        String[] str1 = (String[]) arrayInc(atr, 8);

        print(str1);

    }

    // 修改数组大小

    public static Object arrayInc(Object obj, int len) {

        Class<?> arr = obj.getClass().getComponentType();

        Object newArr = Array.newInstance(arr, len);

        int co = Array.getLength(obj);

        System.arraycopy(obj, 0, newArr, 0, co);

        return newArr;

    }

    // 打印

    public static void print(Object obj) {

        Class<?> c = obj.getClass();

        if (!c.isArray()) {

            return;

        }

        System.out.println("数组长度为: " + Array.getLength(obj));

        for (int i = 0; i < Array.getLength(obj); i++) {

            System.out.print(Array.get(obj, i) + " ");

        }

        System.out.println();

    }

}

将反射机制应用于工厂模式

package net.xsoftlab.baike;

interface fruit {

    public abstract void eat();

}

class Apple implements fruit {

    public void eat() {

        System.out.println("Apple");

    }

}

class Orange implements fruit {

    public void eat() {

        System.out.println("Orange");

    }

}

class Factory {

    public static fruit getInstance(String ClassName) {

        fruit f = null;

        try {

            f = (fruit) Class.forName(ClassName).newInstance();

        } catch (Exception e) {

            e.printStackTrace();

        }

        return f;

    }

}

/**

 * 对于普通的工厂模式当我们在添加一个子类的时候,就需要对应的修改工厂类。 当我们添加很多的子类的时候,会很麻烦。

 * Java 工厂模式可以参考

 * http://baike.xsoftlab.net/view/java-factory-pattern

 * 

 * 现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。

 * 

 * 但是有一点仍然很麻烦,就是需要知道完整的包名和类名,这里可以使用properties配置文件来完成。

 * 

 * java 读取 properties 配置文件 的方法可以参考

 * http://baike.xsoftlab.net/view/java-read-the-properties-configuration-file

 * 

 * @author xsoftlab.net

 */

public class TestReflect {

    public static void main(String[] args) throws Exception {

        fruit f = Factory.getInstance("net.xsoftlab.baike.Apple");

        if (f != null) {

            f.eat();

        }

    }

}

Java团长

微信号:javatuanzhang

每日分享Java技术干货

长按识别二维码

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 关键词找不到了是不是被降权怎么办 购买小程序关键词想退款怎么办? 浏览器审查元素不拆分关键词怎么办 拼多多商品想重新编辑怎么办 新开店铺没有销量怎么办 新开的店铺没有销量怎么办 淘宝的商品权重下降是怎么办 360n5手机耗电快怎么办 怪兽充电宝丢了怎么办 有已处置的评价怎么办 淘宝降权了怎么办2018 使用虚假广告词被工商查到怎么办 为什么手机淘宝店关注不了怎么办 淘宝买东西付钱后卖家不发货怎么办 微信销售群没人买东西怎么办 淘宝想开2个店铺怎么办 拼多多没钱交保证金怎么办 差评一个月后怎么办 淘宝买家投诉成立后怎么办 天猫投诉成立了怎么办 新开实体店铺没生意怎么办 新开淘宝没流量怎么办 白色板鞋有青草弄的绿色怎么办 淘宝租衣服不退押金怎么办 c盘不可以扩展怎么办 实践教学管理平台忘记账号怎么办 淘宝申请售后店家不处理怎么办 全民k歌地区限制怎么办 网络电视hdp无法下载怎么办 淘宝店铺销量为零怎么办 快递号填错卖家拒绝退款申请怎么办 淘宝店代购 售假怎么办 淘宝申请售后卖家没钱怎么办 淘宝禁止评价一个月怎么办 被卖家电话骚扰怎么办 恶意骚扰扣12分怎么办 新店开张交保证金被骗了怎么办 支付宝蚂蚁花呗逾期怎么办 被注销的微信怎么办 花呗有些不能用怎么办 实体店生意不好做怎么办