Java 为什么可以';我有一个两级的深层内部类,它和它的包含类同名吗?

Java 为什么可以';我有一个两级的深层内部类,它和它的包含类同名吗?,java,inner-classes,Java,Inner Classes,今天,其他一些开发人员发现了一个包含一些有趣嵌套的XML模式,JAXB将其编译成如下结构: public class Choices { public static class Choice { public static class Choice { } } } public static class Inner1 { public static class Inner2 { public

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

public class Choices
{
    public static class Choice
    {
        public static class Choice
        {
        }
    }
}
public static class Inner1
{
    public static class Inner2
    {
        public static class Inner3
        {
            public void demo() {
                Class<Inner2> c = Inner2.class; // This is allowed
            }
        }
    }
}
如果你试图编译它,Java编译器会说

class Choices.Choice is already defined in class Choices
当然,在最里面的
类选择
声明上加下划线

但我要说的是,类
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编译器不允许我们创建与包含类同名的内部类,从而试图避免什么问题?

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

public class Choices
{
    public static class Choice
    {
        public static class Choice
        {
        }
    }
}
public static class Inner1
{
    public static class Inner2
    {
        public static class Inner3
        {
            public void demo() {
                Class<Inner2> c = Inner2.class; // This is allowed
            }
        }
    }
}
公共静态类Inner1
{
公共静态类Inner2
{
公共静态类Inner3
{
公共空间演示(){
Class c=Inner2.Class;//这是允许的
}
}
}
}

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

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

i、 e

选择=选择。类别
选择=选择。类别
选择(第二级)=内部选择类

<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,它将被分配给变量Choice(变量名可以嵌套好,而不是类名)

一个更好的问题可能是您为什么要这样做。老实说,我没有。正如我所说,是JAXB的代码生成产生了它。好吧,我要说的是,真正的问题是设计糟糕的XML模式。这一点也可能是正确的。模式也不是我们的,它是EDRM-XML。也许这很可怕。我不确定我们有什么途径来抱怨它。不过,正如我所说,这个模式不是我们的。这是标准的。