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)

これらのメソッドの非静的バージョンのみを使用すると、そのようなメソッドを呼び出さなければならない場所で明示的な nullチェックが強制されます。たとえば、単に呼び出すexample = example.trim()と、NullPointerException ifになりString example = 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のケースを処理するプログラマーによって記述されたよりクリーンなコードになります。ヌルの返却は操作以来、私には理にかなってヌル文字列が生じるはずであるヌル文字列ではなく、エラーが発生しました。

StringJava 1またはJava 2でクラスを設計したときに、Javaデザイナーがこれを考えなかったのはなぜですか。また、後のJavaバージョンでそのような機能を追加したのでしょうか。


17
「JavaデザイナーがXを考えなかった理由」を「JavaデザイナーがXに反対した理由」に置き換えることをお勧めします。オプションを盲目にしないという基本的な信用を彼らに与えてください。
アヴナーシャハルカシュタン

5
null例外的な状態であり、明示的に処理する必要があります。
CodesInChaos

2
@KonradMorawski:個人的には、拡張メソッドのひどい誤用があります。null値がある場合、その上でメソッドを呼び出そうとしているのは一体何をしているのか、そのコードを読んでいるすべての人を混乱させるだけです。Maybe<T>型の再実装が不十分だと思いますか?
Phoshi

1
@Phoshiの1つ、拡張メソッドは実際のメソッドではなく、単なる構文シュガーであることを覚えておく必要があります。しかし、物議を醸すことに同意します。私は、C#/ Javaに、たとえばKotlinのような、組み込みの構文的なnull安全性が備わっていることを望みます。string name = employee?.personalData?.name。これらすべての繰り返しif (employee != null)のショートカットとして。関連のSOの質問:stackoverflow.com/questions/1196031/...
コンラートMorawski

2
@ADTC Erm、あなたはプログラムが値がnullであることを事前に予測できないことを理解していますか?- 値がnullを許可されているかどうかを確認できる方法で、インターフェイス間のコントラクトを定義する必要があります。どこでもヌルチェックを行うということは、プログラム設計の問題があることを意味します。
うおお

回答:


30

null文字列を操作するとエラーではなくnull文字列になるはずなので、nullを返すことは理にかなっています

まあ、それはあなたの意見です。他の人は、文字列を含まないヌルオブジェクトの文字列操作は意味がなく、したがって例外をスローする必要があると主張するかもしれません

「Javaデザイナー」が何かをしたのか、しなかったのかを答えるのは難しい。

Apache CommonsのStringUtilsなど、nullセーフな文字列操作を実行できるライブラリが既にあります。必要に応じて、そのライブラリまたは同様のライブラリを使用できます。


コメントに基づいた追加

コメントを読んで、あなたが直面している本当の問題はnull、コード全体をチェックする必要があるということです。これは、インターフェイス間で明確に定義されたコントラクトがない場合のプログラム設計の不良の指標になる可能性があります。Javaでの「!= null」ステートメントの回避をお読みください


1
ご意見をいただきありがとうございます。本当の疑問は、そのような基本的な機能を標準Javaの一部にできるのに、なぜ外部ライブラリや自作のクラスに依存する必要があるのでしょうか?
ADTC

4
@ADTCでは、逆の質問をしましょう。すでに多くの優れたライブラリがあり、十分にテストされ、文書化されている場合、「Javaデザイナー」が言語に何かを含める必要があるのはなぜですか。「基本機能」の定義方法は意見に基づいています。ほとんどのプロジェクトで、「基本機能」(ユニットテスト、モック、日付と時刻など)のために外部ライブラリが必要なわけではありませんか?大したことじゃないですか?
うおお

ヌルに対処する一つの方法は、グアバの使用しているOptional- code.google.com/p/guava-libraries/wiki/...
コンラートMorawski

10

IMOは、メソッドを記述する「引数がnullの場合はnullを返す」というアプローチ全体で、プログラムの循環的な複雑さを不必要に増加させます。

初期のJavaライブラリはnullを返すアプローチを使用していましたが、JDKのスタッフは例外を使用して常にnullから保護していました。

時間が経つにつれて、後者のアプローチが明確な勝者として出てきたと思います。

どうして?nullフィールドは多くのoo原則を破るので。それらを単に多相クラスのメンバーとして扱うことはできません。これは、nullの特別な場合を常にコーディングする必要があることを意味します。したがって、nullになる可能性があると仮定する必要がある場合、循環的な複雑さが急上昇します。

問題を解決するために、nullフィールドに依存するのではなく、nullオブジェクトパターンの使用を検討してください。


2
しかしString、ポリモーフィックではありませんか?また、文字列などの既存の型に対してnullオブジェクトパターンをどのように使用しますか?
svick

文字列はポリモーフィックではありません。ただし、それでも、所有している任意の文字列参照でインスタンスメソッドを呼び出すことができることを知りたいです。これは、すべての非ヌル参照に対して機能します。文字列にはすでに空の文字列であるnullオブジェクトがあります。リストに空のリストがあるように。なぜ空の文字列では不十分なのかを考えてみてください。null文字列を使用して特別なケースにフラグを立てると思います。その特別な場合に別のフラグを使用できるかどうかを自問してください。
アレクサンダートーストリング

@AlexanderTorstling:intデフォルトのタイプのフィールドは、ではなくゼロですnull。概念的には持つことが可能である必要がありstring、そのデフォルト値ではなく空の文字列になりますタイプnull[そのようなタイプは、意味的には可能性がStringどのようintにあるInteger]を。空でstringはないオブジェクトが内部的にヒープオブジェクトへの参照を保持するという事実は、実装の詳細です。意味的にプリミティブのように振る舞えなかった理由はありません。
supercat

@supercat:同意しました。明示的に有効にしない限り、refefencesのnull値を禁止する方がよかったと思います。デフォルトの非ヌルおよび最終フィールド。多くのタイプにはすでにnullの動作オブジェクトがあります
Alexander Torstling

@AlexanderTorstling:すべてのタイプの格納場所をデフォルトでall-bytes-zeroに設定し、構造タイプをall-bytes-copyを介して割り当てることができるようにすると、フレームワークが大幅に簡素化されますが、可変参照セマンティクスを持つタイプのデフォルトはヌル。ただし、単一の参照カプセル化し、その参照型を「ボックス化」し、その参照型を「アンボックス化」できる値型のフレームワークサポートがあると便利でした
supercat

3

これは理由ではありませんが、toStringを除き、これらのメソッドはすべて静的ヘルパークラスに簡単にカプセル化されますが、その逆は当てはまりません。

つまり、Stings.toUpper(string input)が必要な場合、そのためのコードは簡単に記述できますが、instance.toUpperが必要な場合、String.toUpperだけが必要な場合、拡張メソッドを導入しない限り、それはおそらく当時も考慮されていなかったでしょう。


良い点ですが、答えよりもコメントのほうが多いです。しかし、それでも、そのような基本的な機能を標準Javaの一部にすることができるのに、なぜ外部ライブラリまたは自家製のクラスに依存する必要があるのでしょうか?
ADTC

2
現時点では、String.format(静的)はありますが、できません"something %s".format(id)
コンラッドモラウスキー

@adtc:静的クラスを介してそれを行うことは、言語の基本的な機能ではないためです。その前提から始めて、そうしない多くの理由があります-不必要なコード/コードの膨張、機能の重複、開発/保守のコスト。
jmoreno

-2

Javaでは、その文字列はオブジェクトです。それは設計上の選択です。

オブジェクト参照はnullになる場合があり、オブジェクト参照が割り当てられていない場合はnullになります。このようなオブジェクトを呼び出すと、NullPointerExceptionがスローされます。これが標準的なoo-behaviourです。

Javaデザイナーは、文字列をオブジェクトとして選択し、文字列をオブジェクトにしたい場合にnullポインタ例外をスローするメソッドを選択しました。

Java 1またはJava 2でStringクラスを設計したときに、Javaデザイナーがこれを考えなかったのはなぜですか。さらに、後のJavaバージョンでそのような機能を追加しましたか?

彼らはおそらくそれについて考え、oo-behaviourを組み込むことを選んだでしょう。


OOの動作ではなく nullのケースを処理する静的メソッドをどのように作成していますか?明確にするために、私はそうではありませんが、デザインの決定がオブジェクト指向の動作を組み込むことであるとあなたが言う理由を理解しようとしています。
ADTC

静的メソッドは関数に似ています。そして、あなたが望む使用のために、それらは文字列クラスの一部であってはならず、むしろいくつかのユーティリティクラスの一部であるべきではありません。数学クラスの関数と同じです。
ピーターB

4
文字列がオブジェクトだからといって、Stringクラスに静的メソッドを含めることができないわけではありません。そして確かに、それはすでにいくつかを持っています、例えば。String.format。(ちなみにC#でも同じです)。したがって、それが設計上の選択である場合、文字列がオブジェクトであるという事実だけから来ることはできず、一貫して適用されません。
コンラッド・モラウスキー

@PieterB Stringsユーティリティクラスのように、少なくともそのようなメソッドがユーティリティクラスで提供されていても文句を言わないでしょうArraysただし、配列がプリミティブとオブジェクトの間の奇妙なクロスであるために、必要性から作成されたことがわかります: ))..標準Javaの一部であり、依存関係を必要としない限り。
ADTC
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.