Java动态特性反射

news/2024/5/19 4:21:09 标签: java, jvm, 反射

这里写自定义目录标题

  • 一,反射的概念
  • 二,Class类

一,反射的概念

在运行状态中,这通过Reflection APIs取得任何一个已知名称的class的内部信息以及任意一个对象的内部信息,并且可以调用它的任意一个方法和属性;

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

在这里插入图片描述

二,Class类

在这里插入图片描述
在这里插入图片描述

(一)获取class对象

  • 获取Class对象的方式:
    1. Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
      • 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
    2. 类名.class:通过类名的属性class获取
      • 多用于参数的传递
    3. 对象.getClass():getClass()方法在Object类中定义着。
      • 多用于对象的获取字节码的方式
        在这里插入图片描述

运行时程序,jvm先把Person.java中的Person编译为Person.class文件 ,在通过jvm中的类加载器加载Person.class到jvm内存中,然后使用对象的反射机制映射类加载器中的类对象,达到获取对象

java"> Person person= new Person()
 Class cls1 = person.getClass();

调试
在这里插入图片描述

java">public class DemoReflection {

    public static void main(String[] args) throws ClassNotFoundException{
        Class cls1 = Class.forName("domain.Person");
        System.out.println(cls1);

        Class cls2 = Person.class;
        System.out.println(cls2);


        Class cls3 = danew Person().getClass();
        System.out.println(cls3);


        System.out.println(cls1 == cls2);
        System.out.println(cls1 == cls3);
        
    }

}

运行结果:

java">class domain.Person
class domain.Person
class domain.Person
true
true

同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。

(二)反射构造函数

java">public class Person {
    private String name;
    private int age;
    
    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("有参构造函数被调用 "+this.name);
    }
}

在这里插入图片描述

java">try{
            Constructor constructor1 = personClass.getConstructor(String.class, int.class);
            System.out.println(constructor1);
            Constructor constructor2 = personClass.getConstructor();
            System.out.println(constructor2);

            //调用构造方法
            Object obj = constructor1.newInstance("bai",20);
            System.out.println("*******************");


        }catch (NoSuchMethodException | InstantiationException | InvocationTargetException e){
            e.printStackTrace();
        }

在这里插入图片描述

进调试看看
在这里插入图片描述

(三)反射成员变量

Person类

java">public class Person {
    private String name;
    private int age;

    public String a;
    protected String b;
    String c;
    private String d;
	
    public Person() {
    	a = "a";
    }
}

在这里插入图片描述
在这里插入图片描述

java">public static void main(String[] args) {

        Class personClass = Person.class;
        Field[] fields = personClass.getFields();//返回一个 Field 对象数组
        for (Field field : fields) {
            System.out.println(field);
        }
        
        Field a = personClass.getField("a"); //  返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
        Person person = new Person();
        System.out.println(a.get(person)); 
        a.set(person,"new_a");  // 将指定对象参数上由此字段对象表示的字段设置为指定的新值
        System.out.println( a.get(person));
    }

在这里插入图片描述

(四)反射成员方法

在这里插入图片描述

java">Class personClass = Person.class;
try{
      //获取指定名称的方法
      Method eat_method = personClass.getMethod("getName");
      Person person = new Person("bai",20);
      //执行方法
      Object  value = eat_method.invoke(person); //执行成员方法,如果有返回值则返回
      System.out.println(value);
  }catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e){
          e.printStackTrace();
  }

(五)反射main

java">public class Person {
	 public static void main(String[] args) {
	        System.out.println("这是person的mai方法");
	    }
}
java">try {

	// 获取main方法
	 Method methodMain = personClass.getMethod("main", String[].class);//第一个参数:方法名称,第二个参数:方法形参的类型,
	  //需要将new String[]{} 拆成3个对象。。。所以需要将它强转
	 methodMain.invoke(null, (Object)new String[]{"a","b","c"});
	
	
	
} catch (Exception e) {
	e.printStackTrace();
		}

在这里插入图片描述

结语,反射java进阶中,非常重要的内容,如果哪里写得不对,请在下方评论


http://www.niftyadmin.cn/n/1095664.html

相关文章

【流媒体】初识流媒体与流媒体技术

流媒体 流媒体又叫流式媒体,它是指商家用一个视频传送服务器把节目当成数据包发出,传送到网络上。用户通过解压设备对这些数据进行解压后,节目就会像发送前那样显示出来。 这个过程的一系列相关的包称为“流”。流媒体实际指的是一种新的媒体…

select into from 和 insert into select 的区别和用法及 SQL SELECT INTO 中Undeclared variable错误解决办法...

今天试了一下数据表中的数据备份到另一个空的数据表,然后使用了SQL SELECT INTO语句,然后提示Undeclared variable......错误,现在在这里做下总结并给出解决办法。 应用程序在开发、测试过程中,经常会遇到需要表复制的情况&#x…

第十八天

之前做过一点网络爬虫,使用过正则表达式,看到这道题用正则表达式,就小小的偷个懒 正则表达式 class Solution:def isMatch(self, s: str, p: str) -> bool:result re.match(p, s)if result:result_print Falseresult result.group()i…

获取url据对路径写法

var _absUrl (function () { var a; return function (url) { if (!a) a document.createElement(a); a.href url; return a.href; };})();转载于:https://www.cnblogs.com/blowfish/p/4689346.html

配置单元测试环境,找不到SenTestingKit

报错:ignoring file /Applications/Xcode.app/Contents/Developer/Library/Frameworks/SenTestingKit.framework/SenTestingKit, missing required architecture armv7 in file 解决方式:在Framework Search Paths增加:"${DEVELOPER_LIB…

第十九天

这道题的思路来自于之前学过的分形树的绘制,先绘制右支,再绘制左支,所以我先判断了左支,然后判断右支,如此递归下去,设置边界条件返回答案 class Solution:def isSameTree(self, p: TreeNode, q: TreeNode…

小白笔记之栈,实现简单表达式计算

栈 百度解释 栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元…

习题:加密算法:如果输入的是字母,将其转换为其后第四位字母

1 /*加密算法&#xff1a;如果输入的是字母&#xff0c;将其转换为其后第四位字母*/2 #include<stdio.h>3 int main(void)4 {5 char c;6 while((cgetchar())!\n)7 {8 if(c>A&&c<Z||c>a&&c<z)9 { 10 …