深入解析Java反射

前言

Java中的反射时刻在用,如果对这哥了解不能深入,谈何了解Java?

经过个人的学习和优秀博文的整理,得到以下内容,侵删。

特别鸣谢:sczyh30

1.什么是反射

Oracle官方的解释:

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.
The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.

1.1 定义

反射 (Reflection) 是 Java 的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性。

1.2 功能

我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。程序中一般的对象的类型都是在编译期就确定下来的,而 Java 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。

简而言之:我们一般通过类寻找对象,现在我们可以通过对象寻找类,这就是反射的“反”

核心:

反射的核心是 JVM 在运行时才动态加载类或调用方法/访问属性,它不需要事先(写代码的时候或编译期)知道运行对象是谁。

Java 反射主要提供以下功能:

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法);
  • 在运行时调用任意一个对象的方法

2.反射的主要用途

有一个例子很多大神在讲的时候都会说到:

当我们在使用 IDE(如 Eclipse,IDEA)时,当我们输入一个对象或类并想调用它的属性或方法时,一按点号,编译器就会自动列出它的属性或方法,这里就会用到反射。

那么我举一个实战中的常见的例子:

在JavaEE最基础的Servlet技术中我们配置Web.xml,在xml中:

1
2
3
4
5
6
7
8
<servlet>
<servlet-name>ChangeFactory</servlet-name>
<servlet-class>com.drugs.Servlet.ChangeFactoryServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ChangeFactory</servlet-name>
<url-pattern>/ChangeFactory</url-pattern>
</servlet-mapping>

我们通过配置url/ChangeFactory,映射到com.drugs.Servlet.ChangeFactoryServlet去自动化创建类的对象并调用他的函数,执行对应的操作,这就是JVM在运行中进行的反射操作,他可以构造任意一个类的对象并且调用其中的方法。可以说反射是各种容器实现的核心。当我们深入源代码去理解的时候,就会发现反射虽小,虽基础,但是起到了非常大的作用。

3.反射的基本应用

反射相关的类一般都在java.lang.relfect包里

3.1 获得Class对象

方法有三种:

(1) 使用 Class 类的 forName 静态方法:

比如在 JDBC 开发中常用此方法加载数据库驱动:

1
2
public static Class<?> forName(String className)
java Class.forName(driver);

(2)直接获取某一个对象的 class,比如:

1
Class<?> klass = int.class;Class<?> classInt = Integer.TYPE;

(3)调用某个对象的 getClass() 方法,比如:

1
StringBuilder str = new StringBuilder("123");Class<?> klass = str.getClass();

3.2 判断是否为某个类的实例

一般地,我们用 instanceof 关键字来判断是否为某个类的实例。同时我们也可以借助反射中 Class 对象的 isInstance() 方法来判断是否为某个类的实例,它是一个 native 方法:

1
public native boolean isInstance(Object obj);

3.3 创建实例

通过反射来生成对象主要有两种方式。

  • 使用Class对象的newInstance()方法来创建Class对象对应类的实例。
1
Class<?> c = String.class;Object str = c.newInstance();
  • 先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。这种方法可以用指定的构造器构造类的实例。
1
//获取String所对应的Class对象Class<?> c = String.class;//获取String类带一个String参数的构造器Constructor constructor = c.getConstructor(String.class);//根据构造器创建实例Object obj = constructor.newInstance("23333");System.out.println(obj);

3.4 获取方法

获取某个Class对象的方法集合,主要有以下几个方法:

  • getDeclaredMethods 方法返回类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
1
public Method[] getDeclaredMethods() throws SecurityException
  • getMethods 方法返回某个类的所有公用(public)方法,包括其继承类的公用方法。
1
public Method[] getMethods() throws SecurityException
  • getMethod 方法返回一个特定的方法,其中第一个参数为方法名称,后面的参数为方法的参数对应Class的对象。
1
public Method getMethod(String name, Class<?>... parameterTypes)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值