![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67b6d)
下記のソースについて質問があります。
public class Test{
private String msg;
public Test(){
this("Good morning");
}
public Test(String msg){
msg = msg;
}
public String toString(){/*(2)*/
return ("msg:" + msg);
}
public static void main(String args[]){
System.out.println(new Test());/*(1)*/
}
}
このコードをコンパイルした出力結果は、
msg:null
となるのですが、ここの仕組みがわかりません。
(1)でTestクラスのコンストラクタを呼び出し、msgに"Good morning"を設定し、
処理が終わると思うのですが、(2)の処理も行われてしまいます。
(1)では、Testのコンストラクタを設定しているだけに見えてしまうのですが、
(2)まで処理が行われるのは、何故かのかをご教授の程お願い致します。
No.10
- 回答日時:
一言で言うと、
Testオブジェクトはnullではないですが、
Testオブジェクト内のメンバー変数msgがnullということです。
ここの違いははっきりと確認して下さい。
>ここでは、Objectクラスのobjというインスタンスを作っているため
>nullではないため、obj.toString() の値が出力される。
>と言う認識であっているでしょうか。
この認識で問題ありません。
>戻り値:引数が null の場合は、"null" に等しい文字列。
>そうでない場合は、obj.toString() の値
System.out.println(new Test());
ここでnullかどうか見ている対象は、Testオブジェクトのことです。
Testオブジェクトはnewで生成されているので、nullではありません。
TestクラスのtoString()メソッドで、
return ("msg:" + msg);
こういう記述があると思います。この処理の「"msg:" + msg」の部分に着目します。
これは、"msg:"という文字列と、msgというStringオブジェクトを連結しているわけですが、
実際にはこんな処理が動いています。
"msg:".toString() + msg.toString()
※「+」の処理が内部的にどうなっているかは、ここでは重要でないので省略
文字列連結は、データ型がObject型ならそのtoString()メソッドを返す、となっているためです。
ここで、ようやくmsgがnullということが発覚し、"null"という文字列を返しているのです。
文字列を操作すると、至る所でtoString()メソッドが呼ばれているわけです。
No.9
- 回答日時:
>public static String valueOf(Object obj)
>のメソッドを通ることになりますが、(1)で生成された
>オブジェクト(Object obj)はnullにはならないですよね??
解らないことを棚上げにしない姿勢はいいですが、null かどうかは
御自分で、以下の様なコードを書けばわかります
public class Test{
private String msg;
public Test(){
this("Good morning");
}
public Test(String msg){
msg = msg;
System.out.println("Hello"); //追記
}
public String toString(){
System.out.println("hoge");//追記
return ("msg:" + msg);
}
public static void main(String args[]){
Object obj = new Test();
if(obj == null){//追記
System.out.println("Hello");
} else {
System.out.println("World");
}
}
}
この手法をプリントデバッグと言います、自分のコードがどこを
通っているのかが目で見てわかり、大きなコードや
深いネスト等で重宝します
>nullではないため、obj.toString() の値が出力される。
>と言う認識であっているでしょうか。
正確には オーバーライド された toString() の戻り値が出力されています
参考URL:http://sdc.sun.co.jp/java/docs/j2se/1.4/ja/docs/ …
No.7
- 回答日時:
>焦点にしていることは、
>System.out.println(new Test());
>にて、コンストラクタだけ呼び出されているのに、
まず、ここがおかしいです
public class Test{
private String msg;
public Test(){
this("Good morning");
}
public Test(String msg){
msg = msg;
System.out.println("Hello"); //追記
}
public String toString(){
return ("msg:" + msg);
}
public static void main(String args[]){
new Test();
}
}
コンストラクタだけを呼び出すとは、上記です
元のコードは
System.out.println(Object obj);
ですから、後は戻り値をたどってください
この回答への補足
ご丁寧な説明を頂き、ありがとうございます。
おかげで、自分なりにわかるようになってきました。
で、確認したいことがありますので、下記にその内容を記載します
System.out.println(Object obj);
^^^^^^^^^^^(1)
(1)の箇所で
1.オブジェクトの生成
2.出力処理
が行なわれます。
その際、
public static String valueOf(Object obj)
のメソッドを通ることになりますが、(1)で生成された
オブジェクト(Object obj)はnullにはならないですよね??
APIリファレンスに記載されているvalueOfの戻り値の説明で
戻り値:引数が null の場合は、"null" に等しい文字列。
そうでない場合は、obj.toString() の値
があります。
ここでは、Objectクラスのobjというインスタンスを作っているため
nullではないため、obj.toString() の値が出力される。
と言う認識であっているでしょうか。
宜しくお願い致します。
No.6
- 回答日時:
System.out.println(new Test());
は、以下の処理と同じです。
Object obj = new Test();
System.out.println(obj); // objのtoString()が呼ばれて、msgnull と表示される。
new Test()でコンストラクタが呼び出されてますが、println()にわたっているのはTestインスタンスです。msgnullと表示されるのはprintlnメソッドにTestインスタンスを渡した結果です。
println(Object obj)メソッドの仕様を見ると、以下のようになってます。
http://sdc.sun.co.jp/java/docs/j2se/1.4/ja/docs/ …
↓
http://sdc.sun.co.jp/java/docs/j2se/1.4/ja/docs/ …
↓
http://sdc.sun.co.jp/java/docs/j2se/1.4/ja/docs/ …
↓
引数が null の場合は、"null" に等しい文字列。そうでない場合は、obj.toString() の値、、、が表示されると書いてあります。
参考URL:http://sdc.sun.co.jp/java/docs/j2se/1.4/ja/docs/ …
No.5
- 回答日時:
原因ですが、
public Test(String msg){
msg = msg;
}
ここを、
public Test(String msg){
this.msg = msg;
}
として下さい。これで大丈夫なはずです。
何でそうなるのか?についてですが、
msg = msg;
ここの処理ですが、おそらく
private String msg;で定義したmsg
(ややこしいので、この変数を「メンバー変数msg」と呼びます)に、
public Test(String msg){の引数msg
(こちらを「ローカル変数msg」と呼びます)に代入している、
と考えていませんか?
メンバー変数とローカル変数が同じ名前(この場合「msg」)の場合、
いきなり、「msg」と指定されても、どちらの変数を使用していいかコンピュータには判別できません。
なので、この場合は原則として「ローカル変数とする」と決まっています。
(これはJavaの言語仕様で決まっていることです)
じゃあ、メンバー変数msgの方を指定したい場合はどうするか?
ですが、メンバー変数を表すようにthis.msg
とすることでコンピュータが理解できるようになるのです。
ちなみに、これは変数名がカブっている部分だけ適用されるものです。なので
public String toString(){ /*(2)*/
return ("msg:" + msg);
}
このメソッド内では、msgはカブることはないので、
あえて「return ("msg:" + this.msg);」としなくても問題ないのです。
(this.msgとしても問題ありません。)
public Test(String msg){}
このメソッド内ではmsgがカブってしまうので、使い分けが必要なのです。
以上のことより、
msg = msg;
ここでは、ローカル変数msgに、ローカル変数msgを代入する?
という処理になっており、
メンバー変数msgは、何もされていないのです。
なので、メンバー変数msgは、いつまでたってもnullのままなので、
return ("msg:" + msg);
ここで、「null」が表示されるのです。
この回答への補足
書き込みありがとうございます。
説明で申し訳ございません。
msgがローカル変数であることや、nullになる原因については
判明しております。
焦点にしていることは、
System.out.println(new Test());
にて、コンストラクタだけ呼び出されているのに、
なぜ、public String toString()のメソッドが呼び出されて
画面に
msg:null
と出力される背景へのイメージがつかみにくい状態です。
No.4
- 回答日時:
>このコンストラクタの呼び出しは、オブジェクトの生成と初期化が
行なわれるだけで
そこまでの理解は正しいです。それしか行われません。
それを「System.out.printlnしているからそうなる」んです。
この回答への補足
書き込みありがとうございます。
確認したいことがありますので、下記に記載いたします。
System.out.println(new Test());
^^^^^^^^^^^^(1)
(1)によって、コンストラクタ(オブジェクト生成)の呼び出される。
public Test(){
this("Good morning");
^^^^(2)
}
(2)によって、同クラスの別なコンストラクタ(public Test(String msg))に
移る
public Test(String msg){
^^^^^^^^^^^(3)
msg = msg;
}
(3)によって、msg("Good morning")がローカル変数msgに代入される。
※クラス変数のprivate String msgはnull
public String toString(){ /*(2)*/
return ("msg:" + msg);
^^^^^^^^^^^^^^^^^^^^^^(4)
}
(3)実行後、toStringメソッドが呼び出されて、
(4)の処理(「msg:null(private String msg)」が返される)が実施される。
System.out.println(new Test());
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^(5)
(4)の処理が、画面に出力される。
(1)-(5)までの一連の流れにより、画面に
msg:null
が出力されます。
ただここで、
>このコンストラクタの呼び出しは、オブジェクトの生成と初期化が
>行なわれるだけで
>そこまでの理解は正しいです。それしか行われません。
この返答に矛盾があるように感じてしまいます。
今回のソースでは、コンストラクタ呼出し後
toStringメソッドが呼び出され、return ("msg:" + msg);が行なわれ、
画面に「msg:null」が出力されています。
つまり、(4)の処理は何故行なわれているのかが理解できない状態です。
コンストラクタの呼び出しはオブジェクトの生成のみであり、
メソッドの呼び出しは行なわれないため、矛盾を感じてしまい
理解することに苦しんでおります。
No.3
- 回答日時:
>(2)まで処理が行われるのは、何故かのかをご教授の程お願い致します。
public String toString(){ /*(2)*/ new Throwable().printStackTrace();
として実行すると
java.lang.Throwable
at Test.toString(Test.java:10)
at java.lang.String.valueOf(String.java:2577)
at java.io.PrintStream.print(PrintStream.java:616)
at java.io.PrintStream.println(PrintStream.java:753)
at Test.main(Test.java:14)
msg:null
ANo.1が正しいことがわかりますよ。
この回答への補足
自分の中では、画面に出力されるのは
null
のみになると思われます。
実際の出力は、
msg:null
となり、3つの返信より、イメージをつかむことができないです。
このコンストラクタの呼び出しは、オブジェクトの生成と初期化が
行なわれるだけで、メソッド(public String toString())の呼び出し
には、関係ないと思ってしまいます。
まだ、理解度が足りなくて申し訳ございません。
No.2
- 回答日時:
これでうまくいきました。
public class Test070502{
private String msg;
public Test070502(){
this.msg="Good morning";
}
public Test070502(String msg){
this.msg = msg;
}
public String toString(){ /*(2)*/
return ("msg:" + msg);
}
public static void main(String args[]){
System.out.println(new Test070502()); /*(1)*/
}
}
No.1
- 回答日時:
/* 当方,Java初心者です。
*/public class Test{
private String msg;
public Test(){
this("Good morning"); /* 実はこの書式をはじめて知った人間だったり(汗)*/
}
/* クラスのメンバ変数msgなのかローカル変数msgなのか判別がつきにくいので 勝手に置き換えましたが,
意図してないものであればごめんなさい*/
public Test(String message){
msg = message;
}
public String toString(){ /*(2)*/
return ("msg:" + msg);
}
public static void main(String args[]){
System.out.println(new Test()); /*(1)*/
/*
http://sdc.sun.co.jp/java/docs/j2se/1.5.0/ja/doc …
を参考にします
new Test()によりクラスのインスタンスが出来ます。
これらクラスは全て確かObjectを継承するんじゃありませんでしたっけ?
すると実行されるメソッドは
=======
println
public void println(Object x)
Object を出力して、行を終了します。
このメソッドは、print(object) を呼び出してから println() を呼び出すのと同じように動作します。
パラメータ:
x - 出力される Object 値
=======
です。
さらに読むとこう書かれています。
========
http://sdc.sun.co.jp/java/docs/j2se/1.5.0/ja/doc …
public void print(Object obj)
オブジェクトを出力します。String.valueOf(Object) メソッドにより作成された文字列は
プラットフォームのデフォルトの文字エンコーディングに従ってバイトに変換され、
このバイトが write(int) メソッドとまったく同じ方法で書き込まれます。
パラメータ:
obj - 出力される Object 値
関連項目:
Object.toString()
======
さらに調べるとString.valueOfを調べると
======
http://sdc.sun.co.jp/java/docs/j2se/1.5.0/ja/doc …
valueOf
public static String valueOf(Object obj)
Object 引数の文字列表現を返します。
パラメータ:
obj - Object
戻り値:
引数が null の場合は、「null」に等しい文字列。【そうでない場合は、obj.toString() の値】
関連項目:
Object.toString()
つーことで実行されてます
*/
}
}
この回答への補足
かなり詳しく回答いただきありがとうございます^^
しかし、どうもピンとこないです。
オブジェクトを作成するために、ただコンストラクタを
呼び出しているだけで、画面に出力されるのは
null
のみになると思われます。
>new Test()によりクラスのインスタンスが出来ます。
>これらクラスは全て確かObjectを継承するんじゃありませんでしたっけ?
そうでしたっけ.....自分でもわからないです。
かなり、謎の多が多い状態です、
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・「I love you」 をかっこよく翻訳してみてください
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・昔のあなたへのアドバイス
- ・かっこよく答えてください!!
- ・あなたが好きな本屋さんを教えてください
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
中カッコ{}だけの記述について
-
NoSuchMethodErrorが解決できま...
-
JSP/Servletのパラメータの受け...
-
Javaでlog4jを使ってログ出力を...
-
Javaで日本語の出力が文字化けする
-
プログラミングの問題です。大...
-
System.exit()の値を取得したい
-
変数を動的に利用するには?
-
System.err. printlnとSystem.o...
-
ダブルクォーテーションのrepla...
-
C言語 重複しない4ケタの乱数...
-
javaで質問です。 文字列2023/2...
-
VBAで配列の計算
-
Log4jで機能毎に別ファイルへ出...
-
Path型をString型へ変換する(Java)
-
Java配列でNullPointerExceptio...
-
getStringの値がNULLの時の処理
-
JAVAのServletで、画像表示につ...
-
ORA-01858: 数値を指定する箇所...
-
サーブレットPrintWriterについて
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
変数を動的に利用するには?
-
中カッコ{}だけの記述について
-
プログラミングの問題です。大...
-
NoSuchMethodErrorが解決できま...
-
Javaでlog4jを使ってログ出力を...
-
System.exit()の値を取得したい
-
コンストラクタの引数の中のnew?
-
Javaで日本語の出力が文字化けする
-
インタフェイス実装と抽象クラ...
-
randomで
-
Java プログラム public class ...
-
日本語が文字コードによっては...
-
Socketの接続のタイムアウトを...
-
GetterとSetterをやったのに。
-
javaで特定の文字列から特定の...
-
JSP/Servletのパラメータの受け...
-
(1)を表示するには
-
【初心者です】javaで平均値を...
-
javaのプログラミングで作るRPG...
-
【java】同ディレクトリ別ファ...
おすすめ情報