当前位置: 首页 > 面试题库 >

Java-当返回类型对自己的方法参数类型使用泛型时,覆盖扩展接口的返回类型

卫才哲
2023-03-14
问题内容

我偶然发现了对Java继承的好奇心,我希望您对此提出更好的想法:

假设两个接口A和A1

接口A1扩展了A

接口A具有返回泛型类型的方法。

通用类型将是GenericType<T>

现在的基本思想是将这种通用返回类型从GenericType<Object>接口A中更改 为 GenericType<String>接口A1中的

一开始似乎很容易(不好的事情会在以后出现)

我们将接口A声明为

public interface InterfaceA {
  public GenericType<? extends Object> getAGenericType();  
}

和接口A1一样

public interface InterfaceA1 extends InterfaceA
{
  @Override
  public GenericType<String> getAGenericType();
}

如您所见,我们被迫编写GenericType<? extends Object>接口A本身,以允许使用基于泛型的“子类”覆盖它。(实际上,generictype的generic参数是子类,而不是generic类型本身)

现在,假设GenericType有自己的方法,如下所示:

public interface GenericType<D>
{
  public void doSomethingWith( D something );
}

现在尝试实例化A1效果很好。

而是试图实例化A会很烂。要了解为什么要看这个“使用接口”类:

public class LookAtTheInstance
{
  @SuppressWarnings("null")
  public static void method()
  {
    InterfaceA a = null;
    InterfaceA1 a1 = null;

    GenericType<String> aGenericType = a1.getAGenericType();

    GenericType<? extends Object> aGenericType2 = a.getAGenericType();
    Object something = null;
    aGenericType2.doSomethingWith( something );
  }
}

您问:“现在呢?”

它不适用于最后几行。实际上,参数“某物”甚至不是来自“对象”类型,而是来自“?扩展对象”类型。因此,您不能传递声明的“对象”类型。您什么都不能传递。

因此,您最终需要声明漂亮的接口,事实证明,该接口无法正确实例化。

您是否有想法如何对这样的用例建模,在该用例中,子类将必须覆盖返回类型,而返回类型是泛型?

或者您将如何处理这样的模型案例?

还是我只是在通用声明中遗漏了一个简单的观点,而我的示例可以通过这种方式进行?

-----------(1)根据答案进行编辑-----------

一个非常好的基本想法是使接口更加抽象!首先我有完全相同的想法,但是…(这是必须的)

假设这样做:

我们介绍了一个新的接口AGeneric

public interface InterfaceAGeneric<T>{
  public GenericType<T> getAGenericType();
}

现在,我们必须从这个新接口扩展A和A1:

public interface InterfaceA extends InterfaceAGeneric<Object>{}
public interface InterfaceA1 extends InterfaceAGeneric<String>{}

这样做很好,尽管它打破了原始继承的路径。

如果我们希望A1仍可从A扩展,则必须将A1更改为

public interface InterfaceA1 extends InterfaceA, InterfaceAGeneric<String>{}

再有一个问题。这是行不通的,因为我们用不同的泛型类型间接扩展了相同的接口。不幸的是,这是不允许的。

你看到问题了吗?

--

并指出另一种情况:

如果GenericType<? extends Object>GenericType<Object>其强制转换为显然有效。例:

public class LookAtTheInstance
{
  public static void main( String[] args )
  {
    InterfaceA a = new InterfaceA()
    {
      @Override
      public GenericType<? extends Object> getAGenericType()
      {
        return new GenericType<Object>()
        {
          @Override
          public void doSomethingWith( Object something )
          {
            System.out.println( something );
          }
        };
      }
    };
    ;

    @SuppressWarnings("unchecked")
    GenericType<Object> aGenericType2 = (GenericType<Object>) a.getAGenericType();

    Object something = "test";
    aGenericType2.doSomethingWith( something );
  }  
}

所以对我来说,方法参数类型的解析

public interface GenericType<D extends Object>
{
  public void doSomethingWith( D something );
}

是错的。

如果D与“?extended Object”统一,为什么不将参数类型强制为“ Object”?

这样会更有意义吗?


问题答案:

现在的基本思想是将这种通用返回类型从接口A中的GenericType更改为接口A1中的GenericType

这是不可能的,因为 Java泛型是不变的 。[1]

如您所知,您不能在接口中声明要返回的方法,GenericType<Object>而在子接口中则要覆盖要返回的方法GenericType<String>:后者的返回类型不是前者的子类型。并且有充分的理由!

你试图

使用不同的泛型类型间接扩展相同的接口。不幸的是,这是不允许的。

这不可能行得通:例如,同时实现和的类E中的public E set(int index, E element)in
类型应该是什么?您的子类化接口将必须产生类似的混合体:子接口中的返回值必须同时实现和接口。正如我们所看到的,这是不可能的。List<String>``List<Object>``getAGenericType``GenericType<String>``GenericType<Object>

编译器不知道您要使用type参数做什么GenericType(尽管理论上可以找到,但事实并非如此)。如果您有一个类型为变量的变量,GenericType<String>GenericType<Object>为其分配了a变量,那么您很可能最终将一个Long实例String预期为a,而将一个实例预期为a
ClassCastException

doSomethingWith您的变量方法中,您GenericType<? extends Object> aGenericType2可以传递一件事:nullnull是唯一具有子类型的对象引用? extends Object的下限类型? extends Object是null类型,不能用Java表示,只能作为null引用的类型隐式存在。

[1]
http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29#Java



 类似资料:
  • 我有一个问题,从抽象类中重写泛型方法。 这是我的抽象类: 当我创建类(B)来实现类(a)时,如下所示: 显示了(getData)方法中的以下编译错误: ”“B。getData“(“字符串函数(字符串)”不是“a”的有效重写。getData'('字符串函数(类型)‘)。dart(无效覆盖) 以及返回语句中的此错误: 类型为“String”的值不能从方法'getData'返回,因为它的返回类型为'St

  • 我试图创建一个返回泛型类型参数的方法。 我有一个类车辆订单扩展抽象类订单。在类订单中,我创建了一个抽象方法接收HiredObject。这个方法不会接收任何参数,并将返回一个泛型。 我在VehicleOrder类中实现了这个方法,并将其设置为返回类参数vehicle。 问题是,当我实例化一个新的VeilceOrderorororororororororororororderororororororo

  • 我试图创建一个Java方法,它接受一个对象类型和它应该转换成的数据类型。 例如,如果我应该能够返回一个值1作为Int或双根据需要。我使用类传递数据类型作为参数。 问题:如何使方法泛型以接受基于输入参数的返回类型? 下面的代码只是一个示例,它可能在语法上不正确,用于解释我的问题。

  • 问题内容: 背景 我曾经写过这种方法: 应该这样称呼它: 这很好用(尽管我在研究当前容易出错的问题时在这里的答案中已经看到)。 目前的情况 无论如何,现在我正在编写以下代码(在扩展javax.servlet.jsp.tagext.TagSupport的类中): 目的是可以这样称呼: 我的评估方法中的代码显然不起作用。的第二个参数应该是Class对象。这导致我: 我的问题 如何获得通用(返回)类型的

  • 问题内容: 在Java中,您可以执行以下操作: 虽然这很好地解决了我一直在努力解决的问题,但与此有关的某些“感觉”是错误的。 我在这里犯一些讨厌的设计假舞曲吗? 问题答案: 不,您做对了。协变量返回仅指定该类及其下的类必须返回父类返回的原始常规类参数的特定子类。这也意味着您的子类仍与要求其返回Engine的原始接口兼容,但是如果您 知道 它是ICoolCar,则它具有ICoolEngine-因为更