人间工作P 人间工作P
主站 (opens new window)
首页
  • Bukkit开发教程
投喂
关于
  • 分类
  • 标签
  • 时间线
  • 友情链接

人间工作P

我每天都好困… 最近在学习和进行 VOCALOID 创作
主站 (opens new window)
首页
  • Bukkit开发教程
投喂
关于
  • 分类
  • 标签
  • 时间线
  • 友情链接
  • 关于 找不到java.lang.Record的类文件 的解决方案

    • 变通一下
      • 最坏的情况
        • 总结
        MrXiaoM
        2026-03-07
        开发
        目录

        关于 找不到java.lang.Record的类文件 的解决方案

        Java 8 引用高版本依赖的解决方案

        做 Minecraft 服务器插件开发的时候可能会遇到的问题。

        当你想做一个能兼容至 Java 8、Minecraft 1.8 的插件的时候,必定要设置源兼容性和目标兼容性的版本为 8。当你需要引用一个使用 Java 17 编译的依赖的时候,Maven 不会阻止,Gradle 会不让你引用,只需要添加以下配置即可解除限制。

        java {
            disableAutoTargetJvm()
        }
        
        1
        2
        3

        当然,你点进来这篇文章肯定不是为了看这个的,最主要的问题在下面。

        如果你使用了一个 Java 17 的 Record 类,编译时就会出现如下报错:

        I:\.development\Sweet\SweetMail\src\main\java\top\mrxiaom\sweetmail\utils\items\CraftEngineProvider.java:15: 错误: 无法访问Record
                CustomItem<ItemStack> customItem = CraftEngineItems.byId(Key.of(argument));
                                                                            ^
          找不到java.lang.Record的类文件
        
        1
        2
        3
        4

        一开始我还没找到很好的解决方法,只能一点一点去试它的行为。

        最后发现,你可以去调用它的构造函数,但是不能去调用它的任何方法,包括静态方法都不行。

        我不知道 Java 编译器是怎么工作的,但就这个行为来看,可能是在调用方法这块,为了找到调用的方法是当前类的方法还是父类的方法,需要去找父类的方法列表看看有没有匹配的,再看当前类有没有重载的方法。

        诶☝️🤓,构造方法就不可能有重载了,我亲自试过,调用 Record 类的构造方法是能成功编译不报错的。

        所以我的解决方法如下,查一下 Key.of 的源代码,抄过来就行了。

            public static Key of(String namespacedId) {
                String[] strings = new String[]{"minecraft", namespacedId};
                int i = namespacedId.indexOf(':');
                if (i >= 0) {
                    strings[1] = namespacedId.substring(i + 1);
                    if (i >= 1) {
                        strings[0] = namespacedId.substring(0, i);
                    }
                }
                return new Key(strings[0], strings[1]);
            }
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11

        # 变通一下

        如果你真的要访问 Record 类的方法,如果是在 Object 里就有的方法(equals、toString、hashCode 等)可以用以下方式访问

            public static boolean toString(Key key) {
                // noinspection RedundantCast: 消除“不必要的转换”警告
                return ((Object) key).toString();
            }
        
        1
        2
        3
        4

        我调用的可是 Object 的 toString(),Key 什么的真不熟。做一个强制转换就绕过检查 Record 这个父类了。

        同理,如果这个类实现了什么其它的接口,也能通过强制转换来调用接口的方法。

        # 最坏的情况

        如果你真的要调用 Record 类的方法,假设要调用 Key#asMinimalString(),也有一个不是很优雅的方法。

        新建一个子模块,添加一个类,名为 java.lang.Record,写入以下内容

        package java.lang;
        
        public abstract class Record {}
        
        1
        2
        3

        然后通过 compileOnly() 来引用这个子模块即可。

        能正常编译,但之后会不会出现非预期结果就不知道了,我没有这个需求。

        完整操作流程

        仅限 Gradle 使用,我不会写 Maven。当然,将 record-stub 编译一个 jar 出来给 Maven 用也是可以的。

        // settings.gradle.kts
        
        include(":record-stub")
        
        1
        2
        3
        // record-stub/build.gradle.kts
        plugins {
          id("java")
        }
        val targetJavaVersion = 8
        java {
            val javaVersion = JavaVersion.toVersion(targetJavaVersion)
            if (JavaVersion.current() < javaVersion) {
                toolchain.languageVersion.set(JavaLanguageVersion.of(targetJavaVersion))
            }
        }
        tasks.withType<JavaCompile>().configureEach {
            options.encoding = "UTF-8"
            if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible) {
                options.release.set(targetJavaVersion)
            }
        }
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        // record-stub/src/main/java/java/lang/Record.java
        package java.lang;
        
        public abstract class Record {}
        
        1
        2
        3
        4

        然后再在 build.gradle.kts 里这样引用依赖即可

        compileOnly(project(":record-stub"))
        
        1

        # 总结

        大致总结一下 Record 类在 Java 8 下的行为

        • 不能调用其中的任何方法(字段可能也是)
        • 可以调用它的构造方法
        • 变通一下,做个强制转换可以调用其中一些方法
        • 静态方法大概没有办法去调用
        编辑 (opens new window)
        #Java#Gradle#兼容
        上次更新: 2026/03/07, 21:46:30
        最近更新
        01
        使 Flutter Web 完全离线化运行
        03-06
        02
        为 Github 账户添加 SSH 公钥,使用 SSH 拉取、推送仓库
        03-02
        03
        为 WSL 配置端口转发
        02-28
        更多文章>
        Theme fork from Vdoing | Copyright © 2018-2026 人间工作P | 友情链接
        • 跟随系统
        • 浅色模式
        • 深色模式
        • 阅读模式