Java反射,越过泛型检查,动态配置

本文详细探讨了Java反射机制,包括如何获取Class对象、反射获取和使用构造方法、成员变量和成员方法。通过实例展示了反射如何越过泛型检查,使能装Student的集合也能装其他数据类型。同时,展示了反射在动态配置中的应用,通过修改配置文件即可改变程序运行时调用的方法。

反射概述

  • Java反射机制:是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用再编译期就完成确定,在运行期仍然可以扩展

我们以下的例子都是基于这个学生类Student来操作,下面是学生类Student的代码

学生类有:

  • 静态属性:

  • 私有-介绍-String-introduce
  • 成员属性:

  • 公共-姓名-String-name-;
  • 默认-编号-int-no;
  • 私有-年龄-int-age
  • 构造方法:

  • 公共构造方法,Student()
  • 默认构造方法,Student(String name, int age)
  • 私有构造方法,Student(String name, int no, int age)
  • 静态方法:

  • private static String introduce()
  • 成员方法

  • 公共无参无返回值方法:public void love()
  • 默认无参无返回值方法:void lovelorn()
  • 私有带参无返回值方法:private void love(Student s)
  • 私有无参有返回值方法:private String dream()
  • 重写toString方法

 

package com.testReflex;

/**
 * @author 林高禄
 * @create 2020-06-05-16:49
 */
public class Student {
    // 静态属性
    private static final String INTRODUCE="这是学生类";
    // 成员属性:一个公共,一个默认,一个私有
    public String name;
    int no;
    private int age;

    // 构造器,一个公共,一个默认,一个私有
    public Student() {
    }

    Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    private Student(String name, int no, int age) {
        this.name = name;
        this.no = no;
        this.age = age;
    }

    // 静态方法
    public static String introduce(){
        System.out.println(INTRODUCE);
        return INTRODUCE;
    }

    // 成员方法:一个公共,一个默认,一个私有带参,一个私有有返回值
    public void love(){
        System.out.println("暗恋中!");
    }

    void lovelorn(){
        System.out.println("失恋了!");
    }

    private void love(Student s){
        System.out.println("正在和【"+s.name+"】谈恋爱!");
    }

    private String dream(){
        return "好好学日语!";
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", no=" + no +
                ", age=" + age +
                '}';
    }

}

获取Class类的对象

我们要想通过反射去使用一个类,首先我们要获取到该类的字节码文件对象,也就是类型为Class类型的对象,这里我们提供三种方式获取Cass类型的对象

  • 使用类的class属性来获取该类对应的Class对象。举例:Student.class将会返回Student类对应的Class对象
  • 调用对象的getClass()方法,返回该对象所属类对应的Class对象,该方法是Object中的方法,所有的Java对象都可以调用该方法
  • 使用Class类中的静态方法forName(String className),该方法需要传入字符串参数,该字符串参数的值是某个类的全路径,也就是完整包名的路径
package com.testReflex;

/**
 * @author 林高禄
 * @create 2020-06-05-17:02
 */
public class GetClassDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        // 使用类的class属性来获取该类对应的Class对象
        Class<Student> studentClass = Student.class;
        System.out.println(studentClass);
        Class<Student> studentClass2 = Student.class;
        System.out.println(studentClass == studentClass2);

        // 调用对象的getClass()方法,返回该对象所属类对应的Class对象
        Student student = new Student();
        Class<? extends Student> aClass = student.getClass();
        System.out.println(studentClass == aClass);

        // 使用Class类中的静态方法forName(String className)
        Class<?> aClass1 = Class.forName("com.testReflex.Student");
        System.out.println(studentClass == aClass1);

    }
}

运行输出:

class com.testReflex.Student
true
true
true

从输出三个true可以看出,通过这三种方法获取的类的对象都是同一个对象

反射获取构造方法并使用

calss类中用于获取构造方法的方法

  • Constructor<?>[] getConstructors():返回所有公共构造方法对象的数组
  • Constructor<?>[] getDeclaredConstructors():返回所有构造方法对象的数组
  • Constructor<T> getConstructor(Class<?>...parameterTypes):返回单个公共构造方法对象
  • Constructor<T> getDeclaredConstructor(Class<?>...parameterTypes):返回单个构造方法对象

 反射获取构造方法

package com.testReflex;

import java.lang.reflect.Constructor;
import java.util.stream.Stream;

/**
 * @author 林高禄
 * @create 2020-06-07-10:41
 */
public class GetConstructorDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        // 使用Class类中的静态方法forName(String className)
        Class<?> c = Class.forName("com.testReflex.Student");
        System.out.println("-----------构造方法的获取-----------");
        // 获取公共的构造方法
        System.out.println("获取公共的构造方法");
        Constructor<?>[] publicConstructors = c.getConstructors();
        Stream.of(publicConstructors).forEach(System.out::println);
        // 获取所有的构造方法
        System.out.println("获取所有的构造方法");
        Constructor<?>[] allConstructors = c.getDeclaredConstructors();
        Stream.of(allConstructors).forEach(System.out::println);
        // 获取单个公共的构造方法
        System.out.println("获取单个公共的构造方法");
        Constructor<?> publicConstructor = c.getConstructor();
        System.out.println(publicConstructor);
        // 报错Exception in thread "main" java.lang.NoSuchMethodException: com.testReflex.Student.<init>(java.lang.String, int)
        // 没有这样的方,因为getConstructor(Class<?>...parameterTypes)只能获取公共的
        Constructor<?> defaultConstructor = c.getConstructor(String.class, int.class);


    }
}

运行输出:

-----------构造方法的获取-----------
获取公共的构造方法
public com.testReflex.Student()
获取所有的构造方法
private com.testReflex.Student(java.lang.String,int,int)
com.testReflex.Student(java.lang.String,int)
public com.testReflex.Student()
获取单个公共的构造方法
public com.testReflex.Student()
Disconnected from the target VM, address: 'javadebug', transport: 'shared memory'
Exception in thread "main" java.lang.NoSuchMethodException: com.testReflex.Student.<init>(java.lang.String, int)
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.getConstructor(Class.java:1825)
    at com.testReflex.getConstructorDemo.main(getConstructorDemo.java:29)

后面的报错是因为getConstructor(Class<?>...parameterTypes)只能获取公共的构造方法,要获取默认和私有的还得用Constructor<?>[] getDeclaredConstructor(Class<?>...parameterTypes)

package com.testReflex;

import java.lang.reflect.Constructor;

/**
 * @author 林高禄
 * @create 2020-06-07-10:41
 */
public class GetConstructorDemo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodExc
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

林高禄

你打不打赏,我都会一直写博客

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

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

打赏作者

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

抵扣说明:

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

余额充值