正常的反射实例化一个类很容易,但是当涉及内部类的情况就有点不一样了。本文关于内部类的语法是最核心的部分,更多内容可参考语法书。
本文所有的异常都用Exception,不会区分何种异常。具体情况要根据实际情况。
Test001代码
Test001.java代码如下,在其中包含一个私有的内部类,其构造函数是带有参数的。
package java_code;
public class Test001 {
public Test001(){
System.out.println("burning");
}
private class Test001001 {
public Test001001(String str){
System.out.println(str);
}
}
public class Test001002 {
public Test001002(){
System.out.println("burning002");
}
}
static class Test001003 {
public Test001003(){
System.out.println("burning003");
}
}
private static class Test001004 {
public Test001004(){
System.out.println("burning004");
}
}
}
外部类实例化
公用类的反射实例化:
下面的代码给出了两种方式,不过第一种方式是Deprecated的。
try{
//Class.forName("java_code.Test001").newInstance();
Test001.class.getDeclaredConstructor().newInstance();
} catch (Exception e){
e.printStackTrace();
}
内部类的实例化
内部类的出现是简化了Java那,还是把Java搞复杂了那。笔者更倾向于后者,可能也是我对Java的理解不够。尤其是匿名内部类和lambda表达式的出现,虽然能够在一定程度上减少代码量,但是极大的增加了代码的阅读难度。
内部类
内部类分为如下三种:
- 静态类
- 非静态类
- 局部内部类,具体可参考lambda表达式
内部类的共有4个作用域: 同一个类、同一个包、父子类和任意位置。
静态内部类
静态内部类是外部类的类相关的,而不是外部类的对象相关的。静态内部类只是持有外部类的类引用,没有持有外部类对象的引用,这也就是为什么静态内部类的实例方法不能外部类的实例属性的原因。
非静态内部类
在非静态内部类的对象里,保存了一个它所寄生的外部类的对象引用,所以可以访问外部类的私有成员。
反射
有了反射,Java的灵活性上升了一个层级,不过安全性就. . .
在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何东西都可以。
Android中的很多hook技术,利用的就是反射+代理来实现的,后面的文章会专门写Android的hook机制,包括Binder的HOOK。
API
没有什么比官方文档更权威的解释,如果有,那就是源代码了。相应的API均来自官方文档。
Modifier and Type | Method | Description | Comment |
Class<?>[] | getDeclaredClasses() | Returns an array of Class objects reflecting all the classes and interfaces declared as members of the class represented by this Class object. | 获取到所有的类,包括内部类和接口。 |
Constructor | getConstructor(Class<?>… parameterTypes) | Returns a Constructor object that reflects the specified public constructor of the class represented by this Class object. | 如果是非静态内部类的话,第一个参数需要是其寄生的外部类 |
Constructor<?>[] | getConstructors() | Returns an array containing Constructor objects reflecting all the public constructors of the class represented by this Class object. | 当实在搞不明白参数该怎么传的时候,可以考虑把所有的构造器都打印出来 |
T | newInstance(Object… initargs) | Uses the constructor represented by this Constructor object to create and initialize a new instance of the constructor’s declaring class, with the specified initialization parameters. | 如果是非静态内部类的话,第一个参数需要是其寄生的外部类实例 |
实例化私有内部类
Test.java代码如下,关键地方给出了注释。
最终运行结果:
参考
https://docs.oracle.com/javase/9/javadoc/javadoc.html
写在最后
网上很多写反射的,但是对于内部类的反射涉及的非常少,尤其是这种私有的内部类。也许有人认为私有内部类是不能被外部实例化的,但是强大的反射功能突破了Java本身的一些规则。
公众号