ProgramingTip

생성자에서 setter 호출

bestdevel 2020. 12. 4. 19:48
반응형

생성자에서 setter 호출


생성자 (있는 경우)에서 뮤 테이터를 호출하는 장단점은 무엇입니까?

즉 :

public MyConstructor(int x) {
  this.x = x;
}

대 :

public MyConstructor(int x) {
  setX(x);
}

public void setX(int x) {
  this.x = x;
}

선호하는 염기 서열? (이것은 숙제가 아닙니다. 생성자에서 인스턴스를 호출 할 때 항상 뮤 테이터를 호출하는 코딩 표준 문서를 찾아 보면 항상 그런 것이 아닙니다)


으로 개인적 대부분의 경우 변수를 직접 설정합니다 .

메소드일반적으로 인스턴스가 호출 될 때까지 완전히 제거 될 것으로 예상됩니다. 특히, 생성자에서 재정의 된 메소드를 호출하는 것은 이해하기 어려운 코드와 발견하기 어려운 버그에 대한 레시피입니다.

즉, 나는 종종 클래스가 존재하는 경우에는 세터가 없을 경우에도 당신이 있지만, 어쨌든 불변 만들려고하지만 당신이 말한 어쨌든 생성자에서 설정합니다 :)

속성에 논리가있는 경우 setter 논리는 일반적으로 유효성 검사이며 관찰자에게 전파를 변경합니다. 일반적으로 메소드 시작시 생성자 매개 변수가 명시 적으로 확인 될 예정 이며 인스턴스가 완전히 생성되기 전에 전파가 발생하는 것을 생성 합니다.


생성자에 대한 두 가지 규칙을 따라 문제를 최소화하기 때문에 mutator를 사용하지 않습니다.

최종 클래스가 아닌 생성자는 final 또는 private 메서드 만 호출해야합니다 . 이 규칙을 무시하고 생성자가 최종 / 비공개가 아닌 메소드를 호출 한 다음을 수행합니다.

  • 모든 메소드는 인스턴스가 완전히 초기화되면 가정하지 않아야합니다.
  • (슈퍼 클래스 생성자와 해당 메서드를 호출한다는 사실 인식하지 못하는 하위 클래스)는 하위 클래스 생성자와 슈퍼의 생성자가 완전히 실행하고 가정합니다. 이 문제는 "사악한"생성 된 수퍼 클래스가 상속 계층 구조에서 더 깊어 질수록 악화됩니다.

추가인지 검증이 그만한 가치가 있습니까? 인스턴스 변수에만 값을 할당하는 간단한 뮤 테이터에 대한 예외를 허용 할 수 있습니다. 그럴 가치가없는 것처럼 보이지만 거의 없기 때문입니다.

[[@Jon Skeet는 그의 답변에서 언급합니다. "... 특히 생성자에서 재정의 된 메서드를 호출하는 것은 이해하기 어려운 코드와 발견하기 어려운 만드는 방법입니다." 그러나 나는이 문제의 결과가 충분히 강조되지 않습니다. ]]

는 생성자 this인스턴스가 완전히 초기화되기 전에 누출에 대해주의해야 우리합니다 . 이전 규칙은 클래스 내부의 메서드와 바르에 액세스하는 하위 클래스에 관한 것이,완전히 초기화this되기 전에 다른 클래스 및 유틸리티 함수로전달되는메서드 (최종 / 개인용)에도주의해야합니다this. 생성자가 호출하는 비 개인 재정의 가능한 메소드가 많을수록this.


최종이 아닌 비공개 메서드를 호출하는 생성자에 대한 일부 참조 :

https://www.securecoding.cert.org/confluence/display/java/MET05-J.+Ensure+that+constructors+do+not+call+overridable+methods

http://www.javaworld.com/article/2074669/core-java/java-netbeans--overridable-method-call-in-constructor.html

http://www.javaspecialists.eu/archive/Issue210.html


나는 거의하지 않아 그 때문에 문제가 없었습니다. 특히 setter가 하위 클래스에서 재정의되거나 setter가 초기화 존재하지 않을 수있는 추가 메소드 호출을 시작하는 경우 의도하지 않은 결과가 중요 수도 있습니다.


생성자 내 에서 ,, 메소드 호출하는 것은 사용자에게 달려만이 메소드는 하위 클래스에서 재정의 될 수 있고 실제로이 메소드의 재정의 된 버전 호출되기 때문에 생성자 내에서 호출되기 때문에 가장 좋습니다 ( 동작을 사용하는 경우). .publicstaticnon-final

예를 들면 :

public class Foo {

public Foo() {
    doSmth(); // If you use polymorphic behavior this method will never be invoked
}

public void doSmth() {
    System.out.println("doSmth in super class");
}

public static void main(String[] args) {
    new Bar(200);
}
}

class Bar extends Foo {

private int y;;

public Bar(int y) {
    this.y = y;
}

@Override
public void doSmth() { // This version will be invoked even before Barr object initialized
    System.out.println(y);
}

}

0을 인쇄합니다.

자세한 내용은 Bruce Eckel "Thinking in Java" 장 "Polymorphism"을 참조하십시오.


세터를 어떻게 처리 하느냐에 따라 다릅니다. 클래스가 파생 될 수 있다고 믿는 경우 다른 곳에서 동작을 재정의 할 수 있도록 이러한 호출을 허용 할 수 있습니다. 그렇지 않으면 그대로 설정할 수 있습니다.

물론 setter를 명시 적으로 호출하도록 허용하면 설정 중에 추가 동작을 삽입하는 방법도 제공됩니다 (예 : 필요한 경우 보안 적용).


setter가보다 복잡한 작업을 수행하지 않는 한 this.x = x변수를 직접 설정합니다. 매개 변수는 인스턴스 변수에 직접 매핑되며, 저에게는 더 많은 의도를 보여줍니다.


내 선호는 몇 가지 이유로 생성자에서 직접 설정하는 것입니다. 첫째 this.x = x;, 같은 일을 수행하는 별도의 메서드를 호출하는 것보다 더 명확하지는 않지만 같은 것은 분명합니다. 둘째, 메소드가 final로 표시되지 않는 한 잠재적으로 재정의되었을 수 있으며 생성자에서 잠재적으로 재정의 된 메서드를 호출하는 것은 내 책에서 큰 금지입니다. 셋째, 대부분의 메서드는 일반적으로 개체가 생성되는 도중이 아니라 실행 중일 때 이미 완료되었다고 가정합니다. 이 간단한 경우에 문제가 발생해서는 안되지만 더 복잡한 경우에는 추적하는 데 오랜 시간이 걸리는 심각한 미묘한 버그가 발생할 수 있습니다.

어디에서나 setter / getter를 사용하는 주된 주장은 필드의 이름, 정의, getter / setter 메서드를 3 곳에서 변경하여 필드 이름을 바꿀 수 있으며 모두 컴파일되고 정상이어야한다는 것입니다. 괜찮은 현대 IDE는 간단한 키보드 단축키로 그러한 필드의 모든 발생의 이름을 바꿀 것이기 때문에 그 주장은 요즘 무효입니다.


우리의 코딩 표준이 접근 자 (비공개 일 수도 있음)의 사용을 요구하는 한 가지 이유가 있습니다. 어떤 코드가 필드를 변경하는지 빠르게 확인하려면 Eclipse에서 setter에 대한 호출 계층 구조를 가져 오면됩니다!

이는 200 만 줄의 코드에 도달 한 코드베이스에서 엄청난 시간을 절약하고 리팩토링도 쉽게 해줍니다.


나도 신경 ​​쓰지 않고 강한 편견을 가지고 있지 않습니다 [그리고 엄격한 기준을 고수하지도 않습니다]. 단지 당신의 판단을 사용하십시오. 그러나 setter를 사용하는 경우 클래스를 재정의하는 사람은 객체가 완전히 생성되지 않을 수 있음을 알아야합니다. 즉, setter의 추가 코드가 this참조 를 게시 할 수 없도록해야 합니다.

Setter는 표준 범위 검사 등에 유용 할 수 있으므로 입력을 확인하는 추가 코드가 필요하지 않습니다. 다시 세터를 사용하는 것은 약간 더 더러운 접근 방식입니다.

필드를 사용하면 명백한 이점이 있으며 (예 : 하위 클래스가 악의적으로 동작을 변경할 수 없도록하는 등) 일반적으로 선호됩니다. 도서관에서.

실제로 c-tor는 객체를 생성하는 3 가지 가능한 방법 중 하나입니다 (직렬화 + 복제는 다른 2). 일부 일시적인 상태는 c-tor 외부에서 처리해야 할 수 있으므로 필드 대 setter에 대해 고려해야 할 사항이 있습니다. (편집, 또 다른 방법이 있습니다 : 안전하지 않지만 직렬화가 사용하는 것입니다)

참고 URL : https://stackoverflow.com/questions/4893558/calling-setters-from-a-constructor

반응형