为什么在java中枚举被声明为 Enum> [重复]

2023-12-12

可能的重复:
java 枚举定义

更好地表述问题,不被视为重复:
如果 Enum 声明没有递归部分,Java 中会有什么不同

如果语言设计者简单地使用 Enum 这会对语言产生什么影响?

现在唯一的区别是有人会写



A extends Enum<B>
  

但由于java中不允许扩展枚举,这仍然是非法的。 我也在考虑有人向 jvm 提供一个字节码,将 smth 定义为扩展枚举 - 但泛型不会影响它,因为它们都被删除了。

那么这样的声明的全部意义是什么?

谢谢你!

Edit为了简单起见,我们看一个例子:



interface MyComparable<T> {
    int myCompare(T o);
}

class MyEnum<E extends MyEnum> implements MyComparable<E> {
    public int myCompare(E o) { return -1; }
}

class FirstEnum extends MyEnum<FirstEnum> {}

class SecondEnum extends MyEnum<SecondEnum> {}
  

这个类结构有什么问题? “MyEnum>” 会限制做什么?


这是一个常见的问题,也是可以理解的。看一下这部分是仿制药常见问题解答寻找答案(实际上,请尽可能多地阅读整个文档,它做得相当好,内容丰富)。

简而言之,它强制类对其自身进行参数化;这是超类使用通用参数定义方法所必需的,这些方法与其子类透明地(“本机”,如果您愿意的话)一起工作。

编辑:作为一个(非)示例,请考虑clone()方法上Object。目前,它被定义为返回类型的值Object。由于协变返回类型,特定的子类可以(并且通常确实)定义它们返回更特定的类,但这不能强制执行,因此不能推断任意类。

Now, if对象的定义类似于枚举,即Object<T extends Object<T>>那么你必须将所有类定义为类似的public class MyFoo<MyFoo>。最后,clone()可以声明返回一个类型T并且您可以在编译时确保返回的值始终与对象本身完全相同(甚至子类也不会与参数匹配)。

现在,在这种情况下,Object 不会像这样参数化,因为当 99% 的类根本不会使用它时,在所有类上都带有这个包袱会非常烦人。但对于某些类层次结构来说,它可能非常有用 - 我之前自己也使用过类似的技术,用于具有多种实现的抽象递归表达式解析器类型。这种构造使得编写“显而易见”的代码成为可能,而不必到处进行强制转换,或者复制粘贴只是为了更改具体的类定义。

Edit 2(实际回答你的问题!):

如果 Enum 定义为Enum<E extends Enum>,那么正如你所说,有人可以将一个类定义为A extends Enum<B>。这违背了通用构造的要点,即确保通用参数始终是exact相关类的类型。举一个具体的例子,Enum 将它的compareTo方法声明为

public final int compareTo(E o)

在这种情况下,由于您定义了A延长Enum<B>,实例A只能与实例进行比较B(无论 B 是什么),这几乎肯定不是很有用。With额外的构造,你知道any扩展 Enum 的类只能与其自身进行比较。因此,您可以在超类中提供在所有子类中仍然有用且特定的方法实现。

(如果没有这种递归泛型技巧,唯一的其他选择是将compareTo 定义为public final int compareTo(Enum o)。这实际上并不是同一件事,因为人们可以比较java.math.RoundingMode反对java.lang.Thread.State没有编译器抱怨,这又不是很有用。)


好吧,让我们远离Enum我们似乎对此很着迷。相反,这是一个抽象类:

public abstract class Manipulator<T extends Manipulator<T>>
{
    /**
     * This method actually does the work, whatever that is
     */
    public abstract void manipulate(DomainObject o);

    /**
     * This creates a child that can be used for divide and conquer-y stuff
     */
    public T createChild()
    {
        // Some really useful implementation here based on
        // state contained in this class
    }
}

我们将有几个具体的实现 - SaveToDatabaseManipulator、SpellCheckingManipulator 等等。此外,我们还想让人们定义自己的类,因为这是一个超级有用的类。 ;-)

现在 - 您会注意到我们正在使用递归通用定义,然后返回T来自createChild方法。这意味着:

1)我们知道并且编译器知道如果我打电话:

SpellCheckingManipulator obj = ...; // We have a reference somehow
return obj.createChild();

那么返回值肯定是SpellCheckingManipulator,即使它使用的是超类的定义。这里的递归泛型允许编译器知道什么对我们来说是显而易见的,因此您不必继续转换返回值(就像您经常需要做的那样)clone(), 例如)。

2)请注意,我没有声明该方法为final,因为也许某些特定的子类想要用更适合自己的版本来重写它。泛型定义意味着无论谁创建了一个新类或如何定义它,我们仍然可以断言来自例如的返回BrandNewSloppilyCodedManipulator.createChild()仍将是一个实例BrandNewSloppilyCodedManipulator。如果粗心的开发人员试图将其定义为仅返回Manipulator,编译器不会允许它们。如果他们试图定义class as BrandNewSloppilyCodedManipulator<SpellCheckingManipulator>,它也不会让他们。

基本上,结论是,当您想在超类中提供某些功能并且在子类中以某种方式变得更加具体时,此技巧非常有用。通过这样声明超类,您可以锁定任何子类的通用参数都是子类本身。这就是为什么你可以写一个通用的compareTo or createChild超类中的方法,并防止在处理特定子类时它变得过于模糊。

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

为什么在java中枚举被声明为 Enum> [重复] 的相关文章

  • 日期语句之间的 JPQL SELECT [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我想将此 SQL 语句转换为等效的 JPQL SELECT FROM events WHERE events date BETWE
  • 如何将用户输入与枚举值映射?

    我有一个基本的enum宣言 enum Title Prof Dr Mr Mdm Mrs Miss NA 我正在尝试将用户输入 0 1 2 3 4 5 AnyNumber 映射为正确的值enum像这样 std map
  • 如何通过 javaconfig 使用 SchedulerFactoryBean.schedulerContextAsMap

    我使用 Spring 4 0 并将项目从 xml 移至 java config 除了访问 Service scheduleService 带注释的类来自QuartzJobBean executeInternal 我必须让它工作的 xml 位
  • Java 枚举与创建位掩码和检查权限的混淆

    我想将此 c 权限模块移植到 java 但是当我无法将数值保存在数据库中然后将其转换为枚举表示形式时 我很困惑如何执行此操作 在 C 中 我创建一个如下所示的枚举 public enum ArticlePermission CanRead
  • 动态选择端口号?

    在 Java 中 我需要获取端口号以在同一程序的多个实例之间进行通信 现在 我可以简单地选择一些固定的数字并使用它 但我想知道是否有一种方法可以动态选择端口号 这样我就不必打扰我的用户设置端口号 这是我的一个想法 其工作原理如下 有一个固定
  • 过滤两次 Lambda Java

    我有一个清单如下 1 2 3 4 5 6 7 和 预期结果必须是 1 2 3 4 5 6 7 我知道怎么做才能到7点 我的结果 1 2 3 4 5 6 我也想知道如何输入 7 我添加了i gt i objList size 1到我的过滤器
  • HSQL - 识别打开连接的数量

    我正在使用嵌入式 HSQL 数据库服务器 有什么方法可以识别活动打开连接的数量吗 Yes SELECT COUNT FROM INFORMATION SCHEMA SYSTEM SESSIONS
  • 来自 dll 的 Java 调用函数

    我有这个 python 脚本导入zkemkeeperdll 并连接到考勤设备 ZKTeco 这是我正在使用的脚本 from win32com client import Dispatch zk Dispatch zkemkeeper ZKE
  • Java 公历日历更改时区

    我正在尝试设置 HOUR OF DAY 字段并更改 GregorianCalendar 日期对象的时区 GregorianCalendar date new GregorianCalendar TimeZone getTimeZone GM
  • java.lang.IllegalStateException:应用程序 PagerAdapter 更改了适配器的内容,而没有调用 PagerAdapter#notifyDataSetChanged android

    我正在尝试使用静态类将值传递给视图 而不是使用意图 因为我必须传递大量数据 有时我会收到此错误 但无法找出主要原因是什么 Error java lang IllegalStateException The application s Pag
  • java.lang.IllegalStateException:提交响应后无法调用 sendRedirect()

    这两天我一直在尝试找出问题所在 我在这里读到我应该在代码中添加一个返回 我做到了 但我仍然得到 java lang IllegalStateException Cannot call sendRedirect after the respo
  • 无法创建请求的服务[org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]-MySQL

    我是 Hibernate 的新手 我目前正在使用 Spring boot 框架并尝试通过 hibernate 创建数据库表 我知道以前也问过同样的问题 但我似乎无法根据我的环境找出如何修复错误 休眠配置文件
  • 帮助将图像从 Servlet 获取到 JSP 页面 [重复]

    这个问题在这里已经有答案了 我目前必须生成一个显示字符串文本的图像 我需要在 Servlet 上制作此图像 然后以某种方式将图像传递到 JSP 页面 以便它可以显示它 我试图避免保存图像 而是以某种方式将图像流式传输到 JSP 自从我开始寻
  • jdbc mysql loginTimeout 不起作用

    有人可以解释一下为什么下面的程序在 3 秒后超时 因为我将其设置为在 3 秒后超时 12秒 我特意关闭了mysql服务器来测试mysql服务器无法访问的这种场景 import java sql Connection import java
  • 如何在谷歌地图android上显示多个标记

    我想在谷歌地图android上显示带有多个标记的位置 问题是当我运行我的应用程序时 它只显示一个位置 标记 这是我的代码 public class koordinatTask extends AsyncTask
  • java for windows 中的文件图标叠加

    我正在尝试像 Tortoise SVN 或 Dropbox 一样在文件和文件夹上实现图标叠加 我在网上查了很多资料 但没有找到Java的解决方案 Can anyone help me with this 很抱歉确认您的担忧 但这无法在 Ja
  • java.io.Serialized 在 C/C++ 中的等价物是什么?

    C C 的等价物是什么java io Serialized https docs oracle com javase 7 docs api java io Serializable html 有对序列化库的引用 用 C 序列化数据结构 ht
  • 干净构建 Java 命令行

    我正在使用命令行编译使用 eclipse 编写的项目 如下所示 javac file java 然后运行 java file args here 我将如何运行干净的构建或编译 每当我重新编译时 除非删除所有内容 否则更改不会受到影响 cla
  • 如何使用mockito模拟构建器

    我有一个建造者 class Builder private String name private String address public Builder setName String name this name name retur
  • 如何防止在Spring Boot单元测试中执行import.sql

    我的类路径中有一个 import sql 文件 其中包含一些 INSERT 语句 当使用 profile devel 运行我的应用程序时 它的数据被加载到 postgres 数据库中 到目前为止一切正常 当使用测试配置文件执行测试时 imp

随机推荐

  • 如何更改 iframe 的方向

    就我而言 我已将另一个组织 是的 我被授权这样做 开发的 html 游戏嵌入到网站中 页面和 HTML 游戏文件位于同一域中 该游戏是为支持 iPad 而开发的 但仅限横向 然而 在 iframe 中 它总是显示 请使用横向方向 的消息 即
  • 从命令行守护程​​序使用 MLMediaLibrary 时出现 XPC 错误

    我正在编写一个命令行守护程 序来从 iPhoto 读取图像 我可以初始化并加载MLMediaLibrary从使用 Xcode 项目创建工具创建的成熟 Cocoa 应用程序中得到的结果很好 但是 当我尝试从命令行工具 也在 Xcode 中创建
  • PHP脚本中的内存泄漏

    我有一个 php 脚本 它运行 mysql 查询 然后循环结果 并在该循环中还运行多个查询 sqlstr SELECT FROM user pred WHERE uprType 2 AND uprTurn turn ORDER BY upr
  • 如何根据动态变量进行匹配?

    是否可以匹配动态变量而不仅仅是文字 在此代码中 第一个match应该和注释掉的一样match number 0 being 0 and number 1 being 1 const NUMBERS i8 2 0 1 fn test let
  • 使用 Python 代替 AppleScript

    我经常使用 Applescript 来完成基本任务 例如打开和关闭程序 有时会更深入一些 例如运行特定 Xcode 程序的单元测试 我正在学习Python 我喜欢它 我还没有找到太多有关 AppleScript 和 Python 的文档 我
  • Hadoop 中的 setJarByClass()

    在 Hadoop 算法的驱动程序方法中的某个时刻 我们将作业链接到设置为 Mapper 和Reducer 的类的引用 例如 job setMapperClass MyMapper class job setReducerClass MyRe
  • 如何将 Python2 中的 all: print "string" 替换为:Python3 中的 print("string")? [复制]

    这个问题在这里已经有答案了 正如标题所说 如何将 Python2 中的 all print string 替换为 Python3 中的 print string I really希望他们使这一功能向后兼容 官方推荐使用 2to3 py 脚本
  • 使用实体框架自引用树的最有效方法

    所以我有一个 SQL 表 基本上是 ID ParentID MenuName Lineage Depth 最后两列是自动计算的 以帮助搜索 因此我们现在可以忽略它们 我正在创建一个具有多个类别的下拉菜单系统 不幸的是 我认为 EF 不能很好
  • 使用 xslt 排序对给定顺序进行排序

    我在用着
  • 从 Firebase 获取一个值并将其更新为当前值 + 1

    所以是的 标题有问题 一些信息 这是我的 Firebase 数据库的样子 这是当前的代码 export function updateQTY barcode database ref items barcode update qty cur
  • 如何检测无符号整数溢出?

    I was writing a program in C to find all solutions of ab c where a b and c together use all the digits 0 9 exactly once
  • 替换 pandas dataframe 列中的前 n 个元素

    我想更换第一个n我的数据框中的一列元素与我保存的另一个 pd series 举个例子 category price store testscore 0 Cleaning 11 42 Walmart NaN 1 Cleaning 23 50
  • R - 给定奥尔森时区的 UTC 到 LOCAL 时间

    我有 1974 2013 年的时间序列数据 其中有一列为 datetimeUTC YYYY MM DD hh mm 0000 一列为 Olson 格式的时区 例如 加拿大 太平洋 加拿大 东部 我可以将整个 UTCdatetime 列转换为
  • ListView WP8 中的增量加载

    我读过有关如何在滚动到列表视图底部时进行增量加载的文章 以及如何在滚动到列表顶部时实现延迟加载的文章 当用户到达顶部时 我想将更多项目添加到列表顶部 我们有什么办法可以实现这一目标吗 为此找到了解决方案 旋转两个控件 对于例如 gt
  • 2个php.ini文件

    我发现 当我在终端上输入以下内容时 php i grep php ini 我得到输出 加载的配置文件是 etc php5 cli php ini 然而 从phpinfo 我看到 加载的ini文件是 etc php5 apache2 php
  • Facebook API 限制

    我正在使用应用程序中的 Facebook Graph 和 FQL API 经过 OAuth 身份验证 我在文档中找不到有关速率限制 节流的任何内容 通常 我期望类 用户有某种限制 查看 Facebook 应用程序页面 Insigths gt
  • 如何使用node js将消息从Web服务器推送到浏览器

  • 为 Vaadin 8 Grid 实现列渲染器

    The 瓦丁框架指南有一个描述如何使用列渲染器的页面 in a 瓦丁网格 And 本页描述了渲染器的实现 但一切都太短暂了 我想实施一个InstantRenderer补充 Vaadin 8 1 中添加的部分 java time 渲染器集 添
  • Firebase RecyclerView:未连接适配器,跳过片段布局

    我有一个包含 3 个选项卡的 TabLayout 的活动 我正在尝试加载基于 Firebase 中的动态数据的 recyclerview 但 recyclerview 根本没有填充任何视图 我不确定它是否与 FragmentSectionP
  • 为什么在java中枚举被声明为 Enum> [重复]

    这个问题在这里已经有答案了 可能的重复 java 枚举定义 更好地表述问题 不被视为重复 如果 Enum 声明没有递归部分 Java 中会有什么不同 如果语言设计者简单地使用 Enum 这会对语言产生什么影响 现在唯一的区别是有人会写 A