为什么 Thread 不是一个抽象类,start()不是 final?

为什么 Thread类被实现为一个常规类,而不是一个具有抽象 run()方法的 摘要类。

它会引起什么问题吗? 或者它这样做有什么用处吗?

此外,Thread.start()方法应该是一个非常特定的方法 其功能不能被任何其他类实现(如果我没有错的话)。因此,我认为 final关键字比其他任何方法都更适合这种情况。

但是我可以重写这个方法并随心所欲地使用它,

public class Test extends Thread {
public static void main (String... args) {
Thread test = new Test();
test.start();
}


@Override
public void run() {
System.out.println("New thread started...");
}


@Override
public void start() {
System.out.println("Did anyone tell you I will spawn a new thread??");
}
}

很明显,它只是打印出来,

有没有人告诉你,我会产生一个新的线程? ?

除了让接替你的工程师感到困惑之外,重写还有什么用处吗?

如果没有,为什么在 Thread 类中没有将方法声明为 final?

8929 次浏览

你当然可以选择搬起石头砸自己的脚,但这并不意味着你必须这么做。

为什么 Thread 类实现为常规类而不是具有 run ()方法的抽象类。

因为建议的创建线程启动的方法不是子类 Thread。推荐的方法是定义一个 Runnable,并将其作为参数传递给 Thread 构造函数:

Runnable r = new Runnable() {
@Override
public void run() {
...
}
};
Thread t = new Thread(r);
t.start();

因此,我认为 final 关键字比其他任何方法都更适合于此。

是也不是。您不能用自己的实现替换 start ()的实现,但是如果您愿意,可以在 start ()中执行 附加费的操作:

@Override
public void start() {
System.out.println("Did anyone tell you I will spawn a new thread??");
super.start();
}

也就是说,如果今天重新设计 Java,很有可能它的设计会有所不同。请记住,这个类可以追溯到 Java 1.0,并且仍然是向后兼容的。

为什么 Thread 类实现为常规类而不是 方法是抽象的抽象类。

这个问题实际上可以归结为这样一个事实: 您应该总是更喜欢组合而不是继承。

如果将 Thread类声明为 abstract,则该语言必须提供另一个从它扩展的类,程序员可以使用该类创建 Thread。那么你的问题就是为什么 Thread中的 extends不是 abstract。如果该语言没有提供来自 Thread的另一个 extends类,程序员将不得不创建来自 Thread的自己的 extend类并覆盖 abstract0方法。

如果没有,为什么在 Thread 类中没有将方法声明为 final?

我能给出的唯一可能的解释是,当该类被引入 JDK 时,该语言的开发人员看到了一些重写 start的用例。我使用的 Java 的第一个版本是1.5,我个人还没有遇到过需要覆盖 start的用例。正如 JB Nizet 在他的回答中所说

如果今天的 Java 是从零开始重新设计的,那么设计很有可能会有所不同

为什么 Thread.start()不是 final

你是 当然你永远不会想要覆盖它吗?

Class MyThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
return new Thread(r) {
@Override
public void start() {
LOGGER.info("Starting thread " + this);
super.start();
}
};
}
}

我觉得应该张贴一些关于答案的校对:

“你确定你永远都不想重写它吗?”

不!我不会。这就像是说: “您确定要将这个变量声明为 private 吗?”因为如果我可以声明我作为公共使用的任何变量,而不用担心其他开发人员会扰乱我的设计逻辑,那么编写代码将是轻而易举的事情。OOPS 概念中的作用域、抽象、多态、错误处理等最重要的目的之一就是向其他开发人员传达代码背后的设计和意图。正如问题中指出的那样,当你覆盖 start 方法时,没有人强迫你使用 super.start ()。@ Codebender 没有使用 super.start ()为一个线程编写了一个 start 方法,编译器也从未抱怨过。所以他可以自由地打破整个线程和编译器的机制,假设只是让它通过?线程的 start 方法确保调用 run 方法并在正确的时间执行!这对于线程的概念非常重要。如果我遗漏了什么,我很乐意被纠正。 2.

因为创建线程的推荐方法是不要 子类线程。

好吧,如果设计允许代码转换器,转换线程并搞乱启动方法,按照这个逻辑,这是设计自己在踢自己的脚。 根据另一个声明(我完全同意) ,Runnable 是推荐的方法。那么为什么我们允许 Thread 类在没有任何限制的情况下实例化线程呢?其次是:

您不能用自己的代码替换 start ()的实现 实施,

这实际上支持了 codebender 的声明,当您说. . ^ 时,start 方法应该是 final

有一点是有效的,已经作为边注提到了,但是这个问题的 真正的答案

“向下兼容”。

事实上,在 JDK 5.0之前,改进就已经在进行了,当时他们对 Java 并发模型进行了许多主要的增加和澄清。我们希望所有的向下兼容都能得到支持,这就是为什么线程类仍然和以前一样,尽管现在推荐使用 Runnable 接口。

再说一次,如果我漏掉了什么,我非常乐意被纠正。