【问题标题】:Is a member interface in a class declaration implicitly public?类声明中的成员接口是否隐式公开?
【发布时间】:2012-07-24 20:13:57
【问题描述】:

代码

我有以下带有成员接口的类:

package com.example.withinterface;

public class SomeClass {

    interface SomeInterface {

        void doSomething();
    }
}

另一个类试图访问它:

package com.example.withinterface.main;

import com.example.withinterface.SomeClass;

public class Main {

    public static void main(String[] argss) {
        System.out.println(SomeClass.SomeInterface.class);
    }
}

错误

在 Main 中,我从 javac 收到以下错误:SomeInterface is not public in SomeClass; cannot be accessed from outside package

在 Eclipse 中:SomeInterface is not public in SomeClass; cannot be accessed from outside package

两者都编译为 Java 7。如果我创建 SomeInterface public,一切都可以正常编译。

但规范说

Java Language Specification for Java 7 是这样说的:

成员接口是直接声明的接口 包含在另一个类或接口声明中。

类声明中的成员接口是隐式公共的(第 6.6 节) 除非指定了访问修饰符。

Java Language Specification for Java 5好像没有第二句。

问题

那么 SomeInterface 不应该被认为是公开的,不应该 Main 编译吗?

更新

正如Ajay George 所建议的,这确实是an error in the Java Language Specification 7(感谢JamesB)。与此同时,规范被纠正,不正确的句子被删除。 Last version in Archive.org with the incorrect sentence.

【问题讨论】:

  • 嗯。除非另有说明,否则我一直认为所有东西都受到包装保护。我想我学到了一些新东西。
  • 我认为这是因为没有访问修饰符的成员具有包访问权限。所以它们不能被其他包使用
  • @Desolator 你读过这个问题吗?成员接口默认是公开的
  • 我的问题是,到底是什么让他们引入了这种变化?现在不再有包级成员接口。
  • @MarkoTopolnik 你的意思是我们不能做像protected interface Foo 这样的事情?还是我假设它会做想要的事情是错误的?

标签: java jls


【解决方案1】:

我猜规格是错误的。 这是您的代码的 javap 输出。

E:\workspace>javap com\example\withinterface\SomeClass
Warning: Binary file com\example\withinterface\SomeClass contains com.example.wi
thinterface.SomeClass
Compiled from "SomeClass.java"
public class com.example.withinterface.SomeClass {
  public com.example.withinterface.SomeClass();
}

E:\workspace>javap com\example\withinterface\SomeClass$SomeInterface
Warning: Binary file com\example\withinterface\SomeClass$SomeInterface contains
com.example.withinterface.SomeClass$SomeInterface
Compiled from "SomeClass.java"
interface com.example.withinterface.SomeClass$SomeInterface {
  public abstract void doSomething();
}

我把接口改成public,然后重新编译。

E:\workspace>javap com\example\withinterface\SomeClass
Warning: Binary file com\example\withinterface\SomeClass contains com.example.wi
thinterface.SomeClass
Compiled from "SomeClass.java"
public class com.example.withinterface.SomeClass {
  public com.example.withinterface.SomeClass();
}

E:\workspace>javap com\example\withinterface\SomeClass$SomeInterface
Warning: Binary file com\example\withinterface\SomeClass$SomeInterface contains
com.example.withinterface.SomeClass$SomeInterface
Compiled from "SomeClass.java"
public interface com.example.withinterface.SomeClass$SomeInterface {
  public abstract void doSomething();
}

注意 Inner 类的区别。

【讨论】:

  • 我同意。 JLS 显然是错误的。使用 Java 7 JDK,只有当成员接口显式声明为 public 时,代码才会编译。
  • @assylias 很好。尽管它仍然不会使 JLS 出错——它会使所有实现都出错 :) 我确实希望他们能纠正这一点。像这样的问题在哪里发布?也许它已经被提出了。
  • @MarkoTopolnik 我已经通过电子邮件向 Oracle 提出了这个问题。我在这里使用了信息:docs.oracle.com/javase/feedback.html
  • @assylias 是的,可能是一个错误或错字。但是接口的成员类型已经在JLS section 9.5中讨论过了
猜你喜欢
  • 2021-10-22
  • 1970-01-01
  • 1970-01-01
  • 2013-01-02
  • 1970-01-01
  • 2013-07-24
  • 2015-06-20
  • 2012-07-25
  • 1970-01-01
相关资源
最近更新 更多