基于类型参数的内部类的类型声明

9

Java会隐藏类型参数吗?我发现很难亲自测试,因为Java泛型在运行时不会被实例化。

例如,给定以下代码:

public class NestedGeneric<T> {
    private InnerGeneric<T> innerGenericInstance;

    private static class InnerGeneric<T> {
        public T innerGenericField;
    }

    NestedGeneric() {
    innerGenericInstance = new InnerGeneric<T>();
    }
}

以下两个语句都可以编译通过:

NestedGeneric<Integer> test1 = new NestedGeneric<Integer>();
NestedGeneric.InnerGeneric<String> test2  = new NestedGeneric.InnerGeneric<String>();

当传递类型参数并调用构造函数时,NestedGeneric中的T是什么?它总是与传递给nestedGeneric的类型参数相同吗?
换句话说,外部类的类型参数是否可以传递给内部类的泛型类型声明?

1
可以这样做,但不是必须的。您也可以将内部类作为另一个对象,但您想在嵌套类创建中将T更改为“U”。 - Roel Strolenberg
似乎存在类型参数被遮蔽的情况 http://ideone.com/8DihKQ - ReyCharles
3个回答

6
换句话说,我的理解是,外部类的类型参数是否可以传递给内部类的泛型类型声明?
不行。外部静态类与内部静态类之间没有关系(如继承或作为字段)。您可以在不依赖外部类的情况下创建内部静态类的对象,就像您的示例一样:
NestedGeneric.InnerGeneric<String> test2  = new NestedGeneric.InnerGeneric<String>();

然而,当您使用内部类的一个实例作为字段时,泛型类型是从外部类派生的:

private InnerGeneric<T> innerGenericInstance;

innerGenericInstance = new InnerGeneric<T>();

第三种变化是将内部类定义为一个字段(非静态):
private class InnerGeneric<T> {
    public T innerGenericField;
}

现在这个变量是外部类的成员变量,因此将从外部类获取类型。

正如评论中指出的那样,同时为内部静态类和外部类定义相同的类型只会让读者 (以及之后的自己) 感到困惑。应该使用不同的泛型进行声明,例如

public class NestedGeneric<T> {
    private InnerGeneric<T> innerGenericInstance;

    private static class InnerGeneric<U> {
        private U innerGenericField;
    }

    NestedGeneric() {
        innerGenericInstance = new InnerGeneric<T>();
    }
}

5

这并不是“shadowing”。你的代码只有一个类型参数,即T。因此内部和外部的T是同一类型参数。

当然,你也可以使用更多的类型参数。

public class NestedGeneric<OUTER_TYPE> {

  private static class InnerGeneric<INNER_TYPE> {
    public INNER_TYPE innerGenericField;
  }

  public NestedGeneric() {
    InnerGeneric<OUTER_TYPE> innerGenericInstance = new InnerGeneric<OUTER_TYPE>();

   InnerGeneric<String> secondInnerGenerics = new InnerGeneric<String>();
  } 
}

INNER_TYPEOUTER_TYPE是两个不同的类型参数。在代码行InnerGeneric<OUTER_TYPE> innerGenericInstance = new InnerGeneric<OUTER_TYPE>();中,innerGenericInstance被定义为与OUTER_TYPE相同的参数类型,但它们不一定要相同,就像secondInnerGenerics变量的情况一样。


所以只有声明点是重要的吗?即使它们可以被命名为不同的名称,我也想了解当它们被命名为相同时的行为。如果内部类的类型参数与外部类具有相同的名称,它们仍然是完全独立的吗? - user4699992
在OP的代码中,实际上有两个类型参数:一个用于NestedGeneric,另一个用于InnerGeneric。它们都被称为“T”,这一点很令人困惑。@plastique给出的类定义使用不同的名称来表示类型参数,这使得它们是不同的参数更加明显,但定义在功能上是相同的。 - Josh Milthorpe

4

可以,但不能使用static修饰符:

public class NestedGeneric<T> {
    private InnerGeneric<T> innerGenericInstance;

    private class InnerGeneric<T> {
        private T innerGenericField;

        public InnerGeneric(T innerGenericField){
           this.innerGenericField = innerGenericField;
        }

        public T getInnerGenericField(){
           return this.innerGenericField;
        }
    }

    NestedGeneric(T someGenericVariable) {
        innerGenericInstance = new InnerGeneric<T>(someGenericVariable);
        T innerGenericField = innerGenericInstance.innerGenericInstance();
    }
}

在这种情况下,内部泛型类不是静态的,这会被处理得不同。 - 6ton
内部类是静态的,但内部类实例存储在非静态成员变量中。 - user439793

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接