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

发布于 2024-10-17 01:26:34 字数 702 浏览 7 评论 0原文

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

我的意思是我想模拟的功能

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

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

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

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

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

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

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

I would like to create a new array with a given type from a class object in GWT.

What I mean is I would like to emulate the functionality of

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

The reason I need this to occur is that I have a library which occasionally needs to do the following:

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

This works if I pass it an array class normally, but I can't dynamically create a new array from some arbitrary component type.

I am well aware of GWT's lack of reflection; I understand this. However, this seems feasible even given GWT's limited reflection. The reason I believe this is that in the implementation, there exists an inaccessible static method for creating a class object for an array.

Similarly, I understand the array methods to just be type-safe wrappers around JavaScript arrays, and so should be easily hackable, even if JSNI is required.

In reality, the more important thing would be getting the class object, I can work around not being able to make new arrays.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

鲜肉鲜肉永远不皱 2024-10-24 01:26:34

如果您喜欢创建正确类型的种子数组,则可以使用 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 编译器错误,这表明您需要将本机帮助器方法放在那里。但是,我无法为您提供更多帮助,因为这超出了我的工作合同的范围。

If you are cool with creating a seed array of the correct type, you can use jsni along with some knowledge of super-super-source to create arrays WITHOUT copying through ArrayList (I avoid java.util overhead like the plague):

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

Where seed is a zero-length array of the correct type you want, and length is the length you want (although, in production mode, arrays don't really have upper bounds, it makes the [].length field work correctly).

The com.google.gwt.lang package is a set of core utilities used in the compiler for base emulation, and can be found in gwt-dev!com/google/gwt/dev/jjs/intrinsic/com/google/gwt/lang.

You can only use these classes through jsni calls, and only in production gwt code (use if GWT.isProdMode()). In general, if you only access the com.google.gwt.lang classes in super-source code, you are guaranteed to never leak references to classes that only exist in compiled javascript.

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

Note, you'll probably need to super-source the java.lang.reflect.Array class to avoid gwt compiler error, which suggests you'll want to put your native helper method there. However, I can't help you more than this, as it would overstep the bounds of my work contract.

好久不见√ 2024-10-24 01:26:34

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

public class Foo extends Bar<Baz> {

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

Baz:

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

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

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

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

// add the items you want etc

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

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

The way that I did a similar thing was to pass an empty, 0 length array to the constructor of the object that will want to create the array from.

public class Foo extends Bar<Baz> {

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

Baz:

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

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

In this case the Bar class can't directly create new T[10], but we can do this:

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

// add the items you want etc

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

And you get your array in a typesafe way (otherwise in your call super(new Baz[0]); will cause a compiler error).

七婞 2024-10-24 01:26:34

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

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

I had to do something similar, I found it was possible using the Guava library's ObjectArrays class. Instead of the class object it requires a reference to an existing array.

T[] newArray = ObjectArrays.newArray(oldArray, oldArray.length);
乙白 2024-10-24 01:26:34

为了实现数组串联方法,我还遇到了缺少 Array.newInstance-method 的问题。

它尚未实现,但如果您有现有的数组,则可以使用

Arrays.copyOf(T[] original, int newLength)

它。

For implementing an array concatenation method, I also stepped into the issue of missing Array.newInstance-method.

It's still not implemented, but if you have an existing array you can use

Arrays.copyOf(T[] original, int newLength)

instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文