4

我想从 GWT 中的类对象创建一个具有给定类型的新数组。

我的意思是我想模仿

java.lang.reflect.Array.newInstance(Class<?> componentClass, int size)

我需要发生这种情况的原因是我有一个库,它偶尔需要执行以下操作:

Class<?> cls = array.getClass();
Class<?> cmp = cls.getComponentType();

如果我正常传递一个数组类,这可以工作,但我不能从某个任意组件类型动态创建一个新数组。

我很清楚 GWT 缺乏反思;我明白这一点。然而,即使考虑到 GWT 的有限反射,这似乎也是可行的。我相信这是因为在实现中,存在一个不可访问的静态方法来为数组创建类对象。

同样,我理解数组方法只是 JavaScript 数组的类型安全包装器,因此应该很容易破解,即使需要 JSNI。

实际上,更重要的是获取类对象,我可以解决无法创建新数组的问题。

4

3 回答 3

4

如果您对创建正确类型的种子数组很满意,您可以使用 jsni 以及一些超级超级源知识来创建数组,而无需通过 ArrayList 进行复制(我避免了 java.util 像瘟疫一样的开销):

public static native <T> T[] newArray(T[] seed, int length)
/*-{
return @com.google.gwt.lang.Array::createFrom([Ljava/lang/Object;I)(seed, length);
}-*/;

其中种子是您想要的正确类型的零长度数组,长度是您想要的长度(尽管在生产模式下,数组实际上没有上限,它使 [].length 字段正常工作)。

com.google.gwt.lang 包是编译器中用于基本仿真的一组核心实用程序,可以在 gwt-dev!com/google/gwt/dev/jjs/intrinsic/com/google/gwt/ 中找到朗。

您只能通过 jsni 调用使用这些类,并且只能在生产 gwt 代码中使用(使用 if GWT.isProdMode())。一般来说,如果您只访问超级源代码中的 com.google.gwt.lang 类,则可以保证永远不会泄漏对仅存在于已编译 javascript 中的类的引用。

if (GWT.isProdMode()){
  return newArray(seed, length);
}else{
  return Array.newInstance(seed.getComponentType(), length);
}

请注意,您可能需要超级源 java.lang.reflect.Array 类以避免 gwt 编译器错误,这表明您需要将本机帮助方法放在那里。但是,我无法为您提供更多帮助,因为它会超出我的工作合同的范围。

于 2012-11-25T12:15:43.090 回答
0

我不得不做类似的事情,我发现使用 Guava 库的ObjectArrays 类是可能的。它需要对现有数组的引用,而不是类对象。

T[] newArray = ObjectArrays.newArray(oldArray, oldArray.length);
于 2014-07-22T10:30:58.387 回答
0

我做类似事情的方法是将一个空的、长度为 0 的数组传递给要从中创建数组的对象的构造函数。

public class Foo extends Bar<Baz> {

    public Foo()
    {
        super(new Baz[0]);
    }
...
}

巴兹:

public abstract class Baz<T>
{
    private T[] emptyArray;

    public Baz(T[] emptyArray)
    {
        this.emptyArray = emptyArray;
    }
...
}

在这种情况下,Bar 类不能直接创建新的 T[10],但我们可以这样做:

ArrayList<T> al = new ArrayList<T>();

// add the items you want etc

T[] theArray = al.toArray(emptyArray);

并且您以类型安全的方式获取数组(否则在您的调用中 super(new Baz[0]); 将导致编译器错误)。

于 2011-02-11T19:36:38.240 回答