框架基础-反射

本文详细介绍了静态语言与动态语言的区别,重点阐述了Java中的反射概念,包括如何获取和操作类的Class实例、Constructor、Field和Method,以及其在实例化对象、属性设置和方法调用中的应用。
摘要由CSDN通过智能技术生成

框架基础-反射

1、静态语言VS动态语言

1-1静态语言:运行时结构不可变的语言:JAVA、C、C++,java称为准动态语言,可以利用反射机制获得类似动态语言的特征,让编程更加灵活。但也会牺牲安全性。

1-2动态语言:在运行时代码可以根据某些条件改变自身结构:C#、JavaScript、PHP、python等

2、反射概念:

反射原理

2-1反射机制允许程序在执行期借助Reflection API获取任何类的内部信息,并能直接操作任意对象的内部属性及方法。(可以理解为A:idea怎么做到提示、联想。B:demo.java编译后称为demo.class,依然能够改变demo.class的内部)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-83nJQ24N-1691724936488)(assets/反射机制.png)]

3、反射用法:

3-1获取Student类的Class实例:

  • Class c1=Student.class;

  • Class c2=stu1.getClass();

  • Class c3=Class.forName(“包名.Student”);

  • 一个类的Class实例在虚拟机里有且仅有一个  
    Class studentClass1 = Student.class;//      cn.bdqn.cn.Student.class
    Class studentClass2 = new Student().getClass();
    Class studentClass3 = Class.forName("cn.bdqn.cn.Student");
            System.out.println(studentClass1.hashCode());
            System.out.println(studentClass2.hashCode());
            System.out.println(studentClass3.hashCode());
            三个Class实例实际是同一个对象,哈希值相同
    
    

3-2通过Class实例获取Student类的基本信息

"类全名称:"+studentClass1.getName()
"类简单名称:"+studentClass1.getSimpleName()
"类所在的包名称:"+studentClass1.getPackage().getName()
"父类全名称:"+studentClass1.getSuperclass().getName()
"修饰符对应的常量:"+studentClass1.getModifiers()

3-3通过Class实例操作Student类的Constructor实例

3-3-1获取Constructor实例
//1、获取所有public 修饰的构造函数
Constructor[] constructors1 = studentClass.getConstructors();
//2、获取所有构造函数,没有修饰符限制
Constructor[] constructors2 = studentClass.getDeclaredConstructors();
//3、获取  public 修饰的   指定参数列表的构造函数
Constructor constructor3 = studentClass.getConstructor(String.class, int.class);
//4、获取指定参数列表的构造函数  没有修饰符限制
Constructor constructor4 = studentClass.getDeclaredConstructor(String.class, int.class);
3-3-2获取每个Construtor实例的访问修饰符
for (Constructor constructor : constructors2) {
    String xiuShiFu = "";//修饰符
    int modifier = constructor.getModifiers();   //   1    7
    if ((modifier & Modifier.PUBLIC) == Modifier.PUBLIC) {
        xiuShiFu = "PUBLIC";
    } else if ((modifier & Modifier.PROTECTED) == Modifier.PROTECTED) {
        xiuShiFu = "PROTECTED";
    } else if ((modifier & Modifier.PRIVATE) == Modifier.PRIVATE) {
        xiuShiFu = "PRIVATE";
    } else if ((modifier & Modifier.FINAL) == Modifier.FINAL) {
        xiuShiFu = "FINAL";
    }
    System.out.println("该构造函数的访问修饰符:" + xiuShiFu);
}
3-3-3获取每个Construtor实例的参数列表
for (Constructor constructor : constructors2) {
    //获得参数列表的各个类型
    Class[] paramTypesClass = constructor.getParameterTypes();//参数列表的类型Class实例
    if (paramTypesClass.length == 0) {
        System.out.println("无参构造,没有参数列表");
    } else {
        //有参构造      1个   或多个
        System.out.println("该构造函数的参数列表类型为:");
        for (int i = 0; i < paramTypesClass.length; i++) {
            System.out.print(paramTypesClass[i].getSimpleName() + "  ");
        }
        System.out.println();
    }
}

3-4通过Class实例操作Student类的Field实例

3-4-1获取Field实例
//1、获取所有的public修饰的属性
Field [] studentFields1=studentClass.getFields();
//2、获取所有属性 没有public 限制
Field [] studentFields2=studentClass.getDeclaredFields();
//3、获取指定名称的 public修饰的属性
Field  studentField3=studentClass.getField("name");
//4、获取指定名称的属性  没有public限制
Field studentField4=studentClass.getDeclaredField("name");
3-4-2获取每个Field实例的基本信息(属性名、属性数据类型、属性访问修饰符)
//获取Student类中的所有属性:修饰符、类型、名称
System.out.println("展示所有属性的信息");
for (int i = 0; i <studentFields2.length ; i++) {
    int modifiers=studentFields2[i].getModifiers();
    System.out.println("int modifiers:"+modifiers);
    System.out.println("属性名:"+studentFields2[i].getName());
    System.out.println("属性类型:"+studentFields2[i].getType());
    String xiuShiFu="";
    if((modifiers&Modifier.PUBLIC)== Modifier.PUBLIC){
        xiuShiFu="PUBLIC";
    }else  if((modifiers&Modifier.PRIVATE)== Modifier.PRIVATE){
        xiuShiFu="PRIVATE";
    }else  if((modifiers&Modifier.PROTECTED)== Modifier.PROTECTED){
        xiuShiFu="PROTECTED";
    }
    System.out.println("访问修饰符:"+xiuShiFu);
   if((modifiers&Modifier.FINAL)== Modifier.FINAL){
        xiuShiFu="FINAL";
       System.out.println("访问修饰符:"+xiuShiFu);
    }else  if((modifiers&Modifier.STATIC)== Modifier.STATIC){
       xiuShiFu="STATIC";
       System.out.println("访问修饰符:"+xiuShiFu);
   }
    System.out.println("===========");
}

3-5通过Class实例操作Student类的Method实例

3-5-1获取Method实例
//1、获取所有的public修饰的方法
Method[] studentMethod1 = studentClass.getMethods();
//2、获取所有方法 没有public 限制
Method[] studentMethod2 = studentClass.getDeclaredMethods();
//3、获取指定名称和参数列表的 public修饰的方法
Method studentMethod3 = studentClass.getMethod("setName", String.class);
//4、获取指定名称的方法  没有public限制
Method studentMethod4 = studentClass.getDeclaredMethod("setName", String.class);
3-5-2获取每个Method实例的基本信息(方法名、返回值类型、参数列表类型、访问修饰符)
//展示所有方法信息1、方法名2、返回值类型3、访问修饰符4、抛出异常种类
for (Method method : studentMethod2) {
    System.out.println("方法名:" + method.getName());
    System.out.println("返回值类型:" + method.getReturnType().getSimpleName());
    System.out.println("参数列表类型:");
    Class[] paramClasses = method.getParameterTypes();
    for (Class paramClass : paramClasses) {
        System.out.print(paramClass.getSimpleName() + " ");
    }
    System.out.println();
    int modifiers = method.getModifiers();
    String xiuShiFu = "";
    if ((modifiers & Modifier.PUBLIC) == Modifier.PUBLIC) {
        xiuShiFu = "PUBLIC";
    } else if ((modifiers & Modifier.PRIVATE) == Modifier.PRIVATE) {
        xiuShiFu = "PRIVATE";
    } else if ((modifiers & Modifier.PROTECTED) == Modifier.PROTECTED) {
        xiuShiFu = "PROTECTED";
    }
    System.out.println("访问修饰符:" + xiuShiFu);
    if ((modifiers & Modifier.FINAL) == Modifier.FINAL) {
        xiuShiFu = "FINAL";
        System.out.println("访问修饰符:" + xiuShiFu);
    } else if ((modifiers & Modifier.STATIC) == Modifier.STATIC) {
        xiuShiFu = "STATIC";
        System.out.println("访问修饰符:" + xiuShiFu);
    }
    System.out.println("\n===========");
}
3-5-3获取每个Method实例的抛出异常种类
Class[] exceptionClasses = method.getExceptionTypes();
if(exceptionClasses.length>0){//该方法有异常
    for (Class exceptionClass:exceptionClasses) {
        System.out.print(exceptionClass.getSimpleName()+"\t");
    }
}

3-6通过Constructor实例,创建类的对象

//通过ublic  无参构造函数   创建对象
        Constructor constructor1 = Student.class.getConstructor();
        Object object1 = constructor1.newInstance();
//通过 有参  public 的构造函数    创建对象
        Constructor constructor2 = Student.class.getConstructor(String.class, int.class);
        Object object2 = constructor2.newInstance("李四", 18);
//通过 有参   private 的构造函数  创建对象
        Constructor constructor3 = Student.class.getDeclaredConstructor(String.class);
        constructor3.setAccessible(true);//将私有的构造函数设置为可访问
        Object object3 = constructor3.newInstance("李四");

3-7通过Field实例,给对象的属性,设置/获取值

Class studentClass = Student.class;
//创建Student实例
Student student = (Student) studentClass.newInstance();
//通过Field对象对实例的属性获取值和设置值
Field nameField = studentClass.getDeclaredField("name");
nameField.setAccessible(true);
//通过Field对象获取name属性值
System.out.println("name属性赋值前的值:" + nameField.get(student));
//通过Field对象设置name属性值
nameField.set(student,"张三");
System.out.println("name属性赋值后的值:" + nameField.get(student));

3-8通过Method实例,作用到对象,实现对象调用方法

Class studentClass = Student.class;
//创建Student实例
Object object = studentClass.newInstance();
//获取Method对象
Method setNameMethod = studentClass.getMethod("setName", String.class);
// public void setName(String name) {
//        this.name = name;
//    }
setNameMethod.setAccessible(true);//如果是私有的方法/成员,设置为可访问的
//通过调用setName()方法为obj的属性赋值
setNameMethod.invoke(object, "张三");//invoke:调用       method对象.invoke(对象,实参)
System.out.println(object.toString());
Method showMethod = studentClass.getDeclaredMethod("show");
showMethod.invoke(object);

//如果是私有的方法/成员,设置为可访问的
//通过调用setName()方法为obj的属性赋值
setNameMethod.invoke(object, “张三”);//invoke:调用 method对象.invoke(对象,实参)
System.out.println(object.toString());
Method showMethod = studentClass.getDeclaredMethod(“show”);
showMethod.invoke(object);

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

IT攻城狮培训龙哥

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值