网站首页 > 技术文章 正文
正常的反射实例化一个类很容易,但是当涉及内部类的情况就有点不一样了。本文关于内部类的语法是最核心的部分,更多内容可参考语法书。 本文所有的异常都用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表达式的出现,虽然能够在一定程度上减少代码量,但是极大的增加了代码的阅读难度。
内部类
内部类分为如下三种:
1.静态类2.非静态类3.局部内部类,具体可参考lambda表达式
内部类的共有4个作用域: 同一个类、同一个包、父子类和任意位置。
静态内部类
静态内部类是外部类的类相关的,而不是外部类的对象相关的。静态内部类只是持有外部类的类引用,没有持有外部类对象的引用,这也就是为什么静态内部类的实例方法不能外部类的实例属性的原因。
非静态内部类
在非静态内部类的对象里,保存了一个它所寄生的外部类的对象引用,所以可以访问外部类的私有成员。
反射
有了反射,Java的灵活性上升了一个层级,不过安全性就. . .
在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何东西都可以。
Android中的很多hook技术,利用的就是反射+代理来实现的,后面的文章会专门写Android的hook机制,包括Binder的HOOK。
API
没有什么比官方文档更权威的解释,如果有,那就是源代码了。相应的API均来自官方文档。
Modifier and TypeMethodDescriptionCommentClass<?>[]getDeclaredClasses()Returns an array of Class objects reflecting all the classes and interfaces declared as members of the class represented by this Class object.获取到所有的类,包括内部类和接口。ConstructorgetConstructor?(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.当实在搞不明白参数该怎么传的时候,可以考虑把所有的构造器都打印出来TnewInstance?(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代码如下,关键地方给出了注释。
package java_code;
import java.lang.reflect.Constructor;
public class Test {
public static void main(String[] args) {
Test001 test001 = new Test001();
Object object = getInnerInstance(test001);
try{
Class.forName("java_code.Test001").newInstance();
//Test001.class.getDeclaredConstructor().newInstance();
} catch (Exception e){
e.printStackTrace();
}
}
private static Object getInnerInstance(Test001 test001) {
Object object = null;
try {
Class[] innnerClass = test001.getClass().getDeclaredClasses();
for (Class c: innnerClass){
if (c.getName().indexOf("Test001001") != -1){//有参数
//Constructor cc = c.getConstructors()[0];
Constructor cc = c.getConstructor(test001.getClass(), String.class);
object = cc.newInstance(test001, "欢迎关注我的微信公众号:无情剑客");
} else if (c.getName().indexOf("Test001002") != -1){//无参数
Constructor cc = c.getConstructor(test001.getClass());
object = cc.newInstance(test001);
} else {//静态内部类
Constructor cc = c.getConstructor();
object = cc.newInstance();
}
}
return object;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
最终运行结果:
参考
https://docs.oracle.com/javase/9/javadoc/javadoc.html
写在最后
网上很多写反射的,但是对于内部类的反射涉及的非常少,尤其是这种私有的内部类。也许有人认为私有内部类是不能被外部实例化的,但是强大的反射功能突破了Java本身的一些规则。
公众号
更多内容,欢迎关注我的微信公众号:无情剑客。
猜你喜欢
你 发表评论:
欢迎- 614℃几个Oracle空值处理函数 oracle处理null值的函数
- 605℃Oracle分析函数之Lag和Lead()使用
- 593℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 591℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 585℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 579℃【数据统计分析】详解Oracle分组函数之CUBE
- 568℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 559℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
-
- PageHelper - 最方便的 MyBatis 分页插件
- 面试二:pagehelper是怎么实现分页的,
- MyBatis如何实现分页查询?(mybatis-plus分页查询)
- SpringBoot 各种分页查询方式详解(全网最全)
- 如何在Linux上运行exe文件,怎么用linux运行windows软件
- 快速了解hive(快速了解美国50个州)
- Python 中的 pyodbc 库(pydbclib)
- Linux搭建Weblogic集群(linux weblogic部署项目步骤)
- 「DM专栏」DMDSC共享集群之部署(一)——共享存储配置
- 故障分析 | MySQL 派生表优化(mysql pipe)
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- 前端获取当前时间 (50)
- Oracle RAC (76)
- oracle恢复 (77)
- oracle 删除表 (52)
- oracle 用户名 (80)
- oracle 工具 (55)
- oracle 内存 (55)
- oracle 导出表 (62)
- oracle约束 (54)
- oracle 中文 (51)
- oracle链接 (54)
- oracle的函数 (58)
- 前端调试 (52)
本文暂时没有评论,来添加一个吧(●'◡'●)