Java泛型似乎对类的工作方式与方法的工作方式不同。

2022-09-02 11:36:03

我正在关注这个:

http://rickyclarkson.blogspot.com/2006/07/duck-typing-in-java-and-no-reflection.html

我试图适应这个:

<T extends CanQuack & CanWalk> void doDucklikeThings(T t)
{
    t.quack();
    t.walk();
}

对此:

public class Activate<D extends CanQuack & CanWalk> {

    D d = new MyWaterFowl(); //Type mismatch
}

即使MyWaterFowl实现了这些接口。

我想要一个在<>中从不提及MyWaterFowl的解决方案,因为我最终将注入它(或其他任何实现这些接口的东西)。


如果你的答案基本上是“你不能那样做,那会是什么类型?请解释为什么它适用于doDucklikeThings方法,并最终说明是否不可能对类执行相同的操作,或者如果可能的话,如何执行此操作。

doDucklikeThings中的T必须是有效的东西,因为它正在工作。如果我把它传到一个班级里,我会传给什么?


根据要求,以下是MyWaterFowl代码:

package singleResponsibilityPrinciple;

interface CanWalk { public void walk(); }
interface CanQuack { public void quack(); }
interface CanSwim { public void swim(); }


public class MyWaterFowl implements CanWalk, CanQuack, CanSwim {

    public void walk() { System.out.println("I'm walkin` here!"); }
    public void quack() { System.out.println("Quack!"); }
    public void swim() { System.out.println("Stroke! Stroke! Stroke!"); }
}

请记住,我已经确认了doDucklikeThings的工作原理。我需要语法,让我注入任何实现所需接口的东西。


答案 1

这不起作用,因为类/方法是泛型的,并且类/方法的调用方可以设置为 。DMyAmericanEagle

 Activate<MyAmericanEagle> active = new Activate<>();

然后你的代码将导致

 MyAmericanEagle d = new MyWaterFowl(); 

由于这毫无意义(将导致ClassCastException),编译器拒绝它。


答案 2

// Type mismatch

即使MyWaterFowl实现了这些接口。

这与实现这些接口(和/或扩展类)的类型无关。泛型类型变量绑定到特定的类型参数。该类型可能与以下类型完全不同,因此您无法互换使用它们。DMyWaterFowl


为了回答您的编辑,您在两个片段中做了两件完全不同的事情。类型变量是使用一些边界声明的。因此,它保证是实现某些接口(或扩展某些类)的类型,但在这两种情况下,您都不知道该类型是什么类型。


我想澄清你做的两件事,即。您对问题的期望以及您在答案中给出的解决方案。

泛型是一种编译时功能,其中服务器代码,例如

class Activate<D extends CanWalk & CanQuack> {
    D instance;
    public Activate(D d) {
        this.instance = d;
    }

    public D getInstance() {
        return instance ;
    }
}

声明类型变量。这是一个变量。在其声明上下文中,您在编译时不知道其确切类型。

例如,客户端代码,

new Activate<>(new MyWaterFowl());

将类型绑定到 中声明的类型变量。因此,客户端代码知道编译时的内容。MyWaterFowlActivateD

如果出现以下情况

public D getInstance() {
    D someRef = new MyWaterFowl();
    return someRef;
}

在服务器代码中允许,这将失败

Activate<SomeOtherBird> activate = new Activate<>(new SomeOtherBird());
SomeOtherBird reference = activate.getInstance();

泛型保证它是类型安全的,因为它被声明为返回绑定到类型变量的任何类型。在本例中,即 。如果允许上述代码,类型安全将被破坏,因为将返回与绑定到它的内容不同的内容。getInstance()DSomeOtherBirdgetInstance()getInstance()

这并不能改变这样一个事实,即在服务器代码(泛型类)中,您确实知道 的边界,即。它既是 a 又是 .因此,这些类型的对象可以执行的任何操作,变量引用的对象也可以执行。DCanQuackCanWalkD


推荐