java - 管理泛型外部类及其内部泛型内部类实例化以及声明各自引用的规则是什么?

标签 java generics inner-classes

1) 为什么obj4、obj6、obj7编译错误,而obj5正常?我在哪里可以阅读有关使用此类通用耦合外部内部类进行规范的规则?我没有找到任何直接切中要害的东西。

当我不为 obj3 中的内部类提供任何类型参数时,这很好(虽然内部类需要为其 S 类型的 fld3 字段提供一些东西),但是当我做同样的事情并且不提供类型时对于外部类 - 它不编译(obj4) - 尽管可以隐含对象...

2) 另外,为什么 obj10 编译正常,而 obj11 却失败?在 obj10 行中,我还编写了outerInstance.new Inner<>(),暗示 Inner S 是对象。但这对于内部来说不是问题,但同样的“技巧”对于外部来说是问题......

        //in Class A of package com.sth
        public class MyGen<T> {
            T fld1;

            class GenInner<S> {
                T fld2;
                S fld3;
            }

                // within main of Class Driver of same package com.sth
                MyGen.GenInner obj1 = new MyGen<String>().new GenInner<Integer>();
                MyGen.GenInner obj2 = new MyGen<String>().new GenInner<>();
                MyGen.GenInner obj3 = new MyGen<String>().new GenInner();
                //MyGen.GenInner obj4 = new MyGen().new GenInner<String>();  //ERR !
                MyGen.GenInner obj5 = new MyGen<>().new GenInner<String>();

                //MyGen<String>.GenInner obj6;  // ERR
                //MyGen.GenInner<String> obj7;  // ERR
                MyGen<String>.GenInner<Integer> obj8;
                MyGen.GenInner obj9;     


  MyGen<String>.GenInner<Integer> obj10 = new MyGen<String>().new GenInner<>();

  //Type mismatch: cannot convert from MyGen<Object>.GenInner<Integer> to MyGen<String>.GenInner<Integer>
  //MyGen<String>.GenInner<Integer> obj11 = new MyGen<>().new GenInner<Integer>();  // ERR!

这些答案与我的问题相关,但没有提供任何线索:

  1. Answer 1
  2. Answer 2
  3. Answer 3
  4. Answer 4
  5. Answer 5

最佳答案

无法编译的示例大多是稀有类型的示例。 (此外,正如 John 在评论中指出的那样,obj3 示例也不应该编译。)

A raw type 是通过使用没有附带类型参数列表的泛型类型形成的类型(例如 Set ,而不是 Set<Float> )。 罕见类型是指您拥有通用外部类和通用内部类,其中一个是原始类,另一个不是原始类。

取自JLS 4.8 Raw Types:

More precisely, a raw type is defined to be one of:

  • The reference type that is formed by taking the name of a generic type declaration without an accompanying type argument list.

  • An array type whose element type is a raw type.

  • A non-static member type of a raw type R that is not inherited from a superclass or superinterface of R.

(请注意,粗体部分意味着如果您有原始类型 MyGen ,那么它的非 static 成员类 GenInner 也必须是原始类型,因此不存在 MyGen.GenInner<String> 之类的东西。)

Another implication of the rules above is that a generic inner class of a raw type can itself only be used as a raw type:

class Outer<T>{
    class Inner<S> {
        S s;
    }
}

It is not possible to access Inner as a partially raw type (a "rare" type):

Outer.Inner<Double> x = null;  // illegal
Double d = x.s;

because Outer itself is raw, hence so are all its inner classes including Inner, and so it is not possible to pass any type arguments to Inner.

It is a compile-time error to pass type arguments to a non-static type member of a raw type that is not inherited from its superclasses or superinterfaces.

It is a compile-time error to attempt to use a type member of a parameterized type as a raw type.

This means that the ban on "rare" types extends to the case where the qualifying type is parameterized, but we attempt to use the inner class as a raw type:

Outer<Integer>.Inner x = null; // illegal

This is the opposite of the case discussed above. There is no practical justification for this half-baked type. In legacy code, no type arguments are used. In non-legacy code, we should use the generic types correctly and pass all the required type arguments.

obj11 = new MyGen<>().new GenInner<Integer>() 的例子并不罕见。它看起来就像菱形类型推断的常规失败,因为表达式 new MyGen<>() 没有分配给任何东西。如果没有分配,通常假设为 Object。 (从技术上讲,它可以是类型变量的上限,在本例中为 Object。)

<小时/>

此外,虽然与当前的问题没有直接关系,但以下是新代码中实际应使用的唯一两种形式:

MyGen<String>.GenInner<Integer> ok1 = new MyGen<String>().new GenInner<Integer>();
MyGen<String>.GenInner<Integer> ok2 = new MyGen<String>().new GenInner<>();

所有其他(编译)都使用原始类型,并且不鼓励使用原始类型。

关于java - 管理泛型外部类及其内部泛型内部类实例化以及声明各自引用的规则是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44853227/

相关文章:

java - 在显示 JOptionPane.showMessageDialog 后重新启用 Java 中的工具提示

java - JAVA中如何访问私有(private)内部类的私有(private)参数化方法

java - 单个文件中的多个类 : modifier private not allowed here

java - Websocket Java 服务器。不发送消息也不接收

generics - 如何输入返回子类型的泛型函数

c# - 带有受限泛型参数的奇怪方法重载解析 : overload with base class arg always called

java - 实例化内部类

python - 如何定义嵌套在类下的 Pydantic 模型

java - IllegalArgumentException - Google Guava 将字符串转换为 HashMap

scala - Scala 类定义中 protected 关键字的含义是什么?