How to cleanly handle unchecked conversion with generics in an interface?

∥☆過路亽.° 提交于 2019-12-12 04:34:31

问题


Simplified Code Example

public class SomeBaseClass {
}

public class SomeClass extends SomeBaseClass {
}

public interface SomeInterface {
public <T extends SomeBaseClass> T someMethod();
}

public class BestClass implements SomeInterface {
   // @SuppressWarnings("unchecked")
   @Override
   public SomeClass someMethod() {
      return null;
   }
}

More Detailed Code Example

// Base config class
public class BaseConfigClass {
}

// Some interface for all config classes to implement
public interface SomeInterface {
public <T extends BaseConfigClass> T getConfig();
}

// Class 'A' Config
public class ClassAConfig extends BaseConfigClass {
public doThingOnlyClassAKnows() {
}
}

//Class 'A'
public class ClassA implements SomeInterface {
   // @SuppressWarnings("unchecked")
   @Override
   public ClassAConfig getConfig() {
      return null;
   }
}

// Class 'B' Config
public class ClassBConfig extends BaseConfigClass {
public doThingOnlyClassBKnows() {
}
}

// Class 'B'
public class ClassB implements SomeInterface {
   // @SuppressWarnings("unchecked")
   @Override
   public ClassBConfig getConfig() {
      return null;
   }
}

...

new ClassA().getConfig().doThingOnlyClassAKnows()
new ClassB().getConfig().doThingOnlyClassBKnows()

I have several various SomeClass which extend SomeBaseClass of which an interface has return types of. I am using <T extends SomeBaseClass> to enforce that the return type is as expected.

The issue is that Java is unhappy with this an provides the following warning:

Type safety: The return type SomeClass for someMethod() from the type BestClass needs unchecked conversion to conform to T from the type SomeInterface

Besides just silencing the warning, I can avoid this by instead defining the interface as such:

public interface SomeInterface<T extends SomeBaseClass> {
public T someMethod();
}

But this ends up being very messy as this interface has several methods which each implement different base types; and I end up with a very long winded implements declaration.

Everything seems to be working as I would expect it to now but I feel as though my implementation is somehow wrong as I have to explicitly suppress this warning for each method defined by this interface.

Is there a clean way to design an interface like this without the warning but doesn't require a long-winded implements declararion?


回答1:


The reason the warning is displayed is because your solution is indeed not typesafe. A method with the signature <T extends BaseConfigClass> T getConfig() can return any subclass of BaseConfigClass. In particular, the following code will compile without warnings:

SomeInterface a = new ClassA();
ClassBConfig bConfig = a.getConfig();
bConfig.doThingOnlyClassBKnows();

but will throw a ClassCastException at runtime. (Well, actually, it throws a NullPointerException, but I assume you replaced the return null in your real code :-).

There are a few solutions. First, in your example, you don't use that interface. If you remove SomeInterface, you can still do new ClassA().getConfig().doThingOnlyClassAKnows(). If that interface is indeed never used, remove it!

The cleanest solution is the solution you already mentioned: give the interface a type parameter to tell it what type of object it will return. I understand you don't like this because you would need a lot of type parameters, but it is the cleanest solution.

If you really don't want to add the type parameters, I would simply remove the generics completely:

public interface SomeInterface {
    public BaseConfigClass getConfig();
}

In subclasses, you can still can return the more specific type:

public class ClassA implements SomeInterface {
    public ClassAConfig getConfig();
}

But if you only have a reference to the interface you will need to add a type cast:

SomeInterface a = new ClassA();
ClassAConfig aConfig = (ClassAConfig) a.getConfig();
aConfig.doThingOnlyClassAKnows();


来源:https://stackoverflow.com/questions/41525783/how-to-cleanly-handle-unchecked-conversion-with-generics-in-an-interface

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!