
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で質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 関数ポインタの高速化のメリット 7 2023/05/05 20:15
- Java Java プログラム public class Main { public static void 3 2023/08/10 23:46
- その他(プログラミング・Web制作) python質問 1 2023/08/14 11:54
- Visual Basic(VBA) 別シートのデータを参照して値を入れたい。 まとめデータシートのC列D列の値を商品一覧シートのコードが 7 2022/08/17 13:20
- Visual Basic(VBA) VBAでファイル名を指定して保存するとき 4 2023/03/26 21:55
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- Visual Basic(VBA) 別ブックの列同士の値が一致したときの処理 1 2022/09/03 08:27
- 法事・お盆 従姉妹のお墓参りにて(墓参りのみ) 2 2022/09/05 10:56
- Visual Basic(VBA) Sub 分けてソートして貼り付ける() Dim srcSheet As Worksheet Dim 6 2023/08/04 19:57
- Excel(エクセル) 指定文字列が該当するA列をアクティブセルにするには 3 2022/08/17 13:18
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
private static という変数の修飾
-
javaのクラスの作り方、エラー...
-
インスタンス生成で、○○.xxx();...
-
newしないインスタンス?実体化...
-
VB.NET getとsetの概念がわかり...
-
インスタンス参照でアクセスで...
-
C# インスタンスの破棄
-
JDBC ドライバーのロードの方...
-
サーブレットでレスポンスが返...
-
非staticフィールドを参照でき...
-
SQLを連続発行する時の正しい(?...
-
複数のクライアントがサーバの...
-
static 及びthisについて
-
複数の変数を宣言する時、同時...
-
変数の参照でエラーが出てしま...
-
クラスのインスタンス名をクラ...
-
Servletにおけるスレッド間での...
-
教えてください。
-
クラス、インスタンス、オブジ...
-
Form1上にあるTextBox1を Modul...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
オブジェクト参照がオブジェク...
-
private static という変数の修飾
-
変数名の付け方
-
複数の変数を宣言する時、同時...
-
C#において、同じインスタンス...
-
インスタンス参照でアクセスで...
-
生成したインスタンスを削除す...
-
C# インスタンスの破棄
-
VB.NET getとsetの概念がわかり...
-
変数の参照でエラーが出てしま...
-
フォームの存在をチェックする方法
-
「インスタンス」の意味をわか...
-
[Visual C#] 優先される処理に...
-
javaのクラスの作り方、エラー...
-
クラスのインスタンス名をクラ...
-
C#の構造体の開放のしかた
-
エクセル(複数インスタンス)...
-
VB6.0で、DLLを動的に参照したい
-
C#「オブジェクト参照が必要で...
-
vb.netでFAXを送信する方法
おすすめ情報