Java反射最全面总结

Java中的编译类型

①.静态编译:在编译时确定类型,绑定对象即通过
②.动态编译:在运行时确定对象类型,绑定对象体现了Java的灵活性和多态性,降低类之间的耦合度。
反射的原理

反射是什么?

Java在运行时,对于任何一个类都能获得这个类的信息(属性、方法、修饰符等等),还可以在运行时实例化对象,实现动态创建对象

反射的执行流程

Java程序通过javac产生.class文件,通过JVM的类加载器加载class文件,并生成Class对象(注意Class对象只创建一次)Class对象是反射的源头。反射的本质是获取Class对象之后反向获取被反射类的各种信息。请看下图:

为什么用反射

  • 使用反射可以赋予JVM动态编译的能力,否则类的元数据信息只能使用静态编译的实现,当我们写的程序运行时,需要动态的加载,提升服务器的性能。
  • 使用Java的方式机制可以增加程序的灵活性,避免程序写死

反射的实现类

Class类:反射的源头
主要描述: 当创建一个类的时候首先通过编译生成相应的class文件,之后通过JVM的类的加载器,将class文件加载到内存中,创建一个Class对象Class对象只会加载一次
获取class对象的四种方法:

        // 方式1.调用运行时类本身的class属性Class<Person> clazz1 = Person.class;// getName获取完整路径(全限定名或者完全限定名)System.out.println(clazz1.getName());// 方式2.通过运行时类getClass方法Person person = new Person();Class<Person> clazz2 = (Class<Person>) person.getClass();System.out.println(clazz2.getName());//3.通过Class。forName(“全路径”)静态方法Class clazz3 = Class.forName("com.hpe.reflect.Person");System.out.println(clazz3.getName());// 4.通过类加载器ClassLoaderClassLoader classLoader = this.getClass().getClassLoader();Class class4 = classLoader.loadClass("com.hpe.reflect.Person");System.out.println(class4.getName());

常见的方法:

      getDeclaredFields():获取类所有属性getField(String name):获取类的指定属性getMothods():获取类的public类型方法getMethod (String name,Class [] args)获得类的指定方法getConstrutors()获得类的public类型的构造方法getConstrutor(Class[] args)获得类的特定构造方法newInstance()通过类的无参构造方法创建一个对象getName()获得类的完整名字getPackage()获取此类所属的包getSuperclass()获得此类的父类对应的Class对象

使用反射反射创建对象,访问类的结构

  // 获取Person类的Class类对象Class<Person> clazz = Person.class;// 常见clazz对应的运行时类的Person对象Person person = (Person) clazz.newInstance();System.out.println(person);// 通过反射获取运行时类的指定属性Field f1 = clazz.getField("name");// 设置属性f1.set(person, "jack");System.out.println(person);Field f2 = clazz.getDeclaredField("age");f2.setAccessible(true);// 设置属性f2.set(person, 20);System.out.println(person);// 通过反射获取运行时指定的方法Method method = clazz.getMethod("show");// 调用方法(指明实例对象和参数值)method.invoke(person);Method m2 = clazz.getMethod("display", String.class);m2.invoke(person, "China");

获取Class对象的方式:

// 方式1.调用运行时类本身的class属性Class<Person> clazz1 = Person.class;// getName获取完整路径(全限定名或者完全限定名)System.out.println(clazz1.getName());// 方式2.通过运行时类getClass方法Person person = new Person();Class<Person> clazz2 = (Class<Person>) person.getClass();System.out.println(clazz2.getName());//3.通过Class。forName(“全路径”)静态方法Class clazz3 = Class.forName("com.hpe.reflect.Person");System.out.println(clazz3.getName());// 4.通过类加载器ClassLoaderClassLoader classLoader = this.getClass().getClassLoader();Class class4 = classLoader.loadClass("com.hpe.reflect.Person");System.out.println(class4.getName());

Field:

获取对应运行时类的属性

  // 1.getFields():获取运行时类及其父类声明的public的属性Field[] fields = clazz.getFields();for (int i = 0; i < fields.length; i++) {System.out.println(fields[i]); }// 2.getDeclareFields():获取运行时类的本身声明的所有属性Field[] fields2 = clazz.getDeclaredFields();for (Field field : fields2) {System.out.println(field.getName());}

获取属性的各个部分的内容(权限修饰符、类型、名称)

 Class clazz = Person.class;Field[] fields = clazz.getDeclaredFields();for (Field f : fields) {// 1.获取每个属性的权限修饰符System.out.println(Modifier.toString(f.getModifiers()));// 2.获得属性的类型Class type = f.getType();String typeName = type.getName();System.out.println(typeName);// 3.获取属性名称System.out.println(f.getName());
}

获取运行时类的指定属性

  Class clazz = Class.forName("com.hpe.reflect.Person");// 1.获取指定的属性// getFields(String name):获取运行时类中声明问public的类型名的属性Field name = clazz.getDeclaredField("name");name.setAccessible(true);// 2.创建运行时的随想Person p = (Person)clazz.newInstance();System.out.println(p);// 3.设置属性值name.set(p, "eric");System.out.println(p);// 4.getDeclareField(String filedName):获取运行时指定的属性值Field age = clazz.getDeclaredField("age");// 由于属性权限修饰符的问题,为了给属性赋值时,需要在操作前使得该属性可被操作age.setAccessible(true);age.set(p, 25);System.out.println(p);

Constructor类:

     // 创建对应的运行时的对象使用newInstance 实际上调用了运行时类的空参构造器
// 创建运行类的对象条件①。空参构造器,访问权限要足够
Object newInstance = clazz.newInstance();
Person p = (Person) newInstance;
11.获取构造器:Class clazz = Person.class;Constructor[] cons = clazz.getDeclaredConstructors();for (Constructor c : cons) {System.out.println(c);}

.调用指定的构造器,创建运行时对象

  Class clazz = Person.class;
// 调用空参构造器
Constructor c = clazz.getDeclaredConstructor();Person p1 = (Person) c.newInstance();
System.out.println(p1);
// 通过getDeclaredConstructor方法传入指定的参数可以获取所有参数的构造器
Constructor cons = clazz.getDeclaredConstructor(String.class, int.class);
// 通过构造器newInstance方法传入参数值创建对象
Person person = (Person) cons.newInstance("jack",20);
System.out.println(person);

不能注释掉原类的无参构造器
Method类:表示类的方法:

获取运行类中的方法:

// 1.getMethods():获取运行时类及其父类声明问public的方法Method[] methods = clazz.getMethods();for (Method method : methods) {System.out.println(method);
}System.out.println("---------------------------");// 2.getDeclaredMothods():获取运行类声明的所有方法Method[] m = clazz.getDeclaredMethods();for (Method method : m) {System.out.println(method);}

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

 Class<Person> clazz = Person.class;// 创建运行类的对象Person p = (Person) clazz.newInstance();// 获取属性Field f_name = clazz.getDeclaredField("name");Field f_age = clazz.getDeclaredField("age");// 设置允许访问属性f_age.setAccessible(true);f_name.setAccessible(true);// 设置属性值f_name.set(p, "tina");f_age.set(p, 30);// 1. 获取运行时类中声明为public的方法Method m1 = clazz.getMethod("show");// 2.调用方法 invoke(指定对象,方法的参数)m1.invoke(p);// 调用有返回值的参数Method m2 = clazz.getMethod("sayHello");Object returnVall = m2.invoke(p);System.out.println(returnVall);// 3.调用静态方法Method m3 = clazz.getMethod("info");// 相当于类名。方法名m3.invoke(Person.class);// 4.调用带参数的方法// 获取所有运行时类中所有的方法getDeclareMethod()Method m4 = clazz.getDeclaredMethod("display", String.class);// 调用方法的同时传入参数值m4.invoke(p, "China");

调用有参数的构造器创建运行类对象,调用相关方法:

 Class<Person> clazz = Person.class;Constructor<Person> cons = clazz.getConstructor(String.class, int.class);// 通过有残构造器近视运行类的赋值(初始化成员属性)Person p = cons.newInstance("tom,25");// 获取方法Method m1 = clazz.getMethod("display", String.class);// 调用方法m1.invoke(m1, "CHN");

文件的操作:

   // 读取配置文件(FileReader in = new FileReader(new File("propertices"));// 将流加载到配置文件properties.load(in);in.close();// 获取用户名和密码String username = properties.getProperty("user");String password = properties.getProperty("password");System.out.println("用户名:"+ username + " 密码:"+password);//通过反射获取Class对象Class<?> clazz = Class.forName(properties.getProperty("className"));Method m1 = clazz.getMethod(properties.getProperty("methodName"));// 创建student的运行时对象//Student student = (Student) clazz.newInstance();// 调用show方法m1.invoke(clazz.getConstructor().newInstance());//m1.invoke(student);

泛型擦除 程序编译后产生的。Class文件没有泛型约束的,这种现象就做泛型的擦除:

ArrayList<Integer> arr = new ArrayList<>();arr.add(123);//获取ArrayLiist的字节码对象Class<? extends ArrayList> c = arr.getClass();// 通过反射的方式获得add方法Method m = c.getMethod("add", Object.class);// 调用方法m.invoke(arr, "abc");System.out.println(arr);

Java反射最全面总结(附代码)相关推荐

  1. Java修改图片分辨率(附代码) | Java工具类

    目录 前言 环境依赖 代码 总结 前言 本文提供可以修改图片分辨率的java工具类,实用主义的狂欢. 环境依赖 添加必要的一些maven依赖. <dependency><groupI ...

  2. 京东百万年薪大佬用JAVA绘制“五子棋棋盘”(附代码)

    这篇文章主要为大家详细介绍了java绘制五子棋棋盘,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 具体内容如下 源码: import javax.imageio.Ima ...

  3. Java 实现图片裁剪(附代码) | Java工具类

    目录 前言 Maven依赖 代码 总结 前言 本文提供将图片按照自定义尺寸进行裁剪的Java工具类,一如既往的实用主义. Maven依赖 <dependency><groupId&g ...

  4. Java视频修改分辨率(附代码) | Java工具类

    目录 前言 环境依赖 代码 总结 前言 本文提供可以调整视频分辨率的java代码,实用主义的狂欢. 环境依赖 添加需要的maven依赖. <dependency><groupId&g ...

  5. java编程如何算圆的面具,Java实现人物拼图游戏│附代码

    拼图游戏指将一幅图片分割成若干拼块,并随机打乱顺序,当将所有拼块都放回原位置时就完成了拼图(游戏结束). 01 游戏介绍 在游戏中,拼块以随机顺序排列,网格上有一个位置是空的.完成拼图的方法是利用这个 ...

  6. Java反射 - 私有字段和方法

    尽管普遍认为通过Java Reflection可以访问其他类的私有字段和方法. 这并不困难. 这在单元测试中可以非常方便. 本文将告诉你如何. 访问私有字段 要访问私有字段,您需要调用Class.ge ...

  7. 大家都说 Java 反射效率低,为什么呢?

    我们在 Java 开发中,难免会接触到反射,而在一些框架中,反射的运用更是常见.我相信,每次提到反射,大家的第一反应一定是反射效率低,尽量少使用.但是反射的效率到底低多少?反射效率低的原因在哪里?这篇 ...

  8. 大家都说 Java 反射效率低,你知道原因在哪里么

    [这是 ZY 第 17 篇原创技术文章] 预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低的原因 文章概览 我们在 Java 开发中, ...

  9. Java反射-静态/动态加载类

    title: Java反射-静态/动态加载类 date: 2019-05-28 18:50:00Java反射-静态/动态加载类 Class 类是对象,是java.lang.Class类的实例对象.任何 ...

最新文章

  1. python 获取程序运行时间
  2. mysql 查询临时表列名_为什么mysql会缓存被删除的临时表的列名?
  3. 使用easyexcel导出
  4. BZOJ.1143.[CTSC2008]祭祀(Dilworth定理 最大流ISAP)
  5. Postgres客户端编码问题
  6. Java 中的目录创建处理
  7. Linux 编译安装BIND
  8. java实现权限_Java实现权限管理的两种方式
  9. Python 一键转 Java?“Google 翻译”你别闹
  10. OSI 七层网络协议的定义与理解
  11. Unix环境高级编程笔记:12、高级IO
  12. 水面反光如何拍摄_如何抓拍水的不同瞬间
  13. ELDD Chapter 2..3 Linux Kernel Facilities
  14. 2011年随笔记 5月30号以后的日志薄
  15. PPT2016;插入视频,无法实现自动播放
  16. android 手机红外遥控器
  17. python安装anacondapanda_关于pandas:Pyarrow不安装python 3.7(anaconda 5.3.0,windows x64版本)...
  18. PHP文件开启SSI(以CMSTOP环境为例)
  19. 阿里百秀模仿(基于bootstrap框架)
  20. 欧姆龙485通讯示例程序_远程通讯模块在plc无线通信中的应用

热门文章

  1. java计算机毕业设计外卖点餐系统源代码+数据库+系统+lw文档
  2. 魔幻2022,2023涅槃重生!
  3. moran指数 r语言_白话空间统计之二十五:空间权重矩阵(四)R语言中的空间权重矩阵(2):不同空间关系对莫兰指数的影响...
  4. 干翻Hadoop系列文章【03】:MapReduce概念详解
  5. python使用pip与conda 的区别
  6. PLC高手秘籍!实例讲解PLC故障排查
  7. java powershell出错_PowerShell全局错误处理机制处理脚本错误或异常
  8. 【LOJ 10050】The XOR Largest Pair【Trie】
  9. 华为荣耀10有信号的地方无服务器,二修华为荣耀10青春版进水无信号偶尔有2G信号不能打电话...
  10. python获取ps4手柄信息并使用QT界面显示读取内容