我的 Runnable 实现无法解析已声明接口的对象上的方法
My implementation of a `Runnable` cannot resolve a method on an object of a declared interface
我在 Java 15.
中有一个简单的 Runnable
实现
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) 中的编译器无法解析 run
方法的 this.monster.actOut();
行上的方法 actOut
。
但是界面上明确定义了该方法,如下所示。
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) and 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." );
}
}
……和……
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
方法工作的演示 — 如果我在有问题的 run
方法中删除行 this.monster.actOut();
。
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();
}
}
当运行:
Hello World!
monster = Witch[name=Rowena]
This monster Witch named Rowena casts a spell.
签名 public class MonsterRunnable < Monster > implements Runnable
为 MonsterRunnable
引入了通用参数 Monster
。通用参数使 class .. 通用。这意味着您可以将 class 与任何类型一起使用。
例如当您使用 List<String>
时,<String>
是参数,即元素的类型。 List
本身声明为 public interface List<E> extends Collection<E>
。请注意 E
是通用参数; List<String>
类型的变量使用该参数来引用 String
的列表。您还可以引用 Integer
的列表:List<Integer>
。您可以将 List
与任何元素类型一起使用,因为它具有通用参数 E
。 E
用于“元素”并且是 Java 约定:参见 Type Parameter Naming Conventions。 E
在List
中使用,表示方法等。
因此在您的示例中,通用参数 Monster
“隐藏”类型 Monster
,即 您的 class。引入的泛型类型 Monster
没有方法 actOut
,这是编译器告诉你的。
你要的是monster
是扩展Monster
的类型,简单继承。因此,只需删除通用参数即可获得所需内容:
public class MonsterRunnable implements Runnable
您在评论区的留言:
The actually goal of this entire experiment was to get a generics type declared for a Runnable implementation.
你需要说明 MonsterRunnable
中的泛型是 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
通过使用 T
是通用的,它仅限于扩展(实现)Monster
.
我在 Java 15.
中有一个简单的Runnable
实现
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) 中的编译器无法解析 run
方法的 this.monster.actOut();
行上的方法 actOut
。
但是界面上明确定义了该方法,如下所示。
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) and 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." );
}
}
……和……
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
方法工作的演示 — 如果我在有问题的 run
方法中删除行 this.monster.actOut();
。
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();
}
}
当运行:
Hello World!
monster = Witch[name=Rowena]
This monster Witch named Rowena casts a spell.
签名 public class MonsterRunnable < Monster > implements Runnable
为 MonsterRunnable
引入了通用参数 Monster
。通用参数使 class .. 通用。这意味着您可以将 class 与任何类型一起使用。
例如当您使用 List<String>
时,<String>
是参数,即元素的类型。 List
本身声明为 public interface List<E> extends Collection<E>
。请注意 E
是通用参数; List<String>
类型的变量使用该参数来引用 String
的列表。您还可以引用 Integer
的列表:List<Integer>
。您可以将 List
与任何元素类型一起使用,因为它具有通用参数 E
。 E
用于“元素”并且是 Java 约定:参见 Type Parameter Naming Conventions。 E
在List
中使用,表示方法等。
因此在您的示例中,通用参数 Monster
“隐藏”类型 Monster
,即 您的 class。引入的泛型类型 Monster
没有方法 actOut
,这是编译器告诉你的。
你要的是monster
是扩展Monster
的类型,简单继承。因此,只需删除通用参数即可获得所需内容:
public class MonsterRunnable implements Runnable
您在评论区的留言:
The actually goal of this entire experiment was to get a generics type declared for a Runnable implementation.
你需要说明 MonsterRunnable
中的泛型是 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
通过使用 T
是通用的,它仅限于扩展(实现)Monster
.