首页 > 解决方案 > 我的“Runnable”实现无法解析已声明接口的对象上的方法

问题描述

Runnable在 Java 15 中有一个简单的实现。

package work.basil.example;

public class MonsterRunnable < Monster > implements Runnable
{
    private final Monster monster;

    // Constructor
    public MonsterRunnable ( Monster monster )
    {
        this.monster = monster;
    }

    @Override
    public void run ( )
    {
        this.monster.actOut(); //  Compiler error: Cannot resolve method 'actOut' in 'Monster'
    }
}

我的 IDE(IntelliJ 2020.3)中的编译器无法解析方法行上的actOut方法。this.monster.actOut(); run

然而,该方法已在界面上明确定义,如下所示。

package work.basil.example;

public sealed interface Monster
        permits Demon, Witch
{
    String name ( ); // This getter method implemented implicitly by `record` in our concrete classes `Demon` & `Witch`.

    public void actOut ( );  //  Method is declared, yet cannot be resolved in `Runnable`. 
}

我的小演示应用程序正在使用 Java 15 预览功能JEP 360: Sealed Classes (Preview)JEP 384: Records (Second Preview)。但我不明白这可能是这里的麻烦来源。


我想上面应该是足够的问题代码。但我可以展示接口的这对实现,Demon并且Witch.

package work.basil.example;

public record Demon(String name) implements Monster
{
    @Override
    public void actOut ( )
    {
        System.out.println( "This monster " + this.getClass().getSimpleName() + " named " + this.name + " buys a soul." );
    }
}

……和……</p>

package work.basil.example;

public record Witch(String name) implements Monster
{
    @Override
    public void actOut ( )
    {
        System.out.println( "This monster " + this.getClass().getSimpleName() + " named " + this.name + " casts a spell." );
    }
}

最后,这里是该actOut方法工作的演示——如果我this.monster.actOut();在有问题的方法中删除行run

package work.basil.example;

/**
 * Hello world!
 */
public class MonterMash
{
    public static void main ( String[] args )
    {
        System.out.println( "Hello World!" );
        MonterMash monterMash = new MonterMash();
        monterMash.demo();
    }

    private void demo ( )
    {
        Monster monster = new Witch( "Rowena" );
        System.out.println( "monster = " + monster );
        monster.actOut();
    }
}

运行时:

你好世界!

怪物=女巫[名字=罗维娜]

这个名叫罗伊娜的怪物女巫施展了一个咒语。

标签: javainterfacecompiler-errorsrunnable

解决方案


签名public class MonsterRunnable < Monster > implements Runnable引入了一个通用参数MonsterMonsterRunnable泛型参数使类.. 泛型。这意味着您可以使用任何类型的类。

例如,当您使用 a 时List<String><String>是参数,即元素的类型。List本身被声明为public interface List<E> extends Collection<E>. 请注意,这E是通用参数;类型变量List<String>使用该参数来引用Strings 列表。您还可以引用Integers:的列表List<Integer>。您可以使用List任何元素类型,因为它是通用的,因为它是通用的参数EE用于“元素”并且是 Java 约定:请参阅类型参数命名约定E用于List表示方法等。

因此,在您的示例中,泛型参数Monster“隐藏”了 type Monster,即您的类。引入的泛型类型Monster没有方法actOut,这是编译器告诉你的。

你想要的是monster一种可以扩展的类型Monster,简单的继承。因此,只需删除通用参数,您就会拥有所需的内容:

public class MonsterRunnable implements Runnable

您在评论部分的注释:

整个实验的实际目标是为 Runnable 实现声明一个泛型类型。

您需要表示泛型 inMonsterRunnable是以下的实现Monster

package work.basil.example;

public class MonsterRunnable < T extends Monster > implements Runnable
{
    private final T monster;

    // Constructor
    public MonsterRunnable ( T monster )
    {
        this.monster = monster;
    }

    @Override
    public void run ( )
    {
        this.monster.actOut();
    }
}

现在MonsterRunnable是通用的 using T,仅限于 extend (implement) Monster


推荐阅读