Instantiating Generic Arrays

Greetings Earthlings!

So something that has always bothered me is the outrageous things you need to do to instantiate a generic array (perhaps I’m overreacting).

There are two methods presented EVERYWHERE:


public <T> T[] alloc(Class<T> type, int length) {
   return (T[])Array.newInstance(type, length);
}
public <T> T[] alloc(int length) {
   return (T[])new Object[length]; //eww, doesn't always work
}

The first way sucks, you need to pass in the class type, which means whatever you have creating the array a user needs to pass in the class type… unnecessary code I daresay!

The second way sucks as well, doesn’t work for me always, it’s annoying. Especially in this case:


public class Foo<X extends Bar> {
  public X[] bars;
  public Foo(int length) {
    bars = (X[])new Object[length];
  }
}

NOPE, doesn’t work… since X is at least type Bar, you need to do this:


public class Foo<X extends Bar> {
  public X[] bars;
  public Foo(int length) {
    bars = (X[])new Bar[length];
  }
}

Hey that works! Except you still have warnings… I don’t like warnings, hence why I think both of these options suck.

So yesterday an alternative method POPPED in my head… something that is so simple, there’s no casting, nothing ugly…

Somehow I haven’t found ONE website or code example where someone does this, I feel like a god damn explorer (perhaps of the DORA quality).


public class ArrayUtil {
public static <T> T[] alloc(int length, T ... base) {
  return Arrays.copyOf( base, length );
}
}

Boom. It’s simple and can even be used in two different ways:


String[] x = ArrayUtil.alloc(4);
String[] y = ArrayUtil.alloc(4, "first", "second");

You know how much ugly code exists in sooo many common libraries that require you to pass in Class so it can create an array? I say they get rid of that silliness.

What say you?

You are a goddamn genius ClickerMonkey. I’ve always wanted to get rid of those warnings. Here, eat my medal.

EDIT: Blegh Eclipse now gives a new stupid warning on the “T … base”: “Potential heap pollution via varargs parameter data” -___-

Like I’ve always said: type erasure sucks.

I actually like type erasure. Compared to how C# handles generics.

ps: nice hack, have to take a look at it

update:
sry but your new method does not work.

the var args trick don’t work in your Foo example, you will get a cast exception.
so it seems the old casting an array to the anyway erased generic is the best.

I really don’t know why you have a problem with creating a Bar array, it just a simple thing to know.


class Foo<T extends Bar>
{
  Foo()
  {
    T[] a = alloc(2);//throws exception
    T b = null;
    T[] c = alloc(3, b);//will work but is strange
  }
}

[quote=“ra4king,post:2,topic:40967”]
You can get rid of that warning with @SafeVarargs on the alloc method. Requires Java 7+.

Actually it’s the second call that throws a NPE. The first one works fine. I tested the wrong code.

why should it throw a NPE, it will just create “new T[]{null}”, I’m running java7 btw.

here the test app I use:
http://pastebin.com/WQNJmi2e

which gives me the following results:

test1 fail
test2 win

when you remove “extends Number” both methods work.

ps: I still think casting an array of the generic base class is just the easiest, shortest and performant option

Dynamic languages at run time do not need templates. Everything is an Object. Templates for Dynamic languages are for noobs.

[quote=“Danny02,post:6,topic:40967”]
Sorry about that, I used T[] b (instead of T b) when I tested.

Indeed, the first test fails on JDK 7, but works fine on JDK 8. Will try to find if there’s been a bugfix in 8 related to that.

Edit: Seems like a javac fix. Compilation output for test1:

// JDK 7
Number[] a = (Number[])alloc(3, new Object[0]);
// JDK 8
Number[] a = (Number[])alloc(3, new Number[0]);

seems like the java 7 type inference can’t decide on the type.

did some more tests, when one removes the static from the “alloc” method and replaces the method generic with the class generic everything works.

It’s fine if you’re not using it for anything beyond AOT type checking…beyond that: it sucks.

What is the benefit of type erasure? Would someone designing a language from scratch decide to include it? I thought it was just a hack to maintain backwards compatibility.

Machine code does not need types. Everything is a byte. Type declarations and variable declarations are for noobs.

Machine code is strictly typed. The base types are unions, but it still typed. From a certain point of view what you’re saying isn’t incorrect, but by the same kind of logic C is the ultimate language.

I am aware of the technical correctness but logical absurdity. :slight_smile: (Technically I said type declarations and I would argue the definition of type.) I do not agree that assembly or dynamic languages or C take away the need of certain language features.

Dynamic languages and assembly language share something in common. They are perfectly fine if you develop code by entering one key at a time from start to finish with no breaks and no mistakes, but if you ever want to rewrite portions of the program, port it to a different platform, incorporate another person’s code, or happen to be a mortal, then their practical utility is greatly diminished.