反射

本文深入解析Java反射机制,介绍Class对象的三种获取方式,包括通过对象的getClass()方法,类名.class方式,以及使用Class.forName()方法。同时,探讨如何利用反射实例化对象,包括无参构造和有参构造的方法,以及如何通过反射调用类的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、Class对象的获取有三种方式:
(1)任何类的对象可以通过调用Object类提供的**getClass()取得该类Class对象;
(2)类名称.class可以直接根据某个具体类来取得其Class对象
(3)调用Class类的静态方法
Class.forName(String className)**传入类的全名称来取得其Class对象
且任何一个类的Class对象由JVM加载后产生(该Class对象在JVM中全局唯一)

public class Test1 {
    public static void main(String[] args) {
        /*根据类正向产生对象*/
        Date date=new Date();
        System.out.println(date);
       /*
       * 反射
       * */
       //1.类对象.getClass
        System.out.println(date.getClass());
        //2.类名称.class
        System.out.println(Date.class);
        //3.Class.forName(String className)
        try {
            System.out.println(Class.forName("java.util.Date"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        /*任何一个类的class对象有且只有一个*/
        System.out.println(date.getClass()==Date.class);//true
        try {
            System.out.println(date.getClass()==Class.forName("java.util.Date"));//true
            System.out.println(Class.forName("java.util.Date")==Date.class);//true
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

2、根据反射取得一个类的Class对象后,可以通过反射来实例化对象,在Class类中有如下方法:
(1) public T newInstance() throws InstantiationException, IllegalAccessException
这种方法只能调用无参构造,并且无参构造必须是public权限;
方法是: 类对象.newInstance();

public class CreateObject {
    public static void main(String[] args) throws Exception {
        /*1.获取类的Class对象*/
        Class<?> cls=Class.forName("java.util.Date");
        /*2.通过反射取得Date的实例化对象*/
        Date date=cls.newInstance();
        System.out.println(date);
    }
}

(2)还有一种是Constructor类提供的实例化对象的方法:
public T newInstance(Object … initargs)
方法是:在使用newInstance之前,要先获取构造方法Constructor,再对象.newInstance(…);括号内是要赋予对象属性的值;
而要获取本类中有参构造方法的方式有:
public Constructor getDeclaredConstructor(Class<?>… parameterTypes)
或者 public Constructor getConstructor(Class<?>… parameterTypes)

class Parent {
    private String name;
    private Integer age;
    public Parent(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Parent{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class CreateObject2 {

    public static void main(String[] args) {

        Class<?> cls = Parent.class;
        /*获取构造方法*/
        try {
     //如果类中的构造方法是私有的,getDeclaredConstructor能够拿到该构造方法,但是不能实例化对象
     //要传入获取特定构造方法中的属性的class对象
            Constructor constructor = cls.getDeclaredConstructor(String.class, Integer.class);
            Parent parent = (Parent) constructor.newInstance("张三", 14);//传入实例化的属性值
            System.out.println(parent);
        } catch (NoSuchMethodException | InstantiationException | InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();
        }

    }
}

3.根据反射可以获取类的方法

取得类中指定名称的普通方法
public Method getMethod(String name, Class<?>… parameterTypes)

public Method getDeclaredMethod(String name, Class<?>… parameterTypes)

既要传名称又要传类型,是因为:方法有重载;

取得类中全部普通方法
public Method[] getMethods() throws SecurityException

:取得本类以及父类中所有public方法,

public Method[] getDeclaredMethods() throws SecurityException

:取得本类中所有全部普通方法,包含私有方法;

Method类中提供调用类中普通方法的API:
public Object invoke(Object obj, Object… args) 传入实例化对象和获取到的方法的参数值

        //先获取类对象
          Class<?> cls= Per.class;
          /*创建实例化对象*/
            Per per= (Per) cls.newInstance();
            /*拿到这个类中的setName的方法,传入方法的名称,如果该方法有参数,还要传入参数的类型*/
           Method method= cls.getMethod("setName", String.class);
           /*通过invoke进行调用,invoke方法内要传入创建好的实例化对象,如果该方法有参数再传入要赋予该对象的值*/
            method.invoke(per,"李四");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值