【问题标题】:Is it possible to use parametrize generic inner classes?是否可以使用参数化通用内部类?
【发布时间】:2014-10-19 14:16:11
【问题描述】:
package generics;
public class InnerClassGenerics{
     class Innerclasss{

    }
    public static void main(String[] args) {
        InnerClassGenerics icg=new InnerClassGenerics();
        Innerclasss innerclass=icg.new Innerclasss();
    }
}

上面的代码是可能的并且编译得很好!!!


为什么下面的代码无法编译,是否可以对内部类进行参数化?

package generics;
public class InnerClassGenerics<T>{
    class Innerclasss<T>{

    }
    public static void main(String[] args) {
        InnerClassGenerics<String> icg=new InnerClassGenerics<>();
        Innerclasss<String> innerclass=new Innerclasss<>();
    }
}

在上面的代码中,如果类是静态的,它就可以正常工作!!! 为什么没有 static 关键字就不行?

【问题讨论】:

  • 这与泛型无关,只是说。
  • 您在内部类中的类型参数&lt;T&gt; 对外部类隐藏了&lt;T&gt;。无论如何,您应该更正您的示例(您正在尝试突然创建非静态内部类,而不使用外部类的任何实例)。
  • 只需将Innerclasss&lt;String&gt; innerclass=new Innerclasss&lt;&gt;(); 更改为InnerClassGenerics&lt;String&gt;.Innerclasss&lt;String&gt; innerclass=icg.new Innerclasss&lt;String&gt;();
  • @Tom 这很好用!!

标签: java generics inner-classes


【解决方案1】:

通常,如果外部类上没有任何泛型类型,您可以编写如下代码:

Outer outer = new Outer();
Inner inner = outer.new Inner();

因为内部类中的每个方法都已经知道它应该使用什么类型。

但是当外部类使用泛型类型时,情况会稍微复杂一些。由于内部类可以访问其外部类(或多个类)的所有成员,因此它还需要了解外部类中使用的泛型类型,以确保在操作泛型值时的类型安全。

看看这段代码:

class Outer<T> {
    private T someValue;

    class Inner {
        T getOuterValue(){
            return someValue;
        }
        void setOuterValue(T value){
            someValue=value;
        }
    }
    //rest of code
}

这意味着Inner 类的实例也依赖于其外部类的泛型类型。这就是为什么在创建对内部类的引用时,您需要通过将其写为

来显式使用具有泛型类型的外部类
Outer<String> outer = new Outer<>();
Outer<String>.Inner inner = outer.new Inner();
^^^^^^^^^^^^^

或明确地说外部类使用raw type(不鼓励)喜欢

Outer.Inner inner = outer.new Inner();

因此,要使您的代码正常工作,您需要:

  1. 添加外部类类型(最好使用其泛型)

  2. 在外部类的实例上调用内部类的构造函数(就像没有实例不能调用非静态方法一样,必须使用外部类实例创建非静态(内部)类)

    InnerClassGenerics<String>.Innerclasss<String> innerclass = icg.new Innerclasss<>();
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^                                 ^^^^
             point 1                                           point 2
    

不应该为嵌套类及其外部类中的泛型类型赋予相同的名称,就像在这种情况下

public class InnerClassGenerics<T>{
    class Innerclasss<T>{
        ...
    }
}

因为T 来自Innerclasss 隐藏 T 来自其外部类InnerClassGenerics(不是说它会导致当前的问题,但它会让你以后的生活变得困难)。

【讨论】:

    【解决方案2】:

    所以你有这个类定义,它不会编译,因为你有两种类型,称为T。像这样,它会编译:

    public class OuterClass <O>
    {
        public class InnerClass <I>
        {
        }
    }
    

    另外,请注意您正在从静态方法实例化一个非静态类。你完整的代码应该是这样的:

    public class OuterClass <O>
    {
        public static class InnerClass <I>
        {
        }
    
        public OuterClass ()
        {
        }
        public InnerClass<O> getInnerClass ()
        {
            return new InnerClass<O>();
        }
    
        public static void main (String[] args)
        {
            OuterClass<String> outer = new OuterClass<>();
            InnerClass<String> inner = outer.getInnerClass();
        }
    }
    

    以上代码需要Java 8编译。

    【讨论】:

    • 嗯,这可能是 Java 7 的问题,但InnerClass&lt;String&gt; inner 仍然会导致编译器错误。不应该是OuterClass&lt;String&gt;.InnerClass&lt;String&gt;吗?
    • @Tom 在 Java8 (Eclipse) 上编译得很好
    • 以上代码抛出编译时错误。 (不能对非静态类型InnerClass进行静态引用)
    • @Terminator 正如 Tom 已经指出的,它需要 Java8 来编译
    • 拥有一个隐藏封闭类型的类型变量的类型变量不是问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-21
    • 1970-01-01
    • 2011-07-17
    • 1970-01-01
    • 2018-02-10
    • 1970-01-01
    相关资源
    最近更新 更多