首页 Java java教程 Java反射机制详解

Java反射机制详解

Dec 12, 2016 am 11:45 AM
java反射机制

概要:

Java反射机制详解

1反射机制是什么

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

2反射机制能做什么

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

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

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

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

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

生成动态代理。

3反射机制的相关API

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

Java | 复制

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类对象

Java | 复制

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());
    }
}
登录后复制

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

Java | 复制

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
    }
}
登录后复制

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

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

Java | 复制

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 + "]";
    }
}
登录后复制

获取某个类的全部属性

Java | 复制

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() + ";");
        }
    }
}
登录后复制

获取某个类的全部方法

Java | 复制

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();
        }
    }
}
登录后复制

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

Java | 复制

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);
    }
}
登录后复制

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

Java | 复制

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));
    }
}
登录后复制

反射机制的动态代理

Java | 复制

// 获取类加载器的方法
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类型的对象。

Java | 复制

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));
    }
}
登录后复制

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

Java | 复制

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));
    }
}
登录后复制

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

Java | 复制

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();
    }
}
登录后复制

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

Java | 复制

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();
        }
    }
}
登录后复制


本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何优雅地获取实体类变量名构建数据库查询条件? 如何优雅地获取实体类变量名构建数据库查询条件? Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架进行数据库操作时,经常需要根据实体类的属性名构造查询条件。如果每次都手动...

如何使用MapStruct简化系统对接中的字段映射问题? 如何使用MapStruct简化系统对接中的字段映射问题? Apr 19, 2025 pm 06:21 PM

系统对接中的字段映射处理在进行系统对接时,常常会遇到一个棘手的问题:如何将A系统的接口字段有效地映�...

IntelliJ IDEA是如何在不输出日志的情况下识别Spring Boot项目的端口号的? IntelliJ IDEA是如何在不输出日志的情况下识别Spring Boot项目的端口号的? Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本启动Spring...

公司安全软件导致应用无法运行?如何排查和解决? 公司安全软件导致应用无法运行?如何排查和解决? Apr 19, 2025 pm 04:51 PM

公司安全软件导致部分应用无法正常运行的排查与解决方法许多公司为了保障内部网络安全,会部署安全软件。...

Java对象如何安全地转换为数组? Java对象如何安全地转换为数组? Apr 19, 2025 pm 11:33 PM

Java对象与数组的转换:深入探讨强制类型转换的风险与正确方法很多Java初学者会遇到将一个对象转换成数组的�...

Java程序在ARM和x86架构CPU上内存泄漏差异为何? Java程序在ARM和x86架构CPU上内存泄漏差异为何? Apr 19, 2025 pm 11:18 PM

Java程序在不同架构CPU上的内存泄漏现象分析本文将探讨一个Java程序在ARM和x86架构CPU上表现出不同内存行为的案�...

如何将名字转换为数字以实现群组内排序? 如何将名字转换为数字以实现群组内排序? Apr 19, 2025 pm 01:57 PM

如何将名字转为数字以实现群组内排序?在群组中排序用户时,常常需要将用户的名字转化为数字,以便在不同...

如何利用Redis缓存方案高效实现产品排行榜列表的需求? 如何利用Redis缓存方案高效实现产品排行榜列表的需求? Apr 19, 2025 pm 11:36 PM

Redis缓存方案如何实现产品排行榜列表的需求?在开发过程中,我们常常需要处理排行榜的需求,例如展示一个�...

See all articles