I found this code from a tutorial and I am guessing this method getUriBase return type is String, but not clear what part <T extends IEntity> is playing in this method and why it is placed in the beginning?
public interface IUriMapper {
<T extends IEntity> String getUriBase(final Class<T> clazz);
}
This is the convention of creating a generic method.
The syntax for a generic method includes a type parameter, inside
angle brackets, and appears before the method's return type. For
static generic methods, the type parameter section must appear before
the method's return type.
If you see then before your return type String you defining your type parameter T. Now, coming to <T extends IEntity>, by this basically you are creating a bounded type parameter, where-in you are telling the compiler that T should only be a subclass of IEntity.
An important thing to note is that you need to define <T extends IEntity> before your method (this is what you call "generic method", more info coming...) because your interface is not a generic type, suppose your interface was like below then you need not to define the T type parameter because compiler would know what is the T type parameter.
public interface IUriMapper<T extends IEntity> {
String getUriBase(final Class<T> clazz);
}
So, basically generic method are useful (or in other words meant for situations) when you want to define your own type. Consider below example where-in your generic type (your interface "IUriMapper") defines type parameter "T" but for method getUriBase you are creating a new type "E"
public interface IUriMapper<T extends IEntity> {
<E extends Number> String getUriBase(final Class<E> clazz);
}
This Oracle documentation is best source to learn Generics.
Generic Types
The type parameter section, delimited by angle brackets (<>), follows the class name. It specifies the type parameters (also called type variables) T1, T2, ..., and Tn.
public class Box {
private Object object;
public void set(Object object) { this.object = object; }
public Object get() { return object; }
}
To update the Box class to use generics, you create a generic type declaration by changing the code "public class Box" to "public class Box". This introduces the type variable, T, that can be used anywhere inside the class.
/**
* Generic version of the Box class.
* #param <T> the type of the value being boxed
*/
public class Box<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
Source: https://docs.oracle.com/javase/tutorial/java/generics/types.html
Bounded Type Parameters:
There may be times when you want to restrict the types that can be used as type arguments in a parameterized type. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.
public class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
public <U extends Number> void inspect(U u){
System.out.println("T: " + t.getClass().getName());
System.out.println("U: " + u.getClass().getName());
}
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
integerBox.set(new Integer(10));
integerBox.inspect("some text"); // error: this is still String!
}
}
Source: https://docs.oracle.com/javase/tutorial/java/generics/bounded.html
Related
I have an interface with generic
public interface MessageCallback<T extends JsonModel> {
void onMessage(T t);
}
And I wanna get instance of T.
I found a solution where I can use reflection
public static <T> Class<T> getGenericClass(Class actualClass, int index) {
ParameterizedType genericSuperclass = (ParameterizedType) actualClass.getGenericSuperclass();
// Get generic class
return (Class<T>) genericSuperclass.getActualTypeArguments()[index];
}
But it throws exception.
java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
I wanna know is there a solution without using reflection?
Extra. I also found this
class Foo<T> {
final Class<T> typeParameterClass;
public Foo(Class<T> typeParameterClass) {
this.typeParameterClass = typeParameterClass;
}
public void bar() {
// you can access the typeParameterClass here and do whatever you like
}
}
But its only for class. How I can solve my problem? Thanks for your answers.
And if you wanna know it isn't clean Java. It's in Android
About your first code, Class.getGenericSuperclass() returns the type representing the direct superclass of this class, that it Object in your case.
Class.getGenericInterfaces() that returns the Types representing the interfaces directly implemented by this class would be a better choice to retrieve the generic defined in the MessageCallback interface.
But it will probably not help you as the generic type will be which one statically declared in the MessageCallback interface : JsonModel and not which one defined in the subclass declaration that extends the interface.
About your second code, you should not worry about whether the parameter to capture the generic is Class or Type.
For example, the types declared in a generic class such as interface MessageCallback<T extends JsonModel> or a subclass of a generic class such as MessageCallbackImpl extends MessageCallback<MyJsonModel> are necessary classes as parameterized types can only be Classes. So storing the type of the generic type as Class is perfectly valid.
The Type class that is the common superinterface for all types in Java is much broader (raw types, parameterized types, array types, type variables and primitive types)
So to come back to your question : what you need is having a way to refer at runtime the generic type defined at compile and this idiom is a classical way to do that :
public Foo(Class<T> typeParameterClass) {
this.typeParameterClass = typeParameterClass;
}
You were on the right track.
Now suppose we have a generic interface, as in your example:
public interface MessageCallback<T extends JsonModel> {
void onMessage(T t);
}
And a concrete implementation of it:
class FooMessage {}
public class MyMessageCallback
implements MessageCallback<FooMessage extends JsonModel> {
#Override
public void onMessage(FooMessage t) {
System.out.println("Received foo");
}
}
You want to find the type passed into generic interface, MessageCallback, in this case FooMessage.
We can use reflection to find all interfaces that MyMessageCallback implements and for each interface, check if it is a generic interface then return all of its type parameters.
public static <T> Class<?>[] getGenericInterfaceParameter(Class clazz, Class<T> interfaceType) {
Class<?>[] result = new Class<?>[0];
// make sure interfaceType is a generic interface.
if(!interfaceType.isInterface() || interfaceType.getTypeParameters().length < 1) {
return result;
}
// get all interfaces implemented by concrete class.
Type[] interfaceTypes = clazz.getGenericInterfaces();
// for each interface the concrete class implements
// we check if that interface is actually equal to interfaceType
// and is a parametrized type,
// i.e has a type parameter.
// Once a match is found, we return the type parameters.
for(Type it : interfaceTypes) {
if(it instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) it;
if(!parameterizedType.getRawType().equals(interfaceType)) {
continue;
}
Type[] typeParameters = parameterizedType.getActualTypeArguments();
result = new Class[typeParameters.length];
for(int j = 0; j < typeParameters.length; j++) {
result[j] = (Class) typeParameters[j];
}
}
}
return result;
}
Use the method to find type parameter of MyMessageCallback:
Class<?>[] params = getGenericInterfaceParameter(
MyCallback.class,
MessageCallback.class
);
System.out.println(params[0].getTypeName()); // MyMessageCallback
I have a class A which contains a field of type A (similar to the way a Node in an implementation of a linked list has a Node nextNode) like so:
public class A {
private A otherA;
public A getOtherA() {
return otherA;
}
}
Then I have a class B with a bounded type parameter of <T extends A> which attempts to assign the return value from getOtherA() to a variable of type T:
public class B<T extends A> {
public B(T t1) {
T t2 = t1.getOtherA();
}
}
The above code produces an error at the line
T t2 = t1.getOtherA();
and reads as
Incompatible types. Required T, Found A.
My question is how (if possible) do I modify the code so that I can treat the return value of getOtherA() as type T. After all, t1 is of type T, T extends A and getOtherA() just returns an object of the same type as the object it belongs to. So why does T#getOtherA() not have a return type of T?
It seems to me that my compiler should be satisfied that t1.getOtherA() always returns an object of type T, but I suspect that I have a misunderstanding of generics, in which case I'll bite the bullet and just cast each one to my desired type.
The error is because getOtherA() returns an A, which is not necessarily a T.
You can get close to you requirements if you make A generic, with the type parameter intended to be the class A itself.
// Introduce type parameter T, upper bound itself.
class A<T extends A<T>> {
protected T otherA; // now of type T
public T getOtherA() { // now returns T
return otherA;
}
}
Any subclasses of A are expected to supply themselves as a type parameter:
class ASub extends A<ASub> {
// Implementation
}
Or they can declare their own type parameter with a similar constraint:
class ASub<T extends ASub<T>> extends A<T> {
// Implementation
}
This means that getOtherA can be typed to return an object of its own type.
Class B will supply its T to A.
class B<T extends A<T>> {
public B(T t1) {
T t2 = t1.getOtherA();
}
}
This question already has an answer here:
Java generics 2 set of <K,V> or <T> in method declaration [duplicate]
(1 answer)
Closed 5 years ago.
I am learning Java generic from: https://docs.oracle.com/javase/tutorial/java/generics/bounded.html and I have some doubts on the code sample below:
public class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
public <U extends Number> void inspect(U u) {
System.out.println("T: " + t.getClass().getName());
System.out.println("U: " + u.getClass().getName());
}
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
integerBox.set(new Integer(10));
integerBox.inspect("some text"); // error: this is still String!
}
}
Why wasnt the inspect() method to be written as shown below instead it was ?
public <T extends Number> void inspect(T t) { }
There are some other code samples which has the following syntax. What does the 1st pair stands for?
public <K,V> SomeClass<K,V>
What does static stands for?
public static <T> int countGreaterThan(T[] anArray, T elem)
The method Box.inspect() expects a type that extends Number so it is not applicable when the argument is a String.
Box.inspect() is just an example of generic type applied to a method.
On other hand you have a class Box with generic type T, but you can also have a method that accepts another type U which is broader (upper bounded) than T.
The class itself does not say how to use inspect and why, it just give you the possibility to handle different types. Don't put great expectations by this sample.
Consider that it is a just a sample that explain how to use Generics (not great logic behind).
Regarding public class SomeClass<K,V> declaration, this a declaration with multiple generics types.
The class HashMap<K,V>() is a real sample of this case, K is the type for the key value and V is the type for the value.
public <U extends Number> void inspect(U u) {
waits for a parameter that is of Number type or a derived of it.
So you cannot of course pass a String value :
integerBox.inspect("some text"); // error: this is still String!
In your class, you declare two parameterized type :
one in the class declaration : public class Box<T> {
another in the public <U extends Number> void inspect(U u) method.
These set two distinct constraints.
When you declare an instance of Box with Integer as generic type:
Box<Integer> integerBox = new Box<>();
This following field using the T type will be associated to an Integer type :
private T t;
but the public <U extends Number> void inspect(U u) method doesn't use the T
type.
So you can use distinct types in the two cases:
Box<Integer> integerBox = new Box<Integer>();
integerBox.set(new Integer(10));
integerBox.inspect(Float.valueOf(10)); // I pass a float and it is valid.
If you would declare the method in this way :
public <T extends Number> void inspect(T t) { }
you would have the same behavior as T in the declared method would be another T type as which one declared in the class.
But this way is misleading as you use use twice the same type name (T) while these are distinct types.
Otherwise, to constraint the parameter of the method to the type declared in the class, you have not to declare still a type.
This is enough :
public void inspect(T t) { }
Now you can only use the same type in the two cases:
Box<Integer> integerBox = new Box<Integer>();
integerBox.set(new Integer(10));
integerBox.inspect(Float.valueOf(10)); // doesn't compile
Yes. Freedev answer is correct.
Try
public static void main(String[] args) {
Test1<Integer> integerBox = new Test1<Integer>();
integerBox.set(new Integer(10));
integerBox.inspect(78); // inspect method expect a interger value
}
What does class mean. when we required this kind of classes.
e.g.
class SimpleCounter<T> { /*...*/ }
SimpleCounter<Double> doubleCounter = new SimpleCounter<Double>();
See From Generic Types
A generic class is defined with the following format:
class name<T1, T2, ..., Tn> { /* ... */ }
The type parameter section, delimited by angle brackets (<>), follows the class name. It specifies the type parameters (also called type variables) T1, T2, ..., and Tn.
To update the Box class to use generics, you create a generic type declaration by changing the code "public class Box" to "public class Box<T>". This introduces the type variable, T, that can be used anywhere inside the class.
With this change, the Box class becomes:
/**
* Generic version of the Box class.
* #param <T> the type of the value being boxed
*/
public class Box<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
What is the difference between:
public <T> void createArray(T sample){
ArrayList<T> list = new ArrayList<T>();
list.add(sample);
}
and
public void createArray(T sample){
ArrayList<T> list = new ArrayList<T>();
list.add(sample);
}
I read that the method signature for using types should have <T> before the return type but how come I am still able to create the method without the <T>? What is the implication if I do or do not put it?
In the second method, the type parameter would be typically defined in the class declaration to which the method belongs:
class MyClass<T> {
public void createArray(T sample){
ArrayList<T> list = new ArrayList<T>();
list.add(sample);
}
...
}
So the second method belongs to a generic type.
The first method is a generic method because it defines its own type parameter.
In the first case, the generic parameter T is defined for the method. Other methods may have a different T.
In the second case, the generic parameter T is defined for the class or interface. All methods within that class or interface must have the same T.
Defining a class-wide generic allows you to enforce the same type parameter on many methods. You can also have fields of the generic type. See ArrayList<t> for an example.
From the second example, I am guessing this method is defined in a generic class something like this:
class SomeClass<T> {
public void createArray(T sample){ ... }
}
The difference between the first and second example is that in the first example, the T is effectively a "local" type variable. You could give it a different name, e.g. S, to make it a little bit clearer:
class SomeClass<T> {
public <S> void createArray(S sample){ ... }
}
So, S and T are both type variables, but are unrelated. T is defined at class scope, and so can be used to refer to the same type amongst all methods in the class; S is defined only at method scope.
By using the name T instead of S, you are hiding the class-level type variable, T. This means that, for example, the following would not work:
class SomeClass<T> {
public T getWotsit() { ... }
public <T> void createArray(T sample){
T wotsit = getWotsit();
}
}
because the T in the signature of getWotsit and the T in the variable declaration T wotsit potentially refer to different types; this is more clear if you use the name S to write the equivalent code:
class SomeClass<T> {
public T getWotsit() { ... }
public <S> void createArray(S sample){
S wotsit = getWotsit();
}
}
As far as I'm aware, there is no way to refer to the class-level type variable if you've defined a method-level type variable with the same name.
However, both of the following would be fine:
class SomeClass<T> {
public T getWotsit() { ... }
// No additional type variable, so T is the class-level type variable.
public void createArray(T sample){
T wotsit = getWotsit();
}
}
class SomeClass<T> {
public T getWotsit() { ... }
// Type variable has different name, so `T` is the class-level
// type variable.
public <S> void createArray(T sample){
T wotsit = getWotsit();
}
}
In case of public void createArray(T sample) where T is defined in class definition MyClass<T> is generic for the class
For public <T> void createArray(T sample){ , T is local generic for method and is not related to T in MyClass<T>, this T could be anything X,Y,Z. If you remove <T> before void, it is now <T> from MyClass<T> and cannot be X,Y,Z