Java语言的反射机制初步学习

首先看下基本概念:

(一)在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任
意一个方法?答案是肯定的。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。

Java 反射机制主要提供了以下功能:

①:在运行时判断任意一个对象所属的类。
       ②:在运行时构造任意一个类的对象。   
       ③:在运行时判断任意一个类所具有的成员变量和方法。
       ④: 在运行时调用任意一个对象的方法

反射机制允许程序在运行时通过反射的API获取类中的描述,方法,并且允许我们在运行时改变fields内容或者去调用methods

(二)Java Reflection APIs简介:

在JDK中,主要由以下类来实现Java反射机制,这些类都
    位于java.lang.reflect包中
     ①:Class类:代表一个类。【注:这个Class类进行继承了Object,比较特别】
     ②:Field 类:代表类的成员变量(成员变量也称为类的属性)。
     ③:Method类:代表类的方法。
     ④:Constructor 类:代表类的构造方法。
     ⑤:Array类:提供了动态创建数组,以及访问数组的元素的静态方法

简要说下是使用方法的步骤:

要想使用使用反射,我们要去获取我们需要进行去处理的类或者对象的Class对象,其中我们主要有三种方法去获取

①:使用Class的静态方法forName():例如:Class.forName("java.lang.Class");

②:使用XXX.Class语法:例如:String.Class;

③:使用具体某个对象.getClass()方法:例如String str="abc"; Class<?> tClass=str.getClass();

先看一个例子:这个例子对于指定的类名,使用反射来获取该类中的所有声明的方法,(使用第一种获取Class对象的方法)(主要代码如下:):

  1. package com.jiangqq.reflection;
  2. /**
  3. * 使用反射来获取Class中的生命的方法,包括私有的方法
  4. */
  5. import java.lang.reflect.Method;
  6. public class Reflection1 {
  7. public static void main(String[] args) throws Exception {
  8. //使用Class去调用静态方法forName()获得java.lang.Class的Class对象
  9. Class<?> tClass = Class.forName("java.lang.Class");
  10. //获取该class中声明的所有方法
  11. Method[] methods = tClass.getDeclaredMethods();
  12. for (Method method : methods) {
  13. System.out.println(method);
  14. }
  15. }
  16. }

(三)查看Class的API发现Class类是Reflection API 中的核心类,它有以下几个常用的方法

①: getName():获得类的完整名字。
            ②: getFields():获得类的public类型的属性。
            ③: getDeclaredFields():获得类的所有属性。
            ④: getMethods():获得类的public类型的方法。
            ⑤: getDeclaredMethods():获得类的所有方法。

⑥:getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字parameterTypes参数指定方法的参数类型。

⑦:getConstructors():获得类的public类型的构造方法。

⑧:getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes参数指定构造方法的参数类型。

⑨:newInstance():通过类的不带参数的构造方法创建这个类的一个对象。

先看上面的⑧和⑨其中都能生成对象,但是因为构造函数有无参和有参构造函数两种,所以我们分两种情况考虑

情况一:如果是无参的构造函数来生成对象:

<a>首先我们去获取Class对象,然后直接通过Class对象去调用newInstance()方法就可以

  1. Class<?> tclass = Reflection2.class;
  2. Object reflection2 = classType.newInstance();

<b>首先我们也是去获取Class对象,然后去去调用getConstructor()得到Constructor对象,接着直接调用newInstance()即可

  1. Class<?> classType = Reflection2.class;
  2. t reflection2 = classType.newInstance();
  3. Constructor<?> constructor = classType.getConstructor(new Class[] {});
  4. reflection2 = constructor.newInstance(new Object[] {});

情况二:现在是有参构造函数,那我们只有一种方法来通过反射生成对象:

  1. Class<?> tClass = Person.class;
  2. Constructor cons = classType.getConstructor(new Class[]{String.class, int.class});
  3. Object obj = cons.newInstance(new Object[]{“zhangsan”, 19});

接下来根据以上的一些常用的方法,使用反射举几个例子(使用反射来访问类中的方法):

  1. package com.jiangqq.reflection;
  2. import java.lang.reflect.Constructor;
  3. import java.lang.reflect.Method;
  4. /**
  5. * 反射练习二,使用反射访问类中的方法
  6. *
  7. * @author jiangqq
  8. *
  9. */
  10. public class Reflection2 {
  11. public int sum(int a, int b) {
  12. return a + b;
  13. }
  14. public String addStr(String str) {
  15. return "This is the:" + str;
  16. }
  17. public static void main(String[] args) throws Exception {
  18. Class<?> classType = Reflection2.class;
  19. // Object reflection2 = classType.newInstance();
  20. Constructor<?> constructor = classType.getConstructor(new Class[] {});
  21. Object reflection2 = constructor.newInstance(new Object[] {});
  22. // 通过反射进行反射出类中的方法
  23. Method sumMethod = classType.getMethod("sum", new Class[] { int.class,
  24. int.class });
  25. //invoke方法的值永远只是对象
  26. Object result1 = sumMethod.invoke(reflection2, new Object[] { 6, 10 });
  27. System.out.println((Integer) result1);
  28. Method addStrMethod = classType.getMethod("addStr",
  29. new Class[] { String.class });
  30. Object result2 = addStrMethod.invoke(reflection2,
  31. new Object[] { "tom" });
  32. System.out.println((String) result2);
  33. }
  34. }

④:通过反射机制调用对象的私有方法,访问对象的私有变量....

我们大家都知道,在Java语言中,如果我们对某些变量,或者方法进行private的声明,然后我们在其他类中进行不能去调用这些方法和变量,但是通过反射机制,这些私有声明将不复存在【提醒一点:在写程序的时候,我们最好不要故意经常去使用反射机制来打破这种私有保护...】

要实现这种功能,我们需要用到AccessibleObject类中的public void setAccessible(boolean flag)方法:

使用这个方法,把参数flag设置成true,然后我们的field或者method就可以绕过Java语言的语法访问的检查

具体使用如下:

<a>使用反射去访问私有方法

  1. package com.jiangqq.reflection;
  2. public class Test01 {
  3. private String getName(String name) {
  4. return "This i:" + name;
  5. }
  6. }
  7. package com.jiangqq.reflection;
  8. import java.lang.reflect.Method;
  9. public class TestPrivate01 {
  10. public static void main(String[] args) throws Exception {
  11. Test01 p = new Test01();
  12. Class<?> classType = p.getClass();
  13. Method method = classType.getDeclaredMethod("getName",
  14. new Class[] { String.class });
  15. method.setAccessible(true);
  16. Object object = method.invoke(p, new Object[] { "tom" });
  17. System.out.println((String)object);
  18. }
  19. }

<b>使用反射机制去访问私有变量:

  1. package com.jiangqq.reflection;
  2. public class Test02 {
  3. private String name="张三";
  4. private String getName()
  5. {
  6. return name;
  7. }
  8. }
  9. package com.jiangqq.reflection;
  10. import java.lang.reflect.Field;
  11. import java.lang.reflect.Method;
  12. public class TestPrivate02 {
  13. public static void main(String[] args) throws Exception {
  14. Test02 p = new Test02();
  15. Class<?> classType = p.getClass();
  16. Field field = classType.getDeclaredField("name");
  17. //设置true,使用可以绕过Java语言规范的检查
  18. field.setAccessible(true);
  19. //对变量进行设置值
  20. field.set(p, "李四");
  21. Method method = classType.getDeclaredMethod("getName", new Class[] {});
  22. method.setAccessible(true);
  23. Object object = method.invoke(p, new Object[] {});
  24. System.out.println((String) object);
  25. }
  26. }

以上只是自己的初步学习反射,有很多总结的不到位地方,还请多多包涵,共同学习....

java_ _反射的更多相关文章

  1. luogg_java学习_10_异常_反射

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! 异常_反射 异常 异常就是导致程序中断执行的一段指令流 ...

  2. JavaSE学习总结第27天_反射 & 设计模式 & JDK5、7、8新特性

      27.01  反射_类的加载概述和加载时机 类的加载:当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. 加载:就是指将class文件读 ...

  3. Python-老男孩-01_基础_文件IO_函数_yield_三元_常用内置函数_反射_random_md5_序列化_正则表达式_time

    Python2.7 缩进统一: 约定  常量 大写 , 变量  小写 判断一个变量在内存中的地址,也能看出是不是一个值 id()函数 >>> x = 'abc' >>&g ...

  4. Java_通过反射调用类中的方法

    先上一个基本的封装: /** * 获取classType * * @param type * @param provinceCode * @param cityCode * @return * @th ...

  5. 黑马程序员:Java编程_反射技术

    =========== ASP.Net+Android+IOS开发..Net培训.期待与您交流!=========== Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性 ...

  6. C# Assembly类_反射

    System.Reflection.Assembly类是一个比较常用到的类,在反射中就经常用到. 由于这个类实在有太多的字段.属性与方法.实在不想将一个个属性方法从MSDN复制出来然后逐个属性.方法敲 ...

  7. Android面试基础(一)IOC(DI)框架(ViewUtils)讲解_反射和自定义注解类

    1. Android中的IOC(DI)框架 1.1 ViewUtils简介(xUtils中的四大部分之一) IOC: Inverse of Controller 控制反转. DI: Dependenc ...

  8. C#_反射机制

    一:反射的定义 审查元数据并收集关于它的类型信息的能力.元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等. Sys ...

  9. [19/04/17-星期三] Java的动态性_反射(Reflection)机制

    一.前言 动态语言:程序运行时,可以改变程序结构或变量类型.典型的代表:Python,ruby,JavaScript 如JavaScript代码: function test(){ var s=&qu ...

随机推荐

  1. 【POJ3904】【P1202】水晶密码

    说是莫比乌斯反演,其实只是玩儿玩儿内个miu函数而已…… 原题: wty  打算攻击 applepi  的用来存放机密数据的水晶系统. applepi 早有察觉,于是布置了一个密码系统来防备 wty ...

  2. jquery.ajaxfileupload.js

    jquery.ajaxfileupload.js上传插件,利用iframe提交不刷新页面功能完成. /* // jQuery Ajax File Uploader // // @author: Jor ...

  3. Questions that are independent of programming language. These questions are typically more abstract than other categories.

    Questions that are independent of programming language.  These questions are typically more abstract ...

  4. CENTOS GUI

    http://unix.stackexchange.com/questions/181503/how-to-install-desktop-environments-on-centos-7 How t ...

  5. DATA GUARD架构(一)

    Data Guard传输-应用架构.>图1-1 ------------------------------------------------------------ 重做传输架构>图1 ...

  6. 02-Java 数组和排序算法

    一.Java 数组 1.数组定义:数组是有序数据的集合,数组中的每个元素具有相同的数组名和下标来做唯一标识. 2.数组的分类:一维.二维.三维. 3.数组声明及内存分配: 为数组分配内存空间:如果不分 ...

  7. 【转】图解CSS的padding,margin,border属性(详细介绍及举例说明)

    W3C组织建议把所有网页上的对像都放在一个盒(box)中,设计师可以通过创建定义来控制这个盒的属性,这些对像包括段落.列表.标题.图片以及层.盒模型主要定义四个区域:内容(content).边框距(p ...

  8. Linux 下增大tomcat内存

    我的服务器的配置: # OS specific support.  $var _must_ be set to either true or false. JAVA_OPTS="-Xms10 ...

  9. eclipse打包jar文件(含外部jar包)的方法

    在项目发布前,使用eclipse导出普通的jar包时,如果配置不好,在运行命令Java -jar /test.jar 时可能会出现如下三类错误信息: 1.no main manifest attrib ...

  10. C# Color Table颜色对照表

    .AliceBlue 240,248,255 .LightSalmon 255,160,122 .AntiqueWhite 250,235,215 .LightSeaGreen 32,178,170 ...