JAVA反射

本文详细介绍了Java反射机制,包括Class类的作用、获取Class对象的三种方式、Fields、Constructor和Method的获取与使用。通过示例代码展示了如何动态获取类信息、调用方法和构造器,以及设置私有字段的访问。反射机制在运行时提供了强大的灵活性,能够增强代码的动态性。
摘要由CSDN通过智能技术生成

1. 什么是反射?

当程序在运行时,我们可以获取任意类的构造器、方法、属性等,可以调用其方法、属性等,这种动态获取类信息与动态调用对象方法的方式可以称作反射机制。

2. Class 类

  • Class类也是类的一种,与class关键字是不一样的。
  • 手动编写的类被编译后会产生一个Class对象,其表示的是创建的类的类型信息,而且这个Class对象保存在同名.class的文件中(字节码文件)
  • 每个通过关键字class标识的类,在内存中有且只有一个与之对应的Class对象来描述其类型信息,无论创建多少个实例对象,其依据的都是用一个Class对象。
  • Class类只存私有构造函数,因此对应Class对象只能由JVM创建和加载
  • Class类的对象作用是运行时提供或获得某个对象的类型信息

3. Class对象的获取

public class GetClass {
    public static void main(String[] args) {
        try {
            Class<User> userClass = User.class;
            System.out.println("根据类名:  \t" + User.class);
            System.out.println("根据对象:  \t" + new User().getClass());
            System.out.println("根据全限定类名:\t" + Class.forName("bean.User"));
            // 常用的方法
            System.out.println("获取全限定类名:\t" + userClass.getName());
            System.out.println("获取类名:\t" + userClass.getSimpleName());
            System.out.println("实例化:\t" + userClass.newInstance());
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
}
根据类名:  	class bean.User
根据对象:  	class bean.User
根据全限定类名:	class bean.User
获取全限定类名:	bean.User
获取类名:	User
实例化:	User [name=initName, age=0]

4. Fields的获取

获取fields的方法

方法返回值方法名称方法说明
FieldgetDeclaredField(String name)获取指定name名称的(包含private修饰的)字段,不包括继承的字段
Field[]getDeclaredFields()获取Class对象所表示的类或接口的所有(包含private修饰的)字段,不包括继承的字段
FieldgetField(String name)获取指定name名称、具有public修饰的字段,包含继承字段
Field[]getFields()获取修饰符为public的字段,包含继承字段
public class GetFields {
    public static void main(String[] args) {
        try{
            Class<?> aClass = Class.forName("bean.User");
            Field[] fields = aClass.getFields();
            System.out.println("获取公有字段");
            for (Field field : fields) {
                System.out.println(field.getName());
            }
            Field[] declaredFields = aClass.getDeclaredFields();
            System.out.println("获取所有字段");
            for (Field declaredField : declaredFields) {
                declaredField.setAccessible(true);
                System.out.println(declaredField.getName());
            }
            System.out.println("获取指定字段");
            System.out.println(aClass.getDeclaredField("age"));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

获取公有字段
sex
获取所有字段
name
age
sex
获取指定字段
private int bean.User.age

5. Constructor的获取

方法返回值方法名称方法说明
static Class<?>forName(String className)返回与带有给定字符串名的类或接口相关联的 Class 对象。
ConstructorgetConstructor(Class<?>… parameterTypes)返回指定参数类型、具有public访问权限的构造函数对象
Constructor<?>[]getConstructors()返回所有具有public访问权限的构造函数的Constructor对象数组
ConstructorgetDeclaredConstructor(Class<?>… parameterTypes)返回指定参数类型、所有声明的(包括private)构造函数对象
Constructor<?>[]getDeclaredConstructor()返回所有声明的(包括private)构造函数对象
TnewInstance()调用无参构造器创建此 Class 对象所表示的类的一个新实例,可传递参数。
package bean;

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

public class GetConstructor {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class<?> clazz = Class.forName("bean.User");
        //第一种方法,实例化默认构造方法,User必须无参构造函数,否则将抛异常
        User user = (User) clazz.newInstance();
        user.setAge(20);
        user.setName("Jack");
        user.setSex("男");
        System.out.println(user);

        System.out.println("--------------------------------------------");

        //获取带String参数的public构造函数
        Constructor cs1 =clazz.getConstructor(String.class);
        //创建User
        User user1= (User) cs1.newInstance("hiway");
        user1.setAge(22);
        System.out.println("user1:"+user1.toString());

        System.out.println("--------------------------------------------");

        //取得指定带int和String参数构造函数,该方法是私有构造private
        Constructor cs2=clazz.getDeclaredConstructor(String.class,int.class);
        //由于是private必须设置可访问
        cs2.setAccessible(true);
        //创建user对象
        User user2= (User) cs2.newInstance("dawdawd",25);
        System.out.println("user2:"+user2.toString());

        System.out.println("--------------------------------------------");

        //获取所有构造包含private
        Constructor<?> cons[] = clazz.getDeclaredConstructors();
        // 查看每个构造方法需要的参数
        for (int i = 0; i < cons.length; i++) {
            //获取构造函数参数类型
            Class<?> clazzs[] = cons[i].getParameterTypes();
            System.out.println("构造函数["+i+"]:"+cons[i].toString() );
            System.out.print("参数类型["+i+"]:(");
            for (int j = 0; j < clazzs.length; j++) {
                if (j == clazzs.length - 1)
                    System.out.print(clazzs[j].getName());
                else
                    System.out.print(clazzs[j].getName() + ",");
            }
            System.out.println(")");
        }
    }
}


User{name='Jack', age=20, sex='男'}
--------------------------------------------
user1:User{name='hiway', age=22, sex='null'}
--------------------------------------------
user2:User{name='dawdawd', age=25, sex='null'}
--------------------------------------------
构造函数[0]:public bean.User(java.lang.String,int,java.lang.String)
参数类型[0]:(java.lang.String,int,java.lang.String)
构造函数[1]:private bean.User(java.lang.String,int)
参数类型[1]:(java.lang.String,int)
构造函数[2]:public bean.User(java.lang.String)
参数类型[2]:(java.lang.String)
构造函数[3]:public bean.User()
参数类型[3]:()

6. method的获取

import java.lang.reflect.Method;

public class GetMethod {
    public static void main(String[] args) {
        try {
            Class<?> clazz = Class.forName("testMethod");
            Method[] methods = clazz.getDeclaredMethods();
            Object o = clazz.newInstance();
            System.out.println("获取自己声明的方法");
            for (Method method : methods) {
                System.out.println(method);
            }
            System.out.println("获取指定的方法");
            Method sum = clazz.getMethod("sum", int.class, int.class);
            System.out.println(sum);
            System.out.println("调用该方法");
            int invoke = (int) sum.invoke(o, 1,2);
            System.out.println(invoke);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
class testMethod{
    public int sum(int a, int b) {
        return a + b;
    }

    private int d(int a, int b) {
        return a * b;
    }
}

获取自己声明的方法
public int testMethod.sum(int,int)
private int testMethod.d(int,int)
获取指定的方法
public int testMethod.sum(int,int)
调用该方法
3

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值