How to avoid unchecked casts in a Java Generics extended Comparable interface? - java

Why is the unsafe cast (T) needed in this generic interface? If T is comparable to itself, i.e. implements ExtendedComparable<super of T> which means also ExtendedComparable<T>, then why does type erasure require ExtendedComparable<T> to be cast to T?
/* #param <T> T must be comparable to itself or any of its superclass
* (comparables are consumers, thus acc. to the PECS principle
* = producer-extends,consumer-super we use the bounded wildcard type "super")
*/
public interface ExtendedComparable<T extends ExtendedComparable<? super T>> {
Comparator<? super T> getComparator();
default boolean greaterThen(T toCompare) {
return getComparator().compare((T) this, toCompare) > 0;
}
}

Because there is no guarantee that this is actually an instance of class T or even extend it.
For example consider this:
public class T0 implements ExtendComparable<T0> {...}
public class T1 implements ExtendComparable<T0> {...}
In T0 complies fine as it complies with the bound: T0 extends ExtendComparable<T0> and T0 is super of T0. In this case this is an instance of T0 here so you are fine; the cast (T)this (thus (T0)this) makes sense.
With T1 the declaration is correct also because the bound is applied to T0 no T1, T is substituted T0. However this is T1 and T1 is not super nor a child of T0. Yes, both implement
ExtendedCompatible<T0>, but you cannot cast between siblings. For example Integer and Double extend Number but (Integer) new Double(0.0) fails.
So too does the cast (T) translated to (T0) fail.
The assumption you are making is that T is going to be set to the same as the class that is been declared and currently there is no way to force those semantics. I hope this will change at some point in future releases of the Java language but perhaps there is actual reason why the Java language "task force" are avoiding to do so.
There is a way to avoid the cast altogether but is better when you make ExtendedCompatible an abstract class rather than an interface.
You can declare a final field of type T which value would be set by a protected constructor by extending class which in turn must pass this as its value:
public abstract class ExtendedCompatible<T extends ExtendedCompatible<? super T>> {
private final T thiz;
protected ExtendedCompatible(final T thiz) {
if (this != thiz) throw new IllegalArgumentException("you must pass yourself");
this.thiz = thiz;
}
...
public class MyExtendedCompatible extends ExtendedCompatible<MyExtendedCompatible> {
public MyExtendedCompatible() {
super(this);
}
}
The price you pay is the extra memory consumption of having a silly reference to itself and the added code/CPU burden of passing this to the parent constructor.
Another would be to declare an abstract method to get the T (this):
// Parent abstract class:
protected abstract T getThiz();
// Child class... for each class:
protected MyChildClass getThiz() { return this; }

Thanks. Valentin is right. Even if both types implement the same interface, this does not and should not make the cast between them to work. And yes, there is no mechanism in Java to enforce passing in T the same class as the class being declared.

Related

Java automatic return type covariance with generic subclassing

I have two interfaces that look like this:
interface Parent<T extends Number> {
T foo();
}
interface Child<T extends Integer> extends Parent<T> {
}
If I have a raw Parent object, calling foo() defaults to returning a Number since there is no type parameter.
Parent parent = getRawParent();
Number result = parent.foo(); // the compiler knows this returns a Number
This makes sense.
If I have a raw Child object, I would expect that calling foo() would return an Integer by the same logic. However, the compiler claims that it returns a Number.
Child child = getRawChild();
Integer result = child.foo(); // compiler error; foo() returns a Number, not an Integer
I can override Parent.foo() in Child to fix this, like so:
interface Child<T extends Integer> extends Parent<T> {
#Override
T foo(); // compiler would now default to returning an Integer
}
Why does this happen? Is there a way to have Child.foo() default to returning an Integer without overriding Parent.foo()?
EDIT: Pretend Integer isn't final. I just picked Number and Integer as examples, but obviously they weren't the best choice. :S
This is based on ideas of #AdamGent .
Unfortunately I am not fluent with JLS enough to prove the below from the spec.
Imagine public interface Parent<T extends Number> was defined in a different compilation unit - in a separate file Parent.java.
Then, when compiling Child and main, the compiler would see method foo as Number foo(). Proof:
import java.lang.reflect.Method;
interface Parent<T extends Number> {
T foo();
}
interface Child<R extends Integer> extends Parent<R> {
}
public class Test {
public static void main(String[] args) throws Exception {
System.out.println(Child.class.getMethod("foo").getReturnType());
}
}
prints:
class java.lang.Number
This output is reasonable as java does type erasure and is not able to retain T extends in the result .class file plus because method foo() is only defined in Parent. To change the result type in the child compiler would need to insert a stub Integer foo() method into the Child.class bytecode. This is because there remains no information about generic types after compilation.
Now if you modify your child to be:
interface Child<R extends Integer> extends Parent<R> {
#Override R foo();
}
e.g. add own foo() into the Child the compiler will create Child's own copy of the method in the .class file with a different but still compatible prototype Integer foo(). Now output is:
class java.lang.Integer
This is confusing of course, because people would expect "lexical visibility" instead of "bytecode visibility".
Alternative is when compiler would compile this differently in two cases: interface in the same "lexical scope" where compiler can see source code and interface in a different compilation unit when compiler can only see bytecode. I don't think this is a good alternative.
The Ts aren't exactly the same. Imagine that the interfaces were defined like this instead:
interface Parent<T1 extends Number> {
T1 foo();
}
interface Child<T2 extends Integer> extends Parent<T2> {
}
The Child interface extends the Parent interface, so we can "substitute" the formal type parameter T1 with the "actual" type parameter which we can say is "T2 extends Integer":
interface Parent<<T2 extends Integer> extends Number>
this is only allowed because Integer is a subtype of Number. Therefore, the signature of foo() in the Parent interface (after being extended in the Child interface) is simplified to:
interface Parent<T2 extends Number> {
T2 foo();
}
In other words, the signature is not changed. The method foo() as declared in the Parent interface continues to return Number as the raw type.

Instantiate and apply generic method with unknown generic type - Java

I need to instantiate an object with an unknown generic type and then apply a generic method to it. Here is where I stand :
public static void main(String[] args)
{
BarIf bar = newRandomBarImpl();
Foo foo1 = newFooBar(bar.getClass()); // warning
Foo<?> foo2 = newFooBar(bar.getClass()); // error
Foo<? extends BarIf> foo3 = newFooBar(bar.getClass()); // error
foo1.doSomething(bar); // warning
foo2.doSomething(bar); // error
foo3.doSomething(bar); // error
}
static <T extends FooIf<S>, S extends BarIf> T newFooBar(Class<S> barClass){}
static <T extends BarIf> T newRandomBarImpl(){}
interface FooIf<T extends BarIf>
{
public void doSomething(T t);
}
interface BarIf{}
class Foo<T extends BarIf> implements FooIf<T>
{
public void doSomething(T t){}
}
The strange thing is that for foo2 and foo3, the newFooBar() method returns FooIf rather than Foo. I guess the type inference is messy. But I can't pass the method generic parameters since I don't know the Bar type.
What I would need is Foo<bar.getClass()>. Is there a way to do it?
I tried using TypeToken but I end up with a T type rather than the actual Bar type. Any chance using that?
First of all, a declaration like
static <T extends BarIf> T newRandomBarImpl(){}
is nonsense. It basically says “whatever the caller substitutes for T, the method will return it”. In other words, you can write
ArbitraryTypeExtendingBarIf x=newRandomBarImpl();
without getting a compiler warning. Obviously, that can’t work. newRandomBarImpl() doesn’t know anything about ArbitraryTypeExtendingBarIf. The method name suggests that you actually want to express that newRandomBarImpl() can return an arbitrary implementation of BarIf, but that’s an unnecessary use of Generics,
BarIf newRandomBarImpl(){}
already expresses that this method can return an arbitrary subtype of BarIf. In fact, since BarIf is an abstract type, this method must return a subtype of BarIf and it’s nowhere specified which one it will be.
The same applies to the declaration
static <T extends FooIf<S>, S extends BarIf> T newFooBar(Class<S> barClass){}
It also claims that the caller can choose which implementation of FooIf the method will return. The correct declaration would be
static <S extends BarIf> FooIf<S> newFooBar(Class<S> barClass){}
as the method decides which implementation of FooIf it will return, not the caller.
Regarding your other attempts to deal with FooIf, you can’t work this way using a type parametrized with a wildcard, nor can you fix it using Reflection. But you can write generic code using a type parameter:
public static void main(String[] args)
{
BarIf bar = newRandomBarImpl();
performTheAction(bar.getClass(), bar);
}
static <T extends BarIf> void performTheAction(Class<T> cl, BarIf obj) {
FooIf<T> foo=newFooBar(cl);
foo.doSomething(cl.cast(obj));
}
static <S extends BarIf> FooIf<S> newFooBar(Class<S> barClass){}
static BarIf newRandomBarImpl(){}
interface FooIf<T extends BarIf> {
public void doSomething(T t);
}
interface BarIf{}
The method performTheAction is generic, in other words, works with an unknown type expressed as type parameter T. This method can be invoked with an unknown type ? extends BarIf as demonstrated in the main method.
However, keep in mind, that every reference to a type X implies that the referred object might have a subtype of X without the need to worry about it.
You can simply use the base class BarIf here, regardless of which actual subtype of BarIf the object has:
BarIf bar = newRandomBarImpl();
FooIf<BarIf> foo=newFooBar(BarIf.class);
foo.doSomething(bar);
Note that when you want to use methods of the actual implementation type Foo, not specified in the interface, you will have to cast the FooIf to Foo. You can cast a FooIf<BarIf> to Foo<BarIf> without a warning as the generic type conversion is correct if Foo<X> implements FooIf<X>.
However, it can fail at runtime as the method newFooBar is not required to return an instance of Foo rather than any other implementation of FooIf. That’s why an explicit type cast is the only correct solution as it documents that there is an assumption made about the actual runtime type of an object. All other attempts will generate at least one compiler warning somewhere.

An interface has two type parameters. Can I implement the interface with the two types being the same, such that they are then compatible?

This is an existing interface:
public interface MyInterface<T, U> {
public T foo(U u);
}
I want to implement this interface under the assumption that T and U are the same type. I thought maybe I could leave the type parameters in as they are, and then as long as I only ever instantiate this particular implementation with two of the same type, that it might work:
public class MyOuterClass<A> {
public class MyClass<T, U> implements MyInterface<T, U> {
#Override
public T foo(U u) {
return u; //error here
}
//even though in the only instantiation of MyClass, T and U are the same
private MyClass<A, A> myInstance = new MyClass<A, A>();
}
But, perhaps unsurprisingly, this doesn't work, as types T and U are incompatible.
So then I thought maybe I could change MyClass to specify that its types would always be the same, by changing it to something like MyClass<A, A> implements MyInterface<A, A> or similar, but I get errors saying that T is already defined.
Is there a way to implement MyClass so that its two types will be the same?
(I'm more of a C++ guy than Java, so sorry if I'm missing something fundamental about Java's generic's here.)
Your myclass needs to look like this:
public class MyClass<T> implements MyInterface<T, T> {
#Override
public T foo(T in) {
return in;
}
}
Let's review what your suggested class definition does:
public class MyClass<T, U> implements MyInterface<T, U>
In this code, T and U do two things each:
in the first occurance they define a type variable of your MyClass class
in the second occurance they specify the concrete type of the MyInterface class
Since inside the body of your class T and U are unbounded type variables (i.e. nothing is known about the actual types), they are assumed to be incompatible.
By having only a single type variable in your MyClass you make your assumption explicit: there's only a single type, and I'm using it for both types of the interface.
Last but not least: remember that the compilation of a type is complete once the source is fully handled. In other words: contrary to what C++ does, "instantiation" of a generic type ("template type" or similar in C++; Sorry for my rusty terminology) does not handle. MyClass<Foo> and MyClass<Bar> are the same type, as far as the JVM is concerned (only the compiler actually distinguishes them).
Define a single type parameter for MyClass:
class MyOuterClass<A> {
public class MyClass<T> implements MyInterface<T, T> {
public T foo(T u) {
return u;
}
}
// Need only one 'A' here.
private MyClass<A> myInstance = new MyClass<A>();
}
When you say
public class MyClass<T> implements MyInterface<T, T> {
... you are defining one generic variable for MyClass and you are saying that it fulfills both the roles T and U in MyInterface.

Parameterized Type Parameters?

I'm trying to create library with a container that releases instances of its contained objects according to descriptors it is passed. I'd like to make it so the descriptor determines the type of the returned object, but the descriptor can specify a bounded type. How do I implement this? For example the closest I can get is:
/*Block 1 - First Attempt. Compiles, but forces user to cast*/
interface ItemDescriptor<I> {
Class<? extends I> getType();
}
interface ArchiveContainer<I, D extends ItemDescriptor<? extends I>> {
Iterable<? extends D> getDescriptors();
I getItem(D descriptor);
}
//Implementations
class ChannelItemDescriptor<I extends ByteChannel> implements ItemDescriptor<I>
{
final Class<? extends I> type;
ChannelItemDescriptor(Class<I> type) {
this.type = type;
}
#Override Class<? extends I> getType() {return type;}
}
class ChannelArchive implements ArchiveContainer<ByteChannel, ChannelItemDescriptor<? extends ByteChannel>> {
#Override ByteChannel getItem(ChannelItemDescriptor<? extends ByteChannel> descriptor) {...}
}
The above code compiles, but the problem is ChannelArchive's getItem can return SeekableByteChannels as well. The user of this library knows this at compile time (because they know the type parameter of the descriptor), so I'm trying to avoid adding a method parameter of type Class for forcing the user to explicitly cast the returned value to SeekableByteChannel when necessary. I can't figure out how to get getItem to return a specific subtype of ByteChannel without forcing the user to cast. I want to do this:
/*Block 2 - Test code*/
ChannelArchive archive = ...;
ChannelItemDescriptor<SeekableByteChannel> desc = ...;
ChannelItemDescriptor<ByteChannel> otherDesc = ...;
SeekableByteChannel sbc = archive.getItem(desc);
SeekableByteChannel sbc = archive.getItem(otherDesc); //Should fail to compile, or compile with warning
ByteChannel bc = archive.getItem(otherDesc);
I could add a Class<? extends I> parameter to each method, but the code for the method would completely ignore Class method parameter! It's only purpose would be to help the compiler infer types. I think it just obfuscates the code so much that it would be easier to just have the user use instanceof checks and casts.
I've tried this:
/*Block 3 - Failed attempt.*/
class ChannelArchive implements ArchiveContainer<ByteChannel, ChannelItemDescriptor<? extends ByteChannel>> {
//Won't compile, getItem doesn't override
#Override <II extends ByteChannel> II getItem(ChannelItemDescriptor<II> descriptor) {...}
}
but that doesn't work: ChannelArchive is not abstract and does not override abstract method getItem(ChannelItemDescriptor<? extends ByteChannel>) in ArchiveContainer. I assume this is because the second type parameter <II extends ByteChannel> has different type erasure than <? extends ByteChannel>?
I've also tried this, which compiles:
/*Block 4 - Almost specific enough*/
interface ArchiveContainer<I, D extends ItemDescriptor<? extends I>> {
Iterable<? extends D> getDescriptors();
<II extends I, DD extends ItemDescriptor<II>> II getItem(DD descriptor);
}
class ChannelArchive implements ArchiveContainer<ByteChannel, ChannelItemDescriptor<? extends ByteChannel>> {
#Override <II extends ByteChannel, DD extends ItemDescriptor<II>> II getItem(DD descriptor) {...}
}
Even though it compiles, it won't really work because I need a ChannelItemDescriptor inside that method, and the resulting cast would defeat the purpose of using the added type-safety of generics.
I don't see why I can't do it, because the right types are known at compile time. What I really need on that ArchiveContainer interface is a parameterized type parameter, like: <II extends I, DD extends D<II>>. What am I doing wrong?
NOTE: I don't actually use ByteChannel and SeekableByteChannel, but what I do use is quite similiar.
That's to ruakh, I settled on the code in block 4. In my case, its highly unlikely the user would send the wrong sublcass of ItemDescriptor in a call to a getItem, especially because the descriptors are all returned from the ArchiveContainer itself via getDescriptors!
I think this code, which is (almost?) the same as your third attempt, is as good as you're going to get:
// in ArchiveContainer:
<II extends I, DD extends ItemDescriptor<II>> II getItem(DD descriptor);
// in ChannelArchive:
public <II extends ByteChannel, DD extends ItemDescriptor<II>>
II getItem(DD descriptor)
{ ... }
Generics do offer a way to declare a type variable with two separate upper bounds:
public <T extends Foo & Bar> Foo fooBar(T t) { ... }
but apparently that's not allowed when one of the upper bounds is a type-parameter rather than a class or interface:
Type variables have an optional bound, T & I1 ... In. The bound consists of either a type variable, or a class or interface type T possibly followed by further interface types I1 , ..., In. […] It is a compile-time error if any of the types I1 ... In is a class type or type variable. [link]
(emphases mine). I don't know why this is.
But I don't think this should be a big problem. Note that, even after Map was genericized to Map<K,V>, its get method still took type Object. Naturally that method will always return null if you pass in a reference to an object that's not of type K (since such an object should never have been inserted into the map), but this doesn't harm type-safety.
I know that this is probably not what you want to hear, but even though Java generics look syntactically like C++ templates, they differ quite a bit in how they work.
Look up java type erasure in your favorite search engine.
Just because a type is known at compile-time does not, unfortunately, mean that the type is recoverable at runtime, or even during later compile phases.

what could this generic class declaration could mean?

I know this isn't a good question to ask and I might get cursed to ask it but I cannot find any place to get help on this question
Below is a Generic class that appeared in my interview question (which I have already failed). The question was to tell what this Class declaration is doing and in what circumstances this could be used for ?
I have very limited understanding of Generic programming but I understand that 'T' is Type and 'extends' here means that the Type should have inherited 'SimpleGenericClass' but I do not understand the '?' at the end and in what circumstances this Class could be potentially used for
public abstract class SimpleGenericClass<T extends SimpleGenericClass<?>> {
}
First, because the class SimpleGenericClass is abstract, it is meant to be subclassed.
Second, it is a generic class which means that inside the class somewhere you will almost assuredly be using the generic parameter T as the type of a field.
public abstract class SimpleGenericClass<T...> {
T x;
}
Now the first interesting thing here is that T is bounded. Because it is declared as T extends SimpleGenericClass<?> it can only be SimpleGenericClass<?> or some subclass of SimpleGenericClass<?>. You also asked about thr ?. That's known as a wildcard and there is a pretty good explanation of it at the Java Tutorial on Wildcards. In your case we would say this is a "SimpleGenericClass of unknown." It is needed in Java because SimpleGenericClass<Object> is NOT the superclass of SimpleGenericClass<String>, for example.
The second interesting thing though is that since T is a SimpleGenericClass of some sort, your class is more than likely defining recursive structures. What comes to my mind are trees (think of expression trees) where SimpleGenericClass is the (abstract) node type, designed to be subclassed with all kinds of specialized node types.
UPDATE This SO question on self-bounded generics might be helpful to you.
UPDATE 2
I went ahead and put together some code that illustrates how this can be used. The app doesn't do anything but it does compile and it shows you how the generic bounds can supply some possibly-meaningful constraints.
public abstract class Node<T extends Node<?>> {
public abstract T[] getChildren();
}
class NumberNode extends Node {
int data;
public Node[] getChildren() {return new Node[]{};}
}
class IdentifierNode extends Node {
int data;
public Node[] getChildren() {return new Node[]{};}
}
class PlusNode extends Node {
NumberNode left;
NumberNode right;
public NumberNode[] getChildren() {return new NumberNode[]{};}
}
The nice thing here is that NumberNode[] is a valid return type for PlusNode.getChildren! Does that matter in practice? No idea, but it is pretty cool. :)
It's not the greatest example, but the question was rather open ended ("what might such a thing be used for?"). There are other ways to define trees, of course.
This really only means that you allow the user of class SimpleGenericClass to parametrize instances of the class with the type T. However, T cannot be any type, but must be a subtype of SampleGenericClass (or SampleGenericClass itself).
In the remainder of the code of class SimpleGenericClass you may use type T in method signatures.
Let's assume for a second that SimpleGenericClass is not abstract. When using it, you could then write:
new SimpleGenericClass<SampleGenericClass<String>>();
I.e. you parametrize SimpleGenericClass with SampleGenericClass and SampleGenericClass with String.
This basically sais: in this class you have a Type placeholder called T, and a restriction on that placeholder, it must be of type SimpleGenericClass or something that extends it. Once you obey that rule you can create instances of your class and give an actual type to T, that later on can be used in methods of that class, something like this:
public class C <T extends Number>{
public void doSomething(T t) {
}
public static void main(String... args) {
//works:
C<Number> c = new C<Number>();
c.doSomething(new Number() {
//Aonimous implementation of number
});
//won't work
//C<Object> c = new C<Object>();
C<Integer> c2 = new C<Integer>();
c2.doSomething(new Integer(1));
//won't work
//c2.doSomething(new Number() {
//Aonimous implementation of number
//});
}
}
The SimpleGenericClass<?> is pretty redundant at this point. If another generic type is needed on this class, you can have more than one (SimpleGenericClass<T extends SimpleGenericClass, T2 extends Whatever>)
By definition it says that the SimpleGenericClass can work on a type <T> which is subclass of SimpleGenericClass.
So I assume there will be some operations which will work on <T>.
Now to see why one would define a template like this - (not much I can think of , really ) may be a scenario where the SimpleGenericClass is an abstract class (just realized it is as per OP :P) and expects that it can work on any concrete classes ?
Guys what do you think ?
I guess you have got the question in this form (T instead of ?):
public abstract class SimpleGenericClass<T extends SimpleGenericClass<T>>
Take a look at this code:
abstract class Foo<SubClassOfFoo extends Foo<SubClassOfFoo>>
{
/** subclasses are forced to return themselves from this method */
public abstract SubClassOfFoo subclassAwareDeepCopy();
}
class Bar extends Foo<Bar> {
public Bar subclassAwareDeepCopy() {
Bar b = new Bar();
// ...
return b;
}
}
Bar b = new Bar();
Foo<Bar> f = b;
Bar b2 = b.subclassAwareDeepCopy();
Bar b3 = f.subclassAwareDeepCopy(); // no need to cast, return type is Bar
The trick going on with Foo<SubClassOfFoo extends Foo<SubClassOfFoo>> is:
Any subclass of Foo must supply a type argument to Foo.
That type argument must actually be a subclass of Foo.
Subclasses of Foo (like Bar) follow the idiom that the type
argument they supply to Foo is themselves.
Foo has a method that returns SubClassOfFoo. Combined
with the above idiom, this allows Foo to formulate a contract that
says “any subclass of me must implement subclassAwareDeepCopy() and
they must declare that it returns that actual subclass“.
To say that another way: this idiom allows a superclass (such as an Abstract Factory) to define methods whose argument types and return types are in terms of the subclass type, not the superclass type.
The trick is done for example in Enum JDK class:
public abstract class Enum<E extends Enum<E>>
Refer here for more details.

Categories

Resources