【问题标题】:Why can't I have a two-level-deep inner class with the same name as its containing class?为什么我不能有一个与它的包含类同名的两层深的内部类?
【发布时间】:2013-09-02 02:03:19
【问题描述】:

今天,其他一些开发人员发现了一个带有一些有趣嵌套的 XML 模式,JAXB 将其编译成这样的结构:

public class Choices
{
    public static class Choice
    {
        public static class Choice
        {
        }
    }
}

如果你尝试编译它,Java 编译器会说,

class Choices.Choice is already defined in class Choices

当然还有最里面的class Choice 声明的下划线。

但我说,Choices.Choice 类不是它试图声明的。相反,它试图声明 Choices.Choice.Choice,这将是一个不同的类。

有趣的是,这很好:

public class OuterClass
{
    public static class Inner1
    {
        public static class Inner2
        {
        }
    }

    public static class Inner2
    {
        public static class Inner1
        {
        }
    }
}

但这是被禁止的:

public class OuterClass
{
    public static class Inner1
    {
        public static class Inner2
        {
            public static class Inner1
            {
            }
        }
    }
}

所以我猜规则是类的名称不能与任何级别的包含类相同。显然这里的修复是已知的——让 JAXB 不要生成无效代码。

但我的问题是,为什么还会出现这种限制? Java 编译器试图通过不让我们创建与包含类同名的内部类来避免什么?

【问题讨论】:

  • 一个更好的问题可能是你为什么要这样做。
  • 好吧,老实说,我不知道。就像我说的,生成它的是 JAXB 的代码生成。
  • 好吧,我想说真正的问题是设计糟糕的 XML 模式。
  • 这点也可能是对的。模式也不是我们的,它是 EDRM-XML。也许这很可怕。我不确定我们有什么投诉渠道。

标签: java inner-classes


【解决方案1】:

Java 允许您在不完全指定其名称的情况下引用外部类,如下所示:

public static class Inner1
{
    public static class Inner2
    {
        public static class Inner3
        {
            public void demo() {
                Class<Inner2> c = Inner2.class; // This is allowed
            }
        }
    }
}

如果类的嵌套允许在任何层次结构级别使用相同的名称,那么通过非限定名称引用将是不可能的。 Java 编译器试图通过禁止嵌套声明与其外部类的名称冲突来保留这种能力。

【讨论】:

    【解决方案2】:

    创建一个complexType,然后引用第二层(同名)。使用不同的名称,这将创建一个不同的类并满足 java 要求。

    Choices = Choices.class
    选择 = Choice.class
    选择(第二级)= InnerChoice.class

    <complexType name = "innerChoice" >
      <sequence>
        .....
      </sequence>
    </complexType>
    
     <element name="choices">
       <complexType>
         <sequence>
           <element name="choice">
             <complexType>
               <sequence>
                 <!-- NEW! -->
                 <element name="choice"  type="innerChoice">
                 <!- This used to say 
                 <element name="choice">
                   <complextype>
                    <sequence>
                      ....
                    </sequence>
                   </complexType>
                 -->
              .....
    

    现在您生成的类文件将是 Choices.Choice.InnerChoice 将分配给变量选择(变量名可以嵌套,而不是类名)

    【讨论】:

    • 就像我说的那样,架构不是我们的。这是一个标准的。
    猜你喜欢
    • 2020-11-22
    • 1970-01-01
    • 2016-03-28
    • 2011-03-21
    • 2018-11-08
    • 2021-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多