Creating a new array with a class object in GWT

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

I want to say that I would like to emulate functionality

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

What I need for this to happen is that I have a library that sometimes 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 cannot dynamically create a new array from some arbitrary component type.

I am well aware of the lack of GWT reflection; I understand it. However, this is possible even with limited reflection of the GWT. The reason is that in the implementation there is an inaccessible static method for creating a class object for an array.

Likewise, I understand that array methods are simply type protected wrappers around JavaScript arrays and therefore should be easily hacked even if JSNI is required.

In fact, the more important it would be to get an object of the class, I can do without being able to create new arrays.

+4
source share
3 answers

The way I did this was to pass an empty array of length 0 to the constructor of the object that wants to create the array.

 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 cannot directly create a 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 will get your array in the form of fonts (otherwise in your super call (new Baz [0]), it will lead to a compiler error).

0
source

If you like creating the seed array of the right type, you can use jsni along with some super-super-source knowledge to create arrays WITHOUT copying through an ArrayList (I avoid java.util overhead such as a 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 the seed is an array of zero length of the desired type, and the length is the desired length (although in production mode arrays do not have upper bounds, this makes the [] .length field correct).

The com.google.gwt.lang package is a collection of basic utilities used by the compiler for basic emulation, and can be found in gwt-dev! com / google / gwt / dev / jjs / intrinsic / com / google / GWT / languages.

You can use these classes only through jsni calls and only in production gwt code (use 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 exist only in compiled javascript.

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

Note that you will probably need a super-source for the java.lang.reflect.Array class to avoid the gwt compiler error, which assumes that you want to host your own helper method. However, I cannot help you more than this, since it will go beyond the scope of my employment contract.

+4
source

I needed to do something like this, I found that this is possible using the Guava library of the ObjectArrays class . Instead of a class object, a reference to an existing array is required.

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

Source: https://habr.com/ru/post/1339396/


All Articles