我总是想知道如何仅仅通过实现一个接口,子类就获得了这种行为。例如,如果我实现 Runnable 接口,我的子类开始表现为线程,但如果我实现接口 Runnable 中定义的所有方法但不写“实现 Runnable”,子类不会表现为线程。与 EventListeners 相同。请帮助我理解这种行为。
7 回答
通过实现接口 I,您声明对象“是”I,并且它将包含此接口定义的所有方法。如果你只是实现了接口 I 的方法,而不是通过一个 implement 语句来声明它,编译器将无法确定你的类“是”I,你将无法将它用作我型。
当您实现时,Runnable
您的类不会成为线程并且不会以线程的形式开始行为。但是,如果您的类实现Runnable
了您可以在线程上下文中运行它:
class MyClass1 implements Runnable {
public void run() {
// this stuff will run in thread when thread's start() method is called
}
}
new Thread(new MyClass1()).start();
但是java是强类型语言。您可以像这样创建类:
class MyClass2 {
public void run() {
// this stuff will run in thread when thread's start() method is called
}
}
但它不会Runnable
。因此,您不能只将其发送到线程:
new Thread(new MyClass2()).start();
在这种情况下,您将收到编译错误。编译器无法知道您的类确实实现了看起来像在Runnable
. 您必须声明这一点(如第一种情况)。
ARunnable
只允许你的类在线程中运行。您仍然需要例如 ajava.util.concurrent.Executor
在实际线程中实际运行它。
但是,您可以extend Thread
调用Thread.start()
.
要真正从实现接口中获得行为,您需要第二个对象检查类路径以查找使用反射实现接口的类,然后对该类执行某些操作。
不,Runnable
与表现得像线程无关。它只包含一个简单的、简单的、无效的 null 方法,称为“run”。
不指定implements Runnable
只会使您的对象不是该Runnable
类型的实例,这意味着您将无法将其传递给需要Runnable
. 这只是类型安全的问题。您调用的方法也可以接受Object
并run
使用反射调用,具有完全相同的行为。
你的问题有两个方面:
- 接口作为契约:接口将行为契约强加给实现它的类。例如,如果
Car
是一个带有一些抽象定义汽车的方法的接口,那么任何实现Car
接口的类都必须定义汽车的方法。您可以自由地实际实施该行为。 Runnable
作为线程的类比是不正确的。使Runnable
类充当线程的是Thread class
.Runnable
只是指定一个类作为线程的契约。检查这篇文章。
这不是子类化行为。为了使用子类行为,您需要扩展类。
Wrt 接口这些只是由类实现的模板/合同。为了让runnable工作,调用程序需要实例化一个线程,当线程启动时,它将调用你的类实现的run方法。
我总是想知道如何仅仅通过实现一个接口,子类就获得了这种行为。
它不会“获得”任何“行为”。子类提供行为。实现接口所做的是提供编译时类型签名,以便您可以使用指定接口的子类。