测试了一些东西我尝试做一个枚举,其中枚举中的每个元素都有一个不同的类.
举个例子:
public enum MyEnum {
first{
class First{}
},
second {
class Second{}
};
}
Run Code Online (Sandbox Code Playgroud)
如果我尝试在任何类之前放置一个公共修饰符,则此处不允许使用修饰符.我不太清楚为什么会这样.我不能在枚举之外实例化这些类,也不能看到它们.但是我可以设法让实例这样做:
public enum MyEnum {
first{
class First{}
public Object getObject(){
return new First();
}
},
second {
class Second{}
public Object getObject(){
return new Second();
}
};
public abstract Object getObject();
}
public class Main {
public static void main(String[] args) {
System.out.println(MyEnum.first.getObject().getClass());
System.out.println(MyEnum.second.getObject().getClass());
}
}
Run Code Online (Sandbox Code Playgroud)
随着输出:
class MyEnum $ 1 $ First
class MyEnum $ 2 $秒
我可以清楚地引用这个类,为什么我不能在编译时访问它?
JDK\xc2\xa016 更改了规则,现在允许内部类拥有static成员。看来这个问题的问题已作为副作用得到修复。由于这也应该是早期版本中的行为,public因此即使使用--release 8.
这是一个非常有趣的问题。您将无法在编译时访问这些类,即使public,因为它们包含在隐式匿名类中,因此无论如何都不能通过名称访问它们(除了在匿名类中) )。您可以\xe2\x80\x99t通过变量访问类型,即MyEnum.first.First在Java中根本不可能访问。
尽管如此,没有用并不一定决定可以声明什么,即在一个public内部类中声明一个内部类。private外部类中声明内部类也是可能的。正式规则是相关的,虽然乍一看似乎是预期的行为,但令人惊讶的是它并没有以这种方式得到规范的支持。
\n\n枚举常量的可选类主体隐式定义匿名类声明 ( \xc2\xa715.9.5 ),该声明扩展了直接封闭的枚举类型。类体由匿名类的通常规则\xe2\x80\xa6管理
\n
这给了我们一个有趣的提示,即
\nclass Outer {\n static Object o = new Object() {\n public class Inner {\n }\n };\n}\nRun Code Online (Sandbox Code Playgroud)\n在 JDK\xc2\xa016 之前,也会被编译器拒绝。
\n\n\n\n访问修饰符
\npublic( \xc2\xa76.6 ) 仅适用于顶级类 ( \xc2\xa77.6 ) 和成员类 ( \xc2\xa78.5 ),不适用于本地类 ( \xc2\xa714.3 ) 或匿名类(\xc2\xa715.9.5)。
我们必须决定Inner您属于哪个类别或First类别。\xe2\x80\x99 与它们周围的类是匿名类这一事实无关。显然,它们既不是顶级类,也不是匿名类,因为它们是嵌套的并且有名称。所以它们必须是成员类(public允许)或本地类(public不允许)。
\n\n成员类是其声明直接包含在另一个类或接口声明的主体中的类(\xc2\xa78.1.6、\xc2\xa79.1.4)。
\n
另一个类\xe2\x80\xa6声明\xe2\x80\x9d的\xe2\x80\x9cbody是通过指向\xc2\xa78.1.6来定义的,它确实定义了ClassBody语言语法,通常用于命名声明、匿名声明类和enum常量;它们都指向\xc2\xa78.1.6的\xe2\x80\x9cclass body\xe2\x80\x9d。考虑到这一点,我们的类是\xe2\x80\x9c成员类\xe2\x80\x9d,因为它们包含在类主体中。
现在我们可以尝试将其解释为错误的交叉引用,假设另一个类的 \xe2\x80\x9cbody声明\xe2\x80\xa6 是指引用类声明,即使用命名类声明然而,关键字局部类class的定义反驳了这种解释。
\n\n本地类是一个嵌套类 ( \xc2\xa78 (Classes) ),它不是任何类的成员,并且具有名称 ( \xc2\xa76.2、\xc2\xa76.7 )。
\n\xe2\x80\xa6
\n每个局部类声明语句立即包含在一个块(\xc2\xa714.2)中。局部类声明语句可以与块中的其他类型的语句自由混合。
\n
abstract\xe2\x80\x9cBlock\xe2\x80\x9d 的真正含义是类似于非方法、构造函数或初始化器的定义的块( \xc2\xa714.2 )。这不适用于Inner上述班级或您的First班级Second。它们没有放置在块中,并且不能与该上下文中的语句自由混合,因为此时不允许使用语句。
换句话说,它们绝对不是本地类,并且假设没有规范中未描述的类的其他类别,我们必须将它们视为成员类,正如成员类定义的当前编写和链接也表明的那样,也就是说,根据引用的规则,public该处应该允许修饰符。
为了完整起见,这里是匿名类的定义,只是为了表明没有例外规则说它们的成员类不允许\xe2\x80\x99t public:
\n\n15.9.5。匿名类声明
\n匿名类声明是由 Java 编译器自动从类实例创建表达式派生的。
\n匿名类永远不是
\nabstract(\xc2\xa78.1.1.1)。匿名类始终是隐式的
\nfinal(\xc2\xa78.1.1.2)。匿名类始终是内部类(\xc2\xa78.1.3);它永远不是
\nstatic(\xc2\xa78.1.1,\xc2\xa78.5.1)。
最后一点意味着,反过来,它们的成员类可以是\xe2\x80\x99 static,但是,没有规则禁止它们是public。