枚举常量特定的类体是静态的还是非静态的?

2024-01-26

我有一个枚举类型类:

public enum Operation {
    PLUS() {
        @Override
        double apply(double x, double y) {       
            // ERROR: Cannot make a static reference
            // to the non-static method printMe()...
            printMe(x);
            return x + y;
        }
    };

    private void printMe(double val) {
        System.out.println("val = " + val);
    }

    abstract double apply(double x, double y);
}

正如你在上面看到的,我定义了一个enum有价值的类型PLUS。它包含一个特定的常量主体。在它的身体里,我试图呼唤printMe(val);,但我得到了编译错误:

无法对非静态方法 printMe() 进行静态引用。

为什么我会收到此错误?我的意思是我正在重写一个抽象方法PLUS身体。为什么它在static范围?如何摆脱它?

我知道添加一个static关键字printMe(){...}解决了问题,但我有兴趣知道如果我想保留是否还有其他方法printMe()非静态?


另一个问题,与上面的问题非常相似,但是这次错误消息听起来相反,即PLUS(){...}具有非静态上下文:

public enum Operation {
    PLUS() {
        // ERROR: the field "name" can not be declared static
        // in a non-static inner type.
        protected static String name = "someone";

        @Override
        double apply(double x, double y) {
            return x + y;
        }
    };

    abstract double apply(double x, double y);
}

我尝试声明一个PLUS-具体的static变量,但最终出现错误:

字段“name”不能在非静态内部类型中声明为静态。

为什么我不能在里面定义静态常量PLUS if PLUS是匿名类吗?这两个错误消息听起来相互矛盾,正如第一个错误消息所示PLUS(){...} has static上下文,而第二条错误消息显示PLUS(){...} has 非静态语境。我现在更迷茫了。


嗯,这是一个奇怪的案例。

看来问题是:

  • 在这种情况下,私人成员应该是可以访问的 (6.6.1 http://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6.1.):

    否则,声明成员或构造函数private,并且当且仅当访问发生在包含成员或构造函数声明的顶级类的主体内时才允许访问。

  • 但是,私有成员不会被继承(8.2 http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2):

    声明的类的成员private不被该类的子类继承。

  • 所以,printMe不是匿名子类的成员,编译器在超类中搜索它*Operation (15.12.1 http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.1):

    如果存在封闭类型声明该方法是其中的成员,令 T 为最里面的此类类型声明。要搜索的类或接口是 T。

    这种搜索策略称为“梳状规则”。在查找封闭类及其超类层次结构中的方法之前,它会有效地查找嵌套类的超类层次结构中的方法。

  • 这就是奇怪的地方。因为printMe在一个类中找到还附上 PLUS,调用该方法的对象被确定为一个封闭实例Operation,不存在(15.12.4.1 http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.4.1):

    否则,令 T 为该方法所属的封闭类型声明,并让n是一个整数,使得 T 是n'th 词法封闭类的类型声明,其声明立即包含方法调用。目标参考是n'第一个词法封闭实例this.

    如果出现以下情况,则为编译时错误n'第一个词法封闭实例this不存在。

简而言之,因为printMe只是其中的成员Operation(并且不是继承的),编译器被迫调用printMe 在不存在的外部实例上.

但是,该方法仍然可以访问,我们可以通过限定调用来找到它:

@Override
double apply(double x, double y) {
//  now the superclass is searched
//  but the target reference is definitely 'this'
//  vvvvvv
    super.printMe(x);
    return x + y;
}

这两个错误消息听起来互相矛盾[...]。

是的,这是该语言的一个令人困惑的方面。一方面,匿名类永远不是静态的(15.9.5 http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.9.5),另一方面,匿名类表达式可以出现在静态上下文中因此没有封闭实例(8.1.3 http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3).

匿名类始终是内部类;从来没有static.

内部类的实例I其声明发生在静态上下文中,没有词法封闭的实例。

为了帮助理解它是如何工作的,这里有一个格式化的示例:



class Example {
    public static void main(String... args) {
        new Object() {
            int i;
            void m() {}
        };
    }
}
  

一切都在italics是静态上下文。从表达式派生的匿名类bold被认为是内部的和非静态的(但没有封闭的实例Example).

由于匿名类是非静态的,因此它不能声明静态非常量成员,尽管它本身是在静态上下文中声明的。


*除了稍微掩盖了事情之外,事实是Operation是一个枚举是完全不相关的(8.9.1 http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.9.1):

枚举常量的可选类主体隐式定义了一个匿名类声明,该声明扩展了直接封闭的枚举类型。类主体由匿名类的通常规则管理[...]。

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

枚举常量特定的类体是静态的还是非静态的? 的相关文章

  • (Java) App Engine 中的静态文件无法访问

    The 示例文档 http code google com appengine docs java gettingstarted staticfiles html表示您只需将文件放在 war 或子目录 中 并且应该可以从主机访问它们 只要它
  • Reactive Spring 不支持 HttpServletRequest 作为 REST 端点中的参数?

    我创建了一个 RestController 如下所示 RestController public class GreetingController RequestMapping value greetings method RequestM
  • 从 MS Access 中提取 OLE 对象(Word 文档)

    我有一个 Microsoft Access 数据库 其中包含一个包含 Microsoft Word 文档的 OLE 对象字段 我试图找到代码来检索保存在 OLE 对象中的文件 以便用户可以从我的 JavaFx 应用程序中的按钮下载它 但没有
  • 如何以编程方式枚举枚举类型?

    假设我有一个 TypeScriptenum MyEnum 如下 enum MyEnum First Second Third TypeScript 0 9 5 中生成数组的最佳方法是什么enum价值观 例子 var choices MyEn
  • 您建议使用哪种压缩(GZIP 是最流行的)servlet 过滤器?

    我正在寻找一个用于大容量网络应用程序的 GZIP servlet 过滤器 我不想使用容器特定的选项 要求 能够压缩响应负载 XML Faster 已在大批量应用的生产中得到验证 应适当设置适当内容编码 跨容器移植 可选择解压缩请求 谢谢 我
  • tomcat 7.0.50 java websocket 实现给出 404 错误

    我正在尝试使用 Java Websocket API 1 0 JSR 356 中指定的带注释端点在 tomcat 7 0 50 上实现 websocket 以下是我如何对其进行编码的简要步骤 1 使用 ServerEndpoint注解编写w
  • 为什么Iterator接口没有add方法

    In IteratorSun 添加了remove 方法来删 除集合中最后访问的元素 为什么没有add方法来向集合中添加新元素 它可能对集合或迭代器产生什么样的副作用 好的 我们开始吧 设计常见问题解答中明确给出了答案 为什么不提供 Iter
  • Android蓝牙java.io.IOException:bt套接字已关闭,读取返回:-1

    我正在尝试编写一个代码 仅连接到运行 Android 5 0 KitKat 的设备上的 目前 唯一配对的设备 无论我尝试了多少方法 我仍然会收到此错误 这是我尝试过的最后一个代码 它似乎完成了我看到人们报告为成功的所有事情 有人能指出我做错
  • 如何使用正则表达式验证 1-99 范围?

    我需要验证一些用户输入 以确保输入的数字在 1 99 范围内 含 这些必须是整数 Integer 值 允许前面加 0 但可选 有效值 1 01 10 99 09 无效值 0 007 100 10 5 010 到目前为止 我已经制定了以下正则
  • 如何通过注解用try-catch包装方法?

    如果应该在方法调用中忽略异常 则可以编写以下内容 public void addEntryIfPresent String key Dto dto try Map
  • 从直方图计算平均值和百分位数?

    我编写了一个计时器 可以测量任何多线程应用程序中特定代码的性能 在下面的计时器中 它还会在地图中填充花费了 x 毫秒的调用次数 我将使用这张图作为我的直方图的一部分来进行进一步的分析 例如调用花费了这么多毫秒的百分比等等 public st
  • JAVA中遍历JSON数据

    我是 JSON 新手 我使用 HTTPUrlConnections 并在 JAVA 程序中获得一些响应 响应数据将类似于 data id 1 userId 1 name ABC modified 2014 12 04 created 201
  • IntelliJ 组织导入

    IntelliJ 是否具有类似于 Eclipse 中的组织导入功能 我拥有的是一个 Java 文件 其中多个类缺少导入 例子 package com test public class Foo public Map map public J
  • 禁用 Android 菜单组

    我尝试使用以下代码禁用菜单组 但它不起作用 菜单项仍然启用 你能告诉我出了什么问题吗 资源 菜单 menu xml menu menu
  • ECDH使用Android KeyStore生成私钥

    我正在尝试使用 Android KeyStore Provider 生成的私有文件在 Android 中实现 ECDH public byte ecdh PublicKey otherPubKey throws Exception try
  • 何时在 hibernate 中使用 DiscriminatorValue 注解

    在 hibernate 中使用 DiscriminatorValue 注释的最佳场景是什么以及何时 这两个链接最能帮助我理解继承概念 http docs oracle com javaee 6 tutorial doc bnbqn html
  • HttpClient请求设置属性问题

    我使用这个 HttpClient 库玩了一段时间 几周 我想以某种方式将属性设置为请求 不是参数而是属性 在我的 servlet 中 我想使用 Integer inte Integer request getAttribute obj 我不
  • 使用 JFreeChart 为两个系列设置不同的 y 轴

    我正在使用 JFreeChart 使用折线图绘制两个数据系列 XYSeries 复杂的因素是 其中一个数据系列的 y 值通常远高于第二个数据系列的 y 值 假设第一个系列的 y 值约为数百万数量级 而第二个数据系列的 y 值约为数百万数量级
  • try-with-resources 中出现死代码警告,但翻译后的 try-catch-finally 中没有出现死代码警告

    以下代码使用try 有资源 https docs oracle com javase specs jls se7 html jls 14 html jls 14 20 3Java 8 中引入的构造 偶尔抛出 方法被声明为抛出一个偶尔的异常
  • 即使调整大小,如何获得屏幕的精确中间位置

    好的 这个问题有两部分 当我做一个JFrame 并在其上画一些东西 即使我将宽度设置为 400 并使其在一个项目击中它时 当然 允许项目宽度 它会反弹回来 但由于某种原因 它总是偏离屏幕约 10 个像素 有没有办法解决这个问题 或者我只需要

随机推荐