Up-casting template argument types [duplicate] - java

This question already has answers here:
Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?
(19 answers)
Closed 7 years ago.
Why does Java not support automatic up-casting for template argument types?
For example, the following class will not compile unless the newly created Derived instance will be manually casted to a Base instance:
public class Example implements Iterable<Base> {
#Override
public Iterator<Base> iterator() {
return Arrays.asList(new Derived()).iterator();
}
private class Base {
}
private class Derived extends Base {
}
}

No need to cast.
The problem here is that Arrays.asList(new Derived()) naturally tries to create a List<Derived>,
and then calling .iterator() on a List<Derived> naturally gives an Iterator<Derived>,
which is not a sub-type of Iterator<Base>, so you get a compilation error.
You can specify that you want a List<Derived>, using Arrays.<Base>asList.
This works,
because you can certainly put a Derived instance into a List<Base>,
and then calling .iterator() on a List<Base> naturally gives an Iterator<Base>.
class Example implements Iterable<Base> {
#Override
public Iterator<Base> iterator() {
return Arrays.<Base>asList(new Derived()).iterator();
}
}

Related

Generic type of superclass property lost in subclass with no type bound [duplicate]

This question already has answers here:
What is a raw type and why shouldn't we use it?
(16 answers)
Closed 4 years ago.
Here is a pathological generics example in Java. What is going on here?
public abstract class Foo<X> {
private List<String> stuff;
public List<String> getStuff() {
return stuff;
}
public void setStuff(List<String> stuff) {
this.stuff = stuff;
}
}
Then I created a subclass, but not I did not specify the type bound, which should make it object.
public class Bar extends Foo {
public Bar() {
setStuff(new ArrayList<>());
}
public void whatIsGoingOnHere() {
for(String thing : getStuff())
System.out.println("Why is this a compiler error???");
}
}
Why is this a compiler error?
You call setStuff(new ArrayList<>());. Here ArrayList<> isn't not bound, it is inferred by the compiler if it can. And it can as setStuff is setStuff(List<String>). So the compiler knows it is a ArrayList<String> and uses (infers) that.
Your loop iterates over an List<String> as returned by the getStuff() method, so defining the thing as a String (or any super class or interface) will be okay for the compiler.
The base class does have an X type, but it doesn't matter as your stuff list is declared with a type. Only if you would define stuff as an List<X> it would matter what the subclass defined for X.

Java - Using "<? extends Interface>" vs Interface only [duplicate]

This question already has answers here:
Whats the use of saying <? extends SomeObject> instead of <SomeObject>
(5 answers)
Closed 6 years ago.
I have seen some code as follows
public interface IBean {
}
and its usage at some places as
public void persist(List<? extends IBean> beansList) {
}
However same can achieved with following code
public void persist(List<IBean> beansList) {
}
So what is the difference between both methods, both are excepting objects that must inherit IBean interface?
Here are the bean classes
public class Category implement IBean {
//related fields
}
public class Product implement IBean {
//related fields
}
You can pass a List<Category> to public void persist(List<? extends IBean> beansList), but you cannot pass a List<Category> to public void persist(List<IBean> beansList).
On the other hand, you can pass a List<IBean> to both methods.
The reason is that generics are invariant. This means for example that you can't use a List<Integer> where a List<Number> is expected.
But when turning to wildcards, you can circumvent that restriction. Therefore, when you really have a List<Product> you will not be able to pass that into a method that expects List<IBean> - you would have to somehow convert the list first. To be precise: you would do a "hard" cast; as there is no point in "converting" generic lists, as type erasure kicks in at runtime anyway!
By using the wildcard on the method definition, you can allow for passing Lists that use "real" sub classes of the extended type; without the need of ugly casts.

How to find a class of type variable in Java? [duplicate]

This question already has answers here:
Get generic type of class at runtime
(30 answers)
How do I get a class instance of generic type T?
(23 answers)
Closed 7 years ago.
How can I find the class of XOperation via Reflection API in Java?
public interface Operation<P extends Parameters> {
}
public class XParameters implements Parameters<XOperation> {
}
I'm trying to implement this method.
public <O extends Operation<P>, P extends Parameters> O getOperationByParametersClass(Class<P> parametersClass) {
// TODO
}
You can introduce a member in Parameters that will hold the Class of the type-parameter.
For example:
abstract class Parameters<T> {
protected Class<T> type;
}
Then, in the getOperationByParametersClass() method, you should pass an instance of Parameters (including subclasses):
public <O extends Operation, P extends Parameters<O>> Class<O>
getOperationByParametersClass(P parametersInstance) {
return parametersInstance.type;
}

Java - anonymous instance of abstract class [duplicate]

This question already has answers here:
Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?
(19 answers)
Closed 8 years ago.
Type mismatch: cannot convert from BytecodeCodeProcessor<new AbstractBytecodeCodeVisitor(){}> to BytecodeCodeProcessor<AbstractBytecodeCodeVisitor>
public abstract class AbstractBytecodeCodeVisitor {
}
public class BytecodeCodeProcessor
<T extends AbstractBytecodeCodeVisitor> {
public BytecodeCodeProcessor(ClassSourceResult classSourceResult,
T visitor) {
}
}
BytecodeCodeProcessor<AbstractBytecodeCodeVisitor> processor =
new BytecodeCodeProcessor<>(classSourceResult,
new AbstractBytecodeCodeVisitor() {
});
The anonymous class instantiated via new AbstractBytecodeCodeVisitor() {} is a subclass of AbstractBytecodeCodeVisitor. This anonymous subclass is not equal to the generic type parameter specified by BytecodeCodeProcessor<AbstractBytecodeCodeVisitor>. Anonymous AbstractBytecodeCodeVisitor != AbstractBytecodeCodeVisitor, thus the compilation error. The code can be fixed in numerous ways, some of which are listed in the following link.
Generics and anonymous classes (bug or feature?)
One solution:
BytecodeCodeProcessor<AbstractBytecodeCodeVisitor> processor =
new BytecodeCodeProcessor<AbstractBytecodeCodeVisitor>(
classSourceResult, new AbstractBytecodeCodeVisitor() {}
);

Get class name for the generic class argument [duplicate]

This question already has answers here:
Name of Class <T> of a generic Class
(2 answers)
Closed 9 years ago.
I want to find the class name of the argument sent to the generic class as follows.
public abstract class RootClass<T extends Iface> {
protected ApplicationContext applicationContext;
public T getIfaceBean() {
return applicationContext.getBean(T.class);
}
}
But it looks like I can't do T.class (due to Type Erasure?).
So, Is such an action possible with Java Generics ?
How can I achieve this type of functionality with Java Generics?
Because of Type Erasure, you can't say T.class because T doesn't exist at runtime.
The best you can do is to take a parameter of type Class<T> to get the Class object:
public T getIfaceBean(Class<T> clazz) {

Categories

Resources