今だけ人気マンガ100円レンタル特集♪

インスタンス生成時、メモリを確保するためにnewします。
その時に疑問が生まれました。以下の書き方は何が違うのでしょうか。
そしてどちらが推奨されるのでしょうか?

(1) newを明示的に実施
String str = new String();
str = "hoge";
(2) newは明示的にしない
String str = "hoge";

このQ&Aに関連する最新のQ&A

A 回答 (4件)

あー、違う。

けっこう勘違いしている人多いんだけど。

String str = "Hoge";
String str = new String("Hoge");

これは、実は「別のもの」なんだよ。コンパイル時に、"Hoge"がnew String("Hoge")に変換されたりはしない。なぜなら、これはJava内部ではまったく別のことを行っているからだ。実際、コンパイルしたものをデコンパイルしてみるとわかる。"Hello"は”Hello"だし、new Stringはnew Stringのままだ。これらは、シンタックスシュガーじゃない。それぞれ「別のことを行っている文法」なんだよ。

これは、Javaの中でもかなり引っかかる部分なんだが、実は、"Hello"は、「Hello」というStringオブジェクト「ではない」んだ。これは、うーん、Java仮想マシンの仕組みがわからないとうまく説明できないんだが。

ま、手っ取り早くいっちまえば、「Stringリテラルは、Javaの内部では特別なものとして扱われている」ということ。String str = "Hello";みたいにソースコード内にStringリテラルが登場すると、Java仮想マシンは定数プールと呼ばれるところにその値を保管し、次に同じリテラルが登場するとその定数プールに保管した値の参照を変数に渡す。つまり、

String a1 = "Hello";
String a2 = "Hello";

こんなふうにすると、a1にもa2にも常に同じオブジェクトへの参照が渡される(つまりどちらの変数も同じオブジェクトを見ている)。ところが、

String b1 = new String("Hello");
String b2 = new String("Hello");

このようにnew Stringすると、Java仮想マシンは、定数プールではなく、通常のオブジェクトを配置するヒープ内に新たにインスタンスを作成し、その参照を設定する。つまりこの場合、b1とb2は、それぞれ別のStringオブジェクトを参照していることになる。ためしに、

System.out.println(a1 == a2);
System.out.println(b1 == b2);
System.out.println(a1 == b1);

このように、変数の参照が等しいかどうかをチェックすると、a1とa2は等しいが、b1とb2は等しくないし、またa1とb1も等しくないことがわかる。これらは、それぞれ別のオブジェクトを参照してるんだ。いずれもテキストとしての値はすべて「Hello」なんだが、内部的にはまったく別のものだ。

というわけで、特別な理由がない限り、Stringを変数に設定する場合は、String str = "Hello";というようにリテラルを直接指定し、new Stringは使わない。そうすることにより、Stringオブジェクトを必要最低限で済ませることができ、メモリにもまたパフォーマンス的にもよい結果となる(ま、実際はほとんど違いはないけどな)。

ただし、この「StringリテラルとStringインスタンスは別のものだ」ということを利用して、わざとnew Stringを使うこともある。が、このへんは、もう少しJavaに慣れてから知ればいいことだろう。
    • good
    • 6
この回答へのお礼

すっごい勉強になりました^^
ありがとうございます。結構むずかしいですねぇ。。

お礼日時:2009/06/30 11:21

回答#3を拝見して私の認識も今まで違っていたことが分かりました。


失礼しました。

リテラルプールにStringリテラルが格納されて、重複するリテラルについてはその参照がプール内に1つだけコピーが保持されるんですね。
納得しました。

ありがとうございます。

参考URL:http://codezine.jp/article/detail/2915
    • good
    • 0

Javaではソースコードのコンパイル時に、自動的にソースコードが変換・付加されるものがいくつかあります。



String str = "hoge";

もその1つです。実際にコンパイルされる時ときには

String str = new String("hoge");

と変換されコンパイルされます。

その他、クラス内にデフォルトコンストラクタ(引数なしのコンストラクタ)を実装しなかった場合、コンパイル時に自動的に付加されたりします。
    • good
    • 0
この回答へのお礼

ありがとうございます!自動的に付加されるものって多いですよねー
サブクラスのコンストラクタで、スーパークラスのコンストラクタが自動で呼び出されるとか。結構そこで迷っちゃいます><

お礼日時:2009/06/16 14:10

「""」で囲った構文というのは



"hoge" と、new String("hoge") は、まったく同じ意味として解釈されます。
"hoge"と書くと、自動的にString型の実体をnewで作っているのと同じです。

つまり、(1)の一行目、
String str = new String();
は、少しムダな処理をしていることになります。
ここでメモリを確保してString型の新しい実体を生成していますが、
次の行ではメモリの別の場所に確保された別の実体が割り当てられ、
結果的に、1行目で作ったほうの実体はガベージコレクションで破棄されてしまいます。

(1)のように書くのなら、
String str = null;
str = "hoge";
このようにするのが良いです。
    • good
    • 0
この回答へのお礼

ありがとうございます。では(2)のほうが良いのですねー。
勉強になりました!

お礼日時:2009/06/16 14:08

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qnewしないインスタンス?実体化しなくてもいいの?

JAVAについて教えて下さい。


ServletContext application = getServletContext();

の成り立ちの意味なのですが、newがなぜないのか教えて下さい。

~自身の考え~
(1)サーブレットコンテキストというクラスをインスタンス化して
(サーブレットコンテキスト 変数A = new サーブレットコンテキスト();)
    ↑                         ↑
  クラス                       クラス

(2)変数Aドットメソッド()によって、代入変数Bを作り上げる
(サーブレットコンテキスト 代入変数B = 変数A . メソッド();)

(3)のはずが、上記の式にはnewがありません。

なんで??
~~


~疑問点~
もしかしたらHttpServletでimportしているからそこでnewインスタンス化宣言している?
だとするならどのような式になっているのでしょうか。



もしくはメソッドのF3キーとして上位をたどったときに出てきた
public abstract class GenericServlet
implements Servlet, ServletConfig, Serializable
{
public ServletContext getServletContext()
{
return getServletConfig().getServletContext();
}


として抽象クラスが出てきましたが、どこにもnew実体化していません。
よろしくお願いいたします。

JAVAについて教えて下さい。


ServletContext application = getServletContext();

の成り立ちの意味なのですが、newがなぜないのか教えて下さい。

~自身の考え~
(1)サーブレットコンテキストというクラスをインスタンス化して
(サーブレットコンテキスト 変数A = new サーブレットコンテキスト();)
    ↑                         ↑
  クラス                       クラス

(2)変数Aドットメソッド()によって、代入変数Bを作り上...続きを読む

Aベストアンサー

どこかで作られたインスタンスを受け取っています。

getServletContext() の呼び出し先をたどったみたいですが、
さらにそこで別の呼び出しをしているので、そのもっと先です。
そもそも、呼び出し関係をたどっているだけでは見つかりません。
newしているところは簡単には見つからないでしょう。

こういうときは、インスタンスを受け取れることだけ理解すれば十分です。
それより、「インスタンスを受け取れることだけ理解すれば十分」を実現している仕掛けのような、
基本的なところを勉強する方が重要です。

自分でnewせず、他のどこかで作られたインスタンスを受け取ることもあります。
プログラムの書き方には、ずっと多様なパターンがあります。

なお、import とインスタンス化は関係ありません。

Qprivate static という変数の修飾

お世話になります。

private static final String HOGE = "hoge";

という変数(finalなので定数ですが)があるとします。このような、privateでstaticな変数というのは、どのような使われ方を意図しているのでしょうか?privateな変数がstaticである必要は、どのようなときに生じるのでしょうか?

よろしくご教授ください。

Aベストアンサー

 その private な変数が所属するクラス自身がいくつも定義された場合に、プログラム全体で1つのメモリしか確保されなくなります。
 なんで、メモリ量がものすげー切羽詰ってるときとか、ほんの数バイトでも節約した方がいい気がするときに有効です。

QString a = "a"; と String b = new String ("b"); の違い

String a = "a";
String b = new String ("b");

お伺いしたいのですが、
b は String のインスタンスを作ってると思いますが、
a はどんなことをしてるのでしょうか?

Aベストアンサー

お二人の回答を具体的に言うと、こういうことです。
String a1 = "a";
String a2 = "a";
String b1 = new String ("b");
String b2 = new String ("b");

a1のために、aという文字列のインスタンスが作られますが、
a2に代入されるのは、a1に使われたインスタンスが再利用されます。
これは、
if(a1 == a2) System.out.print("a1と同じインスタンス");
の結果でもわかります。

一方、b1とb2は、bという文字列オブジェクトを引数に、新しいインスタンスを生成する指示がありますので、b1とb2と、その初期化に使った無名のStringインスタンスの3つがメモリ上に存在することになります。
if(b1 != b2) System.out.print("b1とは違うインスタンス");
の結果でもわかると思います。

したがって、
String b = new String ("b"); というのは、Integerに例えると
Integer i = new Integer(new Integer(1)); という処理を
していることになり、ひとつ無駄なインスタンス生成となります。

お二人の回答を具体的に言うと、こういうことです。
String a1 = "a";
String a2 = "a";
String b1 = new String ("b");
String b2 = new String ("b");

a1のために、aという文字列のインスタンスが作られますが、
a2に代入されるのは、a1に使われたインスタンスが再利用されます。
これは、
if(a1 == a2) System.out.print("a1と同じインスタンス");
の結果でもわかります。

一方、b1とb2は、bという文字列オブジェクトを引数に、新しいインスタンスを生成する指示がありますので、b1とb2と、その...続きを読む

Qmainメソッドのthrows節で設定した例外はどこでcatchされる

mainメソッドのthrows節で設定した例外はどこでcatchされる?

java初心者です。

例えば、mainメソッドの中でAというメソッドが呼ばれるとします。
そのAについての宣言文(定義文)にthrows節が書かれているような場合、
mainメソッド内で、Aを呼び出す際、Aの実行の中で、もし例外が発生した場合には、
mainでその例外をキャッチして処理するよう、mainの記述を行う必要があるかと思います。

では、mainメソッド自体に設定したthrows節(つまり、
public static void main(String[] args) throws TestException{ ~略~ } という宣言)
については、
その例外(ここでは、TestException)は、どこでcatchすることになるのでしょうか?

もしや、「投げっぱなし」ということなのでしょうか?

mainメソッド自体は、基本的に他のメソッドから呼ばれるものではないかと思うので、
mainメソッドでスローした例外の受け取り場所がわからなくて質問させていただきました。

色々調べたつもりなのですが、よくわからなくて困ってしまいました。
あまりに初歩すぎて、どこにも書かれていないのかなんなのか、
その説明が見当たらないこと自体にも、疑問を感じている次第です。苦笑

以上、どなたか、宜しくお願い致します。

mainメソッドのthrows節で設定した例外はどこでcatchされる?

java初心者です。

例えば、mainメソッドの中でAというメソッドが呼ばれるとします。
そのAについての宣言文(定義文)にthrows節が書かれているような場合、
mainメソッド内で、Aを呼び出す際、Aの実行の中で、もし例外が発生した場合には、
mainでその例外をキャッチして処理するよう、mainの記述を行う必要があるかと思います。

では、mainメソッド自体に設定したthrows節(つまり、
public static void main(String[] args) throws TestExceptio...続きを読む

Aベストアンサー

そのもしやの「投げっぱなし」です。mainメソッドの場合に限らず、throwされた例外をcatchするメソッドがない場合には標準エラー出力にその例外を表示して、該当スレッドの実行はそこで終了です。

public class QA6049493 {
public static void main(String[] args) throws Exception {
throw new Exception("from main");
}
}

>java QA6049493
Exception in thread "main" java.lang.Exception: from main
at QA6049493.main(QA6049493.java:3)

Q生成したインスタンスを削除する方法

言語:JAVA

生成したインスタンスを削除するにはどのようにすれば良いでしょうか?

testData = new TestData();

testDataはセッション内に格納してあります。
また、testDataはNULLのままだったり、実際に値が入っていたりもします。

NULLのままだと不具合があるため、NULLの場合は、インスタンスそのものを削除してしまいたいと考えています。
初歩的な質問ですみませんが、教えてください。

よろしくお願いいたします。

Aベストアンサー

浅学なため、TestDataというクラス名と「セッション内に格納」という表現だけからどうしてHttpSessionが出てくるのか分かりませんが...

Javaでは、明示的な操作(C++のdeleteのような)によってインスタンスを削除することはできません。そのインスタンスがどこからも参照されなくなったらGCで消えます。もう要らない(消えてほしい)インスタンスを参照している変数やフィールドにはnullを代入することで参照をなくします。

testData = null;

> NULLのままだと不具合があるため、NULLの場合は、インスタンスそのものを削除してしまいたい

何がNULLだとどのように不都合なのかを説明してもらえると、別の回答がつくかもしれません。

Qラジオボタンのグループ化

VC6.0の
ラジオボタンのグループ化についてですが
例えばIDC_RADIO1~IDC_RADIO6まで作ったとして
IDC_RADIO1と
IDC_RADIO4のグループにチェックをいれると
IDC_RADIO1~3と4~6が
それぞれグループになったのですが
1、2、6と3、4、5をグループにしたいときは
どうすればよいのでしょうか?

あるサイトによるとグループボックスでラジオボタンで囲むと
囲んだ部分がグループになると記述されてたのですが
それについてもうまくいかなかったのですが、教えて頂けないでしょうか?

Aベストアンサー

[レイアウト]-[タブオーダー]でタブ順を
IDC_RADIO1,2,6,3,4,5 の順で設定します。
ラジオボタンのプロパティで IDC_RADIO1 と IDC_RADIO3
の[グループ]をチェックします。またIDC_RADIO5 の後の
コントロール(何でも良い)の[グループ]もチェック
します。

>グループボックスでラジオボタン
マジっすか。

Qメソッド宣言の戻り値の型にクラス名を使うには?

メソッドの戻り値の型にクラス名を使ってるプログラムを見かけたのですが、例えばクラス名を
public class Player{
とします。そして
Playerクラスのメソッド宣言に
 private   Player(戻り値の型) startRun(メソッド名) {
とあります。
これは戻り値の型にクラス型の変数を使ってユーザー定義してると思うのですが使い方が分かりません。
javaのサイトはできるだけ調べたのですが戻り値の型にクラス名を使うにはどうすればいいか分かりませんでした。
この使い方を教えてくれるサイトを教えてください。
基本型と参照型のStringクラスについて教えてくれるサイトはたくさん見かけたのですが…。 お願いします。

Aベストアンサー

ご質問の意味を完全に理解できているわけではありませんが、

>>> メソッドの戻り値の型にクラス名を使ってるプログラム

は、
    メソッドの戻り値の型に「自分の」クラス名を使ってるプログラム、
と解釈させていただきます。

例に取り上げている、Stringクラスは使っていると思いますが、この多くのメソッドは、Stringクラスのインスタンス(オブジェクト)を返しています。もっとも、この場合は
publicですが。

つまり、メソッドがそのreturn値をクラスとするのは、おそらく慣れていないだけでごく当然のことなんです。

そこで、

>>> この使い方を教えてくれるサイトを教えてください。

に対する直接のサンプルではありませんが、よく出てくるテクニック(デザインパタン)として、
   Singleton(シングルトン)
がありますので下記のページを紹介します。少しづつ理解を深めていってください。

参考URL:http://www.nulab.co.jp/designPatterns/designPatterns2/designPatterns2-1.html

ご質問の意味を完全に理解できているわけではありませんが、

>>> メソッドの戻り値の型にクラス名を使ってるプログラム

は、
    メソッドの戻り値の型に「自分の」クラス名を使ってるプログラム、
と解釈させていただきます。

例に取り上げている、Stringクラスは使っていると思いますが、この多くのメソッドは、Stringクラスのインスタンス(オブジェクト)を返しています。もっとも、この場合は
publicですが。

つまり、メソッドがそのreturn値をクラスとするのは、おそらく慣れていな...続きを読む

Qラジオボタンの値の取得について(C++)

いつもお世話になっております。初めて投稿させていただきます。

VC++6.0を使い、プログラムを組んでいます。超初心者です。
レジストリから値を読み込み、ラジオボタンのチェックをどちらにつけるかを決め、OKボタンを押すとレジストリに書き込むという処理をしたいのですが、ラジオボタンがどちらについているかの処理方法がわかりません。(レジストリの読み書きに関しては何とかわかりました)

例えばラジオボタンが二つだけの時に
int radio = CWnd::GetCheckedRadioButton(IDC_RADIO1, IDC_RADIO2);
と書き、radioに値を入れて判別したいと思ったのですが、取得できる値が1020とかよくわからない値を取得します。
この場合、IDC_RADIO1やIDC_RADIO2にはあらかじめ0や1といった値を入れる事は出来ますか?
それとも、使っている関数が間違っていますでしょうか、それとも根本的に何か間違っていますでしょうか…

質問が下手ですみませんが、よろしくお願いします。

Aベストアンサー

 こんにちは。
 1020と言う数字は、IDC_RADIO1かIDC_RADIO2のどちらかの数字です。素性は#defineされた定数値です。
 「表示」→「シンボルブラウザ」で確認出来ます。数字も変えれますが、0や1は流石にマズかった様な・・・。

 肝心な使い方は、以下の様にして判断するのではないでしょうか。

const int radio = CWnd::GetCheckedRadioButton(IDC_RADIO1, IDC_RADIO2);
switch(radio)
{
case IDC_RADIO1:
//ラジオ1が押された
break;
case IDC_RADIO2:
//ラジオ2が押された
break;
}

QJava 他クラスの呼び出しが上手くいきません。

Java初心者です。
過去Q&Aとして掲載されていた「iアプリでのクラスファイルが複数ある時の画面遷移」と同趣旨のことがしたく、記事を参考にプログラムを組んでみました。
しかし、コンパイルの際、画面遷移のための別クラスファイルを呼び出しインスタンス化するところで生じる「シンボルを見つけられません。」というエラーの原因がつかめず困っています。
作成したプログラムのどこがいけないのか、ご教示いただければ幸いです。

作成したプログラム
=========
Test01.java
=========
import com.nttdocomo.ui.*;

public class Test01 extends IApplication implements ComponentListener{
Button btn1;
Label lbl1;
public void start() {
Panel p1 = new Panel();
p1.setTitle("p1");
Label lbl1=new Label("p1に居ます。");
p1.add(lbl1);
Button btn1=new Button("next");
p1.add(btn1);
p1.setComponentListener(this);
Display.setCurrent(p1);
}
public void componentAction(Component source, int type, int param) {
if(type == ComponentListener.BUTTON_PRESSED) {
if(source==btn1){
Test02 test02 =new Test02(); //ここでエラーが発生します。
Display.setCurrent(test02);
lbl1.setText("p2に遷移");
}
}
}

}

============
Test02.java
============
import com.nttdocomo.ui.*;

public class Test02 extends IApplication implements ComponentListener{
Button btn1;
Label lbl1;
public void start() {
Panel p2 = new Panel();
p2.setTitle("p2");
Label lbl1=new Label("p2に居ます。");
p2.add(lbl1);
Button btn1=new Button("next");
p2.add(btn1);
p2.setComponentListener(this);
Display.setCurrent(p2);
}
public void componentAction(Component source, int type, int param) {
if(type == ComponentListener.BUTTON_PRESSED) {
if(source==btn1){
lbl1.setText("p1に遷移"); //コンパイルエラーは生じませんが、ラベル表示の切り替えができません。
}
}
}

}

Java初心者です。
過去Q&Aとして掲載されていた「iアプリでのクラスファイルが複数ある時の画面遷移」と同趣旨のことがしたく、記事を参考にプログラムを組んでみました。
しかし、コンパイルの際、画面遷移のための別クラスファイルを呼び出しインスタンス化するところで生じる「シンボルを見つけられません。」というエラーの原因がつかめず困っています。
作成したプログラムのどこがいけないのか、ご教示いただければ幸いです。

作成したプログラム
=========
Test01.java
=========
impo...続きを読む

Aベストアンサー

「シンボルを見つけられません。」でコンパイルできないのは、
Test01クラスからTest02クラスを見つけられないことが原因かと思われます。

No.1様は
==
Test01とTest02は同じパッケージですか?
違うのであればTest01にimport xxxx.Test02;を記述する必要がある
==
とおっしゃってるように思います。


原因がご理解できないようでしたら
まずはJavaの勉強をしたほうがよろしいかと思います。


人気Q&Aランキング