Java:枚举常量内方法和变量的定义

2023-11-22

我在做一些实验时不小心写了一段代码,这很奇怪,我不明白。我什至很惊讶我能编译它。它看起来像这样:

enum Foo {
    VALUE_1 {
        public int myVariable = 1;
    },
    VALUE_2 {
        public void myMethod() {
            //
        }
    },
    VALUE_3;
}

正如预期的那样,不可能通过以下方式访问这样的元素:

Foo.VALUE_2.myMethod();

原因是,编译器将在枚举本身内部查找该方法。

我认为不可能从枚举外部访问这些方法和变量。因此,我尝试创建一个参数构造函数并使用一些内部变量调用它:

enum Foo {
    VALUE(internalVariable) {
        int internalVariable = 1;
    };

    private Foo(int param) {
        //
    }
}

不可能编译这样的结构。现在我在想,如果无法访问常量中的某些内容,那么定义它有什么意义。

我试图在常量以及枚举本身中创建同名的方法,以检查它是否以某种方式发生冲突。没有!

enum Foo {
    VALUE_1 {
        int myVariable = 1;

        public int myMethod() {
            return myVariable;
        }
    },
    VALUE_2 {
        //
    };

    public int myMethod() {
        return 0;
    }
}

有趣的时刻来了!我尝试在枚举中继续调用 myMethod(),并实际弄清楚了这个 Java 魔法是如何工作的。在常量内部定义的方法会覆盖在枚举内部定义的方法。

Foo.VALUE_1.myMethod(); // Returns 1
Foo.VALUE_2.myMethod(); // Returns 0

但是,我们不能覆盖变量,对吧?所以我很好奇,它如何仅适用于变量。

enum Foo {
    VALUE_1 {
        public int myVariable = 1;
    },
    VALUE_2 {
        //
    };

    public int myVariable = 0;
}

....

System.out.println(Foo.VALUE_1.myVariable); // Returns 0
System.out.println(Foo.VALUE_2.myVariable); // Returns 0

现在我终于回答我的问题了:

  1. 为什么我创建时没有收到任何错误公共方法在常量内部并将枚举留空而没有此方法?在这种情况下,我刚刚定义的方法不能被调用根本不。还是我错了?

    Update:我知道枚举可以实现接口。但是,如果我没有 具体来说,整个代码毫无意义。

    有人指出,即使无法从正常的语言访问方法 方式,仍然可以使用反射。好吧...为什么我们不设计一个难以接近的关键词?

    inaccessible void magicalMethod() {
         //
    }
    

    这样的方法会被编译到*.class文件中。当你想使用它时,你必须 自己加载字节码并解释它。

    我只是不明白,为什么可以定义无法访问的方法。唯一的原因 我可以认为程序员正在工作并且还没有接口的定义。所以 他只是准备单个方法的代码,稍后将添加“implements”关键字。旁 这是不合逻辑的,它仍然需要在所有常量中都有这样的方法。

    我认为这应该以错误结束,而不仅仅是警告未使用的方法。你可能会忘记 添加“implement”子句或在枚举中定义方法(这将是 被覆盖)并且在第一次使用后就会意识到这一点。 Java是一种非常严格的语言, 所以我期望这种行为。

  2. 为什么我创建时没有收到任何错误公共变量(更准确地说,是场)在常量内?无论如何(从外部)都无法访问它。因此,修饰语“public”在这里没有任何意义。

    Update:除了可见性之外,它与上一点不太相同 修改器在这里完全没用。是否公开、受保护并不重要 或私有的,因为无论如何你都无法访问它。我认为这是一个错误。

  3. 为什么可以定义一个类(没有可见性修饰符),但是不是接口?是的,您可能不想编写如此残酷的枚举,以至于您需要在常量中定义类,甚至在那里使用继承。但如果可以定义类和抽象类,那就没什么奇怪的了。

    Update:这绝对不是你经常需要的东西,但我理解 它可能有用。但为什么它仅限于类而不能是接口 也定义了?

    enum Foo {
        VALUE {
            class MyClass {
                // OK
            }
    
            abstract class MyAbstractClass {
                // OK
            }
    
            interface MyInterface {
                // FAIL. It won't compile.
            }
        }
    }
    
  4. 您在某处使用过这样的功能吗?我可以想象它可能有用,但有点令人困惑。另外,当我搜索相关资源时,我没有找到任何内容。

    Update:我想看到一些在枚举常量类主体中重写方法的实际示例。你在一些开源项目中见过它吗?

环境:

$ java -version
java version "1.7.0_21"
OpenJDK Runtime Environment (IcedTea 2.3.9) (7u21-2.3.9-0ubuntu0.12.10.1)
OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)

感谢您的宝贵时间和您的回答!


好吧,这个功能我确实用过!我正在编写简单的游戏,想提供两个声音包。因为游戏非常简单,并且将来可能不会扩展,所以我不想创建一些复杂的机制来实现这样的事情。

public enum SoundPack {
    CLASSICAL {
        @Override
        public String getSoundPickUp() {
            return "res/sounds/classical/pick.wav";
        }

        @Override
        public String getSoundNewLevel() {
            return "res/sounds/classical/success.wav";
        }

        @Override
        public String getSoundFail() {
            return "res/sounds/fail.wav";
        }
    },
    UNHEALTHY {
        @Override
        public String getSoundPickUp() {
            return "res/sounds/unhealthy/quick_fart.wav";
        }

        @Override
        public String getSoundNewLevel() {
            return "res/sounds/unhealthy/toilet_flush.wav";
        }

        @Override
        public String getSoundFail() {
            return "res/sounds/unhealthy/vomiting.wav";
        }
    };

    public abstract String getSoundPickUp();
    public abstract String getSoundNewLevel();
    public abstract String getSoundFail();
}

所以,我刚刚定义了您在上面看到的枚举。在保存所有配置的类中,只有一个属性,如下所示:

private SoundPack soundPack = SoundPack.CLASSICAL;

现在,如果我需要播放一些声音,我可以非常简单地获取路径:

configuration.getSoundPack().getSoundNewLevel();

只需向 soundPack 字段分配另一个值,就可以在运行时轻松更改配置。如果声音尚未加载(并且有可能不会加载,因为我经常使用延迟加载),更改将立即生效。无需改变其他任何东西。

另外,如果我想添加新的声音包,可以通过在该枚举中定义新常量来完成。 Eclipse 将显示警告,我只需按 CTRL+1 并生成这些方法。所以这也很容易。

我知道这不是最好的方法。但这很简单,很快,最重要的是:我想try在实践中使用它。 :-)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java:枚举常量内方法和变量的定义 的相关文章

  • 为什么在Java中读取易失性和写入字段成员是不可扩展的?

    观察以下用 Java 编写的程序 完整的可运行版本如下 但程序的重要部分在下面的代码片段中 import java util ArrayList A not easy to explain benchmark class MultiVola
  • Hibernate统计打印HQL:null

    我是使用休眠的新手 我打开了统计信息 与普通的 HQL 查询一起 我得到了许多这样的统计信息 INFO Statistics HQL null time 1724ms rows blah 有人可以以任何方式帮助我为什么null查询大约需要
  • RSA Java 加密和 Node.js 解密不起作用

    我有一个系统 需要在 javascript 中生成 RSA 密钥对 然后将公钥存储在服务器端的数据库中 作为字符串 然后 Java 中的服务器端将使用存储的公钥对字符串进行加密密钥并将其发送到客户端 客户端将使用私钥解密该字符串 我在客户端
  • HQL - 分页的行标识符

    有谁知道HQL是否有一个关键字来标识行 例如ROWID或ROWNUM 我想使用 HQL 实现分页 但我无法使用 setMaxResult 或 setFirstResult 因为我不直接使用会话对象 因此不使用 Query 对象 而只是将查询
  • java中简单程序中的“未为类型定义方法”错误

    所以我只是想学习 Java 在观看了一些教程并阅读了一些基本内容之后 我对为什么它无法运行感到困惑 package Test public class TestProg public static void main String args
  • Apache HttpClient 4.x 在上传较大文件时表现奇怪?

    我正在使用 java 和 scala 开发和测试一个简单的客户端 服务器应用程序 The server是基于com sun net httpserver HttpServer并允许使用 POST 和 PUT 操作通过基本的 RESTful
  • 如何从资源服务器中的 Spring Security OAuth2 Boot 中提取声明?

    我有一个使用 Net Core 内置的授权服务器身份服务器4 https identityserver4 readthedocs io en latest 它正在按预期工作 从 Node Js 和 Net 授权客户端和资源 现在我尝试添加
  • 无法在 PHP 中接收 JSON POST 请求

    我正在将 JSON 对象从 Java 传递到 PHP 我正在使用 jdk 1 8 和 WAMPserver 下面是Java代码 import java io IOException import org apache http client
  • Log4j 2.x 如何实现惰性参数求值?

    鉴于Java 参数评估机制 http docs oracle com javase specs jls se8 html jls 15 html jls 15 12 4 2 如何Log4j 2 x实施惰性评估 https logging a
  • double 或 BigDecimal 会溢出吗?

    Java 8 给了我们Math addExact https docs oracle com javase 8 docs api java lang Math html addExact int int 适用于整数 但不适用于小数 是否有可
  • Apache HTTPClient SSLPeerUnverifiedException

    使用 Apache HttpClient 4 2 1 使用从基于表单的登录示例复制的代码 http hc apache org httpcomponents client ga examples html http hc apache or
  • Python父类访问子私有变量

    以下代码会生成错误 class A object def say something self print self foo print self bar class B A def init self self foo hello sel
  • Java SFTP使用JSch上传,但如何覆盖当前文件?

    我正在尝试使用 JSch 通过 SFTP 将两个文件上传到服务器 如果目录为空 则上传文件效果很好 但我想一遍又一遍地上传相同的文件 只需更改内部的 id 但我不知道如何执行此操作 JSch 中有一些名为 OVERWRITE 的静态参数 但
  • JRuby调用了错误的方法

    我在调用 Java 方法时遇到了一个奇怪的问题JRuby http en wikipedia org wiki JRuby 在我的 Java 类中 这些方法定义了两次 看来 JRuby 调用了错误的方法 所以我尝试使用java method
  • 在同步子句中抛出异常的副作用?

    从同步子句中抛出异常是否有任何不清楚的副作用 锁会发生什么情况 private void doSomething throws Exception synchronized lock doSomething 我没有看到任何副作用 The 锁
  • 方法中缺少 return 语句错误

    我正在尝试编写一个返回计算机 MAC 地址字符串的静态方法 该函数本身可以在此处找到 http www mkyong com java how to get mac address in java http www mkyong com j
  • Scala 不可变 Map 速度慢

    当我创建地图时 我有一段代码 val map gtfLineArr 8 split map split collect case Array k v gt k v toMap 然后我使用这张地图来创建我的对象 case class MyOb
  • 在 Ubuntu 上的 Tomcat 中加载共享本机库

    如何在 Ubuntu 上的 Tomcat6 中加载共享库 我创建了一个名为 libawragrids so 的库 awragrids 并将其放置在 var lib tomcat6 shared 我在调用启动 tomcat 的终端中设置了以下
  • GridLayout 中的 JLabel

    如何添加JLabel出于GridLayout 我有一个 8x8 网格布局 Container content getContentPane content setLayout new GridLayout 8 8 2 2 for int f
  • 如何处理JFreeChart中的SpiderWebPlot?

    发现 JFreeChart 我在使用时遇到了问题蜘蛛网情节 http www jfree org jfreechart api javadoc org jfree chart plot SpiderWebPlot html 这就是我今天所拥

随机推荐

  • Vim - 激活 PHP 文件上的 HTML 片段

    我正在使用vim和snipMate 很多时候我需要将HTML文件命名为PHP 只是因为一两行代码 我每次创建 PHP 文件时 vim 都会将其视为 PHP 文件 因此 HTML 片段不可用 因此必须使用命令手动激活 HTML 片段 set
  • 在网站上创建网站图标的最佳实践是什么? [关闭]

    Closed 这个问题是基于意见的 目前不接受答案 Question 创建一个的最佳实践是什么favicon在网站上 并且是一个 ico同时包含 16x16 和 32x32 图像的文件比 png文件只有 16x16 今天首选的正确方法是否无
  • 实现Spring Data存储库的自定义方法并通过REST公开它们

    我正在尝试将自定义方法添加到我的 Spring 数据存储库PersonRepository如中所述1 3 Spring Data 存储库的自定义实现并通过 REST 公开这些方法 初始代码来自使用 REST 访问 JPA 数据示例 这里是添
  • com.sun.istack.SAXException2 :实例...正在替换“java.lang.Object”,但是...绑定到匿名类型

    我正在将项目从版本 1 x 升级到 jaxb 2 2 7 我的应用程序有时可以运行 但在一些回复中我看到了这一点 java lang RuntimeException javax xml bind MarshalException with
  • CompletableFuture——快速失败的聚合未来

    我一直在使用CompletableFuture allOf 帮助器创建聚合期货 只有当它们的组合期货被标记为完成时才会 完成 即 CompletableFuture future2 new CompletableFuture lt gt C
  • asp.net mvc app_data 文件夹

    我想在服务器图库上存储大量图像 我可以为此创建自己的文件夹 但在默认模板中有一个名为 App Data 的文件夹 显然 我认为模板的创建者是为了让我们在那里存储数据 但我找不到打开该文件夹中任何内容的方法 是故意的吗 或者我该怎么做 或者我
  • 使用 AudioQueue 读取音频缓冲区数据

    我正在尝试通过 AudioQueue 读取音频数据 当我这样做时 我可以验证文件的位深度是否为 16 位 但当我获取实际的样本数据时 我只看到从 128 到 128 的值 但我也看到可疑的交错数据 这让我非常确定我只是没有正确读取数据 首先
  • 从命令行将 MySQL 变量传递给脚本

    我有一个 MySQL 更新脚本 我想从命令行运行 但我希望能够将阶段域变量传递给脚本 我知道这行不通 但这是我描述我正在尝试做的事情的最佳方式 uroot hlocalhost mydatabase execute SET domain m
  • SimpleMembership、MVC4、AuthorizeAttribute 和角色

    我正在尝试向我的一些 MVC4 控制器添加授权属性 只要它是一个计划 它们就可以正常工作 Authorize or Authorize Users myuser 但是当我添加任何类型的角色过滤时 它就会崩溃 例如 Authorize Rol
  • htmlentities() 与 htmlspecialchars()

    两者有什么区别htmlspecialchars and htmlentities 我什么时候应该使用其中之一 htmlspecialchars可能用过了 当不需要对具有 HTML 等效项的所有字符进行编码时 如果您知道页面编码与文本特殊符号
  • PHP - 密码验证问题

    我已经为此摸不着头脑两个多小时了 我研究过 stackoverflow 上的文章 包括 Bcrypt 未正确验证的问题 php的password hash和password verify问题不匹配 password verify 调用返回
  • DB (SQL) 自动压力/负载工具?

    我想测量数据库应用程序的性能和可扩展性 我正在寻找一种工具 允许我对数据库运行许多 SQL 语句 将数据库和脚本 SQL 文件作为参数 必要的详细信息 例如主机名 端口 登录名 理想情况下 它应该让我控制参数 例如模拟客户端的数量 测试持续
  • 无法加载脚本。确保您正在运行 Metro 服务器(运行“react-native start”)或者您的捆绑包“index.android.bundle”

    在 android studio 中运行我的项目时出现该错误 我刚刚安装了所有内容 并且一步一步地遵循了所有内容 我正在使用genymotion作为模拟器 并使用react native start从根目录 检查端口 8081 禁用即时运行
  • 在同一命名容器中重用 Facelets 组合时避免重复 id

    我有一个
  • c中的scanf和换行符[重复]

    这个问题在这里已经有答案了 我今天刚刚在 C 班进行了一次测试 我有理由相信答案可能是错误的 scanf d n x Evaluate the expression for the string 54321 n 这个想法非常简单 找到一个整
  • 如何制作固定div?

    我试图使框固定在页面的右下边框中 并且不会随着页面向下滚动而移动 但它对我不起作用 不知道为什么 这是我的代码 div class tooltip div class tooltip top 1 div div class tooltip
  • 将用 Python 训练的 XGBoost 模型移植到用 C/C++ 编写的另一个系统

    假设我已经用 python 成功训练了 XGBoost 机器学习模型 x train x test y train y test train test split x y test size 0 2 random state 7 model
  • 将视频设置为背景“图像”的方法

    我需要建立一个以视频为背景的网站 我可以使用吗z index将其他元素放置在视频顶部 有更好的选择吗 我没有测试过 但你可以尝试设置宽度 高度
  • 应用内购买以解锁付费功能

    我希望发布我的应用程序的两个版本 免费和付费 付费应用程序将具有更多功能 但没有额外的内容 最初我打算在市场上发布两个独立的应用程序 但事实证明很难保留单个代码库并拥有两个独立的应用程序 应用内购买是更好的方法吗 因此 我发布了一个免费应用
  • Java:枚举常量内方法和变量的定义

    我在做一些实验时不小心写了一段代码 这很奇怪 我不明白 我什至很惊讶我能编译它 它看起来像这样 enum Foo VALUE 1 public int myVariable 1 VALUE 2 public void myMethod VA