Java String에 정적 문자열 조작 방법이없는 이유는 무엇입니까?


17

Java 디자이너java.lang.String클래스 에서 정적 버전의 문자열 조작 메소드를 작성 하지 않은 이유는 무엇 입니까? 다음 메소드는 내가 참조하는 것이지만 클래스의 다른 비 정적 메소드로도 질문을 확장 할 수 있습니다.

concat(String)                        substring(int, int)
replace(char, char)                   toLowerCase()
replace(CharSequence, CharSequence)   toLowerCase(Locale)
replaceAll(String, String)            toString()
replaceFirst(String, String)          toUpperCase()
split(String)                         toUpperCase(Locale)
split(String, int)                    trim()
substring(int)

이러한 메소드의 비 정적 버전 만 있으면 이러한 메소드 를 호출해야하는 곳에서 명시 적으로 널 검사를 수행합니다. 예를 들어 단순히 호출 example = example.trim()하면 NullPointerException if이됩니다 String example = null. 따라서 프로그래머는 다음 상용구 null 확인을 수행해야합니다.

if (example != null)
    example = example.trim();
// OR:
example = (example==null) ? null : example.trim();
example = (example==null) ? null : example.substring(5);

String이 메소드의 정적 버전 (아마도 독점적 인 ) 이 있으면 입력 문자열을 첫 번째 인수로 사용하는 것이 훨씬 편리했을 것입니다.

example = String.trim(example);
example = String.replace(example, 'a', 'b');
example = String.substring(example, 5);

이로 인해 프로그래머가 명시 적으로 null 사례를 처리하도록 강요하는 대신 단순히 null을 반환하여 null 사례를 자동으로 처리하는보다 깔끔한 코드가 프로그래머에 의해 작성되었습니다. 널의 반환은 조작 이후 나에게 의미가 A의 결과를해야 문자열을 문자열이 아닌 오류입니다.

Java 설계자 String가 Java 1 또는 Java 2로 클래스를 설계 하거나 이후 Java 버전에서 이러한 기능을 추가 할 때 이것을 생각 하지 않은 이유는 무엇 입니까?


17
"Java 디자이너가 X를 생각하지 않은 이유"를 "Java 디자이너가 X를 결정한 이유"로 바꾸는 것이 좋습니다. 옵션에 대해 눈이 멀지 않다는 기본 크레딧을 제공하십시오.
Avner Shahar-Kashtan '12

5
null예외적 인 상태이며 명시 적으로 처리해야합니다.
코드 InChaos

2
@ KonradMorawski : 개인적으로 나는 확장 방법을 크게 잘못 사용한다는 것을 알았습니다. null 값을 가지고 있다면 지구상에서 메소드를 호출하려고하는 것은 해당 코드를 읽는 모든 사람을 혼란스럽게 할 것입니다. Maybe<T>유형의 재 구현이 좋지 않습니다 .
Phoshi

1
@Phoshi 확장 메소드가 실제 메소드가 아니라 구문 설탕이라는 것을 명심해야합니다. 그러나 나는 그것이 논쟁의 여지가 있다는 것에 동의합니다. C # / Java가 Kotlin과 같은 일종의 내장 구문 null 안전성을 제공하기를 바랍니다. string name = employee?.personalData?.name. 이 모든 반복적 인 것들에 대한 지름길과 같습니다 if (employee != null). 관련 SO 질문 : stackoverflow.com/questions/1196031/...
콘라드 Morawski

2
@ADTC Erm, 프로그램이 값이 null임을 미리 예측할 수 없다는 것을 알고 있습니까? - 값이 널 (null)인지 여부를 확실 하게 확인할 있도록 인터페이스 간의 계약을 정의해야합니다 . 모든 곳에서 널 검사는 프로그램 설계 문제가 있음을 의미합니다.
Uooo

답변:


30

null 문자열을 조작하면 오류가 아닌 null 문자열이 발생하므로 null 반환은 의미가 있습니다.

글쎄, 그건 당신의 의견입니다. 다른 사람들은 String을 포함하지 않는 null 객체에 대한 String 연산이 의미가 없으므로 예외를 발생시켜야한다고 주장 할 수 있습니다.

왜 "자바 디자이너"가 무언가를했거나하지 않았습니까?

null 안전 문자열 작업을 수행 할 수있는 라이브러리가 이미 있습니다 (예 : Apache Commons의 StringUtils ). 필요한 경우 해당 라이브러리 또는 유사한 라이브러리를 사용할 수 있습니다.


귀하의 의견에 따른 추가

주석을 읽으면 실제로 직면하는 문제는 null코드 전체 를 확인해야한다는 것 입니다. 인터페이스 간의 계약이 명확하게 정의되어 있지 않으면 잘못된 프로그램 설계의 지표가 될 수 있습니다. Java에서 "! = null"문 피하기? 를 읽고 싶 습니까?


1
의견을 보내 주셔서 감사합니다. 실제 질문은 왜 그러한 기본 기능을 표준 Java의 일부로 만들 수있을 때 외부 라이브러리 또는 자체 제작 클래스에 의존해야 하는가하는 것입니다.
ADTC December

4
@ADTC는 다른 방법으로 질문을하자. 왜 이미 자바 라이브러리에 좋은 라이브러리가 많이 있고 테스트되고 문서화되어 있다면 "자바 디자이너"가 언어에 무언가를 포함시켜야 하는가? "기본 기능"을 정의하는 방법은 의견을 기반으로합니다. 대부분의 모든 프로젝트에 "기본 기능"(단위 테스트, 조롱, 날짜 및 시간 등)을위한 외부 라이브러리가 필요하지 않습니까? 별거 아니에요?
Uooo

널 (null)을 처리하는 한 가지 방법은 구아바의 사용 Optional- code.google.com/p/guava-libraries/wiki/...을
콘라드 Morawski에게

10

IMO 메소드 작성에 대한 "arg가 null return null 인 경우"전체 접근 방식은 프로그램의 순환 복잡성을 불필요하게 증가시킵니다.

초기 Java 라이브러리는 null 반환 방식을 사용했지만 JDK 사용자는 예외를 제외하고 항상 null을 방지했습니다.

시간이 지남에 따라 후자의 접근 방식이 확실한 승자라고 생각합니다.

왜? 널 필드는 많은 OO 원칙을 위반하기 때문에. 단순히 다형성 클래스의 멤버로 취급 할 수 없습니다. 이것은 항상 널 (null)에 대해 특수한 경우를 코딩해야하므로, 널이 ​​될 수 있다고 가정해야 할 때 순환 복잡성이 급증합니다.

문제점을 해결하려면 널 필드에 의존하는 대신 널 오브젝트 패턴을 사용하십시오.


2
그러나 String다형성이 아닙니까? 그리고 String과 같은 기존 유형에 null 객체 패턴을 어떻게 사용합니까?
svick

문자열은 다형성이 아닙니다. 그러나 심지어 모든 문자열 참조에서 인스턴스 메소드를 호출 할 수 있다는 것을 알고 싶습니다. 이것은 null이 아닌 모든 참조에 적용됩니다. 문자열에 이미 null 개체가 있습니다. 빈 문자열 목록에 빈 목록이있는 것처럼. 따라서 빈 문자열이 충분하지 않은 이유를 스스로에게 물어보십시오. null 문자열을 사용하여 특별한 경우를 표시한다고 생각합니다. 특별한 경우에 별도의 플래그를 사용할 수 있는지 스스로에게 물어보십시오.
Alexander Torstling

@AlexanderTorstling : 유형의 필드는 int기본값이 아니라 0 null입니다. 개념적으로해야 할 수 있어야 string기본값이 대신 빈 문자열이 될 것이다 유형 null[같은 유형의 의미에 수 String무엇 int이다 Integer]입니다. 비어 있지 않은 string것이 내부적으로 힙 객체에 대한 참조를 보유 한다는 사실 은 구현 세부 사항입니다. 프리미티브처럼 의미 론적으로 행동 할 수없는 이유는 없습니다.
supercat

@ supercat : 동의합니다. 명시 적으로 활성화하지 않으면 참조 값에 대해 null 값을 금지하는 것이 더 좋을 것이라고 생각합니다. 널이 아닌 기본 필드입니다. 많은 유형에 이미 null 동작 객체가 있습니다
Alexander Torstling

@AlexanderTorstling : 모든 유형의 저장 위치를 ​​기본적으로 all-bytes-zero로 설정하고 모든 바이트 복사를 통해 구조 유형을 할당 할 수있게하면 프레임 워크가 크게 단순화되지만 변경 가능한 참조 의미가 있는 유형의 기본값은 없는. 그러나 단일 참조를 캡슐화하고 해당 참조 유형과 같이 상자를 풀고 상자에서 풀 수 있는 값 유형에 대한 프레임 워크 지원을 갖는 것이 도움이되었을 것 입니다.
supercat

3

이것이 이유가 아니라 toString을 제외하고 이러한 메소드는 모두 정적 헬퍼 클래스에 쉽게 캡슐화되지만 그 반대는 사실이 아닙니다.

즉, Stings.toUpper (문자열 입력)를 작성하려면 코드를 작성하기 쉽지만 instance.toUpper를 원하고 String.toUpper 만 있으면 확장 메소드를 도입하지 않는 한 불가능합니다 ... 당시에는 고려되지 않았을 가능성이 높습니다.


대답보다 더 많은 의견이 있지만 좋은 지적입니다. 그러나 그러한 기본 기능이 표준 Java의 일부가 될 때 왜 외부 라이브러리 또는 자체 제작 클래스에 의존해야합니까?
ADTC December

2
현재로서는 String.format(정적) 상태이지만 할 수는 없습니다 "something %s".format(id).
Konrad Morawski

@adtc : 정적 클래스를 통해 언어의 기본 기능이 아니기 때문입니다. 그 전제에서 시작하여 불필요한 코드 / 코드 팽창, 중복 기능, 개발 / 유지 보수 비용 등 여러 가지 이유가 있습니다.
jmoreno

-2

Java에서 해당 문자열은 객체입니다. 그것은 디자인 선택입니다.

오브젝트 참조는 널이 될 수 있으며 오브젝트가 지정되지 않은 경우 널입니다. 이러한 객체를 호출하면 NullPointerException이 발생합니다. 그것은 표준 oo-behaviour입니다.

Java 디자이너는 문자열을 객체로 선택하고 null 포인터 예외를 발생시키는 메소드를 선택하여 문자열을 객체로 만들 수 있습니다.

Java 설계자가 Java 1 또는 Java 2에서 String 클래스를 설계하거나 이후 Java 버전에서 이러한 기능을 추가 할 때 이것을 생각하지 않은 이유는 무엇입니까?

그들은 아마도 그것에 대해 생각하고 행동을 통합하기로 결정했습니다.


OO 동작이 아닌 null 경우를 처리하기 위해 정적 메서드를 만드는 방법은 무엇입니까? 분명히, 나는 그것이 아니라고 말하지만 디자인 결정이 OO 동작을 통합하는 것이라고 말하는 이유를 이해하려고합니다.
ADTC December

정적 메서드는 함수와 더 비슷합니다. 그리고 사용하기 위해서는 문자열 클래스의 일부가 아니고 유틸리티 클래스의 일부가 아니어야합니다. 수학 클래스 함수와 같습니다.
Pieter B

4
문자열이 객체라고해서 String 클래스가 정적 메서드를 가질 수 없다는 것을 의미하지는 않습니다. 실제로, 예를 들어 이미 몇 가지가 있습니다. String.format. (C #과 동일). 따라서 이것이 디자인 선택이라면, 문자열이 객체이고 일관성이 적용되지 않는다는 사실만으로는 올 수 없습니다.
Konrad Morawski

적어도 이러한 방법에서 제공한다면 내가 불평하지 않을 @PieterB Strings우리가 가지고있는 것처럼, 유틸리티 클래스 Arrays(유틸리티 클래스를 나는 그것이 순전히 필요에 의해 만들어진 이해하지만 때문에 배열이 프리미티브와 객체 사이의 이상한 십자가의 일종 인로 : ) ) 표준 Java의 일부이고 종속성이 필요하지 않은 한.
ADTC December
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.