Java反射

文章详细介绍了Java中获取字节码信息的四种方式,包括通过`getClass()`、`Class.forName()`、`Class`的内置属性以及类加载器。接着,文章展示了如何使用反射来获取类的构造器、属性和方法,并创建对象、访问私有成员以及调用方法。此外,文章还涉及到了注解的使用以及获取类的接口、所在包和注解信息。
摘要由CSDN通过智能技术生成

字节码信息

创建类和接口

public interface MyInterface {
    void myMethod();
}
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value();// 属性
}
public class Person implements MyInterface{
    // 属性
    private String name;
    private int age;

    // 方法
    public void eat() {
        System.out.println("person-------eat");
    }

    public void sleep() {
        System.out.println("person------sleep");
    }

    public void myMethod() {
        System.out.println("person-------myMethod");
    }

}
@MyAnnotation("student")
public class Student extends Person implements Serializable {
    // 属性
    private int sno;
    double height;
    protected double weight;
    public double score;

    // 方法
    public String showInfo() {
        return "我是一名三好学生";
    }

    // 方法
    public String showInfo(int sno) {
        return "我是一名三好学生";
    }

    private void work() {
        System.out.println("我以后会找工作----成为一个程序员");
    }

    private void work(double score) {
        System.out.println("我以后会找工作----成为一个程序员");
    }

    // 构造器
    public Student() {
        System.out.println("空参构造器");
    }

    private Student(int sno) {
        System.out.println("一个参数的构造器");
        this.sno = sno;
    }

    public Student(double height, double weight) {
        System.out.println("两个参数的构造器");
        this.height = height;
        this.weight = weight;
    }

    Student(int sno, double weight) {
        System.out.println("两个参数的构造器");
        this.sno = sno;
        this.weight = weight;
    }

    @Override
    @MyAnnotation("hellomyMethod")
    public void myMethod() throws RuntimeException{
        System.out.println("重写了父类方法");
    }

    @Override
    public String toString() {
        return "Student{" +
                "sno=" + sno +
                ", height=" + height +
                ", weight=" + weight +
                ", score=" + score +
                '}';
    }
}

获取字节码信息的四种方式



/**
 * 获取字节码信息的四种方式
 * 方式1 和 方式2 不常用
 * 方式3 用的最多
 * 方式4 了解
 */
public class TestClassInfo {

    //    方式1 通过 getClass() 方法获取
    @Test
    public void test01() {
        Person person = new Person();
        Class<? extends Person> clazz = person.getClass();
        System.out.println("clazz = " + clazz);
    }

    //    方式2 通过内置class属性
    @Test
    public void test02() {
        Class<Person> person = Person.class;
        System.out.println("person = " + person);
    }

    //    方式3 调用Class类提供的静态方法forName()
    @Test
    public void test03() throws ClassNotFoundException {
        Class<?> clazz = Class.forName("com.maliqiang.demo.Person");
        System.out.println("clazz = " + clazz);
    }

    //    方式4 利用类加载器(了解)
    @Test
    public void test04() throws ClassNotFoundException {
        ClassLoader classLoader = TestClassInfo.class.getClassLoader();
        Class<?> loadClass = classLoader.loadClass("com.maliqiang.demo.Person");
        System.out.println("loadClass = " + loadClass);
    }
}

反射测试

获取构造器和创建对象

 //    获取构造器和创建对象
    @Test
    public void test01() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//        获取字节码信息
        Class<Student> sClazz = Student.class;

        // 通过字节码信息可以获取 运行时 public修饰的构造器
        Constructor<?>[] sClazzConstructors = sClazz.getConstructors();
        for (Constructor<?> sClazzConstructor : sClazzConstructors) {
            System.out.println("sClazzConstructor = " + sClazzConstructor);
        }

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

        // 通过字节码信息 获取运行时 所有构造器
        Constructor<?>[] sClazzDeclaredConstructors = sClazz.getDeclaredConstructors();
        for (Constructor<?> sClazzDeclaredConstructor : sClazzDeclaredConstructors) {
            System.out.println("sClazzDeclaredConstructor = " + sClazzDeclaredConstructor);
        }

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

        // 获取指定构造器 空参构造器
        Constructor<Student> sClazzConstructor = sClazz.getConstructor();
        System.out.println("sClazzConstructor = " + sClazzConstructor);

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

        // 得到两个参数的有参构造器 public
        Constructor<Student> studentConstructor = sClazz.getConstructor(double.class, double.class);
        System.out.println("studentConstructor = " + studentConstructor);

        // default
        Constructor<Student> sClazzDeclaredConstructor = sClazz.getDeclaredConstructor(int.class, double.class);
        System.out.println("sClazzDeclaredConstructor = " + sClazzDeclaredConstructor);

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

        // 得到1个参数的有参构造器 并且是private修饰的
        Constructor<Student> studentConstructor2 = sClazz.getDeclaredConstructor(int.class);
        System.out.println("studentConstructor2 = " + studentConstructor2);

        // 有了构造器 可以通过构造器 创建对象
        Student student = sClazzConstructor.newInstance();
        System.out.println("student = " + student);

        Student student1 = studentConstructor.newInstance(110.0, 120.9);
        System.out.println("student1 = " + student1);

        // 不是public修饰的构造器 设置 setAccessible(true)
        sClazzDeclaredConstructor.setAccessible(true);
        Student student2 = sClazzDeclaredConstructor.newInstance(10, 120.9);
        System.out.println("student2 = " + student2);

    }

获取属性和对属性进行赋值

 // 获取属性 和 对属性赋值
    @Test
    public void test02() throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        // 获取运行时 类的字节码信息
        Class<Student> studentClass = Student.class;

        // 获取属性
        // getFields() 获取运行时 类和父类中被public修饰的属性
        Field[] fields = studentClass.getFields();
        for (Field field : fields) {
            System.out.println("field = " + field);
        }

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

        // 获取运行时类中的所有属性
        Field[] declaredFields = studentClass.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println("field = " + field);
        }

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

        //获取指定的属性 public 修饰
        Field score = studentClass.getField("score");
        System.out.println("score = " + score);

        //获取指定的属性
        Field sno = studentClass.getDeclaredField("sno");
        System.out.println("sno = " + sno);

        // 获取修饰符
        int modifiers = sno.getModifiers();
        System.out.println("modifiers = " + Modifier.toString(modifiers));

        // 获取属性的数据类型
        Class<?> snoType = sno.getType();
        System.out.println("snoType = " + snoType);

        // 获取属性的名字
        String snoName = sno.getName();
        System.out.println("snoName = " + snoName);

        // 给属性赋值
        Student student = studentClass.newInstance();
        // 反射 给public以外的属性赋值 要设置 setAccessible(true)
        sno.setAccessible(true);
        sno.set(student, 10);
        System.out.println("student = " + student);

    }

获取方法和调用方法

//    获取方法和调用方法
    @Test
    public void test03() throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        // 获取字节码信息
        Class<Student> sc = Student.class;

//        获取被public修饰的方法
        Method[] methods = sc.getMethods();
        for (Method method : methods) {
            System.out.println("method = " + method);
        }
        System.out.println("============================================");
        // 获取所有的方法
        Method[] declaredMethods = sc.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("declaredMethod = " + declaredMethod);
        }

        // 获取指定方法 public 修饰
        Method showInfo = sc.getMethod("showInfo");
        System.out.println("showInfo = " + showInfo);

        Method showInfo1 = sc.getMethod("showInfo", int.class);
        System.out.println("showInfo1 = " + showInfo1);

        // 获取指定方法
        Method work = sc.getDeclaredMethod("work");
        System.out.println("work = " + work);

        Method work1 = sc.getDeclaredMethod("work", double.class);
        System.out.println("work1 = " + work1);

        /// 获取方法的具体结构:
        /*
   @注解
        修饰符 返回值类型  方法名(参数列表) throws XXXXX{}
         */
        // 名字
        System.out.println("work.getName() = " + work.getName());
        //修饰符
        System.out.println("work.getModifiers() = " + Modifier.toString(work.getModifiers()));
        // 返回值
        Class<?> returnType = work.getReturnType();
        System.out.println("returnType = " + returnType);
        // 参数列表
        Class<?>[] parameterTypes = work1.getParameterTypes();
        for (Class<?> parameterType : parameterTypes) {
            System.out.println("parameterType = " + parameterType);
        }
        // 获取注解
        Method myMethod = sc.getMethod("myMethod");
        Annotation[] annotations = myMethod.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("annotation = " + annotation);
        }

        // 获取异常
        Class<?>[] exceptionTypes = myMethod.getExceptionTypes();
        for (Class<?> exceptionType : exceptionTypes) {
            System.out.println("exceptionType = " + exceptionType);
        }

        // 调用方法
        work.setAccessible(true);
        work.invoke(sc.newInstance());
    }

获取类的接口,所在包,注解

 //    获取类的接口,所在包,注解
    @Test
    public void test04() {
        // 获取字节码信息
        Class<Student> sc = Student.class;

//        获取运行时类的接口

        Class<?>[] interfaces = sc.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println(anInterface);
        }

        // 得到父类的接口 先要得到父类的字节码信息
        Class<? super Student> superclass = sc.getSuperclass();
        Class<?>[] interfaces1 = superclass.getInterfaces();
        for (Class<?> aClass : interfaces1) {
            System.out.println("aClass = " + aClass);
        }

        // 获取运行时 类所在的包
        Package aPackage = sc.getPackage();
        System.out.println("aPackage = " + aPackage);
        System.out.println("aPackage.getName() = " + aPackage.getName());

        // 获取运行类的注解
        Annotation[] annotations = sc.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("annotation = " + annotation);
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值