如何在Java中创建通用数组?


1090

由于Java泛型的实现,因此不能有以下代码:

public class GenSet<E> {
    private E a[];

    public GenSet() {
        a = new E[INITIAL_ARRAY_LENGTH]; // error: generic array creation
    }
}

如何在保持类型安全的同时实现此目的?

我在Java论坛上看到了这样的解决方案:

import java.lang.reflect.Array;

class Stack<T> {
    public Stack(Class<T> clazz, int capacity) {
        array = (T[])Array.newInstance(clazz, capacity);
    }

    private final T[] array;
}

但是我真的不知道发生了什么。


14
您真的需要在这里使用数组吗?怎么样使用一个集合?
马特b

12
是的,我也认为对于这个问题而言,收藏更为优雅。但这是针对班级任务的,它们是必需的:(
tatsuhirosatou

3
我不明白为什么在这里需要反思。Java语法很奇怪:像新的java.util.HashMap <String,String> [10]无效。新的java.util.HashMap <long,long>(10)无效。new long [] [10]无效,new long [10] []有效。这些东西使编写可以编写Java程序的程序变得更加困难。
青铜人

Answers:


703

我必须问一个问题:您的GenSet“已选中”还是“未选中”?这意味着什么?

  • 检查强打字GenSet明确地知道什么类型的包含对象(即它的构造是明确要求有Class<E>参数,当他们通过了类型不是参数的方法会抛出异常E。见Collections.checkedCollection

    ->在这种情况下,您应该写:

    public class GenSet<E> {
    
        private E[] a;
    
        public GenSet(Class<E> c, int s) {
            // Use Array native method to create array
            // of a type only known at run time
            @SuppressWarnings("unchecked")
            final E[] a = (E[]) Array.newInstance(c, s);
            this.a = a;
        }
    
        E get(int i) {
            return a[i];
        }
    }
  • 未选中键入较弱。实际上,不会对作为参数传递的任何对象执行类型检查。

    ->在这种情况下,您应该写

    public class GenSet<E> {
    
        private Object[] a;
    
        public GenSet(int s) {
            a = new Object[s];
        }
    
        E get(int i) {
            @SuppressWarnings("unchecked")
            final E e = (E) a[i];
            return e;
        }
    }

    请注意,数组的组件类型应为type参数的擦除

    public class GenSet<E extends Foo> { // E has an upper bound of Foo
    
        private Foo[] a; // E erases to Foo, so use Foo[]
    
        public GenSet(int s) {
            a = new Foo[s];
        }
    
        ...
    }

所有这些都是由Java中已知的,有意的泛型弱点导致的:它是使用擦除实现的,因此“泛型”类不知道它们在运行时使用什么类型参数创建,因此无法提供类型-安全,除非实施了一些明确的机制(类型检查)。


7
性能方面的最佳选择是什么?我需要经常(在循环内)从此数组中获取元素。因此收集可能较慢,但是这两个中哪一个最快?
user1111929'9

3
如果泛型类型是有界的,则后备数组应为有界类型。
Mordechai

5
@AaronDigulla只是为了说明这不是赋值,而是局部变量的初始化。您不能注释表达式/语句。
kennytm

1
@Varkhan是否可以从类实现中调整这些数组的大小。例如,如果我想在溢出后像ArrayList一样调整大小。我查找了它们Object[] EMPTY_ELEMENTDATA = {}用于存储的ArrayList的实现。是否可以在不使用泛型知道类型的情况下使用此机制来调整大小?
JourneyMan 2014年

2
对于那些想要使用泛型类型(这正是我所寻找的)的方法,请使用以下方法:public void <T> T[] newArray(Class<T> type, int length) { ... }
Daniel Kvist

225

你可以这样做:

E[] arr = (E[])new Object[INITIAL_ARRAY_LENGTH];

这是在有效Java中实现通用集合的建议方法之一项目26。没有类型错误,无需重复转换数组。 但是,这会触发警告,因为它有潜在危险,应谨慎使用。如评论中所述,这Object[]现在伪装成我们的E[]类型,ClassCastException如果使用不安全,可能会导致意外错误或s。

根据经验,这种行为是安全的,只要在内部使用强制转换数组(例如,支持数据结构),并且不将其返回或暴露给客户端代码即可。如果您需要将泛型类型的数组返回给其他代码,则Array提到的反射类是正确的方法。


值得一提的是,List如果使用泛型,那么在可能的情况下,与s而不是数组一起工作的时间会更快乐。当然,有时候您别无选择,但是使用collections框架要健壮得多。


47
如果将数组视为任何类型的类型化数组(例如String[] s=b;上述test()方法),则此方法将无效。那是因为E的数组不是真的,而是Object []。这一点很重要,例如,如果List<String>[]-不能使用- Object[],则必须List[]专门指定。这就是为什么需要使用反映的Class <?>数组创建的原因。
劳伦斯·多尔

8
极端情况/问题是是否要执行操作,例如,public E[] toArray() { return (E[])internalArray.clone(); }何时internalArray将键入为E[],因此实际上是Object[]。这在运行时因类型转换异常而失败,因为Object[]不能将a分配给E恰好是任何类型的数组。
劳伦斯·多尔

17
基本上,只要您不返回数组,不传递数组或将其存储在需要某种类型数组的类之外的某个位置,该方法就可以使用。只要您在班上,就可以了,因为E被删除了。这是“危险的”,因为如果您尝试将其退还,则不会收到任何警告,表明它不安全。但是,如果您小心一点,它将起作用。
newacct 2011年

3
很安全 在E[] b = (E[])new Object[1];你可以清楚地看到,在创建数组的唯一引用b和类型bE[]。因此,不存在通过不同类型的不同变量意外访问同一数组的危险。如果相反,Object[] a = new Object[1]; E[]b = (E[])a; 那么您将对使用方法抱有偏执a
亚伦·麦克戴德

5
至少在Java 1.6中,这会产生一个警告:“未经检查从Object []到T []的转换”
Quantum7 2012年

61

这是在保留类型安全性的同时,使用泛型获取与您正在寻找的类型完全相同的数组的方法(与其他答案相反,其他答案将为您提供Object数组或在编译时产生警告):

import java.lang.reflect.Array;  

public class GenSet<E> {  
    private E[] a;  

    public GenSet(Class<E[]> clazz, int length) {  
        a = clazz.cast(Array.newInstance(clazz.getComponentType(), length));  
    }  

    public static void main(String[] args) {  
        GenSet<String> foo = new GenSet<String>(String[].class, 1);  
        String[] bar = foo.a;  
        foo.a[0] = "xyzzy";  
        String baz = foo.a[0];  
    }  
}

可以在没有警告的情况下进行编译,正如您在中看到的那样main,对于声明GenSetas 实例的任何类型,都可以将其分配a给该类型的数组,并且可以将元素从分配给a该类型的变量,这意味着该数组并且数组中的值是正确的类型。

Java教程中所述,它通过将类文字用作运行时类型标记来工作。类文字被编译器视为的实例java.lang.Class。要使用一个,只需在类名后面加上即可.class。因此,String.class充当Class表示class 的对象String。这也适用于接口,枚举,任意维数组(例如String[].class),基元(例如int.class)和关键字void(例如void.class)。

Class本身是通用的(声明为Class<T>,其中T代表Class对象表示的类型),表示的类型String.classClass<String>

因此,每当您为调用构造函数时GenSet,您都将为第一个参数传入一个类常量,以表示GenSet实例的声明类型的数组(例如,String[].class针对GenSet<String>)。请注意,您将无法获得基元数组,因为基元不能用于类型变量。

在构造函数内部,调用方法cast将传递的Object参数转换为由调用该方法的Class对象表示的类。调用静态方法newInstancejava.lang.reflect.Array返回作为Object由所表示的类型的数组Class作为第一个参数,并通过指定的长度的传递的对象int通过作为第二个参数。调用该方法getComponentType将返回一个Class对象,该对象表示该方法所调用的对象所代表的数组的组件类型Class(例如,String.class对于String[].classnull如果该Class对象不代表数组)。

最后一句话并不完全正确。调用String[].class.getComponentType()返回Class代表该类的对象String,但其类型为Class<?>,而不是Class<String>,这就是为什么您不能执行以下操作的原因。

String foo = String[].class.getComponentType().cast("bar"); // won't compile

Class返回Class对象的每个方法都一样。

关于Joachim Sauer对这个答案的评论(我自己对此没有足够的评价),使用强制转换为的示例T[]将导致警告,因为在这种情况下编译器不能保证类型安全。


编辑有关Ingo的评论:

public static <T> T[] newArray(Class<T[]> type, int size) {
   return type.cast(Array.newInstance(type.getComponentType(), size));
}

5
这是没有用的,它只是编写新String [...]的一种复杂方法。但是真正需要的是公共静态<T> T [] newArray(int size){...}之类的东西,而在java noir中根本不存在,可以通过反射进行模拟-原因是有关如何实例化的泛型类型在运行时不可用。
Ingo

4
@Ingo您在说什么?我的代码可用于创建任何类型的数组。
gdejohn 2011年

3
@Charlatan:当然可以,但是new []也可以。问题是:谁知道类型和时间。因此,如果您拥有的只是一个通用类型,那么您就不可能。
Ingo

2
我毫不怀疑。关键是,您不会在运行时获得泛型类型X的Class对象
。– Ingo

2
几乎。我承认这不仅仅是用new []可以实现的。实际上,这几乎总是可以做的。但是,例如,仍然不可能编写用E参数化的容器类,该容器类具有方法E [] toArray()并确实返回真实的E []数组。仅当集合中至少有一个E对象时,才可以应用您的代码。因此,一般的解决方案是不可能的。
Ingo

42

这是唯一类型安全的答案

E[] a;

a = newArray(size);

@SafeVarargs
static <E> E[] newArray(int length, E... array)
{
    return Arrays.copyOf(array, length);
}

我必须查找它,但是,是的,第二个“长度”参数Arrays#copyOf()独立于作为第一个参数提供的数组的长度。这很聪明,尽管它确实支付了对Math#min()和的调用费用System#arrayCopy(),但两者都不是完成这项工作所必需的。docs.oracle.com/javase/7/docs/api/java/util / ...
seh

8
如果E类型变量不起作用。varargs创建了一个擦除Ewhen 数组,该数组E是type变量,使其与并无太大区别(E[])new Object[n]。请参阅http://ideone.com/T8xF91。这绝不是多种类型的安全比任何其他的答案。
Radiodef

1
@Radiodef-该解决方案在编译时证明是类型安全的。请注意,擦除并不完全是语言规范的一部分;仔细编写该规范,以便我们将来可以进行全面修订-然后,该解决方案也将在运行时完美运行,这与其他解决方案不同。
羽2015年

@Radiodef-禁止创建通用数组是否是一个好主意,尚有争议。无论如何,语言确实会留下后门-vararg需要创建通用数组。就像语言允许一样好new E[]。您在示例中显示的问题是一个一般的擦除问题,并非该问题和此答案独有。
羽2015年

2
@Radiodef-有一些区别。该解决方案的正确性由编译器检查。它不依赖于人为推论的推理。对于此特定问题,差异并不明显。有些人只是想花点时间,仅此而已。如果有人被OP的措辞所误导,则可以通过您的评论和我的意见加以澄清。
羽2015年

33

要扩展更多维度,只需将[]的和维度参数添加到newInstance()T是类型参数,clsClass<T>d1通过d5整数):

T[] array = (T[])Array.newInstance(cls, d1);
T[][] array = (T[][])Array.newInstance(cls, d1, d2);
T[][][] array = (T[][][])Array.newInstance(cls, d1, d2, d3);
T[][][][] array = (T[][][][])Array.newInstance(cls, d1, d2, d3, d4);
T[][][][][] array = (T[][][][][])Array.newInstance(cls, d1, d2, d3, d4, d5);

有关Array.newInstance()详细信息,请参见。


4
+1关于多维数组创建的问题由于这篇文章的重复而被关闭-但没有专门的答案可以解决。
Paul Bellora

1
@JordanC也许; 尽管其精神与stackoverflow.com/a/5671304/616460相同; 我将考虑明天最好的处理方式。我很困
杰森C

14

在Java 8中,我们可以使用lambda或方法引用进行一种通用数组创建。这类似于反射方法(传递a Class),但是这里我们不使用反射。

@FunctionalInterface
interface ArraySupplier<E> {
    E[] get(int length);
}

class GenericSet<E> {
    private final ArraySupplier<E> supplier;
    private E[] array;

    GenericSet(ArraySupplier<E> supplier) {
        this.supplier = supplier;
        this.array    = supplier.get(10);
    }

    public static void main(String[] args) {
        GenericSet<String> ofString =
            new GenericSet<>(String[]::new);
        GenericSet<Double> ofDouble =
            new GenericSet<>(Double[]::new);
    }
}

例如,<A> A[] Stream.toArray(IntFunction<A[]>)

可能也可以使用匿名类做预先的Java 8,但它更繁琐。


您实际上不需要这样的特殊接口ArraySupplier,您可以将构造函数声明为GenSet(Supplier<E[]> supplier) { ...,并在与您相同的行中对其进行调用。
Lii 2015年

4
@Lii与我的示例相同,它将是IntFunction<E[]>,但是是的。
Radiodef

11

这是覆盖在第5章(泛型)有效的Java,第二版,第25项...... 不想名单阵列

您的代码可以运行,尽管它会生成未经检查的警告(您可以使用以下注释将其取消:

@SuppressWarnings({"unchecked"})

但是,最好使用List而不是Array。

OpenJDK项目站点上对此错误/功能进行有趣的讨论。


8

您无需将Class参数传递给构造函数。尝试这个。

public class GenSet<T> {
    private final T[] array;
    @SuppressWarnings("unchecked")
    public GenSet(int capacity, T... dummy) {
        if (dummy.length > 0)
            throw new IllegalArgumentException(
              "Do not provide values for dummy argument.");
        Class<?> c = dummy.getClass().getComponentType();
        array = (T[])Array.newInstance(c, capacity);
    }
    @Override
    public String toString() {
        return "GenSet of " + array.getClass().getComponentType().getName()
            + "[" + array.length + "]";
    }
}

GenSet<Integer> intSet = new GenSet<>(3);
System.out.println(intSet);
System.out.println(new GenSet<String>(2));

结果:

GenSet of java.lang.Integer[3]
GenSet of java.lang.String[2]

7

Java泛型通过在编译时检查类型并插入适当的强制转换来工作,但会擦除已编译文件中的类型。这使得泛型库可以通过不理解泛型的代码使用(这是一个有意的设计决策),但是这意味着您通常无法在运行时找出类型。

公共Stack(Class<T> clazz,int capacity)构造函数需要你通过在运行时类对象,这意味着类信息可在运行时需要它的代码。这种Class<T>形式意味着编译器将检查您传递的Class对象是否恰好是类型T的Class对象。不是T的子类,不是T的超类,而是T。

然后,这意味着您可以在构造函数中创建适当类型的数组对象,这意味着您存储在集合中的对象的类型将在添加到集合时进行类型检查。


6

嗨,尽管线程已死,但我想提请您注意:

泛型用于在编译期间进行类型检查:

  • 因此,目的是检查所需要的东西。
  • 您所返回的就是消费者的需求。
  • 检查一下:

在此处输入图片说明

在编写泛型类时,不必担心类型转换警告。使用时担心。


6

那这个解决方案呢?

@SafeVarargs
public static <T> T[] toGenericArray(T ... elems) {
    return elems;
}

它的工作原理和看起来太简单,难以置信。有什么缺点吗?


3
整洁,但仅当您“手动”调用即单独传递元素时才有效。如果您无法创建的新实例T[],则无法以编程方式构建一个T[] elems传递给函数。而且,如果可以,则不需要该功能。
Orlade

5

还要看这段代码:

public static <T> T[] toArray(final List<T> obj) {
    if (obj == null || obj.isEmpty()) {
        return null;
    }
    final T t = obj.get(0);
    final T[] res = (T[]) Array.newInstance(t.getClass(), obj.size());
    for (int i = 0; i < obj.size(); i++) {
        res[i] = obj.get(i);
    }
    return res;
}

它将任何类型的对象的列表转换为相同类型的数组。


是的,您返回null,这不是预期的空数组。这是您可以做的最好的事情,但并不理想。
凯文·考克斯

如果其中List包含不止一种类型的对象(例如toArray(Arrays.asList("abc", new Object()))将抛出),这也会失败ArrayStoreException
Radiodef

我用的是精简版。我能够使用的第一件事是有效的,尽管坦白地说我没有尝试一些更复杂的解决方案。为了避免for循环和其他循环,我使用Arrays.fill(res, obj);了每个循环,因为我希望每个索引都具有相同的值。
bbarker

5

我找到了一种对我有用的快速简便的方法。请注意,我仅在Java JDK 8上使用过此功能。我不知道它是否可与以前的版本一起使用。

尽管我们无法实例化特定类型参数的泛型数组,但是我们可以将已经创建的数组传递给泛型类构造函数。

class GenArray <T> {
    private T theArray[]; // reference array

    // ...

    GenArray(T[] arr) {
        theArray = arr;
    }

    // Do whatever with the array...
}

现在主要可以像下面这样创建数组:

class GenArrayDemo {
    public static void main(String[] args) {
        int size = 10; // array size
        // Here we can instantiate the array of the type we want, say Character (no primitive types allowed in generics)
        Character[] ar = new Character[size];

        GenArray<Character> = new Character<>(ar); // create the generic Array

        // ...

    }
}

为了使阵列具有更大的灵活性,您可以使用链表。ArrayList和其他在Java.util.ArrayList类中找到的方法。


4

该示例使用Java反射创建数组。通常不建议这样做,因为它不是类型安全的。相反,您应该做的只是使用内部List,而完全避免使用数组。


13
第二个例子(使用Array.newInstance())实际上类型安全。这是可能的,因为Class对象的类型T需要与数组的T相匹配。基本上,它迫使您提供Java运行时为泛型丢弃的信息。
约阿希姆·绍尔


3

我编写了此代码段,以反射方式实例化为简单的自动化测试实用程序传递的类。

Object attributeValue = null;
try {
    if(clazz.isArray()){
        Class<?> arrayType = clazz.getComponentType();
        attributeValue = Array.newInstance(arrayType, 0);
    }
    else if(!clazz.isInterface()){
        attributeValue = BeanUtils.instantiateClass(clazz);
    }
} catch (Exception e) {
    logger.debug("Cannot instanciate \"{}\"", new Object[]{clazz});
}

请注意以下部分:

    if(clazz.isArray()){
        Class<?> arrayType = clazz.getComponentType();
        attributeValue = Array.newInstance(arrayType, 0);
    }

用于数组初始化,其中Array.newInstance(array的类,array的大小)。类可以是原始(int.class)和对象(Integer.class)。

BeanUtils是Spring的一部分。


3

实际上,更简单的方法是创建对象数组并将其转换为所需的类型,如以下示例所示:

T[] array = (T[])new Object[SIZE];

其中SIZE是常量,T是类型标识符


1

其他人建议的强制演员表对我没有用,这是非法演员表的例外。

但是,此隐式强制转换效果很好:

Item<K>[] array = new Item[SIZE];

其中Item是我定义的包含成员的类:

private K value;

这样,您将获得类型为K(如果项目仅具有值)或想要在类Item中定义的任何通用类型的数组。


1

没有人回答您发布的示例中发生了什么的问题。

import java.lang.reflect.Array;

class Stack<T> {
    public Stack(Class<T> clazz, int capacity) {
        array = (T[])Array.newInstance(clazz, capacity);
    }

    private final T[] array;
}

正如其他人所说,泛型在编译过程中被“擦除”。因此,在运行时,泛型实例不知道其组件类型是什么。原因是历史悠久的,Sun希望在不破坏现有接口(源接口和二进制接口)的情况下添加泛型。

另一方面,数组在运行时确实知道其组件类型。

本示例通过使调用构造函数(确实知道类型)的代码传递一个告诉类所需的类型的参数来解决该问题。

因此,应用程序将使用类似

Stack<foo> = new Stack<foo>(foo.class,50)

现在,构造函数(在运行时)知道了组件类型是什么,并且可以使用该信息通过反射API构造数组。

Array.newInstance(clazz, capacity);

最后,我们进行了类型转换,因为编译器无法知道by返回的数组Array#newInstance()是正确的类型(即使我们知道)。

这种样式有点丑陋,但是对于创建泛型类型有时是最坏的解决方案,该泛型类型无论出于何种原因(在创建数组或创建其组件类型的实例等)都需要在运行时知道其组件类型。


1

我找到了解决该问题的方法。

下面的行引发通用数组创建错误

List<Person>[] personLists=new ArrayList<Person>()[10];

但是,如果我将其封装List<Person>在单独的类中,则它可以工作。

import java.util.ArrayList;
import java.util.List;


public class PersonList {

    List<Person> people;

    public PersonList()
    {
        people=new ArrayList<Person>();
    }
}

您可以通过getter公开PersonList类中的人员。下面的行将为您提供一个数组,List<Person>每个元素中都有一个。换句话说,的数组List<Person>

PersonList[] personLists=new PersonList[10];

在我正在处理的某些代码中,我需要这样的东西,而这就是我使它起作用的全部工作。到目前为止没有问题。


0

您可以创建一个Object数组并将其强制转换为E。是的,这样做不是很干净,但至少应该可以。


“我们正在寻找能提供一些解释和上下文的长答案。不要仅仅给出一个答案,而是要解释为什么您的答案正确,最好是带有引文。没有解释的答案可以删除。”
gparyani 2014年

在某些情况下,例如通用类想要实现Comparable接口的BUt将无法工作。
RamPrasadBismil '16

我想,欢迎来到七年前。
Esko

1
如果您尝试将数组从通用代码返回到非通用调用者,则将无法使用。将有一个令人头疼的classcastexception。
plugwash

0

尝试这个。

private int m = 0;
private int n = 0;
private Element<T>[][] elements = null;

public MatrixData(int m, int n)
{
    this.m = m;
    this.n = n;

    this.elements = new Element[m][n];
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
        {
            this.elements[i][j] = new Element<T>();
        }
    }
}

我无法运行您的代码,您的Element课程来自哪里?

0

一个简单但杂乱的解决方法是在主类中嵌套第二个“ holder”类,并使用它来保存数据。

public class Whatever<Thing>{
    private class Holder<OtherThing>{
        OtherThing thing;
    }
    public Holder<Thing>[] arrayOfHolders = new Holder<Thing>[10]
}

3
这实际上是行不通的。new Holder<Thing>[10]是通用数组创建。
Radiodef 2014年

0

也许与这个问题无关,但是当我遇到generic array creation使用错误

Tuple<Long,String>[] tupleArray = new Tuple<Long,String>[10];

我发现以下作品(并为我工作) @SuppressWarnings({"unchecked"})

 Tuple<Long, String>[] tupleArray = new Tuple[10];

是的,这不是很相关,但是植根于相同的问题(擦除,数组协方差)。这里有一个关于创建参数化类型的数组后的一个例子:stackoverflow.com/questions/9542076/...
保罗Bellora

0

我想知道这段代码是否会创建有效的通用数组?

public T [] createArray(int desiredSize){
    ArrayList<T> builder = new ArrayList<T>();
    for(int x=0;x<desiredSize;x++){
        builder.add(null);
    }
    return builder.toArray(zeroArray());
}

//zeroArray should, in theory, create a zero-sized array of T
//when it is not given any parameters.

private T [] zeroArray(T... i){
    return i;
}

编辑:如果知道所需的大小并且很小,也许创建这种数组的另一种方法是将所需数量的“ null”简单地输入到zeroArray命令中?

虽然显然这不像使用createArray代码那样通用。


不,这不起作用。varargs会抹除Twhen T是类型变量,即zeroArray返回Object[]。参见http://ideone.com/T8xF91
Radiodef

0

您可以使用强制转换:

public class GenSet<Item> {
    private Item[] a;

    public GenSet(int s) {
        a = (Item[]) new Object[s];
    }
}

如果要提出这个建议,您确实需要解释其局限性。切勿暴露a在课堂之外!
Radiodef 2015年

0

实际上,我找到了一个非常独特的解决方案来绕过无法启动通用数组的问题。您要做的是创建一个接受通用变量T的类,如下所示:

class GenericInvoker <T> {
    T variable;
    public GenericInvoker(T variable){
        this.variable = variable;
    }
}

然后在您的数组类中让它像这样开始:

GenericInvoker<T>[] array;
public MyArray(){
    array = new GenericInvoker[];
}

开始new Generic Invoker[]会导致未经检查的问题,但实际上应该没有任何问题。

要从数组中获取数据,您应该像这样调用array [i] .variable:

public T get(int index){
    return array[index].variable;
}

其余的操作(如调整数组的大小)可以使用Arrays.copyOf()来完成,如下所示:

public void resize(int newSize){
    array = Arrays.copyOf(array, newSize);
}

可以像这样添加add函数:

public boolean add(T element){
    // the variable size below is equal to how many times the add function has been called 
    // and is used to keep track of where to put the next variable in the array
    arrays[size] = new GenericInvoker(element);
    size++;
}

1
问题是关于创建通用类型参数类型T的数组,而不是某些参数化类型的数组。
Sotirios Delimanolis

它完成了相同的任务,并且不需要您上课就可以使自定义集合更易于使用。
蟹状星云

什么任务?从字面上看,这是一项不同的任务:参数化类型的数组与通用类型参数的数组。
Sotirios Delimanolis

它允许您从泛型类型创建数组吗?最初的问题是使用泛型类型初始化数组,使用我的方法可以使您不必让用户压入类或产生未经检查的错误(例如尝试将Object强制转换为String)而进行操作。像寒意一样,我也不是最擅长的工作,我还没有去上编程学校,但我认为我仍然应该得到一点投入,而不是被互联网上的其他孩子嘲笑。
蟹状星云

我同意Sotiros。有两种思考答案的方法。要么是对其他问题的答案,要么是对问题的概括。两者都是错误的/没有帮助。正在寻求有关如何实现“通用数组”类的指导的人员将/在阅读问题标题时停止阅读。当他们找到一个有30个答案的Q时,他们极不可能滚动到末尾并从SO新手那里读零票答案。
斯蒂芬·C

0

根据vnportnoy的语法

GenSet<Integer> intSet[] = new GenSet[3];

创建一个空引用数组,将其填充为

for (int i = 0; i < 3; i++)
{
   intSet[i] = new GenSet<Integer>();
}

这是类型安全的。


-1
private E a[];
private int size;

public GenSet(int elem)
{
    size = elem;
    a = (E[]) new E[size];
}

您应该始终在代码中添加解释,并解释为什么它可以解决原始发布的问题。
mjuarez 2015年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.