I have created an interface called Identifier. And a class which implements Identifier interface is MasterEntity bean like below.
public class MasterEntity implements Identifier{
}
In DAO method, I wrote a method like below method signature.
public Identifier getEntity(Class<Identifier> classInstance){
}
Now from Service I want to call the method like below.
dao.getEntity(MasterEntity.class);
But am getting compilation error saying -
The method getEntity(Class<Identifiable>) in the type ServiceAccessObject
is not applicable for the arguments (Class<MasterEntity>)
I know if I use like below it will work.
public Identifier getEntity(Class classInstance){
But by specifying the Class of type Identifiable, how it can be done?.
Change DAO method signature to
public Identifier getEntity(Class<? extends Identifier> classInstance)
By declaring method as you described above you specify that the only applicable argument is Identifier.class itself. To be able to accept Identifier.class implementations, you should define generic type bounds.
List<? extends Shape> is an example of a bounded wildcard. The ? stands for an unknown type, just like the wildcards we saw earlier. However, in this case, we know that this unknown type is in fact a subtype of Shape. (Note: It could be Shape itself, or some subclass; it need not literally extend Shape.) We say that Shape is the upper bound of the wildcard.
Also you can take a look at this answer: https://stackoverflow.com/a/897973/1782379
Related
public class MyClass<T> extends T {...}
The above declaration will fail to compile with the error:
error: unexpected type
class MyClass<T> extends T {}
^
required: class
found: type parameter T
where T is a type-variable:
T declared in class MyClass
I can't really think of a reason for this to happen, so I am wondering if someone can shed some light on why it is that Java won't let you inherit from a generic type-variable.
The most obvious reason I can think of isn't even about type-erasure; it is the fact that when you make A a subclass of B, the Java compiler needs to know what constructors B has. If a class does not have a no-arguments constructor, then its sub-classes must call one of its defined constructors. But when you declare
public class MyClass<T> extends T {...}
It is absolutely impossible for the compiler to know what the super constructors are, since T is not fixed at compile-time (that's the whole point of generics after all), which is a situation that cannot be allowed in Java.
Java has quite a lot of language restrictions unlike C++ for example. What you want is not possible for many reasons listed in the comments (T might be final or have abstract methods). However, you are allowed to extend from a supertype having the generic type parameter:
public class MyClass<T> extends AnotherClass<T>
You might find the following alternative interesting:
public class MyClass<T extends AnotherClass> extends AnotherClass
What you want to do does make not much sense.
Your question is not so weird as it may look like :) Consider how would you deal with following:
Suppose your real class for T has a single constructor with 3 parameters. How would you implement the constructor of inherited class, if you don't know how to call the super constructor?
Suppose your real class for T has public final methods and you have defined methods with the same signature in the inherited class. What method would your object have? You cannot resolve such conflict.
Simple deductions based on your question.
T is a type.
MyClass extends T - MyClass is enhanced version of T.
MyClass < T> extends T - MyClass is enhanced T, but only for Type T.
there is no reason to state ' I extend T but only for type T'.
If you extend T, MyClass is already a Type of T & definitely not some X,Y or Z.
Generics are needed if you want to ensure Type safety, if you extend it is already type safe.
Take for instance, the method below.
<T extends MyInterface> void myFunction(Class<T>... types) {
// Do some stuff that requires T to implement MyInterface
}
Now, given the method call below assuming MyClass1 and MyClass2 both implement MyInterface.
myFunction(MyClass1.class, MyClass2.class)
I get the following error.
Incompatible equality constraint: MyClass1 and MyClass2
How do I make this work? More specifically, how would one use a variadic parameter of class types implementing an interface in Java?
You've declared T to have an upper bound of MyInterface. By passing in MyClass1.class and MyClass2.class, the compiler must infer MyInterface for T.
However, the type of the parameter type is Class<T>..., restricting what is passed in to MyInterface.class and no subtypes.
Depending on the "stuff" you're doing, you can place a wildcard upper bound on the type of types to get it to compile.
<T extends MyInterface> void myFunction(Class<? extends T>... types) {
Having a T means that T has one fixed value, which means that all of the Class<T>... parameters must be the exact same type. The compiler cannot infer T==MyInferface because Class<MyClass1> is not a subclass of Class<MyInterface>.
You want to allow each parameter to have a different type. That requires a different signature:
void myFunction(Class<? extends MyInterface>... types)
There's no need for T at all.
With the first parameter, the type variable T is set to MyClass1.
MyClass1 should implement the interface, so the constraint extends MyInterface is fulfilled.
Of course a Class<MyClass2> is not a Class<MyClass1>.
And that's why you get the error.
Here, here is my question, I have three abstracts class which all are generic, and i want something like this:
public abstract class AbstracOne< T extends AbstractTwo< K extends AbstractThree<K> >>>
This is not working and I get the following error (on the second extends):
Syntax error on token "extends", , expected.
However, if I use the following code, it is working:
public abstract class AbstracOne< T extends AbstractTwo< ? extends AbstractThree<?> >>>
So, what is the difference between using K and ?
Thank you very much
Type parameter vs Type argument
You can read this excellent FAQ by Angelica Langer for clearing this distinction.
Generic class has type parameters which are substituted by type argument when you use the generic class.
Type parameters can have constraints. Type arguments can be fully qualified types or previously defined type parameters.
So, you can use K if it is defined already. You can also add constraints while defining it.
public abstract class AbstractOne<K extends AbstractThree<K>, T extends AbstractTwo<K>>
Good luck.
The following types do not produce any compiler warnings:
public abstract Class<? extends BaseType> getSubclassType();
#Override
public Class<SubType> getSubclassType() {
return SubType.class;
}
The following concrete method produces an unchecked cast compiler warning:
public abstract <T extends BaseType> Class<T> getSubclassType();
#Override
public <T extends BaseType> Class<T> getSubclassType() {
return (Class<T>) SubType.class;
}
Is there any way to define the method with a generic type parameter (in the base class) and return the appropriate concrete type in the subclass without generating compiler warnings? Obviously, both examples that I've given above will work just fine, I just want to know if there is a more correct way to define the method. Note: I do know that I could do the following:
public abstract class BaseClass <T extends BaseType>
public abstract Class<T> getSubclassType();
I am wondering if there is a way to define the method header itself, with a generic type, without defining it on the class. And also, I am curious why the wildcard declaration does not give and warnings but the "equivalent" generic declaration does.
The two are very different.
In the first one, the caller does not know what the type argument of the Class that is returned is. The caller cannot make any assumptions about what that type argument is, other than it extends BaseType. The method can choose to return a Class whose type argument is any subtype of BaseType it wants, unknown to the caller.
In the second case, the method is a generic method and T is a type variable of the method. That means that the caller can choose T to be whatever it wants, and expect the method to magically work with T being that type. Notably, the method does not receive any arguments, which means the method does not have any information at runtime regarding what T is at all, and must nevertheless somehow figure out how to return a Class<T>. Obviously, this is impossible, unless it always returns null.
I'm trying to create a kind of service locator class, where there is a
Map<Integer, ? extends ISomething>
but I can't later do
myMap.put(0x00, new SomethingImplementor())
As I get a Error:(18, 33) java: incompatible types: org.sample.SomethingImplementor cannot be converted to capture#1 of ? extends ISomething
My class structure is as follows:
public interface ISomething {
public void doSomething();
}
public class SomethingImplementor implements ISomething {
#Override public void doSomething() {...}
}
Why can't I create this map and put values into it?
You don't need the wildcard at all.
You can directly use
Map<Integer, ISomething>
and you can implement every subclass of ISomething.
Anyway, to work with wildcards in this case you should use super. With extends you don't know what type it will be so you can't add anything to the map.
List is an example of a bounded wildcard. The ? stands for an unknown type, just like the wildcards we saw earlier. However, in this case, we know that this unknown type is in fact a subtype of Shape. (Note: It could be Shape itself, or some subclass; it need not literally extend Shape.) We say that Shape is the upper bound of the wildcard.
There is, as usual, a price to be paid for the flexibility of using wildcards. That price is that it is now illegal to write into shapes in the body of the method. For instance, this is not allowed:
You should be able to figure out why the code above is disallowed. The type of the second parameter to shapes.add() is ? extends Shape-- an unknown subtype of Shape. Since we don't know what type it is, we don't know if it is a supertype of Rectangle; it might or might not be such a supertype, so it isn't safe to pass a Rectangle there.
Wildcards: http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html
Don't use the unknown type ?:
Map<Integer, ISomething> map;
Nothing is gained by using the unknown type, simply specifying ISomething is sufficient and the right choice.
Further, generic types must match exactly; ie ? extends ISomething is not the same type as ISomething