前面一段时间,我编写了一篇关于 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/