Java 为什么可以';t我们创建一个数组";混凝土“;泛型类中的类? 公共类GenericClass{ 类MyClass{ } 公共泛型类(最终T[]参数){ MyClass myObject=新建MyClass();//确定 MyClass[]myArray={new MyClass(),new MyClass()};//无法创建GenericClass.MyClass的泛型数组 } }

Java 为什么可以';t我们创建一个数组";混凝土“;泛型类中的类? 公共类GenericClass{ 类MyClass{ } 公共泛型类(最终T[]参数){ MyClass myObject=新建MyClass();//确定 MyClass[]myArray={new MyClass(),new MyClass()};//无法创建GenericClass.MyClass的泛型数组 } },java,arrays,class,generics,Java,Arrays,Class,Generics,这不是创建通用数组。编译器在理解/确定MyClass时应该没有问题,不是吗?这里有一些。从链接 Java数组携带运行时类型信息,用于标识 所包含的元素 对于编译器,您的代码如下所示: public class GenericClass<T> { class MyClass { } public GenericClass(final T[] param) { MyClass myObject = new MyClass();

这不是创建通用数组。编译器在理解/确定
MyClass
时应该没有问题,不是吗?

这里有一些。从链接

Java数组携带运行时类型信息,用于标识 所包含的元素

对于编译器,您的代码如下所示:

public class GenericClass<T> {

    class MyClass {
    }

    public GenericClass(final T[] param) {
        MyClass myObject = new MyClass();                       // OK
        MyClass[] myArray = { new MyClass(), new MyClass() };   // Cannot create a generic array of GenericClass<T>.MyClass
    }
}
MyClass[]myArray={new GenericClass.MyClass(),…}//T未知
如果你让它静止,它会工作,因为- 静态嵌套类或嵌套接口(顺便说一句,它始终是静态的)除了名称空间嵌套和对私有变量的访问之外,与外部类(或接口)没有任何关系。 作为标准API中的一个示例,查找嵌套在接口映射中的接口映射.Entry,它无法访问其类型参数,需要再次声明它们。

内部类“知道”封闭类的哪个实例创建了它们,并且可以访问此实例的字段/成员。这就好像他们有第二个
这个
变量,其类型是封闭类的具体类型(例如
GenericClass

要克服这种困境,您可以使
MyClass
static
。这将使它与封闭类的任何实例完全解耦(即:它不会有第二个
This
),因此它们可以自由实例化:

Object[] arr=new Object[]{this.new MyClass(), this.new MyClass()};
MyClass[]  myArray = Arrays.copyOf(arr,arr.length, Item.MyClass[].class);   
公共类GenericClass{
静态类MyClass{
}
公共泛型类(最终T[]参数){
MyClass myObject=新建MyClass();//确定
MyClass[]myArray={new MyClass(),new MyClass()};
}
}

介绍这一点的JLS部分是。具体来说,这是因为:

如果ClassOrInterfaceType不表示可修改类型(§4.7),则为编译时错误。否则,ClassOrInterfaceType可以命名任何命名的引用类型,甚至是抽象类类型(§8.1.1.1)或接口类型(§9)

上述规则意味着数组创建表达式中的元素类型不能是参数化类型,而只能是无界通配符


因为
MyClass
是非静态的,所以它依赖于外部类;它实际上是
GenericClass.MyClass
,因此是一个参数化类型。声明它
static
将删除该依赖项并解决问题

奇怪的是如果你这么做

public class GenericClass<T> {

  static class MyClass {
  }

  public GenericClass(final T[] param) {
    MyClass myObject = new MyClass();                       // OK
    MyClass[] myArray = { new MyClass(), new MyClass() };   
  }
}
class-MyClass{
}
公共泛型类(最终T[]参数){
MyClass[]myArray={new MyClass(),new MyClass()};
}

这是合法的。古怪,有点笨拙,但合法。因为您重新声明了类型,所以它会隐藏外部类型。然后。。。数组和泛型不能混合使用。。。除非使用原始类型。为了向后兼容,您可以使用一个rawtype数组,该数组最后保存
MyClass
。这是一件非常糟糕的事情,但它确实可以编译。在这里,你可以不受创意的影响,但最终。。。只是不要这样做。

这里的问题是编译器无法在编译时确定数组myArray的信息。它被认为是泛型的,因为(如eclipse所示)它是在{new GenericClass.MyClass(),…}中转换的。这是因为您将类MyClass放在泛型类中

此代码也不起作用:

class MyClass<T> {
}

public GenericClass(final T[] param) {
    MyClass[] myArray = { new MyClass(), new MyClass() };  
}
打包我的东西;
公共类泛型类{
类MyClass{
静态MyClass[]myArray={new MyClass(),new MyClass()};;
}
公共泛型类(最终T[]参数){
MyClass myObject=新的MyClass();
}
}
但这个代码是有效的:

package my.stuff;

public class GenericClass<T> {

    class MyClass {
        static MyClass[] myArray = { new MyClass(), new MyClass() };;
    }

    public GenericClass(final T[] param) {
        MyClass myObject = new MyClass();
    }
}
打包我的东西;
公共类泛型类{
公共泛型类(最终T[]参数){
MyClass myObject=新的MyClass();
MyClass[]myArray={new MyClass(),new MyClass()};
}
}
类MyClass{
}
因为您没有在MyClass中使用泛型,所以最好的做法可能是使用第二个泛型

如果将其声明为静态,编译器知道MyClass不是泛型的,并且知道该做什么

此外,在java中创建泛型数组的唯一方法是创建一个原始类型,然后将其转换为泛型(请参见此处:)。因此,如果您确实需要在泛型类中使用myClass,则应在myClass中启用它,然后使用以下技巧:创建原始类型并将其强制转换为myClass:

打包我的东西;
公共类泛型类{
类MyClass{
}
@抑制警告(“未选中”)
公共泛型类(最终T[]参数){
MyClass myObject=新的MyClass();
MyClass[]myArray=新MyClass[]{new MyClass(),new MyClass()};
}
}

即使在MyClass类中也不使用t。

@ItayMan有正确的理由。基本上,
MyClass
不是可修改的类型

MyClass
是一个非静态的内部类。因为它是非静态的,所以它在其封闭类的类型参数的范围内。每次您在
GenericClass
的实例方法中自己编写
MyClass
,它实际上是
GenericClass.MyClass
的缩写。因此,尽管它看起来可能不是这样,
MyClass
(本身)实际上是一个参数化类型(由
T
参数化),类似于
List
。因此,当您执行
newmyclass[2]
时,您试图创建一个参数化类型的数组,就像
newlist[2]
一样。我想你已经知道这是不允许的

你该怎么办?这完全取决于你的意图。人们建议将
MyClass
设置为静态。当然,这将使其退出上海合作组织
class MyClass<T> {
}

public GenericClass(final T[] param) {
    MyClass[] myArray = { new MyClass(), new MyClass() };  
}
package my.stuff;

public class GenericClass<T> {

    class MyClass {
        static MyClass[] myArray = { new MyClass(), new MyClass() };;
    }

    public GenericClass(final T[] param) {
        MyClass myObject = new MyClass();
    }
}
package my.stuff;

public class GenericClass<T> {
    public GenericClass(final T[] param) {
        MyClass myObject = new MyClass();
        MyClass[] myArray = { new MyClass(), new MyClass() };
    }
}

class MyClass {
}
package my.stuff;

public class GenericClass<T> {

    class MyClass<T> {
    }

    @SuppressWarnings("unchecked")
    public GenericClass(final T[] param) {
        MyClass<T> myObject = new MyClass<T>();
        MyClass<T>[] myArray = new MyClass[]{ new MyClass<T>(), new MyClass<T>() };
    }
}