Java가 일부 클래스에서 캡슐화를 사용하지 않는 이유는 무엇입니까?


25

내 질문은 클래스 와 관련 이 있습니다 (표준 라이브러리의 질문 System.inSystem.out다른 것이있을 수 있습니다). 왜 그런가요? OOP에서 그렇게 나쁜 습관이 아닙니까? 다음 System.getIn()과 같이 사용해서는 안됩니다 System.getOut(). 나는 항상이 질문을 받았으며 여기서 좋은 답을 찾을 수 있기를 바랍니다.

답변:


36

클래스 내의 inout필드에 대한 정의는 다음 과 System같습니다.

public final static PrintStream out;
public final static InputStream in;

이것들은 상수입니다. 그것들은 또한 물체이기도하지만 상수입니다. Math 클래스와 거의 동일합니다.

public static final double E = 2.7182818284590452354;
public static final double PI = 3.14159265358979323846;

또는 부울 클래스에서

public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);

또는 Color 클래스에서 :

public final static Color white     = new Color(255, 255, 255);
public final static Color black     = new Color(0, 0, 0);
public final static Color red       = new Color(255, 0, 0);

변경되지 않는 퍼블릭 상수에 액세스 할 때이를 개념적으로 또는 성능 기반으로 캡슐화하면 큰 이점이 없습니다. 저기에있어. 변경되지 않습니다.

Color.white와 사이에는 실제 차이가 없습니다 System.out.


글쎄, 나는 그런 식으로 보지 못했다. 그것들은 일정한 물건이다. 꽤 좋은 설명입니다.
Clawdidr

1
오늘날의 자바 @Clawdidr, 하나는 (가) 사용을 고려 enum하지만 ... 그들을 잡아 enum자바 1.5 (1.0 일하지 옵션) 새로운이었다.

호기심에서 (자바 개발자가 아닌) : final staticstatic final? 의 차이점이 있습니까? 그렇다면 무엇입니까?
Marjan Venema

1
@MarjanVenema 차이점은 없으며 수정 자의 선호 순서입니다. checkstyle 수정 자 검사 는 선호하는 순서를 보여줍니다. 분명히, jdk 버전으로 두 소스 파일을 작성한 사람은 순서에 동의하지 않았습니다. 그것은 단지 관습입니다.

:) 응답하고 링크에 시간을내어 주셔서 감사합니다 Michael.
Marjan Venema

5

실제 이유는 이것이 레거시 문제이기 때문입니다. 그만큼System.in,out,err상수는 자바 1.0의 일부 ... 아마 훨씬 더 뒤로했다. 디자인에 문제가 있음이 분명 해지자 너무 늦어서 수정하지 못했습니다. 그들이 할 수있는 최선의 System.setIn,setOut,setErr방법은 Java 1.1 에서 메소드 를 추가 한 다음 언어 스펙 문제 1 을 처리하는 것 입니다.

이것은 왜 정적이 있는지의 문제와 유사합니다 System.arraycopy 이름이 Java 이름 지정 규칙을 위반 메소드 .


이것이 "나쁜 디자인"인지 아닌지는 생각합니다. 현재 비 OO 처리가 심각한 문제인 상황이 있습니다. (생각해보십시오 ... 하나의 Java 프로그램을 어떻게 실행할 수 있습니까? 자신의 "표준 IO"스트림 요구 사항 충돌이. 생각 할 때 다른 ... 장치가 수반는 스트림을 변경하는 것이 코드를 테스트.)

그러나 현재 일하는 방식이 더 편리 하다는 주장과도 관련이 있습니다. 많은 경우에 이 있습니다.


1- System.in,out,err변수가 JLS에서 "특수 시맨틱"을 갖는 것으로 특별히 언급 된다는 점에 주목하는 것이 흥미 롭습니다 . JLS에 따르면 final필드 값을 변경하면 이러한 필드 의 경우를 제외하고는 동작이 정의되지 않습니다 .


2

나는 out 객체가 불변이기 때문에 공개 최종 정적 필드에 보관되는 것이 안전하다는 것을 확신합니다.

JDK의 많은 클래스는 최고의 객체 지향 디자인 원칙을 존중하지 않습니다. 그 이유 중 하나는 객체 지향이 주류 패러다임으로 만 등장하고 많은 프로그래머가 현재와 같이 익숙하지 않은 거의 20 년 전에 작성된 사실입니다. 잘못된 API 디자인의 좋은 예는 Date & Time API인데 19 년이 걸렸습니다.


3
나는 진술을 더욱 강하게 만들었고, 공개 최종 변수 (정적이든 아니든)는 게터처럼 "안전"하고 세터 / 게터 쌍에 대해 불변성을 부여합니다. 세터는 항상 나쁜 생각입니다. (불변은 좋으며, 불변 할 수없는 경우 "설정"방법으로 비즈니스 로직이 약간 필요합니다.) 게터가 필요한 경우 공개 할 수도 있습니다. 마지막으로, 그러나 어느 쪽도하지 않는 것이 바람직합니다. 수업에 데이터를 요구하지 말고, 수업에 데이터에 대해 무언가를하도록 요청하십시오.
Bill K

@BillK : 그렇습니다. 데메테르법칙으로 도 알려져 있습니다 (법칙이 아니라 지침입니다).
sleske

2

이 대답 은 위대하고 사실입니다.

나는 경우에 따라 유용성을 위해 타협 이 이루어 졌다고 덧붙였다.

String이 프리미티브가 아닌 경우 String 유형의 객체를 새로운 이벤트없이 인스턴스화 할 수 있습니다.

String s = "Hello";

기본이 아닌 문자열은 다음과 같이 인스턴스화해야합니다.

String s = new String("Hello");          // this also works 

그러나 String은 API에서 가장 널리 사용되는 클래스이기 때문에 컴파일러는 더 짧고 적은 OO 옵션을 허용합니다.

또한 비 OO 방식으로 배열을 초기화 할 수 있습니다.

int i[] = {1,2,3};

이상하게도 객체는 클래스 또는 배열의 인스턴스입니다. 입니다. 의미 배열은 완전히 별개의 클래스 유형입니다.

배열에는 length상수가 아닌 공개 필드가 있습니다. 또한 클래스 배열에 대한 설명서가 없습니다. (Arrays 클래스 또는 java.reflect.Array와 혼동하지 마십시오).

int a = myArray.length;    // not length()

6
당신은 다른 것들입니다- new String("Hello")항상 새로운 String 객체를 만듭니다. 동안 String s = "Hello";interned 객체를 사용합니다. 비교 : "Hello" == "Hello"true 일 수 있지만 new String("Hello") == new String("Hello")항상 false입니다. 처음에는 컴파일 시간 최적화 마술이 일어나지 않습니다 new String("Hello"). 참조 en.wikipedia.org/wiki/String_interning

@MichaelT 나는 완전성을 위해 배열에 약간의 부가 성을 추가했습니다.
Tulains Córdova 오전

2
@Tarik 나는 "기본이 아닌 문자열 String s = new String("Hello");입니다. 다음과 같이 설명해야합니다."에 반대했습니다 . 문자열 삽입 때문에 짧은 옵션 ( String s = "Hello";)이 정확합니다.

2
를 사용하면 String"보다 정확한"옵션이 없습니다. 둘 다 맞습니다. MichaelT가 말했듯이 String interning 때문에 더 짧은 것이 선호됩니다.
Andres F.

1
@AndresF. "less OO"에 대해 "less correct"를 변경했습니다.
Tulains 코르도바
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.