一、什么是java反射

java的反射机制是指在运行状态中,对于任意的一个类,都能获取到这个类的属性和方法,无论是private还是public。对于任意的一个对象,都能调用到它的任意一个方法和属性,无论是private还是public。这种动态获取类的信息和动态调用对象的方法,我们叫做java的反射机制。当然这种机制如果自己使用不当,在一定程度上破坏了java面向对象的封装性。

二、java反射实例和用法

下面有个person的bean对象,我们就用这个简单的例子来学习,要想使用反射,首先得获取对应类的class对象。

package com.chendsir.exercisejava;public  class Person {private int id;private String name;public  String age;public Person(String age) {this.age = age;}public int getId() {return id;}public String getName() {return name;}public String getAge() {return age;}
}

(1) :获取class对象。

我们给这个例子加一个man函数,在man函数里面我们有三种方式来获取这个Person类的class对象。如果通过第一种方式Class.forName没有获取到指定类会报ClassNotFoundException 异常。

 public static void main(String[] args) throws ClassNotFoundException {// 第一种方式,使用Class类的forName,传入的参数是想要获取类的完整包名加类名Class c1 =Class.forName("com.chendsir.exercisejava.Person");// 第二种方式,直接使用想要获取类的class属性来获取Class对象。Class c2 =Person.class;// 第三种方式,通过实例对象的getClass方法获取Person person = new Person();Class<?> c3 = person.getClass();}

(2): 获取类的属性。

如下可通过默认获取所有属性以及指定属性的两种方式获取。如果没有获取到指定属性会报NoSuchFieldException异常。

        Class c4 = Person.class;//上面说的通过类的class属性获取Class对象// getDeclaredFields根据名字就可以知道,获取所有声明了的属性,无论什么访问权限。Field[] allFileds = c4.getDeclaredFields(); // id ,name,age都能获取到// getFields是访问该Class的所有public属性Field[] pubFileds = c4.getFields();   // 只能访问到age属性,因为age属性是public// 通过指定参数名id,访问Person类的id属性,找不到会报NoSuchFieldException异常Field idField = c4.getDeclaredField("id");// 通过指定参数吗age,访问Person类的公有age属性,找不到会报NoSuchFieldException异常Field ageField = c4.getField("age");

(3):获取类方法

获取方法和获取属性一样,可以默认获取所有,以及指定形参列表的方法。如果没有获取到指定的方法会报NoSuchMethodException 异常。

 public void setAge(String tempAge) {    // 添加一个方法this.age = tempAge;}public static void main(String[] args) throws NoSuchMethodException {Class c5 =Class.forName("com.chendsir.exercisejava.Person");// 获取Class对象所有声明的方法,getId,getName,getAgeMethod[] methods = c5.getDeclaredMethods();// 获取Class对象所有的public方法,假如把上例子的getId,getName改为private,这里只能获取到getAgeMethod[] allpubmethods = c5.getMethods();// 此处获得的是setAge() 没有形参的方法,且权限是publicMethod method = c5.getMethod("setAge");// 此处获得的是setAge(String tempAge) 方法,而且形参为String类型Method method2 = c5.getMethod("setAge",String.class);// 同上,不过无论是public还是private都能获取到Method method3 = c5.getDeclaredMethod("setAge",String.class);}

(4) 获取类的构造函数

   获取类的构造函数也可以获取所有的构造函数,和指定的方式。和上面是一个套路。相信大家已经熟悉了。

 public Person(String age) {  // 添加一个带参数的构造函数this.age = age;}public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {Class c5 =Class.forName("com.chendsir.exercisejava.Person");// 获取所有的构造函数Constructor<?>[]  constructors = c5.getDeclaredConstructors();// 获取public的构造函数Constructor<?> [] constructors1 = c5.getConstructors();  // 获取带形参String参数的构造函数 Constructor<?>  constructor  = c5.getDeclaredConstructor(String.class);// 获取带形参String参数的Public构造函数Constructor<?>  constructor1 = c5.getConstructor(String.class);}

(5) 获取类的注解

获取注解也可以直接获取类中的所有注解或者指定一个注解,同样的套路,Retrofit的自定义ConvertFactory的来定义请求格式和返回格式的时候,经常用到Annotation这个。

       // 获取所有注解,retorfit自定义的话,通过遍历可以来判断你的请求或者返回格式是xml还是jsonAnnotation[] annotations = c5.getAnnotations();// 获取注解为Override的注解Annotation annotation =c5.getAnnotation(Override.class);

(6) 通过反射来生成对象

如何得到一个类的实例对象呢,在第(4) 步中我们已经知道怎么获取构造函数了,既然构造函数都有了,直接调用构造函数的newInstance方法就可以直接生成一个实例了。也可以直接通过Class对象的newInstance()来生成一个对象,调用的是无参构造函数,此处原生native方法会抛出InstantiationException, IllegalAccessException两个异常。

     Class c5 =Class.forName("com.chendsir.exercisejava.Person");// 第一种方式,直接通过Class对象的newInstance方法来生成对象Object obj1 = c5.newInstance();// 第二种方式,通过构造函数来生成对象Constructor<?>  constructor  = c5.getDeclaredConstructor(String.class);Object obj2 = constructor.newInstance("18");// 我们获取的是有参构造函数,这里传入一个参数。

(7) 如何调用类的方法以及修改其属性

通过以上我们已经拿到了对象以及得到了方法,那么一个方法如何取调用以及传参呢。我们一般是通过invoke的方式去调用方法并传入相应参数。

   ...省略public void setAge(String tempAge) {this.age = tempAge;}...省略Class c5 =Class.forName("com.chendsir.exercisejava.Person");Object obj1 = c5.newInstance();// 获取setAge方法Method method = c5.getDeclaredMethod("setAge", String.class);// 第一个参数是生成的实例对象obj1,第二个参数是我们调用setAge传入的参数名method.invoke(obj1,"18");

假如我们的Class中没有setAge这个方法,但是我们又想要修改age的值,该如何做呢。我们通过第(2)步可以直接获取一个类的属性,Filed类已经给我们提供了get和set方法了,如果是基本类型,用setInt、setChar、setBoolean来改,如果是引用类型直接用set方法,通过这个可以直接改,非常强大。

 Object obj1 = c5.newInstance();// 我们先获取id这个属性Field field = c5.getField("id");// 通过setInt的方法来修改这个对象的id值为2field.setInt(obj1,2);// 如果要修改age呢?因为我定义的age是String类型的,不是基本类型,而是引用。Field field2 = c5.getField("age");// 通过set的方法来修改这个对象的age值为19field2.set(obj1,"19");//  想要获取的话,用get方法field2.get(obj1)  //来获得这个String类型的age值

(8) 反射的其他扩展常用方法

     //一些常用判断,为真返回true,否则false   Class c5 =Class.forName("com.chendsir.exercisejava.Person");boolean isPrimitive = c5.isPrimitive(); //是否是基本类型,boolean isArray = c5.isArray();// 是否是集合类boolean isAnnotation = c5.isAnnotation();// 是否是注解类boolean isInterface = c5.isInterface(); // 是否是接口类boolean isEnum = c5.isEnum();    // 是否是枚举类boolean isAnonymousClass = c5.isAnonymousClass();//isAnonymousClass; 判断是否是匿名内部类boolean isAnonationPresent = c5.isAnnotationPresent(Deprecated.class); //判断是否被Deprecated这个注解类修饰String className = c5.getName(); // 这个getName包含了包名的路径Package apackage = c5.getPackage(); // 获取包的信息String classSimpleName = c5.getSimpleName(); //获取class类名int modfiers = c5.getModifiers();//获取class访问权限Type genericSuperclass = c5.getGenericSuperclass();// 获得class对象的直接超类typeType[]  interfaceTypes = c5.getGenericInterfaces(); // 获取class 对象的所有接口的type集合Class<?> []  classes = c5.getDeclaredClasses();//获取内部类Class<?>   classes1 = c5.getDeclaringClass();//获取外部类

三、java反射的一些应用场景

1: Retofit这个框架,注解很强大,也是利用反射和注解结合起来的。

2: EventBus 单纯的反射机制应用框架

3: 反编译

4:JDBC的利用反射加载数据库驱动

5: Spring框架用反射加载xml配置信息

6: 动态生成类框架Gson

7:  动态代理模式

8:某些带有@hide注解的变量或者类,我们无法直接获取,通过反射就可以拿到

四、总结

通过本篇文章学会了如何通过反射,获取一个类,获取该类的属性、方法,构造函数、注解,以及如何调用这些方法,通过反射的方式生成一个对象,赋值,修改某个属性的值。本文讲的都是反射的一些基础,希望能对正在学习java反射的童鞋们有一个很好的引导。深入学习的话得建议去了解一下反射的动态代理模式,通过反射来获取泛型、以及泛型擦除的一些原理。

Java的反射基础与常用方法相关推荐

  1. 反射第一篇,学习Java的反射基础

    反射基础 什么是反射? 反射的使用 介绍:类对象 获取类对象 类对象的方法简介 使用:利用反射创建对象 例 调用特定构造方法 使用:获取成员变量并修改 例 使用:获取成员方法并调用 例 调用特定方法 ...

  2. JAVA 之反射(基础概念) 几个主要常用的重要的方法

    什么叫JAVA反射机制? 能够动态获取的信息以及动态调用对象的方法的功能称为JAVA语言的反射机制. 通过反射机制,能做什么? 正常的编译是将处于JVM中的字节码(CLASS文件)进行处理 可以在程序 ...

  3. 一篇文章弄懂Java反射基础和反射的应用场景

    文章目录 一.Java反射定义 二.Java反射机制实现 1.Class对象获取 2.获取class对象的摘要信息 3.获取class对象的属性.方法.构造函数等 三.反射的应用场景 1.动态代理 2 ...

  4. 【java基础】java的反射机制

    1.简介 java的反射机制是java的特性之一,反射技术是构建框架技术的基础所在. java的反射机制,是指在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法,对于任意一个对象,都能调用它 ...

  5. java 反射基础 万字详解(Class-Constructor-Method-Field一条龙)

    目录 前言 一.反射及其相关概念 1.什么是反射? 2.反射的用途: ①分析类: ②查看并使用对象: 3.反射的应用场景: 4.类加载器: 类的加载时机: 5.Class对象: 联系: 二.获取Cla ...

  6. 支撑Java框架的基础技术:泛型,反射,动态代理,cglib

    以Spring为例要想看明白他的源码需要彻底理解Java的一些基础技术泛型,反射同时对于一些高级技术例如动态代理,cglib和字节码技术也需要掌握,下面就按章节来一一说清楚这些技术的核心部分,最后手写 ...

  7. Java基础教程:反射基础

    Java基础教程:反射基础 引入反射 反射是什么 能够动态分析类能力的程序称为反射. 反射是一种很强大且复杂的机制. Class类 在程序运行期间,Java运行时系统始终为所有对象维护一个被称为运行时 ...

  8. java 反射基础知识

    java 反射 基础知识 反射:reflection 反射关键类 java 反射部分应用 反射:reflection 在运行中分析类. 在运行中查看和操作对象. 基于反射自己创建对象. 调用不可以访问 ...

  9. java 反射基础_Java基础教程:反射基础

    Java基础教程:反射基础 引入反射 反射是什么 能够动态分析类能力的程序称为反射.反射是一种很强大且复杂的机制. Class类 在程序运行期间,Java运行时系统始终为所有对象维护一个被称为运行时的 ...

最新文章

  1. MySQL这样写UPDATE语句,劝退
  2. LeetCode 14. Longest Common Prefix
  3. 关于 屏幕阅读器 和 sr-only
  4. 《系统集成项目管理工程师》必背100个知识点-28范围管理计划和需求管理计划...
  5. 【php学习笔记】ticks篇
  6. easymock 图片_数据模拟神器 easy-mock 正式开源
  7. Turing equation
  8. python 批量读取xlsx并合并_如何用Python快速导入多个excel文件并合并文件数据
  9. 重磅!MobileNetV3 来了!
  10. 【编译原理笔记10】语法制导翻译:在递归预测过程中进行翻译,L属性定义的自底向上翻译
  11. 服务器共享文件夹的管理,管理共享文件夹的权限
  12. Java的指针碰撞简介
  13. bp神经网络实现人脸识别,车牌识别深度神经网络
  14. 猿创征文|后端开发工程师提升开发效率神器推荐
  15. AD转换精度提高方法
  16. 小米手机miui12稳定版蓝牙时断不稳定的解决办法。
  17. C语言学习笔记第十天
  18. Evernote 新搭档Evertracker,掌控自己的时间(视频)
  19. 一、操作系统的概念功能
  20. 支付宝异步通知(notify_url)与return_url.

热门文章

  1. wordpress 、supesite、discuz,ngi…
  2. 5G+4G才是最佳解答:乾元通多网聚合路由器
  3. win10恢复默认字体
  4. Unity 代码切换 Android平台
  5. DOI EXCEL显示报表
  6. Vijos P1485 传球游戏(动态规划)
  7. mysql怎么禁止输出文件_MySQL禁止导出文件时写WebShell的方法 | kTWO-个人博客
  8. 使用echart的map绘制辽宁省地图
  9. InnoDB学习笔记一引擎架构及特性
  10. 如何关闭cmd窗口?七个实用的小技巧。