Java反射

1.1Java反射概述

反射(Reflection)机制是Java语言特性之一,是Java被视为动态(或准动态)语言的一个关键特性。

1.1.1什么是反射

在计算机领域,反射指一种能力,能够自描述和自控制,即在运行状态中,动态获取类信息及动态调用实例方法的能力。

Java 反射有以下3个动态特性:

运行时创建实例
运行期间调用方法
运行时更改属性

之前我们所运行的程序都是在编译时就已经链接了所有所需的类,而 Java 反射机制则允许程序在运行时再加载、探知、使用那些在编译时综全未知的类。例如,在之前课程中使用 JDBC 时、使用Class.forName0方法通过一个字符串形式的类名查找并加载驱动类,就是对反射机制的初步运用每个项目中使用的数据库产品和版本都不是一成不变的,在代码中用 new 关键字实例化驱动类的传统做法是不明智的,而利用反射机制则可以在运行时读取配置文件中的驱动类名,动态加载所需的驱动类。

反射机制允许 Java 程序加载一个运行时才得知其名称的类,获悉其完整 API 信息,包括其修饰符(诸如 public、static 等)、超类、实现的接口,也包括属性和方法的所有信息:并可生成其实例、对其属性赋值或调用其方法。通过 Java 反射可以实现以下功能:

在运行时探知任意一个实例所属的类。
在运行时构造任意一个类的实例。
在运行时探知任意一个类所具有的方法和属性
在运行时调用任意一个实例的方法。

就像照镜子能够看清自己,反射使程序可以看清一个类的情况并加以使用。Java 反射机制能够探知类的基本结构,这种对 Java 类结构探知的能力,称为 Java 类的“自审”。并且,反射机制是构建框架技术的基础所在,掌握 Java 反射机制,对以后学习框架技术有很大的帮助。

1.1.2 Java反射常用API

使用Java反射技术,常用的类如下:

java.lang.Class<T>类:反射的核心类,反射所有的操作都是围绕该类来生成的。通过 Class 类
可以获取类的属性、方法等内容信息
java.lang.reflect.Constructor<T>类;表示类的构造方法
java.langreflect.Field 类:表示类的属性,可以获取和设置类中属性的值。
java.lang.reflect.Method类:表示类的方法,可以用来获取类中方法的信息或执行方法.

1.2反射的应用

在Java 程序中使用反射的基本步骤如下
(1)导入java.lang.reflect 包中的相关类
(2)获得需要操作的类的 Class 实例。
(3) 调用 Class 实例的方法获取 Field、Method 等实例
(4)使用反射API操作实例成员。

1.2.1获取类的信息

一个类或接口被加载后,从系统中都能获得一个代表该类或接口的 Class 类型的实例,通过该实例就可以访问到 Java 虚拟机中的这个类或接口。

1.获取 Class 实例

Java 程序中获得 Class 实例通常有如下 3种方式,可根据实际情况灵活选择。

 调用类或接口实例的gtClass0方法。

getClass0方法是java.lang.Objet 类中的一个方法,所有类和接口的实例都可以调用该方法,该方法会返回该实例的所属类型所对应的 Class 实例。例如,对于通过入参或返回值得到的某个实例获取其类型信息,使用方式如下面的代码所示。

class clz - obj.getclass(); // obj为某个类型的实例

调用类或接口的 class 属性。

在某些类或接口没有实例或无法创建实例的情况下,可以通过其 class 属性获取所对应的 Class实例,这种方式需要在编译期就知道类或接口的名称。使用的方式如下面代码所示。

Class clz = student.class; // student 为自定义的学生类型

     上述代码中,Student.class 将会返回 Student 类对应的 Class 类型的实例。

使用 Class.forName0方法。

若编码时无法确认具体类型,需要程序在运行时根据情况灵活加载,可以使用 Class 类的 forName0方法。该方法是静态方法,需要传入字符串参数,该字符串参数的值是某个类的完全限定类名,即包含包名的完整类名。

Class clz = Class.forName ("com.mysql.cj.jdbc.Driver");

上述代码中的参数值可通过配置文件等灵活设置。如果传入的字符串类名不准确,或者项目中没有包含指定的类型,就会抛出一个 ClassNotFoundException 异常。

java. lang. ClassNotFoundException: com. mysql.cj. jdbc.Driver

 2.从 Class 实例获取信息

在获得了某个类型对应的 Class 实例之后,就可以调用 Class 实例的方法来获得该类型的信息。Class类提供了大量实例方法来获取对应类型的详细信息。

获取对应类型的基本信息,相关方法如表 

方法说明
String getName()以字符事形式返回该类型的名称
String getSimpleName()以字符串形式返回该类型的简称
Package getPackage()获取该类型所在的包
Class getSuperclass()返回该类型的超类的 Class 实例
Classfl getlnterfaces()返回该类型所实现的全部接口的 Class 实例
int getModifiers()返回该类型的所有修饰符,由 public、protected、private、fnal、staic、abstract 等对应的it常量组成,返回的整数应使用 Modifier 工具类来解码,才可以判断修饰符的构成
Classf [] getDeclaredClasses()返回该类型中包含的全部内部类的 Class 实例
Class getDeclaringClass()返回该类型所在的外部类的 Class 实例
创建两个JavaBean,用于测试通过反射的方式获取类型信息

创建两个JavaBean;BaseClass 和 Person 用于测试,其中 Person 继承自 BaseClass

关键代码:

(1)创建基类 BaseClass,无须定义任何成员,关键代码如下

publie class BaseClass ()

(2)创建Person类继承BaseClass.添加测试用的属性方法构造方法等,关键代码如下

public final class Person extends BaseClass implements java,io,Serializable{

    // 成员变量
    private String name;
    static final int age = 30;
    protected String address;
    public string messager
    
    // 成员方法
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    static final int getAge() { return age; }
    protected String getAddress() { return address; }
    private void silentMethod() throws IOException, NullPointerException{
        System.out,println("这是悄悄话");
    }

    //以下声明用于通过反射获取构造方法信息测试
    public Person() {}
    private Person(String name) { this.name = name; }
    protected Person(String name,String address,String message){
        this.name = name;
        this.address = address;
        this.message = message;
    }
    public String toString(){
        return "{name:" + name + ",age:" + age + ", address:" + address + 
        ", message:" + message + "}";
    }
}    
通过反方式获取示例1中 Person 类的类型信息,包括所在包、修饰符、继承关系、实现的接口关键代码:
public class PersonTest {
    public static void main(String[] args) {
        Class clz = Person.class;
        String fullName = clz.getName();
        String simpleName = clz.getSimpleName();
        System.out.println("以下是" + fullName + "类的基本信息");
        System.out.println("-------------------------------");

        //获取Person类所在的包
        Package pkg = clz.getPackage();
        System.out.println(simpleName + "定义在:" + pkg.getName() + "包中");
        System.out.println("-------------------------------");

        //获得clz所表示的实体(类,接口,基本类型或void)的超类的Class
        //获得clz表示Object类、一个接口、一个基本类型或void,则返回null
        //如果clz表示一个数组类,则返回表示Object类的Class实例
        Class superClass = clz.getSuperclass();
        System.out.println(simpleName + "类的超类是:" + superClass.getName());
        System.out.println("-------------------------------");

        //获得clz所表示的类实现的接口
        //如果clz表示一个不实现任何接口的类或接口,则此方法返回一个长度为0的数组
        //如果clz表示一个基本类型或void,则此方法返回一个长度为0的数组
        Class[] interfaces = clz.getInterfaces();
        System.out.println(simpleName + "类所实现的接口:");
        for (Class c : interfaces){
            System.out.println("\t" + c.getName());
            System.out.println("-------------------------------");
        }

        //每个修饰符对应一个Int常量,返回的修饰符信息将类所拥有的修饰符以“或”运算组合
        //通过与Modifier类中的常量进行“与”运算即可判断该类型是否拥有某个修饰符
        int modifier = clz.getModifiers();
        System.out.println(simpleName + "类的修饰符:");
        if ((modifier & Modifier.PUBLIC) == Modifier.PUBLIC){
            System.out.println("\t访问修饰符是:public");
        }else {
            System.out.println("\t访问修饰符是:default(package)");
        }
        if ((modifier & Modifier.FINAL) == Modifier.FINAL)
            System.out.println("\t这个类是final的");
        if ((modifier & Modifier.ABSTRACT) == Modifier.ABSTRACT)
            System.out.println("\t这是一个抽象类");
        if ((modifier & Modifier.INTERFACE) == Modifier.INTERFACE)
            System.out.println("\t这是一个接口");
    }
}

测试结果:

以下是reflect.entity.Person类的基本信息
-------------------------------
Person定义在:reflect.entity包中
-------------------------------
Person类的超类是:reflect.entity.BaseClass
-------------------------------
Person类所实现的接口:
	java.io.Serializable
-------------------------------
Person类的修饰符:
	访问修饰符是:public
	这个类是final的

 获取对应类型所包含的构造方法,常用方法如表:

方法说明
Constructor gerConstructor(Class... params)返回该类型指定参数列表的 public 构造方法,构造方法的参列表与 params所指定的类型列表所匹配。例如:
Constructor co = clz.getConstructor(String.class, List.class):其中,clz 为某 Class 实例
ConstructorgerConstructors()返回该类型的所有 public 构造方法
Constructor getDeclaredConstructor(Class... params)返回该类型的指定参数列表的构造方法,访问级别不限
Constructorl getDeclaredConstructors()返回该类型的所有构造方法,访问级别不限
通过反射获取类的构造方法信息

通过反射方式获取示例中 Person 类的构造方法信息,查看构造方法的修饰符及参数列表关键代码:

public class PersonTest2 {
    public static void main(String[] args) {
        //获取Person类什么的所有构造方法
        //它们是公共、保护、默认(包)访问和私有构造方法
        //如果此Class实例表示一个接口、一个基本类型、一个数组类或void,则此方法返回一个长度为0的数组

        // 获取Person类声明的所有构造方法
        // 它们是公共、保护、默认(包)访问和私有构造方法
        // 如果此class示例表示一个接口、一个基本类型、一个数组类或void,则
        // 此方法返回一个长度为0的数组
        Constructor[] cons = Person.class.getDeclaredConstructors();

        // 构造方法的一些信息
        System.out.println("=================构造方法展示==============");
        for (Constructor con : cons){
            System.out.print("访问修饰符:");
            int modifier = con.getModifiers();

            // 判断该构造方法的访问修饰符
            if ((modifier & Modifier.PUBLIC) == Modifier.PUBLIC)
                System.out.println("public");
            else if ((modifier & Modifier.PROTECTED) == Modifier.PROTECTED)
                System.out.println("protected");
            else if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE)
                System.out.println("private");
            else
                System.out.println("default(package)");

            // 获取构造方法的参数列表
            Class[] params = con.getParameterTypes();
            if (params.length==0){
                System.out.println("该构造方法没有参数 ");
            }else {
                System.out.print("该构造方法的参数列表为:[");
                for (int i = 0; i < params.length; i++){
                    if (i != 0)
                        System.out.print(", ");
                    System.out.print(params[i].getName());
                }
                System.out.println("]");
            }
            System.out.println("---------------------------");
        }
    }
}

测试结果:

=================构造方法展示==============
访问修饰符:public
该构造方法没有参数 
---------------------------
访问修饰符:protected
该构造方法的参数列表为:[java.lang.String, java.lang.String, java.lang.String]
---------------------------
访问修饰符:private
该构造方法的参数列表为:[java.lang.String]
---------------------------

进程已结束,退出代码0

获取对应类型所包含的属性,常用方法如表

方法        说明
Field getField(String name)        返回该类型中指定名称的 public 属性,name 参数用于指定属性名称。制如:clzgetField("age”)://c为某Class 对象,age 为属性名
Field] getFields()返回该类型中的所有 public 属性        
Field getDeclaredField(String name)返回该类型中指定名称的属性,与属性的访问级别无关
Field[] getDeclaredFields()返回该类型中的全部属性,与属性的访问级别无关        
通过反射方式获取类中的属性信息

通过反射方式获取示例1中 Person 类的属性信息,查看属性名、类型、修饰符

关键代码:

public class PersonTest3 {
    public static void main(String[] args) {
        //获取Person类中的所有属性
        //包括公共、保护、默认、私有,但不包括继承的属性
        //如果该类或接口不声明任何属性,或者此Class实例表示一个基本类型、
        //一个数组或void,则此方法返回一个长度为0的数组
        Field[] fields = Person.class.getDeclaredFields();

        //展示属性的一些信息
        System.out.println("==============属性展示==============");
        for (Field field : fields){
            System.out.println("属性名:" + field.getName());
            System.out.println("类型:" + field.getType().getName());
            System.out.print("访问修饰符:");
            int modifier = field.getModifiers();
            //判断该属性的访问修饰符
            if ((modifier & Modifier.PUBLIC) == Modifier.PUBLIC)
                System.out.println("public");
            else if ((modifier & Modifier.PROTECTED) == Modifier.PROTECTED)
                System.out.println("protected");
            else if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE)
                System.out.println("private");
            else
                System.out.println("default(package)");

            //判断该属性是否有static修饰符
            if ((modifier & Modifier.STATIC) == Modifier.STATIC)
                System.out.println("这是一个静态属性");
            //判断该属性是否有final修饰符
            if ((modifier & Modifier.FINAL) == Modifier.FINAL){
                System.out.println("这是一个final属性");
            }
            System.out.println("--------------------------");
        }//遍历属性结束
    }
}

测试结果:

==============属性展示==============
属性名:name
类型:java.lang.String
访问修饰符:private
--------------------------
属性名:age
类型:int
访问修饰符:default(package)
这是一个静态属性
这是一个final属性
--------------------------
属性名:address
类型:java.lang.String
访问修饰符:protected
--------------------------
属性名:message
类型:java.lang.String
访问修饰符:public
--------------------------

进程已结束,退出代码0

 访问对应类型所包含的方法,常用方法如表 

方法说明
Method getMethod(String name,
Class... params)
返回该实例中指定的 public 方法,name 参数用于指定方法名称,params 参数指定参数列表。例如:
clz.getMethod("info",String.class); //clz 为某 Class 实例
clz.getMethod("info",String.class, Integer.class);
Method[] getMethods()返回该实例中所有 public 方法
Method getDeclaredMethod(String name,Class... params)返回该实例中指定的方法,与方法的访问级别无关
Method] getDeclaredMethods()返回该实例中的全部方法,与方法的访问级别无关
 通过反射获取类型中的方法信息

通过反射获取示例中 Person 类的方法信息,包括方法名、修饰符、返回值、参数列表、异常列
表等

关键代码:

public class PersonTest4 {
    public static void main(String[] args) {
        //获取Person类中的所有方法
        //包括公共、保护、默认访问和私有方法,但不包括继承的方法
        //如果该类或接口不声明任何方法,或者此Class实例表示一个基本类型
        //一个数组或void,则此方法返回一个长度为0的数组
        Method[] methods = Person.class.getDeclaredMethods();

        //展示方法的一些信息
        System.out.println("===========方法展示===========");
        for (Method method : methods){
            System.out.println("方法名:" + method.getName());
            System.out.println("返回值类型:" + method.getReturnType().getName());

            //获取方法的参数列表
            Class[] params = method.getParameterTypes();
            if (params.length==0){
                System.out.println("该构造方法没有参数 ");
            }else {
                System.out.print("该构造方法的参数列表为:[");
                for (int i = 0; i < params.length; i++){
                    if (i != 0)
                        System.out.print(", ");
                    System.out.print(params[i].getName());
                }
                System.out.println("]");
            }

            System.out.print("访问修饰符:");
            int modifier = method.getModifiers();
            //判断该属性的访问修饰符
            if ((modifier & Modifier.PUBLIC) == Modifier.PUBLIC)
                System.out.println("public");
            else if ((modifier & Modifier.PROTECTED) == Modifier.PROTECTED)
                System.out.println("protected");
            else if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE)
                System.out.println("private");
            else
                System.out.println("default(package)");

            //判断该方法是否有static修饰符
            if ((modifier & Modifier.STATIC) == Modifier.STATIC)
                System.out.println("这是一个静态方法");
            //判断该方法是否有final修饰符
            if ((modifier & Modifier.FINAL) == Modifier.FINAL)
                System.out.println("这是一个final方法");
            //判断该方法是否有ABSTRACT修饰符
            if ((modifier & Modifier.ABSTRACT) == Modifier.ABSTRACT)
                System.out.println("这是一个ABSTRACT方法");
            //判断该方法是否有SYNCHRONIZED修饰符
            if ((modifier & Modifier.SYNCHRONIZED) == Modifier.SYNCHRONIZED)
                System.out.println("这是一个SYNCHRONIZED方法");

            //获取方法所属的类的接口的Class实例
            Class declaringClass = method.getDeclaringClass();
            System.out.println("方法声明在:" + declaringClass.getName() + "中");

            //获取方法抛出的异常类型,即throws子句中声明的异常
            Class[] exceptions = method.getExceptionTypes();
            if (exceptions.length > 0){
                System.out.print("该方法抛出的异常有:[");
                for (int i = 0; i < exceptions.length; i++){
                    if (i != 0){
                        System.out.print(",");
                    }
                    System.out.print(exceptions[i].getName());
                }
                System.out.println("]");
            }
            System.out.println("-----------------------------------");
        }
    }
}

测试结果:

===========方法展示===========
方法名:toString
返回值类型:java.lang.String
该构造方法没有参数 
访问修饰符:public
方法声明在:reflect.entity.Person中
-----------------------------------
方法名:getAddress
返回值类型:java.lang.String
该构造方法没有参数 
访问修饰符:protected
方法声明在:reflect.entity.Person中
-----------------------------------
方法名:getName
返回值类型:java.lang.String
该构造方法没有参数 
访问修饰符:public
方法声明在:reflect.entity.Person中
-----------------------------------
方法名:setName
返回值类型:void
该构造方法的参数列表为:[java.lang.String]
访问修饰符:public
方法声明在:reflect.entity.Person中
-----------------------------------
方法名:getAge
返回值类型:int
该构造方法没有参数 
访问修饰符:default(package)
这是一个静态方法
这是一个final方法
方法声明在:reflect.entity.Person中
-----------------------------------
方法名:silentMethod
返回值类型:void
该构造方法没有参数 
访问修饰符:private
方法声明在:reflect.entity.Person中
该方法抛出的异常有:[java.io.IOException,java.lang.NullPointerException]
-----------------------------------

进程已结束,退出代码0

 Class 实例可以获得相关类型中的构造方法、属性、方法等成员信息。其中,构造方法由 Constructor类型表示,属性由 Field类型表示,方法由 Method类型表示。Constructor、Field、Method这3个类都定义在java.lang.reflect包下,并实现了java.langreflect.Member 接口。程序可以通过Constructor 实例来调

用相应的构造方法创建相美类型的实例,通过 Field 实例直接访问并修改相关类型实例的属性值,通过Method例来执行相关类型实例的方法

1.2.3 创建实例

潘过天新来合建Jna美型的实例有如下两种方式。

使居Cass文的newlnstanee0方法创建相关类型的实例
使用Oonsiructor实例创建相关类型的实例。
使用Class 的 newnstance0方法创建相关类型的实例,如示例所示,这种方式要求该 Class史驾相关的类型有无参构进方法,执行newlnstance0方法实际上就是调用无参构造方法来创建实例

使用Class.newInstance()方法创建示例中Person类的实例

关键代码:

public class PersonTest5 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class clz = Class.forName("reflect.entity.Person");
        Object obj = clz.newInstance();//调用Person类的无参构造创建Person类实例
        System.out.println(obj);//调用Person实例的toString()方法,属性均为默认值
    }
}

测试结果:

{name:null,age:30, address:null, message:null}

如果创建Java 实例时,需要使用指定的构造方法,则可以利用Constructor 实例,如示例所示每个Constructor实例对应一个构造方法指定构造方法来创建Java对象的步如下

(1)获取与该类型相关的 Class 实例。
(2)调用Class实例的方法获取表示指定构造方法的Constructor实例。

(3)调用Constructor实例的newInstance0方法来创建相关类型的实例

利用Constructor实例通过指定构造方法创建示例中Person类的实例

关键代码:

public class PersonTest6 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class clz = Class.forName("reflect.entity.Person");
        //获取Person的无参构造:public Person()
        Constructor c1 = clz.getDeclaredConstructor();
        //Person的无参构造为public,这里可以直接访问
        Object obj = c1.newInstance();
        System.out.println(obj);

        //获取Person的单参构造:private Person(String)
        Constructor c2 = clz.getDeclaredConstructor(String.class);
        //Person的单参构造为private,这里已超出其访问范围,不能直接访问
        //通过setAccessable方法,设定为可以访问
        c2.setAccessible(true);
        obj = c2.newInstance("New Person");
        System.out.println(obj);

        //获取Person的三参构造:protected Person(String,String,String)
        Constructor c3 = clz.getDeclaredConstructor(String.class,String.class,String.class);
        //Person的三参构造为protected,这里已超出其访问范围,不能直接访问
        //通过setAccessable方法,设定为可以访问
        c3.setAccessible(true);
        obj = c3.newInstance("New Person","beijing","Hello!");
        System.out.println(obj);
    }
}

测试结果:

{name:null,age:30, address:null, message:null}
{name:New Person,age:30, address:null, message:null}
{name:New Person,age:30, address:beijing, message:Hello!}

注意:

受访问修饰符的限制,使用反射方式访问超出访问范围的构造方法、属性、方法时,会引发java.lang.IllegalAccessException 异常。若要禁止Java 语言访问检查强行访问,需要设置相关实例为可访问,语法如下。
c3.setAccessible(true);// 通过构造方法/属性/方法实例调用
当然此种做法会破坏封装,需谨慎使用。

1.2.4 访问类的属性

使用 Field 实例可以对属性进行取值或赋值操作,主要方法如表

方法说明
xxx getXxx(Object obj)xxx 表示8 种基本数据类型之一,如 int getInt(Object obj)。obj 为该属性所在类的实例。假设 instance 表示A 类的实例,feld 表示A类中的属性 a,则 field.getInt(instance)表示以 int 类型返回 instance 中属性a 的值。若 Field 实例表示的是一个静态属性,则 obj可以设置为 null
Object get(Object obj)以 Object 类型返回 obj 中相关属性的值
void setXxx(Object obj, xxx val)将 obj 中相关属性的值设置为 val。xxx 为8 种基本数据类型之一
void set(Object obj, Object val)将 obj 中相关属性的值设置为 val
void setAccessible(boolean flag)对相关属性设置访问权限。设置为 true 可以禁止 Java 语言访问检查

通过反射方式访问示例中Person 类的name 属性,实现取值和赋值

关键代码:

public class PersonTest7 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //通过反射加载一个Person实例
        Class clz = Class.forName("reflect.entity.Person");
        Object person = clz.newInstance();

        //获取private String name 属性
        Field name = clz.getDeclaredField("name");
        //name属性为private,这里已超出其访问范围,不能直接访问
        //通过setAccessable方法,设定为可以访问
        name.setAccessible(true);
        //先取值看一下
        System.out.println("赋值前的name:" + name.get(person));
        //为name属性赋值
        name.set(person,"New Person");
        //展现赋值效果
        System.out.println("赋值后的name:" + name.get(person));
    }
}

测试结果:

赋值前的name:null
赋值后的name:New Person

注意:

示例 8中没有用 getField0方法来获取属性,因为 getField0方法只能获取 public 访问权限的属性,而使用 getDeclaredField0方法则可以获取所有访问权限的属性。

1.2.6调用类的方法

Method类中包含一个ivoke0方法通过invoke0方法Method实例可以调用Java类的实例方注和静态方法。imvoke()方法定义如下

Obiect invoke(Object obj, Object.. args);

其中obj是执行该方法的对象,args 是执行该方法时传入的参数例如,method 表示A类中的fun0方法,instance是A类的实例,则methodinwoke(instoceags)表示调用instance的fun0方法并传入参数args。
若Method实例表示的是一个静态方法,则obj可以为null

通过反射方式调用示例Person类的方法,包括实例方法及静态方法。

关键代码:

public class PersonTest8 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        //通过反射加载Person类
        Class clz = Class.forName("reflect.entity.Person");
        //根据方法名和参数列表获取static final int getAge()方法
        //没有参数可以不写或用null表示
        Method getAge = clz.getDeclaredMethod("getAge",null);
        //getAge方法为default(package),这里已超出其访问范围,不能直接访问
        //通过setAccessable方法,设定为可以访问
        getAge.setAccessible(true);
        //调用getAge方法并传参,没有参数可以不写或用null表示
        //getAge方法为静态方法,调用时可以不指定具体Person实例
        Object returnAge = getAge.invoke(null,null);
        System.out.println("年龄是:" + returnAge);

        Object person = clz.newInstance();//创建Person实例

        //根据方法名和参数列表获取private void silentMethod()方法
        //没有参数可以不写或用null表示
        Method silentMethod = clz.getDeclaredMethod("silentMethod",null);
        //silentMethod方法为private,这里已超出其访问范围,不能直接访问
        //通过setAccessable方法,设定为可以访问
        silentMethod.setAccessible(true);
        //调用silentMethod方法并传参,没有参数可以不写或用null表示
        silentMethod.invoke(person,null);

        //根据方法名和参数列表获取public void setName(String)表示
        Method setName = clz.getDeclaredMethod("setName", String.class);
        //setName方法为public,这里可以直接访问
        //调用setName方法并传参
        setName.invoke(person,"New Person");
        //验证一下结果,调用public String getName()方法得到name的值
        Object returnName = clz.getDeclaredMethod("getName").invoke(person);
        System.out.println("刚才设定的name是:" + returnName);
    }
}

测试结果:

年龄是:30
这是悄悄话
刚才设定的name是:New Person

总结:

①java反射机制是指在运行状态中,动态获取类型信息及动态访问实例成员的能力。

②使用反射可以在程序运行时创建类的实例及访问其属性和方法。

③反射在java框架技术中有着大量的应用

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值