回答:
クラス内のin
およびout
フィールドの定義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
。
enum
... enum
Java 1.5で新しくなりました(1.0日間のオプションではありません)。
final static
ありstatic final
ますか?もしそうなら、それは何ですか?
本当の理由は、これがレガシーな問題だからです。System.in,out,err
定数は、Java 1.0の一部...と、おそらく多く、さらにバックでした。設計に問題があることが明らかになった時点で、修正するには遅すぎました。彼らができる最善のSystem.setIn,setOut,setErr
方法は、Java 1.1にメソッドを追加し、言語仕様の問題に対処することでした1。
これはSystem.arraycopy
、名前がJavaの命名規則に違反する静的メソッドがある理由の問題に似ています。
これが「悪いデザイン」かどうかについては、そうだと思います。現在のオブジェクト指向以外の処理が深刻な問題である場合があります。(たとえば、「標準IO」ストリーム要件が競合する場合に、あるJavaプログラムを別のJavaプログラム内で実行する方法を考えてみてください。
しかし、多くの場合、現在のやり方がより便利であるという議論にも関係します。
1- System.in,out,err
変数が「特別なセマンティクス」を持っているとJLSで特に言及されることに注意するのは興味深いことです。JLSは、final
フィールドの値を変更した場合、これらのフィールドの場合を除き、動作は未定義であると述べています。
outオブジェクトは不変であり、パブリックの最終的な静的フィールドに保持するために何らかの形で安全になります(これは議論の余地があります)。
JDKのクラスの多くは、最高のオブジェクト指向設計原則を尊重していません。その理由の1つは、オブジェクト指向が主流のパラダイムとして出現し始めたばかりで、多くのプログラマーが現在のように単にそれらに慣れていない20年前に書かれたという事実です。悪いAPI設計の非常に良い例はDate&Time APIであり、変更に19年かかりました...
この答えは素晴らしく真実です。
使いやすさのために妥協が行われた場合もあると付け加えました。
String型のオブジェクトは、Stringがプリミティブでない場合、新しいイベントなしでインスタンス化できます。
String s = "Hello";
文字列は非プリミティブなので、次のようにインスタンス化する必要があります。
String s = new String("Hello"); // this also works
しかし、StringはAPIで最も広く使用されているクラスであるため、コンパイラはより短く、少ないOOオプションを許可します。
また、配列はオブジェクト指向以外の方法で初期化できます。
int i[] = {1,2,3};
奇妙なことに、オブジェクトはクラスのインスタンスまたは配列のいずれかです。意味配列は、完全に分離されたタイプのクラスです。
配列には、length
定数ではないパブリックフィールドがあります。また、インスタンスのクラス配列に関するドキュメントもありません。(Arraysクラスまたはjava.reflect.Arrayと混同しないでください)。
int a = myArray.length; // not length()
new String("Hello")
常に新しいStringオブジェクトを作成します。while String s = "Hello";
は、インターンされたオブジェクトを使用します。比較:"Hello" == "Hello"
trueの場合がありますが、new String("Hello") == new String("Hello")
常にfalseです。で不可能な最初のコンパイル時最適化マジックがありますnew String("Hello")
。en.wikipedia.org/wiki/String_interning
String s = new String("Hello");
これは間違っています。短いオプションは(String s = "Hello";
)である以上ので、文字列のインターンの正しいです。
String
、「より正確な」オプションはありません。両方とも正しいです。ただし、MichaelTが言うように、文字列インターンのために短いほうが好まれます。