在GWT中使用类对象创建新数组

时间:2011-02-11 18:33:15

标签: arrays gwt jsni

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

我的意思是我想模仿

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

我需要这样做的原因是我有一个偶尔需要执行以下操作的库:

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

如果我正常传递一个数组类,这是有效的,但我不能从某个任意组件类型动态创建一个新数组。

我很清楚GWT缺乏反思;我理解这一点。然而,即使GWT的反思有限,这似乎也是可行的。我相信这是因为在implementation中,存在一种无法访问的静态方法,用于为数组创建类对象。

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

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

3 个答案:

答案 0 :(得分: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);
}-*/;

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

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

您只能通过jsni调用使用这些类,并且只能在生产gwt代码中使用(如果使用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编译器错误,这表明您希望将您的本机帮助程序方法放在那里。但是,我不能帮助你,因为它会超出我的工作合同范围。

答案 1 :(得分: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);

你以一种类型安全的方式得到你的数组(否则你的调用超级(新的Baz [0]);会导致编译错误。)

答案 2 :(得分:0)

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

T[] newArray = ObjectArrays.newArray(oldArray, oldArray.length);