2015-08-10 2 views
1

У меня есть следующий сокращенный класс:Как установить конечное поле через сеттер?

public class Employee { 

    private final float pointPosition; 

    public Employee(float pointPosition) { 
     this.pointPosition = pointPosition; 
    } 

} 

Я хотел бы сделать проверку на pointPosition быть передаваемым в constuctor, чтобы убедиться, что она не превышает 1,0.

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

Я мог бы изменить конструктор, чтобы что-то вроде:

public Employee(float newPointPosition) { 
    verifyPointPosition(newPointPosition); //Will throw 
    this.pointPosition = pointPosition; 
} 

Но я бы предпочел, чтобы все это завернутый аккуратно в его собственном методе.

Какие у меня варианты?

+4

Были ли проверки метод просто возвращает входные данные. Я делаю это все время в C++ для членов const – Bwmat

+0

@Bwmat Рассмотрите возможность превратить свой комментарий в ответ. –

+0

@Bwmat Хорошая точка. – Carcigenicate

ответ

2

Вариант 1: Не делайте это окончательный

Вы могли бы просто не сделать его окончательным и сделать сеттер частным.


Вариант 2: Выполните проверку и установить в конструкторе

Вот что вы уже показали.


Вариант 3: хаком путь

Вы можете установить окончательные переменные с отражением, однако я бы определенно не рекомендую это, если вы не вынуждены.


Я бы с Вариантом 2. Если вы беспокоитесь, что ваш конструктор становится слишком грязным, вы можете просто создать дополнительные конструктор и установить их частными, например:

public class MyClass { 
    private final float variable; 

    public MyClass(float variable) { 
     this(); 
     if(variable < 0.0f || 1.0f < variable) 
      throw new IllegalArgumentException("'variable' has to be between 0.0 and 1.0"); 
     this.variable = variable; 
    } 

    private MyClass() { 
     //Set everything else 
    } 
} 

На самом деле, этот код будет не компилировать.

+0

Пожалуйста, пожалуйста, никто никогда не делает # 3! –

+0

@tkausl Ваш пример для Варианта 2 на самом деле Вариант 1 - 'variable' больше не' final', иначе 'MyClass()' не будет компилироваться. –

2

Я рекомендую сделать это, просто завернув проход аргумента одним вызовом метода от конструктора.

Вы не сказали, что поведение, которое вы хотите, независимо от того, чтобы бросить исключение, если значение является недействительным, или просто дезинфицировать его к нормальному значению, но в любом случае это будет работать:

public class Employee 
    private static final float MAX_POSITION = 1.0f; 
    private final float pointPosition; 

    public Employee(float pointPosition) { 
    this.pointPosition = sanitizePointPosition(pointPosition); 
    } 

И тогда у вас есть два варианта:

  1. Бросьте исключение:

    private float sanitizePointPosition(float pointPosition) { 
        if(pointPosition > MAX_POSITION) { 
        throw new IllegalArgumentException("Point position must be <= " 
           + MAX_POSITION + ", it was: " + pointPosition); 
        } 
        return pointPosition; 
    } 
    
  2. Установите значение что-то нормальное

    private float sanitizePointPosition(float pointPosition) { 
        return pointPosition > MAX_POSITION ? MAX_POSITION : pointPosition; 
    } 
    
Смежные вопросы