Closed ljnelson closed 8 months ago
Hmmh. I think this was a tricky area, and my immediate thinking is that all array types only really extended Object
, so that Long[]
does not have Number[]
as its super class. I thought (but haven't tested) that this is how casting also works (i.e. does not take into account assignment rules of element type).
Practically speaking, I think that JDK methods for super class and interfaces should probably be followed, to keep compatibility with that part.
It is possible that code, as is, might be taking short-cuts it should not, which could explain the problem. At very least I think Object
should be available as getParentClass()
.
So, maybe PR for test cases would make sense -- like using JDK accessors to verify some basic aspects?
Here are some fun JUnit assertions etc.:
final Class<?> c = Long[].class;
// Interestingly, no Number[].class:
assertEquals(Object.class, c.getSuperclass());
// Just being thorough:
assertEquals(Object.class, c.getGenericSuperclass());
final Class<?>[] interfaces = c.getInterfaces();
assertNotNull(interfaces);
assertEquals(2, interfaces.length);
assertEquals(Cloneable.class, interfaces[0]);
assertEquals(Serializable.class, interfaces[1]);
final Long[] longs = new Long[] { Long.valueOf(1L) };
// Note: no compilation error:
final Number[] numbers = longs;
// Because the JVM is magic (Number[].class is not in the reflective type hierarchy):
assertTrue(Number[].class.isAssignableFrom(Long[].class));
assertTrue(longs instanceof Number[]);
And just for completeness, here is some stuff with primitives:
// Now let's try some primitives:
c = int[].class;
assertEquals(Object.class, c.getSuperclass());
assertEquals(Object.class, c.getGenericSuperclass());
interfaces = c.getInterfaces();
assertNotNull(interfaces);
assertEquals(2, interfaces.length);
assertEquals(Cloneable.class, interfaces[0]);
assertEquals(Serializable.class, interfaces[1]);
final int[] ints = new int[] { 1 };
// Compilation error as expected:
// final long[] longs = ints;
Quick note: I think as per JLS, parent type for array types should be resolved java.lang.Object
.
So if anyone has time and interest, PR for fix with tests -- or just tests at first -- would be appreciated.
Added simple reproduction, hoping to tackle this soon.
The JLS indicates that a subclass array type should have the parent class array type as a supertype, although it stops short of saying that it should have the parent class array as an actual superclass.
The JLS says explicitly that every array type has
Object.class
as its superclass.It also says that every array type directly implements
Cloneable
andSerializable
.If I do
TypeResolver.resolve(Long[].class)
, theResolvedType
that results has:null
as the return value of itsgetParentClass()
methodList<ResolvedType>
as the return value of itsgetImplementedInterfaces()
methodIs this by design? What about
Number[].class
? Should that be its parent class?