Подтвердить что ты не робот

Могу ли я вызвать методы в конструкторе в Java?

У меня есть ситуация, когда я хочу читать файл конфигурации только один раз, когда экземпляр класса создается.

Предположим, что у меня есть метод с именем readConfig(), который читает конфигурацию и помещает ее в объект Map. Когда программа должна использовать значение конфигурации, она считывает объект с помощью ключа define. Я хочу знать, что конструктор вызывает только один раз в жизненном цикле. Могу ли я поместить мой метод readConfig() в конструктор, который даст мне преимущество однократного вызова или есть другой механизм для этого?

4b9b3361

Ответ 1

Лучше будет дизайн

public static YourObject getMyObject(File configFile){
    //process and create an object configure it and return it
}

Ответ 2

Вы можете: для этого нужны конструкторы. Также вы даете понять, что объект никогда не строится в неизвестном состоянии (без загрузки конфигурации).

Вы не должны: вызов метода экземпляра в конструкторе опасен, потому что объект еще не полностью инициализирован (это относится главным образом к методам, чем можно переопределить). Известно, что сложная обработка в конструкторе отрицательно влияет на тестируемость.

Ответ 3

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

Одним из решений является предоставление методов, которые вы можете вызвать для запроса "здоровья" объекта после его создания. Например, метод isConfigOK() может использоваться для проверки работоспособности операции чтения конфига.

Другим решением является бросить исключения в конструкторе после сбоя, но это действительно зависит от того, насколько "фатальными" являются эти сбои.

class A
{
    Map <String,String> config = null;
    public A()
    {
        readConfig();
    }

    protected boolean readConfig()
    {
        ...
    }

    public boolean isConfigOK()
    {
        // Check config here
        return true;
    }
};

Ответ 4

Вы можете. Но, разместив это в конструкторе, вы тщательно проверяете свой объект.

Вместо этого вы должны:

  • предоставить конфигурацию установщиком
  • имеют отдельный метод init()

Вредоносные программы для инъекций дают вам эти параметры.

public class ConfigurableObject {
   private Map<String, String> configuration;
   public ConfigurableObject() {

   }

   public void setConfiguration(..) {
       //...simply set the configuration
   }
}

Пример второй опции (лучше всего используется, когда объект управляется контейнером):

public class ConfigurableObject {
   private File configFile;
   private Map<String, String> configuration;
   public ConfigurableObject(File configFile) {
       this.configFile = file;
   }

   public void init() {
       this.configuration = parseConfig(); // implement
   }
}

Это, конечно, можно записать, просто имея конструктор

public ConfigurableObject(File configfile) {
    this.configuration = parseConfig(configFile);
}

Но тогда вы не сможете предоставить макет конфигурации.

Я знаю, что второй opttion звучит более многословно и подвержен ошибкам (если вы забыли инициализировать). И вам это не очень больно, если вы сделаете это в конструкторе. Но сделать ваш кодекс более ориентированным на зависимость, ориентированным, как правило, является хорошей практикой.

Первый вариант лучше - он может использоваться как с каркасом DI, так и с ручным DI.

Ответ 5

Шаблон Singleton

public class MyClass() {

    private static MyClass instance = null;
    /**
    * Get instance of my class, Singleton
    **/
    public static MyClass getInstance() {
        if(instance == null) {
            instance = new MyClass();
        }
        return instance;
    }
    /**
    * Private constructor
    */
    private MyClass() {
        //This will only be called once, by calling getInstanse() method. 
    }
}