【问题标题】:Method argument extends class implements interface方法参数扩展类实现接口
【发布时间】:2012-05-17 18:38:19
【问题描述】:

我有以下类和接口:

public class BasicObject{...}
public interface CodeObject{...}

我想创建一个方法,其中参数需要是 BasicObject 类型并实现 CodeObject。我尝试了以下代码,但不能保证 clazz 是实现 CodeObject 的类。

myMethod(Class<? extends BasicObject> clazz){...}

我想做这样的事情,但它不编译:

myMethod(Class<? extends BasicObject implements CodeObject> clazz){...}

【问题讨论】:

标签: java


【解决方案1】:

您的模式类必须扩展BasicObject 并扩展/实现CodeObject(实际上是一个接口)。您可以使用方法签名的通配符定义中声明的多个类来执行此操作,如下所示:

public <T extends BasicObject & CodeObject> void myMethod(Class<T> clazz)

请注意,如果您使用以下任何一种方式,它都不会起作用:

  • public &lt;T extends BasicObject, CodeObject&gt; void myMethod(Class&lt;T&gt; clazz)

    这在技术上是有效的语法,但CodeObject 未被使用;该方法将接受任何扩展BasicObject 的类,无论它们是否扩展/实现CodeObject

  • public void myMethod(Class&lt;? extends BasicObject &amp; CodeObject&gt; clazz)
    public void myMethod(Class&lt;? extends BasicObject, CodeObject&gt; clazz)

    根据 Java,这些只是错误的语法。

【讨论】:

  • 关于“,”的部分,“CodeObject”的作用是什么?该类从“BasicObject”扩展而来,但是“CodeObject”呢?
  • 对我来说,它只有在我只使用 T 作为参数类型(没有类)时才有效。全线:public &lt;T extends BasicObject &amp; CodeObject&gt; void myMethod(T clazz)
  • 那么在方法中,如何在clazz对象上调用属于BasicObject的getter呢?
  • 有没有办法在布局 .xml 中做到这一点? &lt;variable name="myvar" type="T : BasicObject"/&gt; ?
  • 哇,这甚至可以与构造函数一起使用! ?
【解决方案2】:

这是一种有点冗长的方法,但可以避免泛型问题。创建另一个进行扩展/实现的类:

public abstract class BasicCodeObject 
    extends BasicObject 
    implements CodeObject {...}

那么你的方法可以是:

public <T extends BasicCodeObject> void myMethod(Class<T> clazz) {...}

【讨论】:

    【解决方案3】:

    有两种方法可以解决您的问题,具体取决于您是要在扩展 BasicObject 并实现 CodeObject 的方法参数中传递 类类型 还是 类对象强> 这样做。两者都有解决方案。

    解决方案 1:

    如果你想传递Class 本身,你可以这样做,正如@bontade 所解释的那样,

    public <R extends BasicObject & CodeObject> void myMethod(Class<R> clazz)
    

    如果你想传递class对象,你可以写

    public <R extends BasicObject & CodeObject> void myMethod(R clazz)
    

    以上是处理泛型的更复杂的方法。

    解决方案 2:

    以下是比较简单的。您可以定义一个抽象类来扩展您要扩展的类并实现它:

    public abstract class TargetClassType extends BasicObject implements CodeObject {
    
    }
    

    现在如果你想传递类本身,那么做

    public void myMethod(Class<TargetClassType> clazz)
    

    或者如果你想传递类对象,写

    public void myMethod(TargetClassType clazz)
    

    上述任一解决方案都适合您的问题,但第二个更简单。

    【讨论】:

      【解决方案4】:

      如果不是所有的 BasicObjects 都实现了 CodeObject,那么您可以在您的方法中使用 instanceof / Class.isInstance() 检查(参见http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html):

      myMethod(Class<? extends BasicObject> clazz)
      {
          if (!clazz.isInstance(CodeObject))
          {
              (indicate that the call was incorrect)
          }
          ...
      }
      

      【讨论】:

      • 是的,但我不想那样做。当然,任何方法都可以使用 myMethod(Object obj) 然后使用 'obj.isInstance(...)' 但这是我试图避免的。我真的希望我的方法的用户被强制传递一个好的参数。
      猜你喜欢
      • 2018-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-07
      • 1970-01-01
      • 2015-02-16
      相关资源
      最近更新 更多