java反射的理解和实现

Java高级特性——反射

本文内容是我在网上所学习总结的,如有侵权,请联系我,我立刻删除。

定义

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

用途 (网上看的)

在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。当然,也不是所有的都适合反射,之前就遇到一个案例,通过反射得到的结果与预期不符。阅读源码发现,经过层层调用后在最终返回结果的地方对应用的权限进行了校验,对于没有权限的应用返回值是没有意义的缺省值,否则返回实际值起到保护用户的隐私目的。

首先创建Student类

public class Student {
    public int age;
    public String name;

    public Student() {
    }

    public Student(int age, String name) {
        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;
    }
}

编写反射类 Reflect.java

在这里我用测试类来运行方法,先一个方法来编写,最后在最后放上总代码。

demo1()
	/**
     * 通过java的反射机制来得到类的包名和类名
     */
    @Test
    public void demo1(){
        Student student=new Student();//实例化Student类
        String name = student.getClass().getName();//获取Student的类名
        String name1 = student.getClass().getPackage().getName();//获取Student的包名
        System.out.println("类名"+name);//输出类名
        System.out.println("包名"+name1);//输出包名
    }
demo2()
    /**
     * 验证所有的类都是Class类的实例对象
     * 异常ClassNotFoundException
     */
    @Test
    public void demo2() throws ClassNotFoundException{
        //定义两个类型都是未知的Class,初始赋值为null,下面赋值成Student类
        Class<?> class1=null;
        Class<?> class2=null;
        //方法一:会抛出ClassNotFoundException异常(建议使用这个写法)
        class1=Class.forName("web.reflect.Student");
        String name2 = class1.getName();//获取Student的类名
        String name3 = class1.getPackage().getName();//获取Student的包名
        System.out.println("类名"+name2);//输出类名
        System.out.println("包名"+name3);//输出包名
        System.out.println("========================");
        //方法二:
        class2=Student.class;
        String name4 = class2.getName();
        String name5 = class2.getPackage().getName();
        System.out.println("类名"+name4);
        System.out.println("包名"+name5);

    }
demo3()
    /**
     * 利用java的反射机制,用Class类创建对象
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    @Test
    public void demo3() throws ClassNotFoundException,IllegalAccessException,InstantiationException{
        //定义一个类型都是未知的Class,初始赋值为null。
        Class<?> class1=null;
        class1=Class.forName("web.reflect.Student");
        //由于这里不能带参数,所以你要实例化的这个类Person,一定要有无参构造函数
        Student student=(Student) class1.newInstance();
        student.setAge(20);
        student.setName("大猩猩");
        System.out.println("我叫"+student.getName()+";今年"+student.getAge()+"岁了");
    }
demo4()
    /**
     * 通过Java反射机制得到一个类的构造函数,并实现创建带参实例对象
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    @Test
    public void demo4() throws ClassNotFoundException,InstantiationException, InvocationTargetException,IllegalAccessException {
        Class<?>  class1=null;
        Student student1=null;
        Student student2=null;

        class1=Class.forName("web.reflect.Student");
        //得到一系列构造函数集合
        Constructor<?>[] constructors=class1.getConstructors();
        student1=(Student) constructors[0].newInstance();
        student1.setAge(30);
        student1.setName("张三");

        student2=(Student) constructors[1].newInstance(20,"王五");
        System.out.println("demo4:"+student1.getName()+":"+student1.getAge()+","+student2.getName()+":"+student2.getAge());

    }
demo5()
    /**
     *通过Java反射机制操作成员变量, set 和 get
     * @throws NoSuchFieldException
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    @Test
    public void demo5()throws NoSuchFieldException,ClassNotFoundException,InstantiationException,IllegalAccessException{
        Class<?> class1=null;
        class1=Class.forName("web.reflect.Student");
        Object obj=class1.newInstance();

        Field studentNameField=class1.getDeclaredField("name");
        studentNameField.setAccessible(true);
        studentNameField.set(obj,"刘德华");

        System.out.println("修改属性之后得到属性变量的值:"+studentNameField.get(obj));

    }
demo6()

写一个接口ReflectInterface

public interface ReflectInterface {
    public void sweet(int m);
}

这里创建一个SugarMan类继承Student类和接口
SugarMan.java


public class SugarMan extends Student implements ReflectInterface{
    private boolean BlueBriefs;

    public void sugar(){
        System.out.println("我是糖人,很甜的糖。");
    }
    public boolean isBlueBriefs(){
        return BlueBriefs;
    }
    public void setBlueBriefs(boolean blueBriefs){
        BlueBriefs=blueBriefs;
    }

    @Override
    public void sweet(int m){
        System.out.println("唐人的甜度是:"+m);
    }

}

测试方法

    /**
     * 通过java反射机制得到类的一些属性:继承接口,父类,函数的信息,成员信息,类型等;
     * @throws ClassNotFoundException
     */
    @Test
    public  void demo6() throws ClassNotFoundException{
        Class<?> class1=null;
        class1=Class.forName("web.reflect.SugarMan");
        //获取父类名称
        Class<?> sugarClass=class1.getSuperclass();
        System.out.println("SugarMan父类名称是:"+sugarClass.getName());
        System.out.println("-------------------------------");

        Field[] fields=class1.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            System.out.println("类中的成员:"+fields[i]);
        }
        System.out.println("-------------------------------");

        //获取类方法
        Method[] methods=class1.getDeclaredMethods();
        for (int i = 0; i < methods.length; i++) {
            System.out.println("Demo6,取得SuperMan类的方法:");
            System.out.println("函数名:"+methods[i].getName());
            System.out.println("函数返回类型:" +methods[i].getReturnType());
            System.out.println("函数访问修饰符:" + Modifier.toString(methods[i].getModifiers()));
            System.out.println("函数代码写法: " + methods[i]);
        }
        System.out.println("-------------------------------");

        //取得类实现的接口,因为接口类也属于Class,所以得到接口中的方法也是一样的方法得到
        Class<?>[] interfaces=class1.getInterfaces();
        for (int i = 0; i < interfaces.length; i++) {
            System.out.println("实现的接口类名: " +interfaces[i].getName());
        }
    }
demo7()
    /**
     * 通过Java反射机制调用类方法
     * @throws ClassNotFoundException
     * @throws SecurityException
     * @throws NoSuchMethodException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws InstantiationException
     */
    @Test
    public  void demo7() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException
    {
        Class<?> class1 = null;
        class1 = Class.forName("web.reflect.SugarMan");

        System.out.println("Demo7: \n调用无参方法sugar():");
        Method method = class1.getMethod("sugar");
        method.invoke(class1.newInstance());

        System.out.println("调用有参方法sweet(int m):");
        method = class1.getMethod("sweet",int.class);
        method.invoke(class1.newInstance(),100);
    }
}

最后放上测试的总代码
Reflect.java

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Reflect {

    /**
     * 通过java的反射机制来得到类的包名和类名
     */
    @Test
    public void demo1(){
        Student student=new Student();//实例化Student类
        String name = student.getClass().getName();//获取Student的类名
        String name1 = student.getClass().getPackage().getName();//获取Student的包名
        System.out.println("类名"+name);//输出类名
        System.out.println("包名"+name1);//输出包名
        System.out.println("--------------------------");
    }

    /**
     * 验证所有的类都是Class类的实例对象
     * 异常ClassNotFoundException
     */
    @Test
    public void demo2() throws ClassNotFoundException{
        //定义两个类型都是未知的Class,初始赋值为null,下面赋值成Student类
        Class<?> class1=null;
        Class<?> class2=null;
        //方法一:会抛出ClassNotFoundException异常(建议使用这个写法)
        class1=Class.forName("web.reflect.Student");
        String name2 = class1.getName();//获取Student的类名
        String name3 = class1.getPackage().getName();//获取Student的包名
        System.out.println("类名"+name2);//输出类名
        System.out.println("包名"+name3);//输出包名
        System.out.println("========================");
        //方法二:
        class2=Student.class;
        String name4 = class2.getName();
        String name5 = class2.getPackage().getName();
        System.out.println("类名"+name4);
        System.out.println("包名"+name5);

    }
    /**
     * 利用java的反射机制,用Class类创建对象
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    @Test
    public void demo3() throws ClassNotFoundException,IllegalAccessException,InstantiationException{
        //定义一个类型都是未知的Class,初始赋值为null。
        Class<?> class1=null;
        class1=Class.forName("web.reflect.Student");
        //由于这里不能带参数,所以你要实例化的这个类Person,一定要有无参构造函数
        Student student=(Student) class1.newInstance();
        student.setAge(20);
        student.setName("大猩猩");
        System.out.println("我叫"+student.getName()+";今年"+student.getAge()+"岁了");
    }


    /**
     * 通过Java反射机制得到一个类的构造函数,并实现创建带参实例对象
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    @Test
    public void demo4() throws ClassNotFoundException,InstantiationException, InvocationTargetException,IllegalAccessException {
        Class<?>  class1=null;
        Student student1=null;
        Student student2=null;

        class1=Class.forName("web.reflect.Student");
        //得到一系列构造函数集合
        Constructor<?>[] constructors=class1.getConstructors();
        student1=(Student) constructors[0].newInstance();
        student1.setAge(30);
        student1.setName("张三");

        student2=(Student) constructors[1].newInstance(20,"王五");
        System.out.println("demo4:"+student1.getName()+":"+student1.getAge()+","+student2.getName()+":"+student2.getAge());

    }

    /**
     *通过Java反射机制操作成员变量, set 和 get
     * @throws NoSuchFieldException
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    @Test
    public void demo5()throws NoSuchFieldException,ClassNotFoundException,InstantiationException,IllegalAccessException{
        Class<?> class1=null;
        class1=Class.forName("web.reflect.Student");
        Object obj=class1.newInstance();

        Field studentNameField=class1.getDeclaredField("name");
        studentNameField.setAccessible(true);
        studentNameField.set(obj,"刘德华");

        System.out.println("修改属性之后得到属性变量的值:"+studentNameField.get(obj));

    }


    /**
     * 通过java反射机制得到类的一些属性:继承接口,父类,函数的信息,成员信息,类型等;
     * @throws ClassNotFoundException
     */
    @Test
    public  void demo6() throws ClassNotFoundException{
        Class<?> class1=null;
        class1=Class.forName("web.reflect.SugarMan");
        //获取父类名称
        Class<?> sugarClass=class1.getSuperclass();
        System.out.println("SugarMan父类名称是:"+sugarClass.getName());
        System.out.println("-------------------------------");

        Field[] fields=class1.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            System.out.println("类中的成员:"+fields[i]);
        }
        System.out.println("-------------------------------");

        //获取类方法
        Method[] methods=class1.getDeclaredMethods();
        for (int i = 0; i < methods.length; i++) {
            System.out.println("Demo6,取得SuperMan类的方法:");
            System.out.println("函数名:"+methods[i].getName());
            System.out.println("函数返回类型:" +methods[i].getReturnType());
            System.out.println("函数访问修饰符:" + Modifier.toString(methods[i].getModifiers()));
            System.out.println("函数代码写法: " + methods[i]);
        }
        System.out.println("-------------------------------");

        //取得类实现的接口,因为接口类也属于Class,所以得到接口中的方法也是一样的方法得到
        Class<?>[] interfaces=class1.getInterfaces();
        for (int i = 0; i < interfaces.length; i++) {
            System.out.println("实现的接口类名: " +interfaces[i].getName());
        }
    }

    /**
     * 通过Java反射机制调用类方法
     * @throws ClassNotFoundException
     * @throws SecurityException
     * @throws NoSuchMethodException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws InstantiationException
     */
    @Test
    public  void demo7() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException
    {
        Class<?> class1 = null;
        class1 = Class.forName("web.reflect.SugarMan");

        System.out.println("Demo7: \n调用无参方法sugar():");
        Method method = class1.getMethod("sugar");
        method.invoke(class1.newInstance());

        System.out.println("调用有参方法sweet(int m):");
        method = class1.getMethod("sweet",int.class);
        method.invoke(class1.newInstance(),100);
    }
}

如果不想用测试类可以写主函数,然后调用方法,建议用静态的,这样代码量少,比较清晰。

如果测试类出错误了,可以看我的另一篇文章

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值