4

Now, I've seen many similar questions to this or this before and I understand the answer is "because of erasure". But I don't understand why erasure prevents us creating an array of generics.

As far as I understand; arrays represent a contiguous allocation of memory, containing primitives or references to objects. Unless I'm mistaken, java arrays are little more than C/C++ arrays with a bit of fancy dressing around them. Is this correct?

If so, why does erasure prevent an array being created like this for generic types? Aren't all references the same size, regardless of the type of the class? The class of course would be bigger or smaller, but that shouldn't affect the reference. So wouldn't we know exactly how big the array should be?

Or is it technically possible to do, but some other problem is encountered if we allow generic arrays to be created?


To be clear: I understand what erasure is and how it works. I understand how I can create an array, given the above restrictions. I don't want to do this.

I just want to understand for what reason the type information is required when I create an array.

Community
  • 1
  • 1
Micheal Hill
  • 1,570
  • 2
  • 16
  • 33
  • It is possible to create a generic array, only the Java compiler will not know it is an array of a that generic type anymore. – Willem Van Onsem May 27 '15 at 03:13
  • Why: because "erasure" means the type is erased, so it's not available at runtime. – markspace May 27 '15 at 03:35
  • see http://stackoverflow.com/questions/2927391/whats-the-reason-i-cant-create-generic-array-types-in-java – ZhongYu May 27 '15 at 03:43
  • I understand what "erasure" means. I'm asking why is the type information important in this situation? What does it provide, that I can't do without when I create an array? – Micheal Hill May 27 '15 at 05:05
  • 2
    java associate component type with an array object. so a `String[]` object is associate with `String.class`. why? because covariance. why? well... I like how @raxod502 puts it - "the whole thing is rather a comedy of errors in the Java design" http://stackoverflow.com/a/2927415/2158288 – ZhongYu May 27 '15 at 05:32
  • @bayou.io Thanks! That's exactly what I was looking for. I had seen that question, but hadn't read all of the answers in detail (mistakenly thinking that the relevant ones would have been upvoted to the top). – Micheal Hill May 27 '15 at 07:13

2 Answers2

0

You are mistaken. Arrays in Java have type information encoded in them. The array itself is an object and a type. You can make a String[] and call wait() and toString() on it, and that type is distinct from the String type. There is not one array type, each type is distinct. You can call getClass() on a String[] and it will return a different class than any other type of array.

So if the type it self is erased (that's what "erasure" means) there there's no type to make a T or whatever.

So you have to fake it with Object[] which will store any type but isn't actually a specific type.

You can however make an array type reflectively. Call

Array.newInstance( t.getClass(), <dim> );

and you can make a specific type of array, as long as t is the right type.

markspace
  • 9,246
  • 2
  • 20
  • 35
  • I understand what the erasure part means, and even the fact that Arrays have extra information encoded within them (hence the "with a bit of fancy dressing around them"). All of the info that you've mentioned (with the exception of getClass) isn't related to the type, though. So, with the exception of getClass (for which there's numerous workarounds), what does the array actually need from the type information? – Micheal Hill May 27 '15 at 05:13
  • I don't think you do understand erasure or that "fancy bit of dressing". Java is a strongly typed language. It does not allow you to assign String[] to Integer[] or vice-versa. It needs the type -- the thing that got erased -- to make the array, period. There's no real other way to express that. – markspace May 27 '15 at 05:27
  • I do understand that. I also understand that String[] is different to Integer[]; but at no point am I trying to mix these together. If I have a generic type T and a class Foo; the compiler doesn't magically let me assign between them. It considers them distinct (in fact, most of the static typing occurs at either compile time, before erasure, or at runtime, well after any of this). "It needs the type to make the array, period" doesn't answer _why_ it needs that type. What is it used for? To stop me assigning an int into a string array? Is that what you're trying to say, or something more? – Micheal Hill May 27 '15 at 05:40
  • To put it another way; if I have `T[] things = ...`, after erasure that will look like `Object[] things = ...`. Are you trying to say that the erasure is to stop me from doing something like `(let T = Foo), things[i] = new String()`? – Micheal Hill May 27 '15 at 07:05
  • I'm saying that `Object[]` is not the same as `String[]` or `Integer[]`. You can't make either of the latter if the type is erased. Which would you make? `List` what type is T, and which array do I make? – markspace May 27 '15 at 16:25
  • I'm still not sure what you're trying to get at with your example, but I can only presume that you're trying describe something along the same lines as this (linked in the comments of the question itself): http://stackoverflow.com/questions/2927391/whats-the-reason-i-cant-create-generic-array-types-in-java/2927415#2927415 In which case thanks! I'm sorry I didn't understand. This link answered the question I was trying to ask. If this isn't what you're trying to say, then I'm sorry but I still have no idea what you're trying to say. – Micheal Hill May 28 '15 at 07:33
  • More or less, yes. Arrays in Java are not just blobs of memory as they are in C. Java arrays are strongly typed and must have the type information available at runtime. It's a bit of design philosophy, but the Java spec requires that behavior, arrays can't be treated as they are in C. – markspace May 28 '15 at 21:14
  • I don't think it's a matter of them not being 'just blobs of memory'. Generics, conceptually, don't mean a lack of type information; if anything they're only meaningful in a strongly typed language. Because of the way Java implements generics, they lose that type information (it's effectively only compile-time typing). The issue was understanding why Java couldn't include that type information with the array at compile time: it could, but there's other issues with the type system that would be more obvious this way. ie. It doesn't fix the underlying problem, so there's no real advantage to it. – Micheal Hill May 29 '15 at 03:05
0

Why not:

Object [] a = new Object[100];

What does a not do that you would expect a hypothetical "generic" array to do? Each element can be a different type of object. You will have to qualify all accesses to the elements but each element can be anything including null.

In this example the symbol a refers to an object which is of fixed size, and operates an array. The only thing that goes "in" the array are references to other objects.

AlanObject
  • 8,408
  • 18
  • 72
  • 122
  • I understand this; that's not what I'm asking. Please see the update I've made to my question; hopefully that clarifies it. – Micheal Hill May 27 '15 at 05:09