Generic error:class is not applicable for the arguments - java

Can someone explain to me why the following code does not work?
public class TestGeneric {
EntityManager entityManager = new EntityManager();
public <T extends Textable & Entity> void doAction(T obj) {
entityManager.getAliasForEntityClass(obj.getClass());
}
}
class EntityManager {
public String getAliasForEntityClass(Class<? extends Entity> clazz) {
return clazz.getCanonicalName();
}
}
interface Entity {
Long getId();
}
interface Textable {
String getText();
}
I'm getting the following error:
The method getAliasForEntityClass(Class<? extends Entity>) in the type EntityManager is not applicable for the arguments
(Class<capture#1-of ? extends Textable>)
If I wrote in this way, I did not have any error:
public class TestGeneric {
EntityManager entityManager = new EntityManager();
public <T extends Entity & Textable> void doAction(T obj) {
entityManager.getAliasForEntityClass(obj.getClass());
}
}
class EntityManager {
public String getAliasForEntityClass(Class<? extends Entity> clazz) {
return clazz.getCanonicalName();
}
}
interface Entity {
Long getId();
}
interface Textable {
String getText();
}
Template <T extends Entity & Textable> and <T extends Textable & Entity> means: T must implements Entity and Textable interfaces. Why position of interface so important in this example?

The reason is that the erasure of T is the leftmost type in the bound. From the getClass() documentation:
The actual result type is Class<? extends |X|> where |X| is the
erasure of the static type of the expression on which getClass is
called.
The JLS specifies that "the erasure of a type variable is the erasure of its leftmost bound" (see here). So the type of obj.getClass() is Class<? extends Textable> in the first case and Class<? extends Entity> in the other.

Related

Incompatible types: inferred type does not conform to upper bound(s)

I was implementing some architecture when I saw the following error:
Error:(33, 55) java: incompatible types: inferred type does not conform to upper bound(s)
inferred: java.io.Serializable
upper bound(s): sandbox.ExpirePolicy,java.io.Serializable
The whole simplified code is below:
interface Configuration<K,V>{}
interface ExpirePolicy{}
interface Factory<T>{}
class FactoryBuilder {
public static <T extends Serializable> Factory<T> of(T instance){
System.out.println(instance.getClass());
return new Factory<T>() {};
}
}
class BaseConfiguration<K,V> implements Configuration<K,V> {
public BaseConfiguration<K,V> setExpiryPolicyFactory(Factory<? extends ExpirePolicy> factory){
return this;
}
}
class C<K,V> extends BaseConfiguration<K,V> {
public C<K,V> setExpiration(){
super.setExpiryPolicyFactory(FactoryBuilder.of((Serializable) getExpirePolicy()));
return this;
}
private ExpirePolicy getExpirePolicy(){
return new ExpirePolicy() {};
}
}
The exception is in trying to call setExpiryPolicyFactory(Factory<? extends ExpirePolicy> factory) with instance of Factory<Serializable>
But if i delete generic in extends BaseConfiguration<K,V> the program will be successfully compiled.
So the next declaration of class C is correct:
class C<K,V> extends BaseConfiguration {
public C<K,V> setExpiration(){
super.setExpiryPolicyFactory(FactoryBuilder.of((Serializable) getExpirePolicy()));
return this;
}
private ExpirePolicy getExpirePolicy(){
return new ExpirePolicy() {};
}
}
The question is: why the second implementation(of class C) will be successfully compiled and the first not?
UPD:
Simpler example of question (delete <T> from extends Base<T>) and program compiles well :
class Base<T> {
public void test(ArrayList<? extends CharSequence> list) {}
}
class Derived<T> extends Base<T> {
public void callTest() {
super.test(new ArrayList<Integer>());
}
}
When you delete <T> from extends Base<T> statement, the Base class starts to be treated as a raw type.
According to Java spec:
The supertype of a class may be a raw type. Member accesses for the
class are treated as normal, and member accesses for the supertype are
treated as for raw types. In the constructor of the class, calls to
super are treated as method calls on a raw type.
This means that super.test(...) call is also treated as method call on a raw type as if it has been declared like:
public void test(ArrayList list) {}
Thus no compilation errors happens.
It seems like the factory builder should take in an ExpirePolicy instead of Serializable for creating the factory. Changing the signature to
class FactoryBuilder {
public static <T extends ExpirePolicy> Factory<T> of(T instance){
System.out.println(instance.getClass());
return new Factory<T>() {};
}
}
enables using
class C<K,V> extends BaseConfiguration<K,V> {
public C<K,V> setExpiration(){
super.setExpiryPolicyFactory(FactoryBuilder.of(getExpirePolicy()));
return this;
}
private ExpirePolicy getExpirePolicy(){
return new ExpirePolicy() {};
}
}
without extra casts.
The second implementation of C compiles, but with warnings, because it's using raw types.

Missing type arguments for generic class

Using a library with an abstract class A and interfaces I and J, I get the following warning message when I extend / implement the class / interfaces:
Missing type arguments for generic class J<T>.
As a MWE, the classes are as follows (T and S are generic type parameters):
public abstract class A {}
public interface I<T extends A> {
public <S extends T> void doStuff(J<? super S> param);
}
public interface J<T extends A> {
public void doOtherStuff();
}
Here are my classes:
public class AExtended extends A {}
public class IImplemented implements I<AExtended> {
#Override
public void doStuff(J param) {}
}
Explicitly using the class AExtended as below does not properly implement doStuff() from I:
public class IImplemented implements I<AExtended> {
#Override
public void doStuff(J<AExtended> param) {}
}
You're not overriding doStuff in IImplemented because the method is not generic and the type bounds are not present. This version of doStuff should work for you:
public <S extends AExtended> void doStuff(J<? super S> param) {}
Notice that since the type of I is AExtended it is used appropriately here, and the lower bound in the wildcard type for J is also included.
try with:
public class IImplemented implements I<AExtended> {
#Override
public <S extends AExtended> void doStuff(J<? super S> param) {
// ...
}
}

Get actual enum class of the Parameterized class T extends Enum<?>

I have a class:
public class MultipleSorting<T extends Enum<?>> {
private T criteriaType;
public Class<T> getCriteriaClass() {
Field field = ReflectionUtils.getField(getClass(),"criteriaType");
ReflectionUtils.makeAccessible(field);
return (Class<T>)field.getType();
}
}
This class is get instantiated as:
public abstract class MultiSortPageableController<T extends MultiSortPageableController<?,?>, U extends Enum<?>> {
private MultipleSorting<U> multipleSorting;
public MultiSortPageableController() {
super();
multipleSorting = new MultipleSorting<U>();
}
}
The actual value of U is passed from the child class of MultiSortPageableController which is:
public abstract class AbstractArticleSearchController<T extends AbstractArticleSearchController<T>> extends MultiSortPageableController<T,ArticleSortField> {
}
The ArticleSortField is an Enum.
I was expecting the method getCriteriaClass of MultipleSorting would return ArticleSortField from a method of MultiSortPageableController. But it is returning java.lang.Enum.
I am unable to figure it out why it is not returning the actual enum and how can I make it so. Any pointer would be very helpful to me. I need to get ArticleSortField.
Purpose:
I two requirement:
To get the actual class of enum type (say ArticleSortField.class)
To list enum value. If I have the enum class, then I could invoke class..getEnumConstants().
Java compiler removes information about generics, therefore when you use reflection you get no information about the declared type, other than Enum. This process is called type erasure.
How about passing the type down, via the constructor, like this:
public class MultipleSorting<T extends Enum<?>> {
private Class<T> criteriaType;
MultipleSorting(Class<T> criteriaType) {
this.criteriaType = criteriaType;
}
public Class<T> getCriteriaClass() {
return criteriaType;
}
}
public abstract class MultiSortPageableController<T extends MultiSortPageableController<?, ?>, U extends Enum<?>> {
private MultipleSorting<U> multipleSorting;
public MultiSortPageableController(Class<U> criteriaType) {
super();
multipleSorting = new MultipleSorting<U>(criteriaType);
}
}
public abstract class AbstractArticleSearchController<T extends AbstractArticleSearchController<T>> extends MultiSortPageableController<T, ArticleSortField> {
public AbstractArticleSearchController() {
super(ArticleSortField.class);
}
}

Call base constructor with different arguments than subclass constructor

I'm sure this is a duplicate, but the keywords for my search are too common... I get a lot of hits, for things I'm not looking for. I'm coming from C#, and Java generics seem to be a bit behind the .NET implementation, so this is pretty frustrating for me.
I have an abstract class BaseRepository like so:
public abstract class BaseRepository<T, K> implements Repository<T, K> {
private Class<T> type;
private Class<K> keyType;
public BaseRepository(Class<T> clazz, Class<K> kClazz) {
type = clazz;
keyType = kClazz;
}
protected Class<T> getType() {
return type;
}
protected Class<K> getKeyType(){
return keyType;
}
}
Now I want to derive from my base class with an EmployeeRepository like so:
public class EmployeeRepository extends BaseRepository<Employee, UUID>{
}
With c#, I would not need to make such heroic efforts to instantiate the base class, but it seems java's implementation of generics requires you to pass the generic type(s) in the constructor.
So how do I create a parameterless constructor for my EmployeeRepository class that instantiates the base class with an entity type of Employee and a key type of UUID? I want to be able to write this:
EmployeeRepository foo = new EmployeeRepository();
... and have it instantiate the abstract class with Class<Employee> and Class<UUID>.
AFAIK, there is no way round this other than invoking the superclass constructor from the default subclass constructor thus:
public EmployeeRepository() {
super(Employee.class, UUID.class);
...
}
You could use reflection to determine the type of the generic arguments.
public abstract class BaseRepository<T, K> implements Repository<T, K> {
private Class<T> type;
private Class<K> keyType;
public BaseRepository() {
Type[] actualTypes = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments();
this.type = (Class<T>)actualTypes[0];
this.keyType = (Class<K>)actualTypes[1];
}
protected Class<T> getType() {
return type;
}
protected Class<K> getKeyType(){
return keyType;
}
}
However, the real question is: why do you want to have the types?
As an alternative, use the Builder pattern:
public class EmployeeRepository extends BaseRepository<Employee, UUID>{
public static EmployeeRepository newInstance() {
return new EmployeeRepository(Employee.class, UUID.class);
}
...
}
EmployeeRepository foo = EmployeeRepository.newInstance();

How to convert implementors on one interface into another?

I'm having trouble finding a way to do this in a way that doesn't seem wrong, given the following
public interface IType {}
public interface IMode {}
public interface Factory<T extends IType> {
IMode get(T o);
Class<T> getIType();
}
I have the above interfaces and a large list on classes the implement both IType and IMode with corresponding factories.
I need to be able to convert from one to the other, for example,
public class A implements IType {}
public class One implements IMode {}
public class AToOne implements Factory<A> {
public IMode get(A o){
return new One();
}
public Class<A> getIType(){
return A.class;
}
}
Given that there is a 1 to 1 mapping of these classes, ie for every concrete IType there is one and only one concrete IMode with corresponding factory, how would I go about converting a list of ITypes to a list of IModes?
ie.
private List<Factory<? extends IType>> factoryList;
public List<IMode> getConversions(List<? extends IType> types){
???
}
My first try did not go so well,
//Fill this using the getIType() method from each factory
Map<Class<IType>, Factory<? extends IType>> factoryList = new HashMap<Class<IType>, Factory<? extends IType>>();
public List<IMode> getConversions(List<IType> types){
List<IMode> modes = new ArrayList<IMode>();
for(IType type : types){
//Derp
Factory<? extends IType> factory = factoryList.get(type.getClass());
//Error
factory.get(factory.getIType().cast(type));
}
}
Error:
The method get(capture#12-of ? extends IType) in the type
Factory<capture#12-of ? extends IType>
is not applicable for the arguments (capture#14-of ? extends IType)
Like I mentioned in my comment, you just need to use a generic helper method to access the map, which performs an unchecked cast from Factory<? extends IType> to a Factory<T> where T matches the type of what's passed in:
Map<Class<? extends IType>, Factory<? extends IType>> factoryList =
new HashMap<Class<? extends IType>, Factory<? extends IType>>();
private <T extends IType> IMode convert(T iType) {
//unchecked cast - implementation must guarantee map holds correct data
Factory<T> factory = (Factory<T>)factoryList.get(iType.getClass());
//then convert
return factory.get(iType);
}
You can call this helper method from the loop:
public List<IMode> getConversions(List<IType> types) {
List<IMode> modes = new ArrayList<IMode>(types.size());
for (IType type : types) {
IMode iMode = convert(type);
modes.add(iMode);
}
return modes;
}
The simple solution is the following:
interface IFoo {
}
interface IBar {
}
private static class Foo implements IFoo {
}
private static class Bar implements IBar {
}
interface IFoo2IBarConverter<B extends IBar, F extends IFoo> {
B convert(F foo);
}
private static class Foo2BarConverter implements IFoo2IBarConverter<Bar, Foo> {
public Bar convert(Foo foo) {
return new Bar();
}
}
private static class IFoo2IBarFactory {
private static HashMap<Class<? extends IFoo>, IFoo2IBarConverter<? extends IBar, ? extends IFoo>> converters = new HashMap<>();
static {
converters.put(Foo.class, new Foo2BarConverter());
}
public static<F extends IFoo, B extends IBar> B convert(F foo) {
// ugly unchecked cast here
IFoo2IBarConverter<B, F> converter = (IFoo2IBarConverter<B, F>) converters.get(foo.getClass());
return converter.convert(foo);
}
}
public static void main(String[] args) {
Foo foo = new Foo();
IBar bar = IFoo2IBarFactory.convert(foo);
}
You just take a HashMap that maps a specific class that's a subtype of IFoo to some converter interface. The converter takes the IFoo instance and converts it into a IBar.. actually into the specific classes we want. Sadly we get an ugly cast in IFoo2IBarFactory.convert() and I don't think there's any way to avoid that one. Still at least it's only in one localized position and with the right comment and a SuppressWarning you can live with it, I'd think

Categories

Resources