Java Questions Regarding declaring a list of Comparable objects - java

It is a pretty simple one. I want to declare a list of objects, but I want make sure all objects implemented the Comparable interface. What should I do? I try to write
List<Comparable> heap = new ArrayList<Comparable>();
But compiler gives me a warning. What is the proper way to write it?
Thanks
Follow up:
I thought I had finished the question before I post it but apparently I didn't. So let me finish it up.
My purpose is to have a list of objects that:
Implements the Comparable interface
Are all with the same type
Can I make it
List<Comparable<?>> heap = new ArrayList<Comparable<?>>()
No, I can't. The reason is because I need to retrieve the elements from the list and compare them. like:
if( heap.get(0).compareTo(heap.get(1)) > 0)
If I use wildcard List<Comparable<?>>, the complier will give me an error. Saying heap.get(0) cannot match heap.get(1) So I need to know the correct way to declare it.
I find somebody asking me what the warning is.... that surprises me.....well, the warning is:
Comparable is a raw type. References to generic type Comparable should be parameterized

It's because you're using the raw type Comparable. You can try giving Comparable a wildcard type parameter:
List<Comparable<?>> heap = new ArrayList<Comparable<?>>();
If you want the objects to all be of the same type, you can do something along the lines of
public static <T extends Comparable<? super T>> List<T> getList() {
...
}
and return your list from getList().

Since all your objects are of the same type (let's say f.e. FooType), then just use a List<FooType>.

Perhaps you could write a method that only takes a type that extends Comparable and returns a List of that type:
public <T extends Comparable> List<T> getComparableList(T t) {
List<T> heap = new ArrayList<T>();
return heap;
}

Related

How can I use a generic class with wildcard declaration?

I have the following member in my class:
List<? extends SomeObject> list;
When I try to do:
list.add(list.get(0));
I get:
Test.java:7: error: no suitable method found for add(CAP#1)
list.add(list.get(0));
^
method Collection.add(CAP#2) is not applicable
(argument mismatch; Object cannot be converted to CAP#2)
method List.add(CAP#2) is not applicable
(argument mismatch; Object cannot be converted to CAP#2)
where CAP#1,CAP#2 are fresh type-variables:
CAP#1 extends Object from capture of ? extends Object
CAP#2 extends Object from capture of ? extends Object
My question is twofold:
Why doesn't it compile? Why can't I pass get()'s result to add()?
And how can I achieve this in another way without resorting to casting?
I understand that in a method with <T extends SomeObject> I can't just say:
T someObject = list.get(0);
list.add(someObject);
since my T could be another extension than the ? extension.
I also understand I can't say:
List<? extends SomeObject> list1;
List<? extends SomeObject> list2;
list1.add(list2.get(0));
But since the add and the get should work with the same generic type in list.add(list.get(0)) I don't understand why the compiler doesn't accept it.
What I really need is
[something of type T where T is whatever was used to instantiate list] someObject = list.get(0);
list.add(someObject);
so that I can later
list.add(someObject);
I don't think I should have to template my whole class to achieve this, should I?
class MyClass<T extends SomeObject> {
List<T> list;
and then later a method with
T someObject = list.get(0);
of course works, but screws other parts of my code.
So the first question is why doesn't this work, second question is what's the best workaround?
My question is twofold, why can't I do:
list.add(list.get(0));
Because the compiler isn't smart enough to know that you're adding something from list back into list. The compiler doesn't consider list.get(0) to have anything to do with list once it is evaluated: it's just "some expression" of type ? extends SomeObject.
To solve this, add a method with its own type variable:
private <T> void addFirst(List<T> list) {
list.add(list.get(0));
}
and replace the original list.add(list.get(0)); with an invocation of this:
addFirst(list);
This only defines a type variable on the method, and does not need to be visible outside the class, so you don't need a class-level type variable.
It's perhaps worth pointing out this is analogous to the Collections.swap method: that's using set rather than add, but, from a generics point of view, it's the same thing:
#SuppressWarnings({"rawtypes", "unchecked"})
public static void swap(List<?> list, int i, int j) {
// instead of using a raw type here, it's possible to capture
// the wildcard but it will require a call to a supplementary
// private method
final List l = list;
l.set(i, l.set(j, l.get(i)));
}
This takes an approach which is technically type-safe, and does avoid casts; but it's a bit gross, because it uses raw types.
I would imagine that it is only like this for backwards-compatibility reasons. Given a chance to write it again, you could just define a type variable as in the addFirst method above.
When use wildcards, we should follow The Get and Put Principle which introduced in Java Generics and Collections:
The Get and Put Principle: use an extends wildcard when you only get values out of a
structure, use a super wildcard when you only put values into a structure, and don’t use
a wildcard when you both get and put.
In your case, don't use a wildcard as you both get element from list and put element to list.

Sorting list with unknown type in Java

I have this list in a method:
List<? extends Object> objects;
or it can be also:
List<?> objects;
I wanted to sort it this way, with Java 8 lambda:
objects.sort((p1, p2) -> p1.compareTo(p2));
But it says:
The method compareTo(capture#6-of ?) is undefined for the type
capture#6-of ?
I also tried with generic type:
List<O extends Object> objects;
But then it says:
The method compareTo(O) is undefined for the type O
How could I sort a list like this way? I need it in my abstract class, where it recognizes the list field by reflection, and it can sort it.
compareTo is available for object that implements Comparable interface.
If you want to do that you should use
List<? extends Comparable> objects;
For a clean code check #Holger answer
If you are confident, that all elements of the list are mutually comparable, that is, they are not only implementing Comparable, but also Comparable<CommonBaseType>, e.g. while String and Integer instances are Comparable, you can’t compare a String with an Integer and must not have instances of both types in your list, then you can bypass the compile-time checking using
objects.sort(null);
of course, with all consequences of bypassing the compile time type checks.

Why does Java have lower bounds in generics?

I'm trying to design my own programming language, and am thinking about generics. I've been doing Java for quite a while now and know about the extends and super generic bounds.
I'm reading this post and trying to understand the need for the lower bounds.
In my language, I am planning to do generics the same way as a regular field, if you say List<MyObject>, you can store either a MyObject, or any subtype of MyObject. Makes sense right?
On the post, they have the following class hierarchy:
class Person implements Comparable<Person> {
...
}
class Student extends Person {
...
}
They then have a sort method:
public static <T extends Comparable<T>> void sort(List<T> list) {
...
}
What I think, is that you should be able to send a List<Student> to this method. As a Student extends Person, the compare method would be handled by it's superclass, Person.
The reason for the error message is that the compiler infers the type parameter of the sort method as T:=Student and that class Student is not Comparable<Student> . It is Comparable<Person> , but that does not meet the requirements imposed by the bound of the type parameter of method sort. It is required that T (i.e. Student ) is Comparable<T> (i.e. Comparable<Student> ), which in fact it is not.
The above doesn't make any sense to me...you should be able to do student.compare(person), so why doesn't this work?
Maybe it's saying that Student should implement it's own comparable method so that Student has a say in the comparison? You don't need to do anything special, just override Person's method. You won't be able to guarantee you are comparing to another Student, but that can be checked with instanceof.
Is there something I'm missing here?
And after all this thinking, I'm now wondering what the purpose of extends is. From my understanding, in a List<MyType>, you can only put a MyType in, not any of it's subclasses. As mentioned above, this doesn't make any sense to me and you should be able to put any subclass in the list like a field.
I should probably make this clear, it's not "why doesn't it work in Java", but "why doesn't it work in generics theory". I just tagged java because that is where I'm making my comparisons.
First: The method declaration
public static <T extends Comparable<T>> void sort(List<T> list)
does not make much sense for me. I thing it should be
public static <T extends Comparable<? super T>> void sort(List<T> list)
Then it would be possible to write sort(listOfStudents). Now I will explain the advantage of upper and lower bounded wildcards:
Polymorphism of type parameters is not transferred to it's generic type
This mean a list of students (List<Student>) is not a list of persons (List<Person>). A instruction like
List<Person> list = new List<Student>();
would fail in Java. There is a simple reason: list.add(new Person()); would be illegal for a list of students but not for a list of persons.
Upper Bounded Wildcards
But maybe you have a function which doesn't care whether the objects are subclasses or not. For example: You could have a method like this:
void printAll(List<Person> list)
They just print some data about all persons to stdout. If you have a list of students (List<Student> listOfStudents) you could write:
List<Person> listOfPersons = new ArrayList<>();
for (final Student student : listOfStudents) {
listOfPersons.add(student);
}
printAll(listOfPersons);
But you may see that it isn't a very nice solution. Another solution would be to use upper bounded wildcards for printAll:
void printAll(List<? extends Person> list)
You can write something like Person person = list.get(0) in printAll. But you cannot write print.add(new Person()) because list could be a list of students or something else.
Lower Bounded Wildcards
Now the same in the other direction: Lets say you have a function which generates some students and put them in a list. Something like this:
void generateStudents(List<Student> list) {
for (int i = 0; i < 10; ++i) {
list.add(new Student());
}
}
Now you have a list of persons (List<Person> listOfPersons) and want to generate students in this list. You could write
List<Student> listOfStudents = new ArrayList<>();
generateStudents(listOfStudents);
for (Student student : listOfStudents) {
listOfPersons.add(student);
}
You may see again, that it is not a very nice solution. You could also change the declaration of generateStudents to
void generateStudents(List<? super Student> list)
Now, you can just write generateStudents(listOfPersons);.
I think your confusion may be coming from the fact that while elements of List<Student> can be compared to each other by virtue of the fact that class Student subclasses Person which implements Comparable<Person> (class Student therefore inherits compareTo(Person o), which can be called with an instance of Student), you still cannot call the sort method with a List<Student>...
The problem is that when the Java compiler encounters the statement:
sort(studentList);
Where studentList is an instance of parameterized type List<Student>, it uses type inference to infer that the type argument to the sort method T is Student, and Student does not satisfy the upper bound: Student extends Comparable<Student>. Therefore, the compiler will throw an error in this case, telling you that the inferred type does not conform to the constraints.
The article that you linked to shows you that the solution to this is to re-write the sort method as:
public static <T extends Comparable <? super T > > void sort(List<T> list)
This method signature loosens the constraint on the type parameter so that you can call the method with a List<Student>.
I'm not too clear on the last part of your post:
in a List<MyType>, you can only put a MyType in, not any of it's subclasses.
If you're referring to the elements of List<MyType>, yes, you can put any element that is a subtype of MyType in this list, say, MySubType. If you're referring to a variable with List<MyType> as its reference type, then no, you cannot put a reference to List<MySubType> in a variable of type List<MyType>. The reason for this is easy to see when you consider the following:
List<MyType> a;
List<MySubType> b = new ArrayList<>();
a = b; // compile-time-error, but assume OK for now
a.add(new MyType()); // Based on the type of a, this should be OK, but it's not because a is actually a reference to List<MySubType>.
I also think you should refer to Java Generics by Wadler and Naftalin, an excellent introduction to Java (5+) Type System.
When you ask "what is the purpose of extends keyword?" based on your observations about collections of objects, the first thing you should remember is generic collections are tricky. I quote from the Wadler/Naftalin book (emphasis mine):
In Java, one type is a subtype of another if they are related by an
extends or implements clause: Integer is a subtype of Number.
Subtyping is transitive.
If A is a subtype of B, B is the supertype of A.
Liskov’s Substitution Principle tells us that wherever a value of one
type is expected, one may provide a value of any subtype of that type:
a variable of a given type may be assigned a value of any subtype of
that type, and a method with a parameter of a given type may be
invoked with an argument of any subtype of that type.
It’s because of violation of Liskov’s Substitution Principle (that
would arise very rapidly in practice) that a List<Integer> is not a
subtype of List<Number> although Integer is a subtype of Number. The
other way round also does not work because List<Number> is NOT a
subtype of List<Integer>.
This paragraph should help us understand why the keyword extends is essential to support inheritance and polymorphism, and yet it (sort of) comes in the way of generic collections.
I think your question would be stated better as: "What are valid use cases for using lower bound generics in JAVA"? I had the same question and it makes sense to use the upper bounds when you have a list and you want to use different types that are all subtypes or the supertype of a hierarchy of classes.
For example, you want methods to populate a list of numbers with int, double, and long. Using extends you can do this as they are all subtypes of Number.
On the other hand, if you want to restrict methods to only use Integer, then you want the more narrowly defined class so that only int is allowed, not float, double, etc.
From the java docs:
The abstract class Number is the superclass of platform classes
representing numeric values that are convertible to the primitive
types byte, double, float, int, long, and short.
The Integer class wraps a value of the primitive type int in an
object. An object of type Integer contains a single field whose type
is int.
A better example might be work you are doing at the JVM level, so you want to restrict your methods to use the VirtualMachineError to get specific information written to the logs, rather than using the Error class, from which it inherits, to limit the number of errors you write to the logs for something very refined, possibly relating to some debugging task.
These are obviously contrived examples, but the theme is the lower bounds can be used to restrict method type parameters.

Difference between List<T> and List<? extends T> [duplicate]

Given the following example (using JUnit with Hamcrest matchers):
Map<String, Class<? extends Serializable>> expected = null;
Map<String, Class<java.util.Date>> result = null;
assertThat(result, is(expected));
This does not compile with the JUnit assertThat method signature of:
public static <T> void assertThat(T actual, Matcher<T> matcher)
The compiler error message is:
Error:Error:line (102)cannot find symbol method
assertThat(java.util.Map<java.lang.String,java.lang.Class<java.util.Date>>,
org.hamcrest.Matcher<java.util.Map<java.lang.String,java.lang.Class
<? extends java.io.Serializable>>>)
However, if I change the assertThat method signature to:
public static <T> void assertThat(T result, Matcher<? extends T> matcher)
Then the compilation works.
So three questions:
Why exactly doesn't the current version compile? Although I vaguely understand the covariance issues here, I certainly couldn't explain it if I had to.
Is there any downside in changing the assertThat method to Matcher<? extends T>? Are there other cases that would break if you did that?
Is there any point to the genericizing of the assertThat method in JUnit? The Matcher class doesn't seem to require it, since JUnit calls the matches method, which is not typed with any generic, and just looks like an attempt to force a type safety which doesn't do anything, as the Matcher will just not in fact match, and the test will fail regardless. No unsafe operations involved (or so it seems).
For reference, here is the JUnit implementation of assertThat:
public static <T> void assertThat(T actual, Matcher<T> matcher) {
assertThat("", actual, matcher);
}
public static <T> void assertThat(String reason, T actual, Matcher<T> matcher) {
if (!matcher.matches(actual)) {
Description description = new StringDescription();
description.appendText(reason);
description.appendText("\nExpected: ");
matcher.describeTo(description);
description
.appendText("\n got: ")
.appendValue(actual)
.appendText("\n");
throw new java.lang.AssertionError(description.toString());
}
}
First - I have to direct you to http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html -- she does an amazing job.
The basic idea is that you use
<T extends SomeClass>
when the actual parameter can be SomeClass or any subtype of it.
In your example,
Map<String, Class<? extends Serializable>> expected = null;
Map<String, Class<java.util.Date>> result = null;
assertThat(result, is(expected));
You're saying that expected can contain Class objects that represent any class that implements Serializable. Your result map says it can only hold Date class objects.
When you pass in result, you're setting T to exactly Map of String to Date class objects, which doesn't match Map of String to anything that's Serializable.
One thing to check -- are you sure you want Class<Date> and not Date? A map of String to Class<Date> doesn't sound terribly useful in general (all it can hold is Date.class as values rather than instances of Date)
As for genericizing assertThat, the idea is that the method can ensure that a Matcher that fits the result type is passed in.
Thanks to everyone who answered the question, it really helped clarify things for me. In the end Scott Stanchfield's answer got the closest to how I ended up understanding it, but since I didn't understand him when he first wrote it, I am trying to restate the problem so that hopefully someone else will benefit.
I'm going to restate the question in terms of List, since it has only one generic parameter and that will make it easier to understand.
The purpose of the parametrized class (such as List<Date> or Map<K, V> as in the example) is to force a downcast and to have the compiler guarantee that this is safe (no runtime exceptions).
Consider the case of List. The essence of my question is why a method that takes a type T and a List won't accept a List of something further down the chain of inheritance than T. Consider this contrived example:
List<java.util.Date> dateList = new ArrayList<java.util.Date>();
Serializable s = new String();
addGeneric(s, dateList);
....
private <T> void addGeneric(T element, List<T> list) {
list.add(element);
}
This will not compile, because the list parameter is a list of dates, not a list of strings. Generics would not be very useful if this did compile.
The same thing applies to a Map<String, Class<? extends Serializable>> It is not the same thing as a Map<String, Class<java.util.Date>>. They are not covariant, so if I wanted to take a value from the map containing date classes and put it into the map containing serializable elements, that is fine, but a method signature that says:
private <T> void genericAdd(T value, List<T> list)
Wants to be able to do both:
T x = list.get(0);
and
list.add(value);
In this case, even though the junit method doesn't actually care about these things, the method signature requires the covariance, which it is not getting, therefore it does not compile.
On the second question,
Matcher<? extends T>
Would have the downside of really accepting anything when T is an Object, which is not the APIs intent. The intent is to statically ensure that the matcher matches the actual object, and there is no way to exclude Object from that calculation.
The answer to the third question is that nothing would be lost, in terms of unchecked functionality (there would be no unsafe typecasting within the JUnit API if this method was not genericized), but they are trying to accomplish something else - statically ensure that the two parameters are likely to match.
EDIT (after further contemplation and experience):
One of the big issues with the assertThat method signature is attempts to equate a variable T with a generic parameter of T. That doesn't work, because they are not covariant. So for example you may have a T which is a List<String> but then pass a match that the compiler works out to Matcher<ArrayList<T>>. Now if it wasn't a type parameter, things would be fine, because List and ArrayList are covariant, but since Generics, as far as the compiler is concerned require ArrayList, it can't tolerate a List for reasons that I hope are clear from the above.
It boils down to:
Class<? extends Serializable> c1 = null;
Class<java.util.Date> d1 = null;
c1 = d1; // compiles
d1 = c1; // wont compile - would require cast to Date
You can see the Class reference c1 could contain a Long instance (since the underlying object at a given time could have been List<Long>), but obviously cannot be cast to a Date since there is no guarantee that the "unknown" class was Date. It is not typsesafe, so the compiler disallows it.
However, if we introduce some other object, say List (in your example this object is Matcher), then the following becomes true:
List<Class<? extends Serializable>> l1 = null;
List<Class<java.util.Date>> l2 = null;
l1 = l2; // wont compile
l2 = l1; // wont compile
...However, if the type of the List becomes ? extends T instead of T....
List<? extends Class<? extends Serializable>> l1 = null;
List<? extends Class<java.util.Date>> l2 = null;
l1 = l2; // compiles
l2 = l1; // won't compile
I think by changing Matcher<T> to Matcher<? extends T>, you are basically introducing the scenario similar to assigning l1 = l2;
It's still very confusing having nested wildcards, but hopefully that makes sense as to why it helps to understand generics by looking at how you can assign generic references to each other. It's also further confusing since the compiler is inferring the type of T when you make the function call (you are not explicitly telling it was T is).
The reason your original code doesn't compile is that <? extends Serializable> does not mean, "any class that extends Serializable," but "some unknown but specific class that extends Serializable."
For example, given the code as written, it is perfectly valid to assign new TreeMap<String, Long.class>() to expected. If the compiler allowed the code to compile, the assertThat() would presumably break because it would expect Date objects instead of the Long objects it finds in the map.
One way for me to understand wildcards is to think that the wildcard isn't specifying the type of the possible objects that given generic reference can "have", but the type of other generic references that it is is compatible with (this may sound confusing...) As such, the first answer is very misleading in it's wording.
In other words, List<? extends Serializable> means you can assign that reference to other Lists where the type is some unknown type which is or a subclass of Serializable. DO NOT think of it in terms of A SINGLE LIST being able to hold subclasses of Serializable (because that is incorrect semantics and leads to a misunderstanding of Generics).
I know this is an old question but I want to share an example that I think explains bounded wildcards pretty well. java.util.Collections offers this method:
public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
If we have a List of T, the List can, of course, contain instances of types that extend T. If the List contains Animals, the List can contain both Dogs and Cats (both Animals). Dogs have a property "woofVolume" and Cats have a property "meowVolume." While we might like to sort based upon these properties particular to subclasses of T, how can we expect this method to do that? A limitation of Comparator is that it can compare only two things of only one type (T). So, requiring simply a Comparator<T> would make this method usable. But, the creator of this method recognized that if something is a T, then it is also an instance of the superclasses of T. Therefore, he allows us to use a Comparator of T or any superclass of T, i.e. ? super T.
what if you use
Map<String, ? extends Class<? extends Serializable>> expected = null;

How do I use arrays of generic types correctly?

I have a class that maps incoming messages to matching readers based on the message's class. All message types implement the interface message. A reader registers at the mapper class, stating which message types it will be able to handle. This information needs to be stored in the message reader in some way and my approach was to set a private final array from the constructor.
Now, it seems I have some misunderstanding about generics and / or arrays, that I can't seem to figure out, see the code below. What is it?
public class HttpGetMessageReader implements IMessageReader {
// gives a warning because the type parameter is missing
// also, I actually want to be more restrictive than that
//
// private final Class[] _rgAccepted;
// works here, but see below
private final Class<? extends IMessage>[] _rgAccepted;
public HttpGetMessageReader()
{
// works here, but see above
// this._rgAccepted = new Class[1];
// gives the error "Can't create a generic array of Class<? extends IMessage>"
this._rgAccepted = new Class<? extends IMessage>[1];
this._rgAccepted[0] = HttpGetMessage.class;
}
}
ETA:
As cletus correctly pointed out, the most basic googling shows that Java does not permit generic arrays. I definitely understand this for the examples given (like E[] arr = new E[8], where E is a type parameter of the surrounding class). But why is new Class[n] allowed? And what then is the "proper" (or at least, common) way to do this?
Java does not permit generic arrays. More information in the Java Generics FAQ.
To answer your question, just use a List (probably ArrayList) instead of an array.
Some more explanation can be found in Java theory and practice: Generics gotchas:
Generics are not covariant
While you might find it helpful to
think of collections as being an
abstraction of arrays, they have some
special properties that collections do
not. Arrays in the Java language are
covariant -- which means that if
Integer extends Number (which it
does), then not only is an Integer
also a Number, but an Integer[] is
also a Number[], and you are free to
pass or assign an Integer[] where a
Number[] is called for. (More
formally, if Number is a supertype
of Integer, then Number[] is a
supertype of Integer[].) You might
think the same is true of generic
types as well -- that List<Number>
is a supertype of List<Integer>, and
that you can pass a List<Integer>
where a List<Number> is expected.
Unfortunately, it doesn't work that
way.
It turns out there's a good reason it
doesn't work that way: It would break
the type safety generics were supposed
to provide. Imagine you could assign a
List<Integer> to a List<Number>.
Then the following code would allow
you to put something that wasn't an
Integer into a List<Integer>:
List<Integer> li = new ArrayList<Integer>();
List<Number> ln = li; // illegal
ln.add(new Float(3.1415));
Because ln is a List<Number>, adding
a Float to it seems perfectly legal.
But if ln were aliased with li, then
it would break the type-safety promise
implicit in the definition of li --
that it is a list of integers, which
is why generic types cannot be
covariant.
It is right what cletus said. There is a general mismatch between the usually enforced invariance of generic type parameters vs. covariance of Java arrays.
(Some background: Variance specifies how types relate to each other concerning subtyping. I.e. because of generic type parameters being invariant
Collection <: Collection does not hold. So, concerning the Java type system, a String collection is no CharSequence collection. Arrays being covariant means that for any types T and U with T<:U, T[] <: U[]. So, you can save a variable of type T[] into a variable of type U[]. Since there is a natural need for other forms of variance, Java at least allows wildcards for these purposes.)
The solution (the hack, actually) I often use, is declaring a helper method which generates the array:
public static <T> T[] array(T...els){
return els;
}
void test(){
// warning here: Type safety : A generic array of Class is created for a varargs parameter
Class<? extends CharSequence>[] classes = array(String.class,CharSequence.class);
}
Because of erasure the generated arrays will always be of type Object[].
And what then is the "proper" (or at least, common) way to do this?
#SuppressWarnings(value="unchecked")
public <T> T[] of(Class<T> componentType, int size) {
return (T[]) Array.newInstance(componentType, size);
}
public demo() {
Integer[] a = of(Integer.class, 10);
System.out.println(Arrays.toString(a));
}
Arrays are always of a specific type, unlike how Collections used to be before Generics.
Instead of
Class<? extends IMessage>[] _rgAccepted;
You should simply write
IMessage[] _rgAccepted;
Generics don't enter into it.
IMHO,
this._rgAccepted = (Class<? extends IMessage>[])new Class[1];
is the appropriate way to handle this. Array component types have to be reified types, and Class is the closest reified type to Class<whatever>. It'll work just as you would expect a Class<whatever>[] to work.
Yes, technically it is unchecked and might cause issues later if you cast it to another more general array type and put wrong stuff in it, but since this is a private field in your class, I presume you can make sure it is used appropriately.

Categories

Resources