#java
#java
Вопрос:
Рассмотрим эту программу:
public class test {
public static void main(String [] args){
Runnable r = new Runnable() {
public void run() {
System.out.print("foo");
}
};
Thread t = new Thread(r) {
public void run() {
System.out.print("bar");
}
};
t.start();
}
}
При запуске вывод
bar
Я хотел бы знать, почему это так.
Мое понимание:
Мы создаем экземпляр анонимного внутреннего класса, который реализует Runnable, переопределяя метод run. И назначьте его r.
Затем мы передаем этот runnable конструктору класса Thread. Но мы также создаем новый анонимный внутренний класс, который расширяет поток, переопределяя run.
Итак, теперь у нас есть два метода запуска, и 2-й будет иметь предпочтение перед 1-м.
Я в замешательстве, пожалуйста, поправьте меня, если я ошибаюсь.
Также используются ли такие сумасшедшие вещи в реальном программировании на Java? (Мой профессор говорит «да», и это то, что заставляет нас двигаться дальше : D).
Ответ №1:
Хотя вы передаете исполняемый экземпляр конструктору, вы переопределяете метод run таким образом, что он не используется r
.
Ответ №2:
Происходит то, что стандартный Thread.run
метод вызывает run
тот Runnable
, который вы передали. В вашем случае вы переопределяете поведение потока и заменяете его run
методом, который игнорирует заданное Runnable
.
К сожалению, такие сумасшедшие вещи действительно происходят в реальном мире. Вот почему рекомендуется использовать инструменты статического анализа и модульные тесты, чтобы убедиться, что вы получаете ожидаемое поведение 🙂
Ответ №3:
Вы переопределяете поведение потока по умолчанию, когда переопределяете его метод run(). Таким образом, вы контролируете порядок и выполняется ли r
вообще.
public void run() { // ignores "r"
System.out.print("bar");
}
или
public void run() {
super.run(); // runs "r" first.
System.out.print("bar");
}
или
public void run() {
System.out.print("bar");
super.run(); // runs "r" second.
}
или
public void run() {
super.run(); // runs "r" first.
System.out.print("bar");
super.run(); // and runs "r" second.
}
или
public void run() {
r.run(); // runs "r" first.
System.out.print("bar");
r.run(); // and runs "r" second.
}
Ответ №4:
Метод Thread.run()
обычно проверяет, был ли поток создан с помощью runnable. В этом случае он вызывает Runnable.run()
, в противном случае ничего не делает. Вы изменили это поведение, переопределив Thread.run()
и, таким образом, ваш runnable никогда не вызывается.