【 java 反射下篇】java反射机制不难吧?来看看这篇

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

📋 个人简介

  • 💖 作者简介大家好我是阿牛全栈领域优质创作者。😜
  • 📝 个人主页馆主阿牛🔥
  • 🎉 支持我点赞👍+收藏⭐️+留言📝
  • 📣 系列专栏java 小白到高手的蜕变🍁
  • 💬格言要成为光因为有怕黑的人🔥
    请添加图片描述

目录

前言

本篇我将总结如何使用反射调用类的内部结构

通过反射创建对应的运行时类对象

public static void main(String[] args) throws Exception {
        Class<People> cl = People.class;
        // newInstance():调用此方法创建对应的运行时类对象
        // java9之后这个方法过期了应使用getConstructor().newInstance()
        // 也就是先调用空参构造器然后newInstance()创建对象
        People obj = cl.getConstructor().newInstance();
        System.out.println(obj);
    }

在这里插入图片描述
要想此方法正常的创建运行时类的对象要求
1.运行时类必须提供空参的构造器
2.空参的构造器的访问权限得够。通常设置为 public 。
在 javabean 中要求提供一个 public 的空参构造器。原因
1.便于通过反射创建运行时类的对象
2.便于子类继承此运行时类时默认调用 super (时保证父类有此构造器

通过反射获取运行时类的内部结构了解

提供结构丰富的People

这里提供一个结构丰富的People类用于下面的测试

package java反射;

import java.io.Serializable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;

// 父类
class Creature<T> implements Serializable{
    private char sex;
    public double weight;

    private void breath(){
        System.out.println("呼吸");
    }
    public void eat(){
        System.out.println("吃东西");
    }
}
// 接口
interface Myinterface{
    void info();
}

// 注解
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
    String value() default "hello";
}
// 子类
@MyAnnotation(value="hi")
public class People extends Creature<String> implements Comparable<String>,Myinterface {
    private String name;
    int age;
    public int id;

    public People(){

    }
    @MyAnnotation(value="aniu")
    private People(String name) {
        this.name = name;
    }

    People(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @MyAnnotation
    private void show(String nation){
        System.out.println("国籍" + nation);
    }

    public String display(String interests){
        return interests;
    }

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

    @Override
    public int compareTo(String o) {
        return 0;
    }

    @Override
    public void info() {
        System.out.println("我是一个人");
    }
}

这个结构中有继承注解接口泛型以及不同权限的属性和方法等接下类我们通过反射来获取这些结构学习

获取运行时类的属性结构

public static void main(String[] args) {
        Class cls = People.class;
        // 获取属性结构
        // getFields():获取当前运行时类及其父类中声明为public的访问权限的属性
        Field[] fields = cls.getFields();
        for (Field item:fields){
            System.out.println(item);
        }

        System.out.println("------------------------------------");
        // getDeclaredFields():获取当前运行时类中生申明的所有属性不包含父类中的属性
        Field[] declaredFields = cls.getDeclaredFields();
        for (Field item:declaredFields){
            System.out.println(item);
            // 属性的权限修饰符 数据类型 变量名 也可单独获取到
            // 1.权限修饰符
            int modifiers = item.getModifiers();
            System.out.print(Modifier.toString(modifiers) + "\t");
            // 2.数据类型
            Class type = item.getType();
            System.out.print(type.getName() + "\t");
            // 3.变量名
            String name = item.getName();
            System.out.print(name);

            System.out.println("\n");
        }
    }

在这里插入图片描述

获取运行时类的方法结构

public static void main(String[] args) {
        Class cls = People.class;
        // getMethods() 获取当前运行时类以及父类中声明为public的方法
        Method[] methods = cls.getMethods();
        for(Method m:methods){
            System.out.println(m);
        }
        System.out.println("--------------------------");
        // getDeclaredMethods() 获取当前运行时类声明的所有方法不包含父类
        Method[] declaredMethods = cls.getDeclaredMethods();
        for(Method m:declaredMethods){
            System.out.println(m);
            // 方法也可以获取方法申明的注解 权限修饰符 返回值类型 方法名 形参列表 抛出的异常
            // 这里我只写一下获取方法的注解
            Annotation[] annotations = m.getAnnotations();
            for(Annotation a : annotations){
                System.out.println(a);
            }
        }
    }

在这里插入图片描述

获取运行时类的构造器结构

和上面的一样
getConstructors()和getDeclaredConstructors();我不再写案例

获取运行时类的父类以及父类的泛型

package java反射;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * @AuthorAniu
 * @Date2023/1/17 21:35
 * @description 获取运行时类的父类以及父类的泛型
 */
public class Demo4 {
    public static void main(String[] args) {
        Class<People> cls = People.class;
        // getSuperclass() 获取运行时类的父类
        Class<? super People> superclass = cls.getSuperclass();
        System.out.println(superclass);

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

        // getGenericSuperclass() 获取运行时类的带泛型的父类
        Type genericSuperclass = cls.getGenericSuperclass();
        System.out.println(genericSuperclass);

        System.out.println("--------------");
        
        // 获取运行时类的带泛型的父类的泛型
        ParameterizedType genericSuperclass1 = (ParameterizedType) genericSuperclass;
        Type[] actualTypeArguments = genericSuperclass1.getActualTypeArguments();
        System.out.println(actualTypeArguments[0].getTypeName());
    }
}

在这里插入图片描述

获取运行时类的接口包注解等

package java反射;

import java.lang.annotation.Annotation;

/**
 * @AuthorAniu
 * @Date2023/1/17 21:43
 * @description 获取运行时类的接口包注解等
 */
public class Demo5 {
    public static void main(String[] args) {
        Class<People> cls = People.class;
        // getInterfaces() 获取运行时类实现的接口 获取父类实现的接口cls.getSuperclass().getInterfaces();
        Class<?>[] interfaces = cls.getInterfaces();
        for(Class c : interfaces){
            System.out.println(c);
        }
        System.out.println("------------------");

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

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

        // getAnnotations() 获取运行时类的注解
        Annotation[] annotations = cls.getAnnotations();
        for(Annotation a : annotations){
            System.out.println(a);
        }
    }
}

在这里插入图片描述

通过反射调用运行时类的内部结构重要

调用运行时类中的指定构造器

package java反射;

import java.lang.reflect.Constructor;

/**
 * @AuthorAniu
 * @Date2023/1/19 17:00
 * @description 调用运行时类中的指定构造器
 */
public class Demo8 {
    public static void main(String[] args) throws Exception {
        Class<People> cls = People.class;
        // 1.获取指定构造器
        // getDeclaredConstructor 参数构造器的参数列表
        Constructor<People> declaredConstructor = cls.getDeclaredConstructor(String.class);
        // 2.保证此构造其实可访问的
        declaredConstructor.setAccessible(true);
        // 3.调用此构造器创建对象
        People p = declaredConstructor.newInstance("aniu");
        System.out.println(p);
    }
}

在这里插入图片描述
jdk9之后我们用这种方式创建运行时类的对象即调用空参构造器创建运行时类的对象

调用运行时类中的指定属性

package java反射;

import java.lang.reflect.Field;

/**
 * @AuthorAniu
 * @Date2023/1/19 16:15
 * @description 调用运行时类中的指定属性
 */
public class Demo6 {
    public static void main(String[] args) throws Exception {
        Class<People> cls = People.class;
        // 创建运行时类的对象
        People p = cls.getConstructor().newInstance();
        
        // 获取指定的属性 getField()要求运行时类的属性权限修饰符为public
        // 通常不用此方法
        Field id = cls.getField("id");
        // 设置当前属性的值
        // set(): 参数:1指明设置那个对象的属性  参数2将此属性值设置为多少
        id.set(p,10);
        // 获取当前属性的值
        // get(): 参数1获取那个对象当前的属性值
        int pid = (int) id.get(p);
        System.out.println(pid);

        System.out.println("--------------");
        
        // 1.获取指定的属性 通常用getDeclaredField
        Field name = cls.getDeclaredField("name");
        // 2.保证当前属性是可访问的 对于private和默认权限的属性设置和获取之前都要加这个
        name.setAccessible(true);
        // 3.设置指定对象的此属性值
        name.set(p,"aniu");
        // 4.获取指定对象的此属性值
        String s = (String) name.get(p);
        System.out.println(s);
    }
}

在这里插入图片描述

调用运行时类中的指定方法

package java反射;

import java.lang.reflect.Method;

/**
 * @AuthorAniu
 * @Date2023/1/19 16:39
 * @description 调用运行时类中的指定方法
 */
public class Demo7 {
    public static void main(String[] args) throws Exception {
        Class<People> cls = People.class;
        // 创建运行时类的对像
        People p = cls.getConstructor().newInstance();

        // 1.获取指定的某个方法   getMethod只能获取public
        // getDeclaredMethod所有权限方法都可获取。参数一指明获取的方法的名称 参数二指明获取的方法的形参列表
        Method show = cls.getDeclaredMethod("show", String.class);
        // 2. 保证当前方法可访问
        show.setAccessible(true);
        // 3. 调用方法
        // invoke() 参数一方法的调用者 方法二给方法的参数
        // invoke() 方法的返回值即为调用的类中方法的返回值
        Object c = show.invoke(p, "China");
        System.out.println(c);
    }
}

在这里插入图片描述
那如何调用静态方法呢我给People类加一个静态方法

public static void print(){
       System.out.println("我是阿牛");
   }
Method print = cls.getDeclaredMethod("print");
print.setAccessible(true);
print.invoke(People.class); // 静态方法可以用类名直接调用

结语

如果你觉得博主写的还不错的话可以关注一下当前专栏博主会更完这个系列的哦也欢迎订阅博主的其他好的专栏。

🏰系列专栏
👉软磨 css
👉硬泡 javascript
👉flask框架快速入门

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Java