反射进阶,编写反射代码值得注意的诸多细节

  前面一段时间,我编写了一篇关于 Java 反射基础知识的博文,内容挺多的,涉及到了 Class 的获取,Field、Method、Constructor、Array 及 Enum 的获取与操作。如果学会了这些知识,就能阅读或者是编写大多数反射相关代码。

  但是,因为反射这一块的内容实在是太多了,编写代码过程中难免会遭遇到各种各样的 Exception,对于一个刚熟悉反射基础知识的新手而言,往往会感到深深的挫败感。其实,反射仍然算不难,但需要耐心与细心地对待它,本文的目的是列举编写反射代码中值得注意的一些细节,大家可以针对下面的目录部分,结合自己对反射这一块的熟悉程序,进行选择性地阅读。

  获取不存在的对象

  获取不到 Class 对象

  获取不到 Field

  获取不存在的 Field

  Field 存在但获取不到

  如何获取一个 Class 中继承下来的非 public 修饰的 Field

  获取不到 Method

  获取本身就不存在的 Method

  Method 存在却获取不到

  因为参数类型不匹配而找不到

  获取不到 Constructor

  获取本身不存在的构造器

  Constructor 存在却获取不到

  参数不匹配的问题

  获取一个 Class 的内部类或者接口

  getInterfaces 的作用

  反射中的权限问题

  操纵非 public 修饰的 Field

  操纵一个 final 类型的 Field

  操纵非 public 修饰的 Method

  操纵非 public 修饰的 Constructor

  setAccessible 的秘密

  ClassnewInstance 和 ConstructornewInstance 的区别

  谨慎使用 Methodinvoke 方法

  静态方法和非静态方法的区别

  Methodinvoke 参数的秘密

  Method 中处理 Exception

  总结

  编写反射代码时,一些常见的异常。

  

这里写图片描述

  如果你反射的基本知识都没有掌握,建议先仔细阅读我这篇文章《细说反射,Java 和 Android 开发者必须跨越的坎》

  获取不存在的对象

  比如获取不存在的 Class 对象,比如获取不到一个类中并不存在的 Field、Method 或者是 Constructor。 而 Field、Method 和 Constructor 都是一个 Class 对象中的成员。

  获取不到 Class 对象

  我们知道获取 Class 对象有 3 种方式。

  通过一个对象的 getClass() 方法。

  通过 .class 关键字。

  通过 Class.forName()。

  前两种方式,基本上是没有什么值得注意的地方,需要注意的是第 3 种,因为 Class.forName() 传递进去的参数是一个字符串类型,所以理论上你可以这样编写代码。

  Class test = Class.forName("hello world");11

  显然,在虚拟机中并不会存在这样一个类,所以,Java 提供了一个异常用来在获取不到 Class 文件时进行抛出。这个异常是 ClassNotFoundException。我们应该对于这一块进行处理。

  Class cls1 = new String("1").getClass();

  Class cls2 = int.class;

  try {

  Class test = Class.forName("hello world");

  } catch (ClassNotFoundException e1) {

  // TODO Auto-generated catch block

  e1.printStackTrace();

  System.out.println("find class error:"+e1.getMessage());

  }

  1234567891011121312345678910111213

  可以看到,只有通过 Class.forName() 的方式获取 Class 的时候才要进行异常的捕获处理,如果查找不到这个 Class 那么程序就会抛出异常。

  java.lang.ClassNotFoundException: hello world

  at java.net.URLClassLoader.findClass(Unknown Source)

  at java.lang.ClassLoader.loadClass(Unknown Source)

  at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)

  at java.lang.ClassLoader.loadClass(Unknown Source)

  at java.lang.Class.forName0(Native Method)

  at java.lang.Class.forName(Unknown Source)

  1234567891012345678910

  获取不到 Field

  获取不到 Field 的情况分两种:

  1. 确实不存在这个 Field

  2. 由于修饰符导致的权限问题。

  获取不存在的 Field

  我们先定义一个类 Base。

  public class Base {

  public String b;

  }

  12341234

  我们知道,获取一个 Class 中 Field 方式有 4 种。

  public Field getField(String name);

  public Field getDeclaredField(String name);

  public Field[] getFields();

  public Field[] getDeclaredFields()1234567812345678

  现在,我们可以用 getField() 方法获取 b 这个 Field。

  Class clzBase = Base.class;

  try {

  Field fieldBase = clzBase.getField("b");

  } catch (NoSuchFieldException e1) {

  // TODO Auto-generated catch block

  e1.printStackTrace();

  } catch (SecurityException e1) {

  // TODO Auto-generated catch block

  e1.printStackTrace();

  }1234567891012345678910

  但是,我们却没有办法去获取一个不存在的 Field,如 d。

  Field fielddBase = clzBase.getField("d");11

  它会导致程序抛出 NoSuchFieldException 异常。

  java.lang.NoSuchFieldException: d

  at java.lang.Class.getField(Unknown Source)1212

  Field 存在,但获取不到

  public class Base {

  public String b;

  int d;

  }

  public class NonExistTest {

  public static void main(String[] args) {

  Field fieldBase = clzBase.getField("d");

  System.out.println(Base.class.getSimpleName()+" has a field "+ fieldBase.getName());

  }

  }1234567891011121314151612345678910111213141516

  可以发现程序报错了。




宁波好的整形医院http://www.iyestar.com/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值