2014-12-26 5 views
11

Java에서 (내가 아는 한) 필드 변수를 비공개로 유지하고 getters 및/또는 setter를 사용하여 액세스하십시오. 이것은 변수 값을 변경하는 규칙을 설정할 수 있도록하기위한 것입니다.필드 변수가 최종 일 때 getter가 필요합니까?

하지만 변수가 최종적인 경우 어떻게해야합니까? 예 :

public class Test { 

    public final int MY_INT; 

    public Test(int myInt) { 
     MY_INT = myInt; 
    } 

} 

허용 되나요? 그것은 컴파일되고 잘 작동하지만 좋은 코드로 간주됩니까?

+4

당신은 getter/setters가 없으므로 기본적으로 불변의 객체를 생성합니다. 이것은 좋은 것입니다. –

+2

@pbabcdefp 최종적입니다 –

+0

죄송합니다. 일시적인 뇌의 동결. –

답변

16

이것은 컴파일되지만 좋은 코드로 간주되지 않습니다.

MY_INT는 이름 지정 규칙을 위반 : 모두 대문자로 이름도 "클래스 상수"(너무 thisthis, Google's Java style guide 참조)로 알려진 static final 변수에 사용됩니다. 명명 규칙을 따르려면 myInt으로 이름을 변경하는 것이 좋습니다.

클래스의 구현 세부 사항을 숨기려면 getter를 제공하는 것이 좋습니다. 인터페이스에는 메서드가 포함되며 필드는 포함되지 않습니다. 다른 클래스가이 필드를 이름으로 참조하도록 허용하면 이름 또는 나중에 내부 표현을 자유롭게 변경할 수 없습니다.

하지만 가장 중요한 것은 하위 클래스가 필드를 재정의 할 수 없으며 메서드를 재정의 할 수 있다는 것입니다. 필드 대신 getter를 제공하면 하위 클래스가이를 무시하고 다른 동작을 구현할 수 있습니다. 그래서 getter를 제공하고 필드 자체에 대한 직접 액세스를 금지하는 것이 좋습니다.

(감사 코딩 스타일 가이드 링크 @Sotirios Delimanolis, 많은 감사!에)

+0

정말입니까? 나는 항상 모든 상수가 대문자이어야한다고 생각 해왔다. – Ludwig

+3

이 대문자 화되어야하는지 여부에 대한 가장 적절한 대답은 다른 SE 사이트에서 설명됩니다. http://programmers.stackexchange.com/questions/252243/naming-convention-final-fields-not-static – nmagerko

+1

@ 루드비히 네 그럼요. [관련] (http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-135099.html#367) [docs] (http://docs.oracle.com/javase/tutorial/java) /nutsandbolts/variables.html)은 읽기가 쉽지는 않지만 모든 대문자 사용 규칙은'final'이 아닌'static final' 변수 ("클래스 상수")만을위한 것입니다. @nmagerko에 의해 링크 된 게시물에서, @MichaelT는 직렬화 논리에 대해 훌륭한 점을 제시합니다. – janos

4

값이 할당되기 전에 (즉 생성자를 호출하지 않고) 클라이언트가 질문의 공개 입력란에 액세스 할 수 있다면 명백한 문제가있을 수 있습니다. 특히이 필드는 클라이언트가 액세스하려고 할 때 예상/적절한 값을 가질 수 없습니다. 그럼에도 불구하고 주석에서 지적한대로 을 static 식별자로 선언하지 않았기 때문에이 상수의 값을 생성자를 먼저 호출하지 않고 검색 할 수 없습니다.

따라서, 당신이하고있는 일을하는 것이 (불변의 관점에서) 현명한 것으로 보일 것입니다. 그러나 "좋은 코드"라는 측면에서 보면 (다른 사람들이 말했듯이) 자신과 고객이이 값을 명시 적으로 이름으로 참조하도록 강요합니다. 그래도 getter를 사용하고 MY_INT이라는 이름을 변경해야 할 경우 상수의 용도를 동일하게 유지해야하므로 사용자 또는 클라이언트 모두 Test의 구현을 넘어서는 변경을 강요 당할 수 없습니다.

좀 더 명확하게 말하면, 클래스에 게터 및 사유화 된 상수를 제공합니다.

public class Test { 

    private final int MY_INT; 

    public Test(int myInt) { 
     MY_INT = myInt; 
    } 

    public int getAssignedIntValue() { 
     return MY_INT; 
    } 

} 

나는 할당 된 정수 값과 같이 얻을 것입니다 :

Test test = new Test(1); 
// with your class 
test.MY_INT; 
// with the above class  
test.getAssignedIntValue(); 

을 지금, 명명 규칙에 맞게 MY_INTmyInt에 이름을 변경 말한다. 두 경우 모두 클래스의 모든 발생을 MY_INT으로 변경해야합니다.

// if this is the old code from above 
Test test = new Test(1); 
// I need to change this to test.myInt, or I get an ERROR! 
test.MY_INT; 
// since I didn't change the name of the getter, all is well 
test.getAssignedIntValue(); 

참고 :이 허용 답을되었을 수도 있지만, 반드시 가장 적합한 추론이없는 나는 새로운 상수 이름 값을 얻을 필요하지만, 두 구현의 차이는 분명해진다 . 보다 일반적인 맥락에서 주어진 이유에 대해서는 this answer을 참조하십시오.

+3

인스턴스없이 액세스 할 때 꽤 빨리 실패합니다. –

+0

'Test.MY_INT'는 여전히 유효합니다. 정교하게, 기회가 있다면 – nmagerko

+2

Nope. 그것은 심지어 IDE 자동 제안에 나오지 않을 것입니다. –

3

가능합니다. 클래스 수준이나 다른 설정자에서 변수를 초기화하지 않는 한.

+1

나는 이것이 비슷한 이유로 좋다고 대답하지 않는다고 생각합니다. –

3

클래스가 데이터 클래스가 아닌 경우 개인적으로 공개 입력란을 좋아하지 않습니다. 클래스는 변경할 수 없지만 변경할 수 없도록하고 싶으십니까? 어떤 이유로 든 가변적 인 복사본이 필요한 경우 getter 및 setter를 사용하여 변경 가능하고 변경 불가능한 복사본을 갖는 것이 더 쉽습니다.

공개 필드가있는 경우 클라이언트는 코드에서 필드를 사용하므로 나중에 사용자의 이름을 변경할 수 없습니다.

이렇게하면 캡슐화가 손상됩니다.

4

공급자의 답변이 불완전 (심지어 "대답"으로 선택된 하나). 문제의 필드가 Collection 또는 객체 배열 인 경우 어떻게 될지 고려하십시오. 모든 필드를 비공개로 만들고 이러한 필드에 "getters"를 제공하는 것이 좋습니다. 그러나 구체적으로, getter는 필드에 대한 (불변) 참조 (즉, String) 또는 변경 가능한 필드 (즉, 객체 배열)의 방어 복사본을 반환해야합니다. 이는 문제의 객체의 기본 주소를 변경할 수 없더라도 단순히 기본 주소를 가져 와서 객체 (배열 또는 컬렉션)의 내부를 변경할 수 있기 때문입니다. 변경할 수있는 필드는 배열이나 컬렉션 만 의미하는 것은 아닙니다. 그것은 모든 변경 가능한 클래스에 적용됩니다.

질문에 돌아 오면, 게터가 이어야합니다.? 내 대답은 아니오 야. 언제든지 강력한 코드를 사용하려면 이러한 모범 사례를 따르는 것이 가장 좋습니다. 비록 그것이 좋은 습관을 창조하는 것이라 할지라도. 규칙적으로 연습하지 않는 한, 코드 작성시 우수 사례를 따르지 않을 것입니다.

관련 문제