一、什么是反射?

我们先来看一个例子:

package venus;
public class Student {public String name;public Student(){System.out.println("无参构造方法");}public void doHomework(){System.out.println(name + "正在做作业~~~");}}

我们平常是如何调用Student类里的方法的?

package venus;
public class Test {public static void main(String[] args) {Student student = new Student(); student.name = "小白";student.doHomework();}
}//结果:
无参构造方法
小白正在做作业~~~

以上这种方法是普通的方法:其中Student student = new Student()通过new关键字来创建对象,调用无参构造方法;接着的student.name = "小白"是调用的其中的成员变量;student.doHomework()是调用普通方法。

一般情况下,我们使用某个类时是知道这个类是什么类,是用来做什么的,所以我们可以直接对这个类进行实例化,之后使用这个类的对象进行操作,就例如上面的
      但反射则是一开始我们并不知道要初始化的类对象是什么,就无法通过new关键字来创建对象了;也就是说反射是在运行时才知道要操作的类是什么,并且可以通过相应的方法可以获得这个类完整的样子!

综上所述,反射就是一种新的操作类中成员变量、构造方法和普通方法的机制,它可以将类中的各个组成部分进行剖析,可以得到每个组成部分,然后对每个组成部分进行操作!

二、Class类

要实现对类中的成员变量、构造方法和普通方法的操作,我们需要借助Java自身提供的java.lang包下的Class类和java.lang.reflect包下的反射API(接口)。

  • Class类是Java反射机制的入口,封装了一个类或接口的运行时信息,通过调用Class类的方法可以获取这些信息。
  • Class类的特点 :
    • 该类在Java.lang包中;
    • 该类被final所修饰,即该类不可以被子类继承;
    • 该类实现了Serializable接口;
    • 该类的构造方法被private所修饰,即不能通过new关键字创建该类的对象。

2.1获取Class实例化对象

获取Class类实例化对象有以下六种方法:

  1. 通过Class.forName("包名.类名")来获取Class类实例:

       try {Class clazz = Class.forName("venus.Student");//抛出检查时异常,所以使用try-catchSystem.out.println(clazz.getName()); //venus.Student} catch (Exception e) {e.printStackTrace();}
    
  2. 通过类名.class来获取Class类实例:
        Class clazz = Student.class;System.out.println(clazz.getName()); //venus.Student
    
  3. 如果已创建了引用类型的对象,则可以通过调用对象中的getClass()方法来获取Class类实例:
      Student student = new Student();//已创建了引用类型的对象Class clazz = student.getClass();System.out.println(clazz.getName());
    
  4. 如果是基本数据类型,则可以通过包装类.TYPE来获取Class类实例,当然,也可以通过基本数据类型.class获取Class类实例:
      Class clazz = Integer.TYPE;System.out.println(clazz.getName()); //intclazz = int.class;System.out.println(clazz.getName()); //int
    
  5. 通过元素类型[].class来获取数组所对应的Class类实例:
      clazz = String[].class;System.out.println(clazz.getName()); //[Ljava.lang.String;
    
  6. 如何获取某个类父类所对应的Class类实例?通过类名.class.getSuperclass()来获取:
       clazz = Student.class.getSuperclass();System.out.println(clazz.getName()); //java.lang.Object
    

三、 借助Class类某些可以获取对应类中声明的构造方法实例化对象:

  • 其中getConstructor([参数类型])只能获取由public修饰的构造方法

    1. Constructor[] getConstructor():获取 无参构造方法:

      Class clazz = Student.class; //获取Class实例化对象
      try {Constructor constructor = clazz.getConstructor(); //获取无参构造方法System.out.println(constructor.getName()); //venus.StudentSystem.out.println(constructor); //public venus.Student()
      } catch (Exception e) {e.printStackTrace();
      }
      
    2. Constructor getConstructor(Class<?>... parameterTypes):获取 对应的有参构造方法:

      Class clazz = Student.class;
      try {//获取参数类型为String的有参构造方法Constructor constructor = clazz.getConstructor(String.class); System.out.println(constructor.getName()); //venus.StudentSystem.out.println(constructor); //public venus.Student(java.lang.String)
      } catch (Exception e) {e.printStackTrace();
      }
      
  • 其中getDeclaredConstructor([参数类型])可以获取所有的构造方法,不区分访问权限(即使是私有的也可以):

    1. Constructor getDeclaredConstructor():获取 无参构造方法

      Class clazz = Student.class;
      try {//获取无参构造方法Constructor constructor = clazz.getDeclaredConstructor(); System.out.println(constructor.getName()); //venus.StudentSystem.out.println(constructor); //public venus.Student()
      } catch (NoSuchMethodException e) {e.printStackTrace();
      }
      
    2. Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):获取 对应的有参构造方法:

      Class clazz = Student.class;
      try {//获取参数类型为 int的有参构造方法constructor = clazz.getDeclaredConstructor(int.class);System.out.println( constructor.getName()); //venus.StudentSystem.out.println(constructor); //private venus.Student(int)
      } catch (NoSuchMethodException e) {e.printStackTrace();
      }
      

3.1 通过Constructor类某些方法获取某个构造方法的的信息:

Class clazz = Student.class;
try {//获取参数类型为 String 和 int的有参构造方法Constructor constructor = clazz.getConstructor(String.class,int.class);
} catch (Exception e) {e.printStackTrace();
}
  • 获取该构造方法的相关信息:

    1. 获取该构造方法的类的Class对象(Class<T> getDeclaringClass()):

      Class result = constructor.getDeclaringClass();
      System.out.println(result); //class venus.Student
      
    2. 获取该构造方法的修饰符(int getModifiers()):

      int mod = constructor.getModifiers();
      String result = Modifier.toString(mod);
      System.out.println(result); //public
      
    3. 获取该构造方法的名称(String getName()):

      String result = constructor.getName();
      System.out.println(result); //venus.Student
      
    4. 获取该构造方法的形参类型对应的Class对象组成的数组

      Class[] clazzs = constructor.getParameterTypes();
      for (Class c:clazzs) {System.out.println(c); // {class java.lang.String , int}
      }
      
    • 注意:

      • getConstructors()getConstructor(Class<?>... parameterTypes)方法无法获取非public类中默认无参构造方法对应的Constructor对象。
      • getDeclaredConstructor()getDeclaredConstructor(Class<?>... parameterTypes)方法可以获取非public类中默认无参构造方法对应的Constructor对象。
  • 操作构造方法 ---- 创建对象:

    void setAccessible(boolean flag):如果操作的构造方法是私有的,则需要下面一行代码来忽略访问权限:

    constructor.setAccessible(true);
    

    T newInstance(Object... initargs):使用此Constructor对象表示的构造方法来创建声明该构造方法类的新对象。其中initargs为传入该构造方法中的参数,如果该构造方法没有参数,则可设定为null或一个长度为0的数组:

    Object object = constructor.newInstance("Tom",18);
    Student stu = (Student) object; //下转型
    stu.doHomework();
    

四、借助Class类某些可以获取对应类中声明的普通方法实例化对象:

  • Method[] getMethods():获取被public修饰的方法(不仅仅限于本类,还包括继承自父类中的public方法)

    Class clazz = Student.class;
    Method[] methods =  clazz.getMethods();
    for (Method method:methods) {System.out.println(method.getName());
    }
    

    结果:

  • Method[] getMethod(String methodName, Class<?>... paramenterTypes):获取与该Class对象表示类或接口中方法名和参数类型相匹配的public方法(含继承的)的Method对象:

    try {Method method = clazz.getMethod("doHomework");System.out.println(method.getName()); //doHomework
    } catch (Exception e) {e.printStackTrace();
    }
    
  • Method[] getDeclaredMethods():获取一个该Class对象表示类或接口内声明定义的所有访问权限的方法(不含继承的)对应的Method对象数组:

    Method [] methods = clazz.getDeclaredMethods();//(任何"访问权限"的方法)
    for (Method method:methods) {System.out.println(method.getName());
    }
    
  • Method getDeclaredMethod(String methodName Class<?>... parameterTypes):获取与该Class对象表示类或接口中方法名和形参类型相匹配的方法(不含继承的)对应的Method对象。

4.1 操作普通方法 ---- 获取普通方法的信息:

  • 先获取某个普通方法:

    try {//获取方法名为cooking,参数类型为int和String的方法Method method = clazz.getMethod("cooking", int.class, String[].class);
    } catch (Exception e) {e.printStackTrace();
    }
    
  • 获取该普通方法的相关信息:
    1. String getName():获取该普通方法的方法名:

      String result = method.getName();//获取方法名
      System.out.println(result); //cooking
      
    2. Class<?> getDeclaringClass():获取该普通方法的类或接口的Class对象:
      Class c = method.getDeclaringClass();//获取方法的类的Class对象
      System.out.println(c); //class venus.Student
      
    3. int getModifiers():获取该普通方法的修饰符(以整数形式),应该使用Modifier类中的toString()方法对所返回的整数进行解码:
      int mod = method.getModifiers(); //获取方法的修饰符
      String result = Modifier.toString(mod);
      System.out.println(result); //public static
      
    4. Class<?>[] getParameterTypes():获取该普通方法的形参类型对应Class对象组成的数组。如果方法没有参数,则数组长度为0:
      Class [] zzs = method.getParameterTypes();//获取方法的参数类型组成的数组 {Integer.YPTE, String[].class}
      for (Class cla :zzs) {System.out.println(cla.getName());
      }
      
    5. Class<?> getReturnType():获取该普通方法的返回值类型所对应的Class对象:
      Class clazzs = method.getReturnType();//获取方法的返回值类型★
      System.out.println(clazzs.getName());
      
    • 调用该普通方法:

      void setAccessible(boolean flag):如果该普通方法是非public的,则需要使用下一行代码来忽略访问权限,true表示忽略:

      method.setAccessible(true);
      

      Object invoke(Object obj, Object... args):调用该普通方法并返回Object类型结果(即返回该普通方法的【返回值】,如果没有,则返回null)。obj表示该方法所在类实例,如果方法是静态的,则obj可以指定为null;args表示传入该方法的参数,如果该方法没有参数,则args数组长度可以为0或null:

      Object object = method.invoke(new Student(),1,new String []{}); //调用这个方法,并返回该方法的【返回值】,如果该方法没有【返回值】,则返回null
      System.out.println(object);
      

Java反射(详述版)相关推荐

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

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

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

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

  3. java getconstructors,java 反射 constructors的问题,真心需要解决

    java 反射 constructors的问题,真心需要解决 mip版  关注:225  答案:1  悬赏:10 解决时间 2021-01-25 15:17 已解决 2021-01-25 10:12 ...

  4. dwr java有返回值但是js获取不到返回值_一探究竟:Java反射效率低的原因到底在哪?...

    预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低的原因 文章概览 我们在 Java 开发中,难免会接触到反射,而在一些框架中,反射的运 ...

  5. Java反射的底层原理,以及Java反射的性能分析及优化

    java的反射技术,号称是编程界的九阳神功,也可以说是框架的灵魂.也正是这种反射机制使静态语言的java具备了动态语言的某些特质.就是有了反射,才让java动态,编程的时候更加灵活,能够动态获取信息以 ...

  6. Java虚拟机规范 Java SE 8版 - class文件格式(二)

    Java虚拟机规范 Java SE 8版 - class文件格式(二) 4.5 字段 4.6 方法 4.7 属性 4.7.1 自定义和命名新的属性 4.7.2 ConstantValue 属性 4.7 ...

  7. Java反射破坏了封装性?

    这是本菜鸡面试时被问到的一个问题,觉得挺有意思的,遂打算写一篇文章简单的谈下自己的看法. 在讨论这个问题之前,让我们先来简单复习一下Java反射的知识. Java 反射 一.类型信息 在回顾Java反 ...

  8. 【EduCoder答案】Java高级特性- Java反射

    简介 答案查询的入口网页版 并不是所有的关卡都有答案,有些只有部分关卡有 不要直接复制答案哦 Java高级特性 - Java反射 >>>查看 第1关:了解 Class 对象 解题代码 ...

  9. java 反射机制详解

    火星十一郎 海纳百川, 有容乃大,QQ:791909235,Tel:13137910179 posts - 774, comments - 556, trackbacks - 0, articles ...

最新文章

  1. 实现统计一个字符串中的每个单词出现的次数--基于Go语言
  2. [转载]在SQL Server数据库之间进行数据导入导出,OPENDATASOURCE
  3. 深入Java调试体系之JDWP协议及实现
  4. 【杂谈】怎么使用有三AI完成系统性学习并赚钱
  5. 纯 js 导出 excel
  6. java 1.8 vm_HotSpot虚拟机在java 1.8中的新实现
  7. 腾讯管家去除桌面快捷小图标
  8. shell中各种括号()、(())、[]、[[]]、{}的作用
  9. 从人脸识别到内容审核,百度硬核AI技术推荐!
  10. 计算机教师自检自查报告,信息技术教学工作自查报告
  11. 搜索引擎难做,为什么微软必应活了下来?
  12. maven 搭建私有仓库
  13. redimine 插件_3DMine软件与国内外同类软件对比
  14. cpi计算机性能指标,将CPU时间=(CPI指令总数).ppt
  15. (附源码)php二手服装网站 毕业设计201711
  16. 不要迷恋我,虽然我利用Python来耍植物大战僵尸,威力加强版
  17. 三维图形的平移,旋转与错切
  18. 【教程】怎样在PC查看动漫之家(DMZJ)不能观看漫画
  19. 夏斌:半年宏观调控思路的建议
  20. 编写Firefox扩展(翻译)

热门文章

  1. C语言的单链表求交点
  2. l-logger命令基本介绍
  3. OpenCV 像素存储
  4. 《UNIX高级环境编程》 -- apue.h
  5. untitled与前端——初学
  6. 黑帽大会2014:10个酷炫的黑客工具
  7. C++ Primer 读书笔记 - 第十三章
  8. CS5中动作和批处理
  9. 充分理解表达式——《狂人C》习题解答2(第二章习题5)
  10. 图像特征点检测与匹配评价准则——量化