Можно ли объявить самоисполняемый работоспособным? - PullRequest
3 голосов
/ 13 декабря 2011

Как так?

abstract public class BaseTask extends Runnable {
    public BaseTask(ParamA aParam) {
         // do something with aParam
         StaticExecutorService.submit(this);
    }
}

public class AbcTask extends BaseTask {
    public ABC(ParamA aParam, ParamB bParam) {
        super(aParam);
    }
    @Override
    public void run() {

    }
}

Затем класс можно просто создать и поставить в очередь на выполнение, выполнив

new AbcTask();
  1. Я не уверен, что это нормально, потому что, возможно, он все еще создается, когда ExecutorService решает выполнить AbcTask?

  2. Если вы по какой-либо причине не рекомендуете это, укажите и уточните.

Спасибо

Ответы [ 4 ]

2 голосов
/ 13 декабря 2011

Это может сработать (по крайней мере, я не достаточно знаком с Java, чтобы понять, почему это не так), но я бы не рекомендовал его, поскольку он вводит слишком сильную связь: AbcTask будет привязано к StaticExecutorService и будет менее многоразовым, чем это может быть легко. Это также затруднит тестирование и отладку AbcTask.

Кроме того, вы «перегружаете» смысл конструирования объекта, складывая в него представление для исполнителя. Что если позже вы решите, что хотите что-то сделать с AbcTask объектами между их созданием и отправкой?

1 голос
/ 13 декабря 2011
  1. Его тесно связаны
  2. В Effective Java Джошуа Блох объяснил, почему не рекомендуется вызывать защищенный / публичный метод из конструктора. См. Второе издание, СН-4: конструкторы не должны вызывать переопределяемые методы, напрямую или косвенно .

    StaticExecutorService.submit(this);
    

    Выше строки вызовет открытый метод run из конструктора, и это не ожидается.


Объяснение из книги: Конструкторы не должны вызывать переопределяемые методы, напрямую или косвенно

Если вы нарушите это правило, произойдет сбой программы. Конструктор суперкласса запускается до конструктора подкласса, поэтому метод переопределения в подклассе получит вызывается до запуска конструктора подкласса. Если метод переопределения зависит при любой инициализации, выполняемой конструктором подкласса, метод не будет ведите себя как положено.

1 голос
/ 13 декабря 2011

Мы не должны использовать this, пока конструктор не будет завершен.

Объект создается полностью после завершения его проверки.поэтому объект, переданный в StaticExecutorService, может быть создан не полностью и не может быть использован.

Я не знаю, поддерживает ли спецификация мое утверждение выше.но я так чувствую.

Следовательно, в соотв.для меня этого следует избегать.

0 голосов
/ 13 декабря 2011

В вашем примере это, вероятно, будет работать , но , так как вызов super() должен быть первым в дочерних классах BaseTask, это означает, что конструктор не сможет выполнить какую-либо операцию до подачи задания.

Из вашей выборки второй параметр использовать нельзя, поскольку задача будет отправлена ​​до того, как вы сможете назначить ее атрибуту.

Если мы рассмотрим следующий код:

public class MyTask extends BaseTask {
    public ABC(ParamA aParam, String name) {
        super(aParam);
        this.name = name == null ? "Default Value" : name;
    }
    @Override
    public void run() {
         System.out.println("Name length: "+ name.length());
    }
}

Поскольку run() может быть вызван до присвоения this.name, строка System.out может заканчиваться NullPointerException

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...