Java反射机制详解

反射

如何在运行期间查找对象和类信息

主要用两种形式:

  • 传统的“RTTI”,他假定我们已知编译和运行期拥有所有类型。
  • Java反射机制,利用他可在运行期独立查找类信息。

为什么不用RTTI,因为它有一个限制:类型必须是在编译期间已知的。

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。对于一个对象,都能够调用它的任意方法和属性。

这种动态获取信息以及动态调用对象的方法的功能称为Java语言的反射机制。


用反射的条件?

要想使用反射机制,就必须要先获取该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法、属性、类名、父类、实现的所有接口等等)。

在运行期,一旦我们想生成那个类的一个对象,用于执行程序的JVM首先会检查那个类型的class对象是否已经载入。若尚未载入,JVM就会查找同名的.class文件,并将其载入。

每一个类对应着一个字节码文件也就对应着一个class类型的对象,也就是字节码文件对象。


反射常用API

在反射中,要获取一个类或调用一个类的方法,我们首先需要获取到该类的class对象。

1.获取反射中的class对象

首先我们介绍一下动态加载静态加载

动态加载:程序在运行时调用相应方法,即使其他方法是错误的,程序依旧会执行。通过动态加载可以让程序的可延长性大大提升,对以后的维护和扩展有重要意义。

静态加载:程序在编译时执行。在执行过程中加载所有可能执行到的程序。在这种加载方式下,只要加载中一个方法出错,程序就不能运行。我们一般写程序默认的是静态加载。

有三种方法:

  • 当知道该类的全路径名时,可以使用Class.forName(类名)
    • 动态加载,运行时,开始装入类,并作类的静态初始化。
    • 指定什么类名就获取什么类字节码文件对象。
    • 该方法含义是加载参数指定的类,并且初始化他。
  • Class clz = String.class只适合在编译前就知道要操作的Class。
    • 静态加载(编译时已加载)
  • 通过类对象的获取class对象obj.getClass()。
    • 静态加载(编译时已加载)

第一种有更好的扩展性,所以一般情况下,第一种用的较多。


2.通过反射创建类对象

有两种方式:

  • 通过Class对象的newInstance()方法

    • Class clz = Person.class;Person per = (Person)clz.newInstance();
  • 通过Constructor对象的newInstance()

    • 选择无参构造方法构造对象:
    Class clz = Person.class;
    Constructor constructor = clz.getConstructor();
    Person per = (Person)constructor.newInstance();
    • 选择带参的构造方法来构造对象
    Class clz = Person.class;
    Constructor constructor = clz.getConstructor(String.class, int.class);
    Person per = (Person)constructor.newInstance("小明", 15);

3.通过反射获取类属性、方法、构造器

通过class对象的getFields()可以获取到class的非私有属性。

通过class对象的getDeclaredFields()方法可以获取包括私有属性在内的所有属性。

通过class对象得getMethods获取该类中的所有方法,包括继承和实现的方法。

通过class对象得getDeclaredMethods获取该类中的所有方法(包括私有方法),不包括包括继承方法。

PS:私有方法和私有属性不能直接访问,因为权限不够。不过还是有办法的。

  • method.setAccessible(true)

  • field.setAccessible(true)


4.通过反射调用私有方法

通过反射,我们可以调用其它类的私有方法。

import java.lang.reflect.Method;

class A
{
    private void pow(int n)
    {
        System.out.println(n * n);
    }
}

class Test
{
    public static void main(String args[]) throws Exception
    {
        Class<A> c = A.class;
        Object obj = c.newInstance();

        Method m = c.getDeclaredMethod("pow", new Class[]{ int.class });
        m.setAccessible(true);//修改访问权限
        m.invoke(obj, 4);//调用方法
    }
}

转载于:https://www.cnblogs.com/yjz6/p/9799598.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值