Java程序设计——反射(Java高级应用)

目录

​编辑

1.Executable抽象类

2.Constructor类

3.Method类

4.Field类

5.Parameter类


Java中的许多对象在运行时都有两种类型:

  • 编译时类型
  • 运行时类型

在程序运行时获取对象的真实信息有以下两种做法:

  • 在知道对象的具体类型的情况下,可以先使用instanceof运算符进行判断,再使用强制类型转换将其转化成运行时的类型变量即可
  • 在无法预知该对象是属于哪些类的情况下,必须通过反射来发现该对象和类的真实信息

反射机制允许程序运行时借助Reflection API取得任何类的内部信息,并能直接操作对象的内部属性和方法

Reflection API提供了Constructor、Field和Method类,分别用于描述类的构造方法、属性和方法

Java反射机制的功能:

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时获取任意一个类的成员变量和方法
  • 在运行时调用任意一个对象的方法
  • 生成动态代理

如:获取类对象的所有方法

import java.lang.reflect.Method;

public class Demo {
    public static void main(String[] args) throws ClassNotFoundException {

        Class cs = Class.forName("java.lang.String"); // 获取String类的Class对象  
        Method[] methods = cs.getDeclaredMethods();   // 获取当前类对象的所有方法
        for (Method method: methods
             ) {
            System.out.println(method);
        }
    }
}

1.Executable抽象类

Executable抽象类派生出了Constructor和Method两个子类,其提供了大量方法来获取参数、修饰符或注解等信息

方法功能
Parameter[ ]  getParameters()获取所有形参,返回一个数组 
int getParameterCount()获取形参个数
abstract int getModifiers()获取修饰符,返回的整数是修饰符public、protected、private、final、static、abstract等关键字所对应的常量
boolean isVarArgs()判断是否包含数量可变的形参

2.Constructor类

Constructor类用于表示类的构造方法,通过调用Class对象的getConstructors()方法可以获取当前类的构造方法的集合

方法功能
String getName()返回构造方法的名称
Class[ ] getParameterTypes()返回当前构造方法的参数类型
int getModifiers()获取修饰符的整形标识,返回的整数是修饰符public、protected、private、final、static、abstract等关键字所对应的常量,需要使用Modifier工具类的方法解码后才能获得真实的修饰符
package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

public class ConstructorDemo {
    public static void main(String[] args) throws ClassNotFoundException {

        //  1.获取String类的对象
        Class cs = Class.forName("java.lang.String");

        //  2.返回所有构造方法
        Constructor[] constructors = cs.getConstructors();

        //  3.遍历所有构造方法
        for (Constructor constructor : constructors) {

            //  4.输出构造方法的名称
            String constructorName = constructor.getName();
            System.out.println(constructorName+"()");

            //  5.获取构造方法修饰符的整型标识
            int mod = constructor.getModifiers();

            //  6.使用Modifier工具类的方法输出真实的修饰符
            String modifier = Modifier.toString(mod);
            System.out.println(modifier);

            //  7.获取构造方法的参数类型
            Class[] paraTypes = constructor.getParameterTypes();

            //  8.输出构造方法的参数类型名称
            for (Class cas : paraTypes) {
                System.out.print(cas.getName() + " ");
            }
            System.out.println("\n------------------------");
        }
    }
}


3.Method类

Method类用于封装方法的信息,调用Class对象的getMethods()方法或getMethod()可以获取当前类的所有方法或指定方法

方法功能
String getName()返回方法的名称
Class[ ]  getParameterTypes()返回当前方法的参数类型
int getModifiers()返回修饰符的整形标识
Class getReturnType()返回当前方法的返回类型
package reflect;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class MethodDemo {
    public static void main(String[] args) throws ClassNotFoundException {

        //  1.获取String类的对象
        Class cs = Class.forName("java.lang.String");

        //  2.返回所有方法
        Method[] methods = cs.getMethods();

        //  3.遍历所有方法
        for (Method method : methods) {

            //  4.输出方法的名称
            String methodName = method.getName();
            System.out.println(methodName+"()");

            //  5.获取方法修饰符的整型标识
            int mod = method.getModifiers();

            //  6.使用Modifier工具类的方法输出真实的修饰符
            String modifier = Modifier.toString(mod);
            System.out.println(modifier);

            //  7.获取方法的参数类型
            Class[] paraTypes = method.getParameterTypes();

            //  8.输出方法的参数类型名称
            for (Class cas : paraTypes) {
                System.out.print(cas.getName() + " ");
            }
            System.out.println("\n------------------------");
        }
    }
}


4.Field类

Field类用于封装属性的信息,调用Class对象的getFields()或getField()方法可以获取当前类的所有属性或指定属性

方法功能
String getName()返回属性的名称
int getModifiers()返回修饰符的整型标识
getXxx(Object obj)获取属性的值,此处Xxx对应Java8中的基本类型,如果属性是引用类型,直接使用get(Object obj)方法
setXxx(Object obj,Xxx val)设置属性的值,此处Xxx对应Java8中的基本类型,如果属性是引用类型,直接使用set(Object obj,Object val)方法
Class[ ] getType()返回当前属性的类型
package reflect;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

class Student{
    private String name;
    protected int age;
    public String toString(){
        return ("姓名:" + name + "---" + "年龄:" + age);
    }
}
public class FieldDemo {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException {

        //  1.获取Student类对应的Class对象
        Class studentClass = Student.class;

        //  2.返回所有属性(不包括超类属性)
        Field[] fields = studentClass.getDeclaredFields();

        //  3.遍历所有属性
        for (Field field : fields) {

            //  4.输出属性的类型
            Class fieldType = field.getType();
            System.out.println(fieldType);

            //  5.获取属性的修饰符
            int mod = field.getModifiers();

            //  6.使用Modifier工具类输出修饰符对应的常量
            String val = Modifier.toString(mod);
            System.out.println(val);

            //  7.输出属性的名称
            String fieldName = field.getName();
            System.out.println(fieldName);
            System.out.println("----------------");
        }

        //  1.创建一个Student对象
        Student student = new Student();

        //  2.获取Student类的属性对象
        //  getDeclaredField:获取各种访问控制符的成员变量
        Field nameField = studentClass.getDeclaredField("name");
        Field ageField = studentClass.getDeclaredField("age");

        //  3.设置通过 反射 访问该类成员变量时取消访问权限检查
        nameField.setAccessible(true);
        ageField.setAccessible(true);

        //  4.获取Student类Class对象对应的实例
        Object obj = studentClass.newInstance();

        //  5.获取Student类的属性对象的值
        String name = (String) nameField.get(obj);
        int age = ageField.getInt(obj);
        System.out.println("Student类属性对象的值:" + name + ":" + age);

        //  6.设置Student类的属性对象的值
        nameField.set(student,"lisi");
        ageField.setInt(student,18);

        //  7.输出对象student的信息(默认调用toString()方法)
        System.out.println(student);
    }
}


5.Parameter类

每个Parameter对象代表方法的一个参数,调用Class对象getParameters()可以获取当前方法的所有参数,Parameter类中提供许多方法获取参数信息

方法功能
int getModifiers()返回参数的修饰符的整型标识
String getNmae()返回参数的形参名
Type getParameterizedType()获取带泛型的形参类型
Class<?>  getType()获取形参类型
boolean isVarArgs()判断该参数是否是可变参数
boolean isNamePresent()判断.class文件中是否包含方法的形参名信息
package reflect;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

class MethodParameter{
    public void test1(String str){

    }
    public void test2(int val, boolean bool){

    }
}
public class ParameterDemo {
    public static void main(String[] args) {

        //  1.获取MethodParameter类的Class对象
        Class cls = MethodParameter.class;

        //  2.获取MethodParameter类的所有方法
        Method[] methods = cls.getMethods();

        //  3.遍历MethodParameter类的所有方法
        for (Method method : methods) {

            //  4.输出该方法名
            String methodName = method.getName();
            System.out.println("方法名:" + methodName);

            //  5.输出该方法的形参个数
            int count = method.getParameterCount();
            System.out.println("形参个数:" + count);

            //  6.获取该方法的所有参数
            Parameter[] parameters = method.getParameters();

            //  7.遍历该方法的所有参数
            for (Parameter parameter : parameters) {

                //  8.输出参数名
                System.out.println("参数名:" + parameter.getName());

                //  9.输出形参类型
                System.out.println("形参类型:" + parameter.getType());

                //  10.输出泛型类型
                System.out.println("泛型类型:" + parameter.getParameterizedType());
                System.out.println("——————————————————————————————");
            }
        }
    }
}

使用javac命令编译java源文件时,默认生成的.class文件不包含方法形参名信息,所以调用getName()不能得到正确的形参名

如果希望javac命令编译java源文件时保留形参信息,则需要为编译命令指定-parameters选项


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来得晚一些也行

观众老爷,请赏~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值