자바 : 정적 클래스?


130

유틸리티 함수로 가득 찬 클래스가 있습니다. 인스턴스를 인스턴스화하는 것은 의미 론적으로 의미가 없지만 여전히 메소드를 호출하고 싶습니다. 이것을 처리하는 가장 좋은 방법은 무엇입니까? 정적 클래스? 요약?


14
그건 그렇고 당신은 최상위 클래스를 정적으로 만들 수 없습니다 ...
Jon

답변:


163

final로 표시된 클래스의 개인 생성자와 정적 메서드


19
@matt b : David Robles가 그의 대답에서 지적한 것처럼 클래스를 최종적으로 만들 필요는 없습니다. 서브 클래스는 프라이빗이기 때문에 서브 클래스가 슈퍼 클래스 생성자를 호출 할 수 없기 때문에 서브 클래스 화 될 수 없습니다. 그러나 ... 명시 적으로 해를 입히지 않습니다. 그러나 jfyi :-).
Tom

93

"Effective Java"라는 훌륭한 책에 따르면 :

항목 4 : 개인 생성자로 비 인스턴스 시행

-클래스 추상을 만들어서 인스턴스화 불가능 성을 강요하는 것은 효과가 없습니다.

-기본 생성자는 클래스에 명시적인 생성자가없는 경우에만 생성되므로 개인 생성자를 포함하여 클래스를 인스턴스화 할 수 없게 만들 수 있습니다.

// Noninstantiable utility class
public class UtilityClass
{
    // Suppress default constructor for noninstantiability
    private UtilityClass() {
        throw new AssertionError();
    }
}

명시 적 생성자는 비공개이므로 클래스 외부에서는 액세스 할 수 없습니다. AssertionError는 꼭 필요한 것은 아니지만 생성자가 클래스 내에서 실수로 호출 된 경우 보험을 제공합니다. 어떤 상황에서도 클래스가 인스턴스화되지 않도록 보장합니다. 이 관용구는 생성자가 명시 적으로 제공되어 호출 할 수 없으므로 약간 반 직관적입니다. 따라서 위에 표시된대로 주석을 포함시키는 것이 좋습니다.

부작용으로이 관용구는 클래스가 하위 클래스로 분류되는 것을 방지합니다. 모든 생성자는 명시 적 또는 암시 적으로 수퍼 클래스 생성자를 호출해야하며 서브 클래스는 호출 할 수있는 수퍼 클래스 생성자가 없습니다.


1
왜 선택 했는가 AssertionError와 같은 다른 대안을 통해 IllegalStateException, UnsupportedOperationException등?
Pacerier

참조 @Pacerier .
bcsb1001

@ bcsb1001, 그것은 우리에게 이것을 가져옵니다 .
Pacerier

21

java.lang.Math 와 유사한 유틸리티 클래스가있는 것 같습니다 .
접근 방식에는 개인 생성자와 정적 메소드가있는 최종 클래스가 있습니다.

그러나이 테스트 용이성을 위해 무엇을 조심, 내가이 글을 읽어 보시기 바랍니다
정적 방법은 테스트 용이성에 죽음이다


java.lang.Math는 "죽음의 테스트 가능성"입니까?
Pacerier

1
을 통해 실행할 때 어떻게 점수를 보는 것이 재미있을 code.google.com/p/testability-explorer
크라운

6

상류 수영을하기 위해 정적 멤버와 클래스는 OO에 참여하지 않으므로 악합니다. 아니요, 악하지는 않지만 진지하게 액세스하기 위해 싱글 톤 패턴의 정규 수업을 추천합니다. 이런 식으로 어떤 상황에서든 동작을 재정의해야하는 경우 큰 재조정이 아닙니다. OO는 당신의 친구입니다 :-)

내 $ .02


17
싱글 톤도 악으로 간주됩니다.
Dan Dyer

3
개인 생성자를 사용하여 다른 사람이 클래스를 인스턴스화하거나 서브 클래 싱하지 못하게합니다. David Robles의 답변을 참조하십시오 : stackoverflow.com/questions/1844355/java-static-class/…
rob

5
싱글은 : 의존성 주입보다 더 악하지 더
irreputable

12
OO는 그 자리를 가지고 있지만 실제로 실용적이지 않거나 Math.abs ()와 같은 단순한 리소스와 같이 리소스를 낭비하는 경우가 있습니다. 정적 메소드 호출이 OO- 오버 헤드 없이도 서비스를 제공했을 때 객체를 인스턴스화하기 위해 객체를 인스턴스화 할 이유가 없습니다. ;)
rob

2
@rob re OO, Math.Abs는 인스턴스가 필요하지 않을 것입니다. "유틸리티 클래스가 있습니다"라는 음성이 들리면 이제 가중 평균에 대한 지원을 추가해야하는 Math.Avg ()가 표시됩니다. href 생성 또는 URL 만 지원하기 위해 리팩터링해야하는 URL 생성기, 매개 변수 입력, URL 출력 등이 있습니다. 이러한 이유로 OO 기반 유틸리티 클래스를 사용하면 상환 할 수 있습니다. 또한 이제 표준 OO 방어 전술을 테스트하겠습니다! / me ducks
Bennett Dill

3

"비공개 생성자"인수에 대한 의견 : 이제 개발자들은 그렇게 어리석지 않습니다. 그러나 그들은 게으르다. 객체를 만든 다음 정적 메소드를 호출합니까? 일어나지 않을 것입니다.

수업이 잘못 사용되지 않도록 너무 많은 시간을 소비하지 마십시오. 동료들에게 믿음을 가지십시오. 어떻게 보호하든 항상 학급을 오용 할 수있는 방법이 있습니다. 오용 될 수없는 유일한 것은 완전히 쓸모없는 것입니다.


7
jsut 학생 코드가 아닌 프로덕션 코드에서 object.staticMethod를 본 사람 Joe Random Programmer의 능력을 과대 평가한다고 생각합니다! :-P
TofuBeer

2
  • 최종 클래스 및 개인 생성자 (양호하지만 필수는 아님)
  • 공개 정적 메소드

1

클래스를로 선언 할 필요는 없습니다 static. 메소드를 선언하고 staticJava의 Math 클래스 와 같이 클래스 이름에서 정상적으로 호출하십시오 .

또한 생성자를 비공개로 만들어야 할 필요는 없지만 그렇게하는 것이 좋습니다. 생성자를 private으로 표시하면 다른 사람이 클래스의 인스턴스를 만든 다음 해당 인스턴스에서 정적 메서드를 호출 할 수 없습니다. (이러한 호출은 Java에서 정확히 동일하게 작동하며 오해의 소지가 있으며 코드의 가독성을 손상시킵니다.)


1
또한 개인 생성자를 만드는 것을 잊지 마십시오.
Asaph December

@Asaph : 동의합니다. 나는 그것에 대한 답변을 조금 추가했습니다. 감사.
Bill the Lizard

내부 클래스 내에서 정적 메소드를 원하면 클래스도 정적이어야합니다.
Rui Marques

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.