質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

4回答

2687閲覧

staticフィールドについて

退会済みユーザー

退会済みユーザー

総合スコア0

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2016/08/21 13:55

編集2016/08/21 14:59

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ページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

てことはSystem.outってインスタンスということになります。

この表現がよくわからないですが、
インスタンス変数にはインスタンスへの参照が入っていて、厳密に言えばインスタンスそのものではありません。

staticメンバはクラスに所属するような振る舞いとなるので、そのクラスから生じるインスタンスは関係ありません。
この意味ではstaticメンバ自体はアプリケーション内で一つと言えます。

どのインスタンスが用いられるかは、実行時、そのstaticメンバにどのインスタンスへの参照が入っているか次第です。
言語仕様なのでルールですね。

投稿2016/08/21 14:46

flied_onion

総合スコア2604

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/08/22 06:14

私の理解では、outは参照型の変数でPrintStream型のインスタンスを参照しており、static変数だから、クラスに属する形になっており、outが参照するPrintStreamインスタンスは(PrintStreamインスタンスが複数存在したとしても)常に一つである。 というような理解なのですが、どうでしょうか?
flied_onion

2016/08/22 06:44

ちょっと「複数存在したとしても」のあたりが回りくどいけどそうですね。
退会済みユーザー

退会済みユーザー

2016/08/23 03:38

回答ありがとうございました。
guest

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

swordone

総合スコア20651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/08/22 06:10

私の理解では、outは参照型の変数でPrintStream型のインスタンスを参照しており、static変数だから、クラスに属する形になっており、outが参照するPrintStreamインスタンスは(PrintStreamインスタンスが複数存在したとしても)常に一つである。 というような理解なのですが、どうでしょうか?
swordone

2016/08/22 06:57

この場合、「PrintStreamインスタンスが複数存在したとしても」というのは違います。あえて言うなら、「Systemインスタンスが複数存在したとしても」が正しい解釈になります。先に言ったとおり、Systemはインスタンス化できませんが…
退会済みユーザー

退会済みユーザー

2016/08/22 11:28

>この場合、「PrintStreamインスタンスが複数存在したとしても」というのは違います。 なぜでしょうか? PrintStreamクラスはインスタンス化が可能ですよね?
swordone

2016/08/22 14:37

「PrintStreamインスタンスが複数存在したとしても」というのがどういう状態を指しているのかがよくわかりません。 そもそも一つの変数が複数の値・オブジェクトを指すということ自体あり得ません。
退会済みユーザー

退会済みユーザー

2016/08/23 00:50

newでPrintStreamインスタンスを複数生成しても、outが参照するPrintStreamインスタンスは一つである、という意味です。
swordone

2016/08/23 01:11 編集

そもそも変数の概念がわかっていませんね。staticフィールドであろうとなかろうと、一つの変数が指すインスタンス(プリミティブ型の場合は値)は常にひとつです。 問題は、その変数が何らかのインスタンスに属するものか、インスタンスに属さずクラス唯一の存在か、という話です。後者がstaticフィールドに該当します。 加えてSystem.outはfinalなので、あらたにnewでインスタンス生成して代入する、ということは不可能です。そんなことをしたら標準出力が消滅するなどの危険な状態になります。
退会済みユーザー

退会済みユーザー

2016/08/23 02:37

その通りだと思いますが、 「newでPrintStreamインスタンスを複数生成しても、outが参照するPrintStreamインスタンスは一つである」 という文章の何がおかしいのでしょうか? System.outがfinalであるかどうかにかかわらず、PrintStreamクラスのインスタンスは生成することができます。 もちろん、生成したインスタンスをSystemクラスのstatic変数outが参照することはできませんが。(finalであるため)
swordone

2016/08/23 02:49

そもそもなぜそんな話が出てきたのかがよくわかりません。outにかぎらず、いかなる状況でも同じ型のインスタンスをいくつ生成しようと、その変数に代入しないかぎり参照するインスタンスに変化はありません。
退会済みユーザー

退会済みユーザー

2016/08/23 03:38

回答ありがとうございました。
guest

0

java

1synchronized(対象インスタンス){}

そもそもこれ本当ですか?と思って仕様を確認しましたが、

SynchronizedStatement:
synchronized ( Expression ) Block

The 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
hekigyoku2

総合スコア10

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/08/22 01:04

回答ありがとうございます。 言語仕様では()の中には参照型の変数が使われるのですね。 >reference typeとは参照型、つまり「オブジェクト」の事であってあらゆるオブジェクトが該当しますよね。 「オブジェクト」という言葉をどういう意味で使われていますか? オブジェクト=参照型の変数 という意味でしょうか?
hekigyoku2

2016/08/23 00:33

オブジェクトの意味ですか? o instanceof Object つまり o is_a Object(oはオブジェクトである) という意味で使っています。
hekigyoku2

2016/08/23 00:51

1.javaの型には、参照型と基本型があります。基本型とはintとかlongとかで、参照型とは「オブジェクト」の事です。 (ここまでは全員がagreeだと思うのですが) 2.基本型以外、すべてオブジェクトです。クラスもオブジェクトです。 3.全てのオブジェクト(a)は、それが何かを示すオブジェクト(A)を持ちます。それをクラスといいます。Aはaのクラスであり、aはAのインスタンスです。 つまりクラスーインスタンスとは、オブジェクト間の関連のことです。 (この辺の解釈が人によるんですよね。でも言語仕様を見ればこれは明確な事実だと思うのですが、違うという人がいるんですよね・・・)
退会済みユーザー

退会済みユーザー

2016/08/23 01:05

>基本型以外、すべてオブジェクトです。クラスもオブジェクトです。 これは変数の話をしているのでしょうか? Stringで話をすると、 String s = new String("aaa); において、変数sは参照型だからオブジェクトということですか? hekigyoku2さんはクラスやインスタンスを指すものとしてオブジェクトという言葉を用いているのでしょうか?
hekigyoku2

2016/08/23 02:56

そうです。全てオブジェクト。それがオブジェクト指向です。
hekigyoku2

2016/08/23 02:59

SystemもSystem.outもオブジェクトです。SystemがSystem.outを参照している。それだけです。
hekigyoku2

2016/08/23 03:02

おうたがいなら、 System.class instanceOf Object してみてください。
guest

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

Mr_Roboto

総合スコア2208

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/08/22 05:38

>Systemクラスには有用なクラス・フィールドおよびメソッドがあります。インスタンス化することはできません。 これはSystemクラスがインスタンス化できないという意味ではないのでしょうか。 フィールドについて言及しているわけではないと思っているのですが。 >outフィールドは、staticと宣言されているので、インスタンスではありません。 outフィールドはインスタンスの参照ではないのですか? PrintStreamインスタンスの参照と思っているのですが。
Mr_Roboto

2016/08/22 05:57

インスタンス化されていないクラスのフィールドがインスタンスであるわけがない。 マイナスもついてるし私の説明では通じないようなので、他の方の回答を参考にしてください。
退会済みユーザー

退会済みユーザー

2016/08/22 06:13

そんなこと言わずに、議論しませんか? 私は是非ともお願いしたいです。 >インスタンス化されていないクラスのフィールドがインスタンスであるわけがない。 そうすると、outフィールドは一体何なのでしょうか? 参照ではないのですよね?
Mr_Roboto

2016/08/22 13:35

単に理解していないだけで議論ではないですね。 もう少し言葉の意味を理解しましょう。 なぜ今参照という言葉が出てくるのか。 どういう意味で使っているのか分かりませんが、 outフィールドは、クラス型なので参照型です。 staticフィールドでもインスタンスフィールドでも参照型はあります。 いずれにせよ、この質問で参照かどうかは関係ないです。 別の言葉を持ってくるから意味が理解できなくなるのです。 > outフィールドは一体何なのでしょうか? Systemクラスのstaticフィールドだという以外にどう説明すれば分かるのですか? しつこいようですが、staticは、インスタンスではありません。 もしも Systemクラスが new でインスタンスが作成されていて、 out フィールドがstaticと宣言されていなければインスタンスフィールドです。 でも違うでしょう? 追記も見ましたが書籍の説明が間違っている、またはそのレベルの時点で理解できる範囲の説明であるという可能性は考えないのでしょうか? 言葉の意味と概念を理解せずに細かいことにこだわりすぎていると思いますよ。
退会済みユーザー

退会済みユーザー

2016/08/22 13:45

まず、あなたの言う「インスタンス」とは「インスタンスの参照」で間違いないですか? staticフィールドでもインスタンスの参照は指定できると思うのですが、「インスタンス化されていないクラスのフィールドがインスタンスであるわけがない」の意味するところが理解できません。
Mr_Roboto

2016/08/22 13:53

これ以上説明できません。ギブアップです。 単に知識不足です、Javaの基礎の本を10冊くらい読みましょう。 プログラムを1万行くらい書きましょう。 以上
swordone

2016/08/23 01:15

私から見て、あなたの回答も的を外しているように感じます。 「staticだからインスタンスではあり得ない」というのはおかしな話です。 結論から言うなら、System.outはPrintStreamクラスのインスタンスを指す変数になります。 変数がインスタンスか否かというのは、staticかどうかということとは全く無関係です。 「インスタンスではない」ということと、「インスタンスフィールドではない」ということもまた違う話です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問