staticフィールドについての質問です。
terateilでスレッドの調停時に使うsynchronizedについて質問した時に出た話題からの質問です。(その質問を見なくても、全然大丈夫です)
もともとの質問から大きくずれますので、こちらで新たに質問します。
synchronizedでは
Java
1synchronized(対象インスタンス){}
のような表記になります。
そして、以下のようなパターンを目にしました。
Java
1synchronized(System.out){}
てことはSystem.outってインスタンスということになります。
そのインスタンス化のタイミングは定かではないのですが、このインスタンスの個数は絶対に1つなのでしょうか?
回答者の方が言うには、staticフィールドなので、インスタンスは一つだとのことですが、そうなのですか?
Java
1public class Family{ 2 static Airconditioner aircon; 3 String name; 4}
のようなコードを考えた時に、staticフィールドのインスタンスはクラスおよびそれから生じるインスタンスに属するような形になるので、一つが自然だとは思うのですが、ルールとして決まっているのでしょうか?
回答お願いします。
みなさん、回答ありがとうございます。
System.outがインスタンスと私が書いているので、皆さんそれを指摘されてますね。
私の使用している参考書にsynchronizedブロックについての次のような記述があります。
synchronized(対象インスタンス){
//複数スレッドから同時実行されないよう保護したいコード
}
そして、synchronized(System.out)というような記述があるということはSystem.outはインスタンス(正確にはインスタンスの参照)になるのではないでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
てことはSystem.outってインスタンスということになります。
この表現がよくわからないですが、
インスタンス変数にはインスタンスへの参照が入っていて、厳密に言えばインスタンスそのものではありません。
staticメンバはクラスに所属するような振る舞いとなるので、そのクラスから生じるインスタンスは関係ありません。
この意味ではstaticメンバ自体はアプリケーション内で一つと言えます。
どのインスタンスが用いられるかは、実行時、そのstaticメンバにどのインスタンスへの参照が入っているか次第です。
言語仕様なのでルールですね。
投稿2016/08/21 14:46
総合スコア2604
0
ベストアンサー
そもそもstaticが何かを理解しないと混乱するばかりでしょう。
まず、「staticではないフィールド」を考えます。
java
1public class A { 2 int a; 3}
このようなクラスAがあったとします。aはstaticではないフィールドです。staticではないので、このAクラスのインスタンスごとにaは異なる値を取ることができます。
java
1A a1 = new A(); 2A a2 = new A(); 3A a3 = new A(); 4 5a1.a = 1; 6a2.a = 2; 7a3.a = 3; 8 9System.out.println("a1.a = " + a1.a); 10System.out.println("a2.a = " + a2.a); 11System.out.println("a3.a = " + a3.a);
このようなコードを実行してみると、各インスタンスのaの値が異なることが確認できるはずです。
一方、「staticなフィールド」を考えてみましょう。
java
1public class B { 2 static int b; 3}
このようなクラスBを考えます。このbはstaticフィールドです。staticフィールドはそのクラスに唯一の存在であり、インスタンスとは独立した領域にメモリを取ります。
java
1B b1 = new B(); 2B b2 = new B(); 3 4b1.b = 1; 5 6System.out.println("b1.b = " + b1.b); 7System.out.println("b2.b = " + b2.b);
このようなコードを実行したとします。途中b1インスタンスからbを変更しました。b2は生成してから何も操作していません。普通に考えたら、2行目でb2.bを出力した結果は初期状態の0であるように思われるかもしれません。しかしbはBクラス唯一の変数であり、b1からでもb2からでも同じ変数を指します。つまり、b1からだけbを操作したつもりでも、そのbはb2から見ても同じ変数のため、出力結果はどちらも「1」になります。
このようにstatic変数はインスタンスとは切り離されたものであり、それをインスタンスから操作・参照するのは整合性が悪いので、staticなフィールドやメソッド(フィールドやメソッドをまとめてメンバと呼ぶ)はクラス名.メンバ
と書くことが推奨されています。
話を戻すと、System.outはクラス唯一の変数です。そのため、どこからアクセスしようとSystem.out
という変数はただひとつしか存在しないのです。「変数」と言っていますが、このSystem.outはその型がPrintStream型であるというだけの話です。
投稿2016/08/21 14:37
総合スコア20651
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/08/22 06:57
退会済みユーザー
2016/08/22 11:28
2016/08/22 14:37
退会済みユーザー
2016/08/23 00:50
2016/08/23 01:11 編集
退会済みユーザー
2016/08/23 02:37
2016/08/23 02:49
退会済みユーザー
2016/08/23 03:38
0
java
1synchronized(対象インスタンス){}
そもそもこれ本当ですか?と思って仕様を確認しましたが、
SynchronizedStatement:
synchronized ( Expression ) BlockThe type of Expression must be a reference type, or a compile-time error occurs.
としか書かれていません。どこにも「インスタンス」などという名前は出て来てないきがしますが。
reference typeとは参照型、つまり「オブジェクト」の事であってあらゆるオブジェクトが該当しますよね。
インスタンスももちろん、クラスだってオブジェクトです。実際
java
1synchronized(Object.class){}
これでコンパイルエラーは発生しません。これは単に「何をキーにロック管理するか」だけの話であろうかと思うのですが。
ちなみに、
java
1 System.out.println(System.out.getClass());
の結果は
class java.io.PrintStream
です。つまり「System.outはPrintStreamのインスタンスです」と思うのですが・・・
いかがでしょうか。
「対象インスタンス」という文言の意図は、単に「それが当てはめられる事が多い」程度の意味ではありませんか?
投稿2016/08/21 16:32
編集2016/08/21 16:34総合スコア10
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/08/22 01:04
2016/08/23 00:33
2016/08/23 00:51
退会済みユーザー
2016/08/23 01:05
2016/08/23 02:56
2016/08/23 02:59
2016/08/23 03:02
0
Java
1synchronized(System.out){}
てことはSystem.outってインスタンスということになります。
どうしてそうなるのか。
synchronizedは、スレッドに関する命令でインスタンスとは関係ありません。
System (Java Platform SE 8 ) を見ればわかりますが、
Systemクラスには有用なクラス・フィールドおよびメソッドがあります。インスタンス化することはできません。
とあります。outフィールドは、staticと宣言されているので、インスタンスではありません。
staticに対してインスタンスという言葉を使うこと自体が間違ってます。
staticフィールドは、クラスがロードされた時点で初期化されます。
ひとつしか用意されません。ルールというより仕様として決まっています。
インスタンスフィールドというのは、new命令によって
クラスのインスタンスが作成されるた時に初期化されます。
なので、インスタンス化された分だけ存在します。
もう一度言います、staticフィールドは、インスタンスフィールドではありません。
staticフィールドは、クラスに属するもの
インスタンスフィールドは、インスタンス化されたオブジェクトに属するものです。
投稿2016/08/21 14:48
総合スコア2208
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/08/22 05:38
2016/08/22 05:57
退会済みユーザー
2016/08/22 06:13
2016/08/22 13:35
退会済みユーザー
2016/08/22 13:45
2016/08/22 13:53
2016/08/23 01:15
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/08/22 06:14
2016/08/22 06:44
退会済みユーザー
2016/08/23 03:38