I have the following classes:
public interface ServiceSynchronizableEntity {
....
}
public class BaseListResponse<T> {
....
}
public class BaseSynchronizableListResponse<T extends ServiceSynchronizableEntity> extends BaseListResponse<T> {
....
}
public class MySecondClass implements ServiceSynchronizableEntity {
....
}
public class MyFirstClass extends BaseSynchronizableListResponse<MySecondClass> {
....
}
public class What<S extends BaseSynchronizableListResponse<ServiceSynchronizableEntity>> {
}
Then I use it as:
What what = new What<MyFirstClass>();
When I want to use MyFirstClass as a type parameter which extend BaseListResponse<ServiceSynchronizableEntity>> it shows me
Main.java:26: error: type argument MyFirstClass is not within bounds of type-variable S
What what = new What<MyFirstClass>();
^
where S is a type-variable: S extends BaseSynchronizableListResponse<ServiceSynchronizableEntity> declared in class What
What is wrong?
Edit: One class was missing. Look at: http://ideone.com/D4snKP
Thanks!
The solution I previously posted (now deleted) was similar in that it required a change to the generic signature.
The important change is going from:
class What<S extends BaseSynchronizableListResponse<ServiceSynchronizableEntity>> {}
to:
class What<S extends BaseSynchronizableListResponse<? extends ServiceSynchronizableEntity>> {}
See http://ideone.com/wyXvcl for the fixed version
Related
My current abstraction model does not work. I am not sure why and how should I fix it. Please refer the following classes.
public class ErrorCaptchaRequired extends AbstractError {
public String getCaptchaUrl(){
return this.captchaUrl;
}
}
public abstract class AbstractError<E extends AbstractError> {
public E getError(int errorCode){
if(error_code == 1)
return new ErrorCaptchaRequired("abc", "abc", "abc");
if(error_code == 2)
return new AnotherErrorType();
}
}
public class MyObject<E extends AbstractError>{
private E error;
public E getAbstractError(){
return error;
}
}
Later on I want to use it like this:
AbstractError<ErrorCaptchRequired> myError = myObject.getAbstractError();
String captchaUrl = myError.getCaptchaUrl();
Compilation error during return statement: Incompatible types But I am not sure why, as in my understanding since I've parametirized class I can return any type which extends from AbstractError and ErrorCaptchaRequired is extending it. Could you please suggest a fix or better design? Thanks for any help!
The problem is raw (untyped) types. Raw types have all generic info stripped from them - hence no type match.
The type of AbstractError is itself raw: Change:
public abstract class AbstractError<E extends AbstractError> {
To
public abstract class AbstractError<E extends AbstractError<E>> {
Next, ErrorCaptchaRequired extends the raw (untyped) form of AbstractError, so every instance of ErrorCaptchaRequired is then raw.
Change:
public class ErrorCaptchaRequired extends AbstractError {
To:
public class ErrorCaptchaRequired<E extends AbstractError<E>> extends AbstractError<E> {
And change:
public class MyObject<E extends AbstractError>{
To:
public class MyObject<E extends AbstractError<E>>{
In a Java application, I'd like to use a generic type parameter which implements an interface which uses a generic parameter itself.
public interface SuperInterface<T> { ... }
public interface MyInterface extends SuperInterface<MyClass> { ... }
public class Worker<T extends SuperInterface<U>> extends SuperWorker<String, Boolean> {
}
However, the class declaration won't work like that. T should be of type MyInterface (or any other interface which implements the SuperInterface) and U should be of type MyClass (or any other class according to the interface).
You have to declare all of the type parameters at the top level. It's annoying, but that's how it is.
public class Worker<U extends MyClass, T extends SuperInterface<U>> { ...
The order of the parameters doesn't matter; you can also do Worker<T extends..., U extends...>. All that matters is that each is declared at the top level of the nested generics.
Here's a complete class:
public class MyClass {
public interface SuperInterface<T>{}
public interface MyInterface extends SuperInterface<MyClass> {}
public class Worker<U extends MyClass, T extends SuperInterface<U>> {}
public void compileTest() {
// just to make sure the declaration compiles
Worker<MyClass, MyInterface> worker = null;
}
}
public class TowerOfHanoi<E> {
private class Disk<T extends Comparable<E>> {
}
private class Peg<S extends Disk<T extends Comparable<E>>> extends Stack<Disk<T extends Comparable<E>>> {
}
}
With the above code, I'm getting the following compilation error.
Syntax error on token "extends", , expected
However, if I change the definition of Peg as follows, it works:
private class Peg<T extends Disk<? extends Comparable<E>>> extends Stack<Disk<? extends Comparable<E>>> {
}
I don't want to use a wildcard. Is there a way to change that to a named parameter?
You can't use generics like that. Simply pass the type (not the bound) to the extended type.
This compiles:
public class TowerOfHanoi<E> {
private class Disk<T extends Comparable<E>> {
}
private class Peg<T extends Disk<Comparable<E>>> extends Stack<Disk<Comparable<E>>> {
}
}
Is there any reason why you can't make E comparable?
public class TowerOfHanoi<E extends Comparable<? super E>>
{
private class Disk implements Comparable<Disk> { }
private class Peg extends Stack<Disk> { }
}
This is my code:
public interface InterfaceA<J>{
// …
}
public interface InterfaceB extends InterfaceA<String> {
// …
}
public interface InterfaceC extends InterfaceA<Long>{
// …
}
public class Creator<J, I extends InterfaceA<J>> {}
public abstract class Base<J, J1> implements InterfaceA<J> {
protected Creator<J, J1> creator;
protected Base() {
creator=ObjectCreator.createCreator();
}
}
public class Extension1 extends Base<Integer> implements InterfaceB {
// …
}
public class Extension2 extends Base<Double> implements InterfaceC {
// …
}
I want Extension1 to have Creator<Integer, InterfaceB> and Extension2 to have Creator<Double, interfaceC>. See the pattern? Creator<T1, T2> where T1 is the type of immediate parent and T2 is the interface implemented by said class. Is there any way to do this? can anybody tell the code of ObjectCreator.createCreator()?
Right now my code looks like this:
public class ObjectCreator {
public static <J, I extends InterfaceA<J>> Creator<J, I> createCreator() {
return new Creator();
}
}
I got errors all over my code. I'm really confused. What am I missing here?
There's a whole bunch of stuff you missed, a compiling version would look something like this:
package scratch;
interface InterfaceA<J> {
// …
}
interface InterfaceB extends InterfaceA<String> {
// …
}
interface InterfaceC extends InterfaceA<Long> {
// …
}
class Creator<J, I extends InterfaceA<J>> {
}
abstract class Base<J, I extends InterfaceA<J>> {
protected Creator<J, I> creator;
protected Base(Class<J> jClass, Class<I> iClass) {
creator = ObjectCreator.createCreator(jClass, iClass);
}
}
class Extension1 extends Base<String, InterfaceB> implements InterfaceB {
protected Extension1() {
super(String.class, InterfaceB.class);
}
}
class Extension2 extends Base<Long, InterfaceC> implements InterfaceC {
protected Extension2() {
super(Long.class, InterfaceC.class);
}
}
class ObjectCreator {
public static <J, I extends InterfaceA<J>> Creator<J, I>
createCreator(Class<J> jClass, Class<I> iClass) {
return new Creator();
}
}
In no particular order of importance:
When you have a class with a signature like createCreator() has, you need to pass Class objects as type tokens to it. The Java compiler can't infer the types based on the type of the variable you're assigning the return value to. Besides, you want them there anyway because of type erasure, otherwise you couldn't specialise the Creator based on the given types.
If you have Base<J, I> with two type parameters, extending classes should use both of those type parameters.
Your extension class signatures were odd. You can't have class Extension1 extends Base<Integer, InterfaceA<String>>, because you can't have a Creator<Integer, InterfaceA<String>>. Using explicit type tokens in createCreator() would have forced you to propagate this constraint everywhere it needs to be and made the error less mysterious. You can't really make Base independent of the constraint between the J and I type parameters.
the following java class declaration is incorrect:
public class BookKeeping<T extends Transaction<K extends Money>> { ... }
here, one cannot use the generic declaration K extends Money.
my question is why this declaration is not allowed? And how should one declare such a class with java generics?
solution
class Money {
}
class Dollar extends Money {
}
class Transaction<T extends Money> {
}
public class BookKeeping<K extends Money,T extends Transaction<K>> {
public void foo () {
Dollar d = new Dollar();
Transaction<Dollar> t = new Transaction<Dollar>();
BookKeeping<Dollar, Transaction<Dollar>> b = new BookKeeping<Dollar, Transaction<Dollar>>();
}
}
You need to specify the generic parameters and the appropriate constraints and then use them for any anything additional.
public class BookKeeping<K extends Money, T extends Transaction<K>> { ... }
public class BookKeeping<K ,T extends Transaction<K extends Money>> { ... }
You need to "declare" the K generic before you can nested or use it. Its the same rule as local variables.