Предотвращение создания экземпляра класса, если аргумент для конструктора является незаконным?

У меня есть открытый конструктор, который принимает параметр (int age) для создания объекта. Я хочу проверить, является ли переданный параметр законным или нет, например, возраст не может быть отрицательным. Если это незаконно, то не создавайте объект/экземпляр. Если это законно, не проблема.

Я могу только думать об одном способе сделать это -

Сделать конструктор закрытым. Создайте статический метод с параметром (int age), чтобы выполнить все проверки и вернуть null, если вы передадите ему незаконное значение. Если вы передадите ему юридическое значение, создайте объект и верните его ссылку. Есть ли другой способ сделать это? Может быть, внутри самого конструктора?

РЕДАКТИРОВАТЬ: Я думал об одной проблеме с указанным выше методом. Метод создателя метода/объекта factory может быть только статическим методом по очевидным причинам. Что произойдет, если метод factory должен получить доступ к переменной-члену (чтобы выполнить некоторую проверку) для создания объекта? Затем мы будем вынуждены сделать эту переменную-членом статической. Во всех случаях это может быть не совсем нормально.

Имеет ли смысл?

Ответ 1

Есть ли другой способ сделать это? Может быть, внутри самого конструктора?

Да. Я предлагаю выбросить Exception из конструктора

public class Person
{


    int age;
    public Person(int age) throws Exception
    {
       if(age <= 0)
       {

          throw new Exception("Age is not allowed");
       }
       // Do some stuffs
       this.age = age;
    }

}

Edit:

Вы также можете использовать IllegalArgumentException, как предложено Till Helge Helwig

public class Person
{


    int age;
    public Person(int age) throws IllegalArgumentException
    {
       if(age <= 0)
       {

          throw new IllegalArgumentException("Age is not allowed");
       }
       // Do some stuffs
       this.age = age;
    }

}

Ответ 2

Рассмотрим этот пример: реализация java.util.HashMap

public HashMap(int initialCapacity, float loadFactor) {
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal initial capacity: " +
                                           initialCapacity);
    if (initialCapacity > MAXIMUM_CAPACITY)
        initialCapacity = MAXIMUM_CAPACITY;
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
        throw new IllegalArgumentException("Illegal load factor: " +
                                           loadFactor);

    // Find a power of 2 >= initialCapacity
    int capacity = 1;
    while (capacity < initialCapacity)
        capacity <<= 1;

    this.loadFactor = loadFactor;
    threshold = (int)(capacity * loadFactor);
    table = new Entry[capacity];
    init();
}

см. больше в Effective Java 2nd Edition, Item 38: Check parameters for validity Джошуа Блоха, который также является автором вышеуказанного кода

Ответ 3

Для этого лучше использовать статический factory. Потому что бросать исключение из конструктора не очень хорошая идея.

public class Person
{     
    public static Person newPerson(int age) /* throws SomeException -- if you want */ {
        if (age <= 0 || age >= 150) {
           return null; // or throw an Exception - it is how you want   
        }
        return new Person(age);
    }

    private Person(int age) {
        // assign age to field value
    }
}

Ответ 4

Скорее бросьте Exception, если параметр является незаконным.

public Test(int age) throws IllegalArgumentException {
    if(age<0)
        throw new IllegalArgumentException(...);
    this.age = age;
}