No.7ベストアンサー
- 回答日時:
> あと補足なんですがインスタンスが確保されているものに
> a = null;とかするのは問題あるでしょうか?
> なんとなくメモリリークが起きる気がするのですが、、
問題ありません。メモリリークも起きません。
確かに、文字列を連結したりするたびに新しい文字列のインスタンスが生成されていきますが、Javaでは、不要になったインスタンスのメモリは、自動的に「ガーベジコレクタ」によって開放されます。
つまり、不要なインスタンスを破棄・処分するためのコードをいちいちプログラマが書く必要は無いのです。
ある変数に代入されているインスタンスが不要になったら、その変数にnullを代入しておくだけで、あとは適当なタイミングにガーベジコレクタがメモリを開放してくれます。(メモリの開放はnull代入の直後とは限りません)
No.6
- 回答日時:
(1)
String a;
a = "aaa";
(2)
String a = new String();
a = "aaa";
(1)と(2)の動作の違いについて。
(1)
String型の参照を格納する変数aを宣言。(つまりStringオブジェクトはまだ生成されていない。)
aに"aaa"というStringオブジェクトの参照を代入する。
メモリでいうならば「参照用のa」「"aaa"という内容のStringオブジェクト」の分だけ確保されます。
(2)
String型の参照を格納する変数aを宣言し、そのaに新しく生成(new)したStringオブジェクトの参照を代入する。
aに"aaa"というStringオブジェクトの参照を代入する。(これはaの参照先を"aaa"に書き換えただけで、上でnewしたStringオブジェクトに文字列"aaa"を代入したわけではありません。)
メモリでいうならば「参照用のa」「newしたStringオブジェクト」「"aaa"という内容のStringオブジェクト」の分だけ確保されます。
Stringであろうとオブジェクトは全て例外なく参照渡しです。Javaでは配列はオブジェクトなので配列も参照渡しです。このことを利用したのが#1さんの
>ちょっとずるいですが、
>要素数1の配列にすればできます。
です。
>Stringというのは特別なクラスなのでしょうか?
Java内部の仕様に組み込まれた特別なクラスですが、プログラマはいちいちそのことを意識しなくてもいいと思います。
意識しなければならないのは、String同士を連結して代入する際、新しいオブジェクトが生成されるという点です。(#4参照)
このことを知らないと今回のteststrのように文字列の「内容」を別のメソッドで書き換えたつもりが、実は書き換わっていない、というバグに繋がる可能性があります。
「頻繁に内容が変更される文字列」を扱うのでしたらStringBufferを使用することをお勧めします。=や+での操作はできなくなりますが、メモリやパフォーマンスの面でStringBufferの方が上回ります。Stringは「固定長の文字列」を扱うのに便利なクラスであると心得てください。
No.5
- 回答日時:
プリミティブ型でもオブジェクト型でも、変数を宣言しただけでは、まだ実体は存在しないことに注意してください。
変数の中に実体が存在するのは、代入を行ってからです。(ただし、オブジェクト型変数にnullを代入した場合は、実体は実質的に存在しないことになりますが)
> Cのポインタ渡しとは違うのでしょうか
「参照渡し」は、「ポインタ渡し」と同じことです。ただ、Javaではポインタとは言わずに参照という言葉を使うのです。
> String a = new String();とString a;
> ではメモリ管理が変わるのでしょうか
メモリ管理が異なるというより、処理の内容全体が異なります。
String a;
というのは、変数を宣言しただけです。
まだ代入していないので、変数の中身を取り出すことはできません。(この点C言語とは若干異なります)
String a = new String();
では、大きく分けて三つの処理が行われます。
一つ目は、上と同じく、変数領域の確保です。
二つ目は、新しいStringのインスタンス(実体)の生成です。
三つ目は、生成した文字列インスタンスを代入することです。(厳密には、代入されるのはインスタンスそのものではなくてインスタンスへの参照です)
上と異なる点は、代入《までも》行われる点です。つまり、このあと変数の中身を取り出すことができます。
最後に、
a = a + "bbb";
についてですが、これは、
「二つの文字列をつなげて、新しい文字列インスタンスを作り、それを代入する」
ということが行われます。
(厳密な処理内容は、4番目の回答でSephyさんがおっしゃっている通りですが)
注意する点は、もともと変数aに入っていた文字列インスタンスの中身が書き換えられるのではなく、まったく新しい文字列インスタンスが生成してそれが代入されるという点です。
> 関数teststrのString aの実体はコピーが渡されるているのでしょうか
(Stringはオブジェクト型なので)渡されるのはあくまでも参照です。そして、変数の中身も参照です。
ただし、teststrメソッドの中で、
a = a + "bbb";
としても、これはteststrメソッドの中で使われている変数aに文字列を代入し直しただけです。
つまり、teststrメソッドの変数aの中身は、"aaa"への参照から"aaabbb"への参照に代わりますが(もちろんこの二つの文字列は別なインスタンスです)、mainメソッドの変数aの中身は、aaa"への参照が代入されたままだということです。
>String a; というのは、変数を宣言しただけです。
>まだ代入していないので、変数の中身を取り出すことはできません。(この点C言語とは若干異なります)
確かにString aの時点ではnull状態ですね。
a = "aaa";をはじめて実行したときにインスタンスが確保されるということですね?
あと補足なんですがインスタンスが確保されているものに
a = null;とかするのは問題あるでしょうか?
なんとなくメモリリークが起きる気がするのですが、、
No.4
- 回答日時:
teststrメソッド内の
a = a + "bbb";
のところで混乱しているのだと思います。
Stringの代入
a = a + "bbb";
は、コンパイラによって
a = new StringBuffer().append(a).append("bbb").toString();
のように書き換えられます。ここで新しくStringBufferがnewされていることに注目してください。
ご回答ありがとうございます。大変参考になりました。
コンパイラが値渡しであるかのように見せかけているのですね?
Stringというのは特別なクラスなのでしょうか?
或いは他にも、StringとStringBufferの関係のクラスってあるのでしょうか?
No.3
- 回答日時:
intやfloatなどはプリミティブタイプですのでその値が直接格納されます。
引数渡しにおいては値のコピーが渡されることになります。
そして、Stringはクラスですので引数渡しは参照渡しになります。
しかしStringはデータを変更できません。
String str="Hello";
str+=" world";
とした場合には、まず最初に「Hello」というデータもつStringオブジェクトを
strが参照することになります。
しかし、その後「world」という文字列を追加しようとしても、もとのオブジェクトとは別の
「Hello world」というデータをもつオブジェクトを参照することになります。
よって「一応」参照渡しとなっていますが呼び出し元のオブジェクトを書き換えることが出来ません。
(値を見ることは出来ますが)
文字データを参照で扱う場合にはStringBufferクラスを使います。
プリミティブタイプを参照で扱うためにはIntegerクラスやDoubleクラスなどがあります。
この回答への補足
import java.util.Vector;
class test{
public static void main(String[] args) throws NumberFormatException,IOException{
String a;
a = "aaa";
System.out.println(a);
teststr(a);
System.out.println(a);
return;
}
public static void teststr(String a){
a = a + "bbb";
System.out.println(a);
}
}
ちょっと混乱してきました。
これは参照渡しですよね?
先ほどのプログラムを
String a = new String();
に書き換えると、最後のaaaが表示されなくなりました。
ただのString a;でも実体はありますよね?
String a = new String();とString a;
ではメモリ管理が変わるのでしょうか?
ご回答ありがとうございます。
例えば下記この場合
関数teststrのString aの実体はコピーが渡されるているのでしょうか?
class test{
public static void main(String[] args) throws NumberFormatException,IOException{
String a;
a = "aaa";
System.out.println(a);
teststr(a);
System.out.println(a);
return;
}
public static void teststr(String a){
a = a + "bbb";
System.out.println(a);
}
}
No.2
- 回答日時:
intやdoubleなどの値型は必ず値渡しです。
Stringや配列などのオブジェクト型は必ず参照渡しです。
> 関数にStringを渡したとき内部的に自分のコピーを作っているということなのでしょうか
そのようなことはありません。メソッド(Javaでは関数とは呼びません)に文字列を渡しても、インスタンスが勝手にコピーされるということはありません。なぜなら、参照渡しだからです。
見た目が値渡しであるかのように見えるのは、文字列のインスタンスの内容を書き換えられないからです。
ご回答ありがとうございます。ひょっとすると私が「参照渡し」という言葉の定義を勘違いしているのかもしれません。
Cのポインタ渡しとは違うのでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/12】 急に朝起こしてきた母親に言われた一言とは?
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・好きな「お肉」は?
- ・あなたは何にトキメキますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・チョコミントアイス
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・あなたの習慣について教えてください!!
- ・ハマっている「お菓子」を教えて!
- ・高校三年生の合唱祭で何を歌いましたか?
- ・【大喜利】【投稿~11/1】 存在しそうで存在しないモノマネ芸人の名前を教えてください
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・家の中でのこだわりスペースはどこですか?
- ・つい集めてしまうものはなんですか?
- ・自分のセンスや笑いの好みに影響を受けた作品を教えて
- ・【お題】引っかけ問題(締め切り10月27日(日)23時)
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・ちょっと先の未来クイズ第4問
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
変数名の付け方
-
C#において、同じインスタンス...
-
オブジェクト参照がオブジェク...
-
インスタンス参照でアクセスで...
-
フォームの存在をチェックする方法
-
C# インスタンスの破棄
-
生成したインスタンスを削除す...
-
複数の変数を宣言する時、同時...
-
vb.netでFAXを送信する方法
-
javaのクラスの作り方、エラー...
-
VB.NET getとsetの概念がわかり...
-
private static という変数の修飾
-
変数の参照でエラーが出てしま...
-
SerialPort処理でInvokeメソッ...
-
SQLを連続発行する時の正しい(?...
-
ファイル読み込み/書き込み速度...
-
他のファイルの変数参照
-
「インスタンス」の意味をわか...
-
インスタンスのハンドル
-
DLLのプロパティ値の非共有
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
変数名の付け方
-
private static という変数の修飾
-
複数の変数を宣言する時、同時...
-
インスタンス参照でアクセスで...
-
オブジェクト参照がオブジェク...
-
C# インスタンスの破棄
-
VB.NET getとsetの概念がわかり...
-
C#において、同じインスタンス...
-
生成したインスタンスを削除す...
-
「インスタンス」の意味をわか...
-
変数の参照でエラーが出てしま...
-
フォームの存在をチェックする方法
-
C#「オブジェクト参照が必要で...
-
javaのクラスの作り方、エラー...
-
SQLを連続発行する時の正しい(?...
-
他のファイルの変数参照
-
文字列を日付に変換でParseExce...
-
インスタンスを同じ名前で作成...
-
[Visual C#] 優先される処理に...
-
newしないインスタンス?実体化...
おすすめ情報