给定这个示例代码...
package example;
public class Main {
public static void main(String[] args) {
System.out.println(MyEnum.X.getValue());
}
private enum MyEnum {
X(){
@Override
String getValue() {
return toString("XYZ"); //error here
}
};
abstract String getValue();
private static String toString(String output) {
return output;
}
}
}
产生以下编译器错误:
Error:(12, 40) java: method toString in class java.lang.Enum<E> cannot be applied to given types;
required: no arguments
found: java.lang.String
reason: actual and formal argument lists differ in length
IntelliJ出现了另一个问题:toString
中的toString("XYZ")
用红色下划线标出,并且显示消息“'toString(java.lang.String)'在'example.Main.MyEnum'中具有私有访问权限”,并带有解决方案“将'MyEnum.toString'打包为私有”。
我感到很奇怪的是,以下任何一项均可解决此问题:
通过枚举引用:X.toString("XYZ")
调用该方法。
通过类引用MyEnum.toString("XYZ")
调用该方法。
通过super调用方法:super.toString("XYZ")
。 (但是this.toString("XYZ")
不起作用)
将方法设置为私有或公开
命名方法“ toString2”
现在,对于任何生产代码,我可能会将该方法命名为其他方法(可能是对我将要执行的操作的更多描述),然后继续前进,但是我仍然想知道为什么会发生这种情况?为什么IntelliJ和javac的错误消息不同?
这个问题可能类似于Cannot make a static reference to the non-static field memberVariable with private variable,但是我觉得它不能完全解释问题-为什么重命名有效?
参考方案
首先,此问题并非特定于枚举。它适用于任何内部类。我重构了您的示例以删除该枚举,该枚举在内部类和匿名内部类中都演示了相同的问题。
class Main {
public static void main(String[] args) {
Main main = new Main() {
{
System.out.println(toString("XYZ")); // same error
}
};
}
class Foo {
{
System.out.println(toString("XYZ")); // same error
}
}
private static String toString(String output) {
return output;
}
}
在JLS here中进行了解释:
示例6.5.7.1-1。简单方法名称
以下程序演示了范围界定的作用
确定要调用的方法。
class Super {
void f2(String s) {}
void f3(String s) {}
void f3(int i1, int i2) {}
}
class Test {
void f1(int i) {}
void f2(int i) {}
void f3(int i) {}
void m() {
new Super() {
{
f1(0); // OK, resolves to Test.f1(int)
f2(0); // compile-time error
f3(0); // compile-time error
}
};
}
}
对于调用f1(0)
,作用域中只有一个名为f1的方法。这是方法Test.f1(int)
,其声明在范围内
在整个测试过程中,包括匿名类声明。
由于匿名类,§15.12.1选择在Test类中进行搜索
声明没有名为f1
的成员。最终,Test.f1(int)
是
解决。
对于调用f2(0)
,两个名为f2
的方法在范围内。第一,
方法Super.f2(String)
的声明在整个范围内
匿名类声明。二,方法的声明
Test.f2(int)
涵盖整个测试范围,包括
匿名类声明。 (请注意,两个声明都没有阴影
另一个,因为在每个被声明的位置,另一个是
不在范围内。)§15.12.1选择在Super类中搜索,因为它
有一个名为f2
的成员。但是,Super.f2(String)
不适用于
f2(0)
,因此会发生编译时错误。请注意,类Test
不是
搜索。
对于调用f3(0)
,范围为三个名为f3
的方法。第一
第二,方法Super.f3(String)
的声明和
Super.f3(int,int)
属于整个匿名类的范围
宣言。第三,方法Test.f3(int)
的声明位于
整个测试主体的范围,包括匿名类
宣言。 §15.12.1选择搜索类Super
,因为它具有
一个名为f3
的成员。但是,Super.f3(String)
和Super.f3(int,int)
是
不适用于f3(0)
,因此会发生编译时错误。注意
不搜索类Test
。
选择先搜索嵌套类的超类层次结构
词汇上包含范围的范围称为“梳子规则”(§15.12.1)。
我有一个字符串4.9.14_05_29_16_21,我只需要获取4.9。数字各不相同,所以我不能简单地获得此char数组的前三个元素。我必须找到最正确的.并将其子字符串化直到那里。我来自Python,因此我将展示Python的实现方法。def foobar(some_string): location = some_string.rfind('.&…
Java-搜索字符串数组中的字符串 - java在Java中,我们是否有任何方法可以发现特定字符串是字符串数组的一部分。我可以避免出现一个循环。例如String [] array = {"AA","BB","CC" }; string x = "BB" 我想要一个if (some condition to tell wheth…
Java:线程池如何将线程映射到可运行对象 - java试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …
JAVA:字节码和二进制有什么区别? - javajava字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…
在Java中使用新关键字和直接赋值的字符串 - javaString s="hi"; String s1=new String("hi"); 从内存角度看,s和s1存储在哪里?无论是在堆内存还是堆栈中。s指向“ hi”,而s1指向hi存在的内存位置?请帮忙? 参考方案 考虑以下 String s = "hi"; String s1 = new Strin…