- ベストアンサー
オーバーロード
以前の質問「質問:参照渡し」 http://oshiete1.goo.ne.jp/kotaeru.php3?q=708770 の続きななですが Javaで演算子のオーバーロードの方法はわかりました。 ところでStringを他の関数に引数で渡したときは StringBufferで新しいインスタンスが作成されると教わりました。 同じように自作のクラスで、関数に値を渡したとき 独自の定義をすることって可能でしょうか? また可能な場合どのようにするのでしょうか? 自作クラスでオブジェクトを引数で渡すとき値渡しのように見せかけたいのです。 宜しくお願い致します。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
> String a = "aaa"; > String b = "aaa"; > の"aaa"はメモリ的に別の参照先のような気がしますが一緒なのですね。 今回の"aaa"のように、同一の内容の文字列をいくつかの場所で使っている場合、これらはコンパイラによってひとつのStringオブジェクトにされます。 Stringは内容が不変の文字列です。同一の内容ならば、いくつも作ってメモリを圧迫するより、ひとつだけ作ってそれをみんなで参照した方が無駄が少ないのです。
その他の回答 (4)
- Sephy
- ベストアンサー率35% (7/20)
> =演算子の場合は該当しますよね? いいえ。=演算子は参照を代入するだけです。ですから例えば > a = "aa"; と > a = new String("aa"); は同じ処理ではありません。 前者は"aa"というStringオブジェクトの参照をaに代入しています。 後者は"aa"という内容のStringオブジェクトを新たに生成し、その参照をaに代入しています。 つまり前者では新しいオブジェクトは生成されていません。 "aa"のように"で囲んだ文字列は、プログラムの実行時にすでにStringオブジェクトとして生成されています。 ですからa = "aa"は既に生成されているStringの参照を代入しているにすぎないのです。 以下の例を試してみてください。ちなみに以下のa == bについて補足。これは文字列の内容を比較しているのではありません。参照先が一致しているかどうかを比較しています。 <trueが表示される例> class aaa{ public static void main(String[] args){ String a = "aaa"; String b = "aaa"; if(a == b){ System.out.println("true"); } else{ System.out.println("false"); } } } <falseが表示される例> class aaa{ public static void main(String[] args){ String a = new String("aaa"); String b = new String("aaa"); if(a == b){ System.out.println("true"); } else{ System.out.println("false"); } } } (レイアウトの問題でTABを全角スペースに変換してあります。)
お礼
かなり納得できました。(ような気がします。) 昔==で同じ文字列なのにfalseになって困っていた事がありました。 compareToメソッドで解決できたのですがそういうことだったのですね。 String a = "aaa"; String b = "aaa"; の"aaa"はメモリ的に別の参照先のような気がしますが一緒なのですね。 ご回答有難うございました。
- NUNUNUNUNU
- ベストアンサー率55% (11/20)
>は可変長に見えるのですがやはりこれも >a = new String("aa"); >a = new String("bb"); >と置き換えていると解釈したので良いのでしょうか? String を C++ と同じイメージでとらえると混乱するんですよね。 実は考え方が逆で、文字列リテラルは既にStringなんですよ。ほいでStringは定数なんです。 "aa" も "bb" も既にStringなんで、その参照をaに代入してるに過ぎないというお話。 バッファじゃなくて定数なんで、何かの関数にStringを引数で渡しても「値渡し」のように見えるんです。だってconstだから中身を変更できないもんね。 cで void func( const char *p ) { p = "123"; } としてもpの中身が変更されないのと同じ。cなら*pで中身にアクセスできるがJAVAは無理。 >となると = や + を独自定義出来るのでは?と思ったのですが、 私も「JAVAってoperator定義できないの?」と悲しんだ記憶があります。 >はStringが演算子「+」に対してappendメソッドと同じような >処理をオーバーロードしているのかと >勝手に思ってしまいました。。 私もはじめそう思いました。 だから operator+ が書けるんだって勘違いするんですよね。 >Stringのようなものを自作するということは出来ないのでしょうか? 「ようなもの」が何を指してるかによりますが、 演算子を定義したいというのであれば無理です。
お礼
つまりStringは文字列リテラル指すポインタみたいなものという事ですね。 かなり分かりやすい説明でした。 ご回答ありがとうございました。
- Sephy
- ベストアンサー率35% (7/20)
>ところでStringを他の関数に引数で渡したときは >StringBufferで新しいインスタンスが作成されると教わりました。 の間違いだけを指摘します。 >Stringを他の関数に引数で渡したときは ここが違います。 >StringBufferで新しいインスタンスが作成される のは、Stringを+演算子で連結したときです。 a = a + "bbb"; などがその例です。(aはStringであるとする)
お礼
何度もご回答ありがとうございます。 勉強不足を実感させられます。 =演算子の場合は該当しますよね?
- UKY
- ベストアンサー率50% (604/1207)
なんだか非常に言いづらい回答になってしまいますが。 > Javaで演算子のオーバーロードの方法はわかりました。 演算子のオーバーロードなんてできませんよ。オーバーロードできるのはメソッドとコンストラクタです。そもそもJavaでは独自の演算子を定義することもできません。 > ところでStringを他の関数に引数で渡したときは > StringBufferで新しいインスタンスが作成されると教わりました。 文字列をメソッドの引数にするだけで、自動的に文字列バッファに変換されるという意味でしょうか? そのような事実はありませんが。 そもそも、オブジェクトをメソッドの引数として渡しただけで、自動的に新たなインスタンスが作られるということは起こりえませんし、そのようにさせることもできません。 (暗黙的なキャストと勘違いしているのでしょうか?) > 自作クラスでオブジェクトを引数で渡すとき値渡しのように見せかけたいのです。 文字列と同じように、「一つの値に対して一つのインスタンスを作る」「インスタンスを作成したら、そのインスタンスの持つ値は変化しない」という設計のクラスにすることで、可能です。 とにかく、質問者さんはいろいろ誤解なさっているようですので、まずそれを解くのが先であるかと思います。特に、用語の意味を間違えると言いたい内容が明確に伝わりませんので……。
お礼
度々すみません。 例えばC++のように演算子のオーバーロードができるのかと思ってしまいました。 例えば string a = "aa"; a = a + "bbb"; はStringが演算子「+」に対してappendメソッドと同じような 処理をオーバーロードしているのかと 勝手に思ってしまいました。。 前の方の回答を引用させて頂きますと a = new StringBuffer().append(a).append("bbb").toString これは元のポインタを破棄して、まったく新しいインスタンスに 書き換えるということですよね? StringとStringBuffer は関係していることはわかったのですが。。。 Stringのようなものを自作するということは出来ないのでしょうか?
補足
sunのページのStringBufferの説明をみると x = "a" + 4 + "c"は x = new StringBuffer().append("a").append(4).append("c").toString() と解釈されるとなっていました。 またStringは「固定長」となっていました。しかし String a; a = "aa"; a = "bbb"; a = "cccc"; やa = a + "ddddd"; は可変長に見えるのですがやはりこれも a = new String("aa"); a = new String("bb"); と置き換えていると解釈したので良いのでしょうか? となると = や + を独自定義出来るのでは?と思ったのですが、 単にStringやStringBufferが特別な存在なのでしょうか。
お礼
回答してくださった皆様ご回答ありがどうございました。