Java高级之反射篇

一、什么是反射?
反射就是在运行过程中,对于任意一个类,都能够知道其所有方法和属性;对于任意一个对象,都能调用其任意方法和属性。这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。总的来说反射就是把类中的各个成员映射成一个对象。
使用反射的前提是要有 .class 文件。

在Java中,万物皆的对象,当我们创建了一个类的时候,这个类也是一个对,是java.lang.Class类的实例对象。根据Class类的源码可以看到Class没有公有构造函数,Class的对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的,所以并不需要我们再去手动创建。

二、为什么要使用反射?
当我们的程序在运行时,需要动态的加载一些类这些类可能之前用不到所以不用加载到jvm,而是在运行时根据需要才加载,这样做好处有很多,一个简单的例子就是JDBC,根据需要动态地根据实际情况加载驱动类,而不必一开始就直接把数据库相关类加载到jvm中。
反射在各种框架中用到的是最多的。很多框架都有配置文件,如Spring、Struts2等,一Struts2为例,struts.xml配置文件建立了一种映射关系,当 View 层发出请求时,请求会被 StrutsPrepareAndExecuteFilter 拦截,然后 StrutsPrepareAndExecuteFilter 会去动态地创建 Action 实例。

三、获取Class的三种方式
看实例

package com.demo.test;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        Person p = new Person(); //第一种方式获取Class对象
        Class person1 = p.getClass();
        System.out.println(person1.getName());

        Class person2 = Person.class; //第二种
        System.out.println(person2.getName());
        System.out.println(person1 == person2);

        Class person3 = Class.forName("com.demo.test.Person"); //第三种,最常用,参数是类的全名
        System.out.println(person3.getName());
        System.out.println(person1 == person3);
    }
}
/**
结果:
com.demo.test.Person
com.demo.test.Person
true
com.demo.test.Person
true
*/

上面例子中使用最多的是第三种,第一种,都有Person对象了,再使用Class进行反射意义何在呢;第二种,如果使用反射的类和被反射的类不在同一个包下,需要导入类,相对来说依赖性比较强;第三种,采用传参的方式,比较方便,参数可以存放在配置文件中。

反射常用的方法

package com.demo.test;

import test2.Test;

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

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<ReflUtils> reflUtilsClass = (Class<ReflUtils>) Class.forName("com.demo.test.ReflUtils"); //获取Class对象
        Object o = reflUtilsClass.newInstance(); //获取Class对象对应的实例

        Method[] methods = reflUtilsClass.getMethods(); //获取公有方法,包含了父类的方法也包含Object类
        System.out.println("所有公有方法:");
        for(Method method : methods)
            System.out.println(method);

        Method[] methods1 = reflUtilsClass.getDeclaredMethods(); //获取所有的成员方法,包括私有的(不包括继承的)
        System.out.println("所有成员方法:");
        for (Method method : methods1)
            System.out.println(method);

        Constructor<ReflUtils>[] constructors = (Constructor<ReflUtils>[]) reflUtilsClass.getConstructors(); //获取公有构造函数
        System.out.println("公有构造函数");
        for (Constructor constructor : constructors)
            System.out.println(constructor);

        Constructor<ReflUtils>[] constructors1 = (Constructor<ReflUtils>[]) reflUtilsClass.getDeclaredConstructors(); //获取全部构造函数
        System.out.println("全部构造函数");
        for (Constructor constructor : constructors1)
            System.out.println(constructor);

        Method method = reflUtilsClass.getMethod("add",int.class,int.class); //获取指定方法并调用
        Object o1 = method.invoke(o,5,8);
        System.out.println(o1);

        Constructor<ReflUtils> constructor = reflUtilsClass.getDeclaredConstructor(String.class);//获取私有构造函数并调用
        constructor.setAccessible(true);
        Object o2 = constructor.newInstance("admin");
        ReflUtils reflUtils = (ReflUtils)o2;
        System.out.println(reflUtils.getName());

        Constructor<ReflUtils> constructor1 = reflUtilsClass.getDeclaredConstructor(String.class,int.class); //获取公有构造并调用
        constructor1.setAccessible(true);
        Object o3 = constructor1.newInstance("张三",20);
        ReflUtils reflUtils1 = (ReflUtils)o3;
        System.out.println(reflUtils1.getName() + " " + reflUtils1.getAge());
    }
}

/*
运行结果:
所有公有方法:
public int com.demo.test.ReflUtils.add(int,int)
public java.lang.String com.demo.test.ReflUtils.toString(java.lang.String,int)
public java.lang.String com.demo.test.ReflUtils.getName()
public void com.demo.test.ReflUtils.setName(java.lang.String)
public int com.demo.test.ReflUtils.getAge()
public void com.demo.test.ReflUtils.setAge(int)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
所有成员方法:
public int com.demo.test.ReflUtils.add(int,int)
public java.lang.String com.demo.test.ReflUtils.toString(java.lang.String,int)
public java.lang.String com.demo.test.ReflUtils.getName()
public void com.demo.test.ReflUtils.setName(java.lang.String)
private java.lang.String com.demo.test.ReflUtils.dance(java.lang.String)
public int com.demo.test.ReflUtils.getAge()
public void com.demo.test.ReflUtils.setAge(int)
公有构造函数
public com.demo.test.ReflUtils(java.lang.String,int)
public com.demo.test.ReflUtils()
全部构造函数
private com.demo.test.ReflUtils(java.lang.String)
public com.demo.test.ReflUtils(java.lang.String,int)
public com.demo.test.ReflUtils()
13
admin
张三 20
*/

总结:总的来说,反射常用的方法分为三大块:
1、构造函数
2、自定义成员函数
3、变量

四、反射翻越泛型检查的例子

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");

        //下面通过反射向list中存入其他类型
        Class<ArrayList> arrayListClass = (Class<ArrayList>) list.getClass();
        Method method = arrayListClass.getMethod("add",Object.class); //这里是Object.class
        method.invoke(list,555);
        method.invoke(list,new Person());

        for(Object o2 : list)
            System.out.println(o2);
    }
}

参考文章:java反射(特别通俗易懂)深入Java反射

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值