我想强制使另一个库中的类对子类开放.类本身是public的,但它唯一的构造函数是package—private.我已经探索了用字节码生成一个类,以打开构造函数并进行super()调用.在JASM(超级酷)中,类看起来是这样的:

public class com/internal/OpenChild
extends com/external/Parent
{
  public <init>()V {
    try {
      ldc com/external/Parent
      iconst 0
      anewarray java/lang/Class
      invokevirtual java/lang/Class.getDeclaredConstructor([java/lang/Class)java/lang/reflect/Constructor
      iconst 1
      invokevirtual java/lang/reflect/Constructor.setAccessible(Z)V
    } catch (java/lang/Throwable) {
      astore 0
      new java/lang/RuntimeException
      dup
      aload 0
      invokespecial java/lang/RuntimeException.<init>(java/lang/Throwable)V
      athrow
    }
    aload 0
    invokespecial com/external/Parent.<init>()V
    return
  }
}

这个类,com.internal.OpenChild,扩展com.external.Parent.它的public no—args构造函数使后者的package—private no—args构造函数可以访问,并随后调用super.等效的Java可能看起来像这样:

package com.internal;

import com.external.Parent;

public class OpenChild extends Parent {
  public OpenChild() {
    try {
      Parent.class.getDeclaredConstructor().setAccessible(true);
    } catch (Throwable t) {
      throw new RuntimeException(t);
    }
    super();
  }
}

当反射工作正常时,超级调用会失败,并出现IllegalExcellent异常.我相信我可能还有希望——毕竟,使用反射来创建一个com.external.Parent的实例是可能的.我的策略中缺少了什么?难道就不能动用这种黑魔法吗?

推荐答案

人们对the accessible property所做的事情有一个普遍的误解.

它根本不会改变反射构件.它只允许通过调用了setAccessible(true)的一个实例访问它.这意味着,反映同一成员的其他实例(例如,当其他代码站点查询类时)仍然有自己的可访问状态,默认为false,并且试图通过普通非反射访问(即字节码指令)访问该成员的类不受影响.

真正改变类的唯一(官方)方法是通过Instrumentation

或者,您可以inject a subclass into the same package个访问package—private构造函数.如果你的子类需要在另一个包中,你可以创建一个间接子类,即在包中注入一个子类,访问package—private构造函数,但有一个公共或受保护构造函数,可以由不同包中子类的子类访问.

Java相关问答推荐

编译期间错误(Java 0000)Android .Net MAUI

将具有多个未知字段的SON映射到Java POJO

Java 21虚拟线程会解决转向react 式单线程框架的主要原因吗?

Spring Batch 5-不要让它在数据库中自动创建表

@org.springframework.beans.factory.annotation.Autowired(required=true)-注入点有以下注释:-SpringBoot

如何才能使我的程序不会要求两次输入?

AssertJ Java:多条件断言

使用Spring Boot3.2和虚拟线程的并行服务调用

使用GridBagLayout正确渲染

使用htmlunit和java单击按钮

是否为计划任务补偿系统睡眠?

EXCEL中的公式单元格显示#NAME?

Quarkus:运行时出现EnumConstantNotPresentException

JFree Chart从图表中删除边框

有没有办法在o(log(N))中以系统的方式将数组中的小块元素复制和移动到新增长的数组中的左侧?

在Spring Boot中使用咖啡因进行缓存-根据输出控制缓存

Java 21内置http客户端固定运营商线程

Spring Mapstruct如何获取Lazy初始化实体字段的信息?

窗口启动后不久,从java.awt.Graphics disapear创建的矩形

Spring Integration SFTP 连接失败 - 无法协商 kex 算法的密钥交换