跨不同类加载器覆盖默认访问器方法会破坏多态性

2023-11-25

我在尝试使用以下方法重写方法时遇到了奇怪的行为默认访问器 (ex: void run())。 根据Java规范,如果类属于同一个包,则类可以使用或覆盖基类的默认成员。 当所有类从同一个类加载器加载时,一切正常。 但是如果我尝试从中加载子类separate类加载器则多态性不起作用。

这是示例:

应用程序.java:

import java.net.*;
import java.lang.reflect.Method;

public class App {
    public static class Base {
        void run() {
            System.out.println("error");
        }
    }
    public static class Inside extends Base {
        @Override
        void run() {
            System.out.println("ok. inside");
        }
    }
    public static void main(String[] args) throws Exception {
        {
            Base p = (Base) Class.forName(Inside.class.getName()).newInstance();
            System.out.println(p.getClass());
            p.run();
        } {
            // path to Outside.class
            URL[] url = { new URL("file:/home/mart/workspace6/test2/bin/") };
            URLClassLoader ucl = URLClassLoader.newInstance(url);
            final Base p = (Base) ucl.loadClass("Outside").newInstance();
            System.out.println(p.getClass());
            p.run();
            // try reflection
            Method m = p.getClass().getDeclaredMethod("run");
            m.setAccessible(true);
            m.invoke(p);
        }
    }
}

Outside.java:应该位于单独的文件夹中。否则类加载器将是相同的

public class Outside extends App.Base {
    @Override
    void run() {
        System.out.println("ok. outside");
    }
}

输出:

class App$Inside
ok. inside
class Outside
error
ok. outside

然后我打电话Outside#run() I got Base#run()(输出中的“错误”)。反射工作正常。

怎么了?或者这是预期的行为? 我可以以某种方式解决这个问题吗?


From Java虚拟机规范:

5.3 创建与加载
...
在运行时,类或接口是 不仅由其名称决定,而且 通过一对:其完全限定名称 及其定义类加载器。每个 这样的类或接口属于 单身的运行时包。运行时 类或接口的包是 由包名和 定义类的类加载器或 界面。


5.4.4 Access Control
...
A field or method R is accessible to a class or interface D if and only if any of the following conditions is true:
  • ...
  • R 是protected或包私有(即,既不是public nor protected nor private), 并且是 由同一类中声明 运行时包为 D.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

跨不同类加载器覆盖默认访问器方法会破坏多态性 的相关文章

随机推荐

  • PHP 当会话过期时做一些事情

    假设用户在我的网站上做了一些事情 例如上传了一些图像或其他内容 然后他没有注销就离开了 并且再也没有回来 或者假设他在几个月后确实回来了 所以我的问题是 是否有某种方法可以在会话过期后删除他上传的文件 比如说 30 分钟后 请记住用户从未重
  • 如何通过索引从字符串中获取字符?

    假设我有一个由 x 个未知字符组成的字符串 我怎样才能得到 char nr 13 或字符编号 x 14 首先确认需要的数量是有效索引对于从 begin 或 end 开始的字符串 那么您可以简单地使用数组下标表示法 使用len s 获取字符串
  • 如何从 C# 调用 MS Access 数据库宏

    我只是想知道是否可以从外部调用 MS Access 数据库中的模块函数或宏 使用C Thanks 是的 您可以运行宏 This Article 仅可通过 archive org 获取 显示您需要的一切
  • 我们如何计算处理时间?

    我创建了一个PopupPanel并已展示出来 我想在一分钟过去后隐藏它 在那一分钟内 该过程不应停止或暂停 我怎样才能实现这种行为 GWT 有自己的实现Timer 这是一个非常小的例子 public void onModuleLoad fi
  • 使用 Node.js 管理 sdk 创建令牌时的 Firebase REST 身份验证

    我知道这个问题在这里被问了很多 但我似乎仍然找不到可以解决我的问题的确切答案 我希望通过添加 access token 参数使用 REST 调用访问 Firebase access token 是使用 Node js Admin SDK 创
  • MICE 不会估算某些列,但也不会给出错误

    我知道以前曾问过类似的问题 例如 1 2 3 但我还是不明白为什么mice即使我尝试像示例中那样的无条件均值 也无法预测缺失值1 我的稀疏矩阵是 k1 k3 k5 k6 k7 k8 k11 k12 k13 k14 k15 1 NA NA N
  • 将单词(字符串)转换为 Int

    我确信这已经被做过一百次了 但我希望有一种非常简单的方法来完成这个任务 我想将单词更改为整数 就像下面的例子 One 1 Two 2 Three 3 所以基本上 如果我有字符串 One 它会转换为 1 即使我可以返回字符串 1 我也可以将其
  • Java:如何查看代码的哪些部分运行最多? (分析)

    我正在用 Java 编写一个简单的跳棋游戏 当我将鼠标悬停在主板上时 我的处理器性能提升至 50 核心上为 100 我想找出我的代码的哪一部分 假设是我的错 在此期间正在执行 我尝试过调试 但在这种情况下逐步调试效果不太好 有没有什么工具可
  • 获取当前正在运行的活动的实例?

    我想做的是将运动事件分派给当前正在运行的活动 我从这段代码中获取了当前活动的 ComponentName ActivityManager am ActivityManager getSystemService ACTIVITY SERVIC
  • 排除类型的重载的类型注释(某些类型与其他类型)

    我正在尝试使用 overload传达调用函数的不同方式 但是通过简单的代码可以轻松传达什么else声明在类型注释中是不可能的 如果没有 else MyPy 正确地 会抱怨重载版本不匹配 例如 请参见下面的代码片段 error Overloa
  • 错误 X3000:着色器文件中存在非法字符

    我粘贴了一行着色器代码 现在我的项目无法工作 我删除了受污染的代码行 我已经按照 VS Notepad 和 Notepad 的建议从头开始多次重写着色器Unity 论坛 我在 Notepad 中使用了十六进制编辑器视图来排除前两个字节不是0
  • CA2000 将对象引用传递给 C# 中的基本构造函数

    当我通过 Visual Studio 的代码分析实用程序运行一些代码时 我收到一条警告 我不确定如何解决 也许这里有人遇到过类似的问题 解决了它 并愿意分享他们的见解 我正在编写一个在 DataGridView 控件中使用的自定义绘制单元格
  • 为什么VS中的Debug模式比Release慢?

    我已经用谷歌搜索过这个问题 通常答案相当复杂 而且我并不真正理解所有的行话 有没有简单的解释为什么调试模式这么慢 为什么不总是在发布版本中运行呢 调试模式已关闭所有优化 以确保连接的调试器按预期工作 一个版本将会开启很多优化 比这更简单的我
  • 清除 Java 缓存

    我想知道如何使用 Java 代码或 CMD 行代码清除 Java 缓存 这应该在 Windows 7 及以上版本的 Microsoft Windows 计算机上完成 这应该在多台计算机上完成 因此文件路径会有所不同 该应用程序使用 Java
  • 查询GAE数据存储时如何修复索引错误?

    当我尝试对按日期排序的数据存储运行查询时 出现以下错误 NeedIndexError no matching index found The suggested index for this query is kind Message pr
  • 根据 bin 大小将列表分为多个列表

    我有一个包含超过 100 000 个值的列表 我需要根据特定的 bin 宽度 例如 0 1 将列表划分为多个较小的列表 谁能帮我写一个Python程序来做到这一点 我的清单看起来像这样 0 234 0 04325 0 43134 0 315
  • .R 脚本文件位于 PC 上的哪里?

    我想找到用于 R 中计算的脚本 R 文件的位置 我知道通过输入对象函数 我将获得正在运行的代码 然后我可以复制 编辑并将其另存为新的脚本文件并使用它 要求查找 foo R 文件的原因是 好奇心 了解数值计算中使用的算法是什么 更直接的是 函
  • C++ Visual Studio 编译错误

    我收到以下编译错误 致命错误 C1189 error 错误 使用 C 运行时库内部头文件 我对此完全不知道 谁能解释一下吗 完整的错误 C Program Files Microsoft Visual Studio 8 VC ce incl
  • 使用一次性使用令牌将 Auth0 实现到 chrome 扩展中

    我正在制作一个 chrome 扩展程序 我想为我的 chrome 扩展程序创建一个安全方法 以阻止它在没有我参与的情况下被共享 我有一个想法在某个地方生成一个令牌 通常是一些后端 也许是网站的服务器 该服务器获取我用 worpress 构建
  • 跨不同类加载器覆盖默认访问器方法会破坏多态性

    我在尝试使用以下方法重写方法时遇到了奇怪的行为默认访问器 ex void run 根据Java规范 如果类属于同一个包 则类可以使用或覆盖基类的默认成员 当所有类从同一个类加载器加载时 一切正常 但是如果我尝试从中加载子类separate类