プロが教えるわが家の防犯対策術!

「ラッパークラス」の存在意義が分かりません。

ラッパークラスの使い方などについての解説はよく目にしますが、
その意義となると、明確な説明を見たことがありません。
(本質問では、使い方を質問しているわけではありません。)

どういう意味で、便利なのか、
つまり、その存在価値について、お聞きしたいのです。

これがないと乗り越えられない壁があるのでしょうか。
その壁を乗り越えるための道具として、用意されたものであるなら、
その壁というものを教えて頂きたいです。

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

A 回答 (11件中1~10件)

個人的に納得している状況を話しますね。


プリミティブなデータ(例えばint)はそれ自体に実体が
あるから、「インスタンス化」なんてしませんよね。
ということは「null」には絶対にならないわけです。
ところで、データベースからレコードを読み込み、整数型の
フィールドのデータを受け取ることを想定します。
そのフィールドがnullだった場合、受け取る変数がint型で
あったら、「nullであること」を表現できません。nullと
0は違いますからね。でも、Integer型の変数ならnullにする
ことができます。それにtoStringで編集したりできるのも
ウレシイところです。
あと、リフレクションをやると分かりますけど、実行させる
メソッドに渡す変数は本体の定義がプリミティブ型でも、
オブジェクト型の配列にする必要があるので、ラッパークラスに
限られます。
    • good
    • 0
この回答へのお礼

こちらの回答を読み、また一歩、理解が深まりました。
核心に触れた回答をありがとうございます。

・プリミティブなデータ型では、nullを受け取れない。

・オブジェクトならば、toStringメソッドで編集ができる。
(つまり、ラッパークラス付属の各メソッドが使える。
もっとも、そのメソッドの中に、どんな便利なものがあるのかが、
具体例として、ここでは知りたいわけですが。)

・リフレクションのことはまだ分かりませんが、このリフレクションの分野において、
プリミティブなデータをオブジェクト型に変換する必要性があり、その際に、
ラッパークラスのようなものがあると便利、ということですね。

以上、ざっくりとではありますが、ラッパークラスの意義が見えてきました。
大枠が掴めてきた、といった感じです。

お礼日時:2010/07/22 17:26

ちょろっと調べてみましたが、あるサイトにこんなことが書かれていました。


「オブジェクト指向言語なのにプリミティブ型を残したのは,C,C++などの互換性と,メモリ節約のためである」

C,C++との互換性というのは、native キーワードを使用する際に関わってくるのでしょうかね?(私も native は使った事ないのでわかりませんが)

メモリの節約というのはちょっと思っていました。無駄なものがない分、プリミティブのほうがメモリ節約になるかと思います。(int=4byte, Integer=8byte なのか?)

あと、引数として扱う場合、プリミティブは値渡し、オブジェクトは参照渡しとなるという違いもあるかと思います。
    • good
    • 0
この回答へのお礼

大変興味深く読ませて頂きました、
「プリミティブ型の存在意義」 についてのお話を。笑

CやC++との互換性(言語習得者への配慮的互換性といったところでしょうか)については、
その互換性は、本当に必要だったのか、と思えますけどね。
(もし、言語習得とは関係のない互換性、というのがあるのだとしたら、教えて頂けますでしょうか。CとJavaを連結?させてプログラムを組むなんて場合?の互換性?)

互換性の意味を取り違えると、せっかくのお話を誤解したままになってしまうので、
少々わざとらしく騒いでみました。笑

一方、そのあとに記述されていた、「メモリ節約のため」という所は、
私もその通りだと思います。この効果は言語設計の際、意図されていただろうと思います。

また、値渡し、参照渡しの件は、
むしろ、どちらかに統一されていた方が混乱が少なくて済むのではないかなと思えるので、
すべてをオブジェクトにし、渡し方もすべて参照渡しにする、
という方が良かったのではないか、という気もします。

以上、色々と考えさせられる回答でした。
大変参考になりました、ありがとうございます。

お礼日時:2010/07/23 10:18

ちょろっと #7 に書いたんだけど, それをいうと「だったら最初から全部オブジェクトにしておけばいいじゃん」って突っ込まれそうな気がする>#9. 実際, 「純粋なオブジェクト指向言語」 (例えば Smalltalk) では「全てのものがオブジェクト」というきれいな世界を実現していたりしますし.


で, こう考えると質問とは逆に「プリミティブ型の存在意義ってなんだろう」となってしまうわけでした.
ああ, 質問に全く答えてないよ....
    • good
    • 0
この回答へのお礼

確かに、そうですよね、
プリミティブ型の方が、Javaの世界では異端児であり、
この異端児の存在を許したせいで、
ラッパークラスなるものを存在させることになってしまった、
と考えると、
「プリミティブ型の存在意義ってなんだろう」

こう考える方が、自然と言えば自然のような気がしますね。

私はJavaの前に、PHPというオブジェクト指向なしでも扱える言語を使っていたため、
このJavaの世界において、プリミティブ型を基準に、
オブジェクト型という謎なヤツと格闘してきましたが、
このJavaの世界では、逆にプリミティブ型って何やねん、なんですね。笑

PHPから渡ってきた私からすると、
Javaのオブジェクト指向度は凄まじいと感じましたが、Smalltalkを知ると、
Javaはプリミティブ型というのを残している点で、
ちょこっとオブジェクト指向型としては、不完全なわけですね。
大変よくわかりました。
ちょっと賢くなりました。

お礼日時:2010/07/23 00:09

 #3です。



 また、抽象的な説明になりつつありますが、お許しを。


 透過的に扱う例として、比べるというものがあるかもしれません。

int i = 1;
String str = "文字列";

 この二つは、比べることができません。

if (i == str)

もだめですし、

if (str.equals(i))

 も、だめです。
(オートボクシングについては、とりあえず忘れてください)

 false が出てほしいのに、コンパイルエラーで、比べることすら許されません。
 しかし、

Integer i = Integer.valueOf(1);
String str = "文字列";

if (str.equals(i))

 これは、可能で、ちゃんと、 false になります。


 仮に、配列にプリミティブ型とオブジェクト型が混在できたとしましょう。
 その中から、あるデータと同じものを探すというのは、ありそうなことです。
 そんな時はいったいどうしましょう?
 プリミティブ型とオブジェクト型の型検査ができたとしても(Java では無理ですが)

1. 配列からデータを一つ取り出す。
2. プリミティブ型かオブジェクト型かを調べる。
3. プリミティブ型なら、比べるデータとさらに型があっているかどうか調べ、違うならfalse。
4. 同じなら、改めて、比べる

 こんな複雑なことをするくらいなら、最初からラッパークラスに包んで、すべて equals メソッドで比べた方が、透過的で、シンプルです。
    • good
    • 0
この回答へのお礼

文字修飾情報の例で、さらに詰めて補足して頂けるものと期待しておりましたが、
今度はちょっと角度を変え、equals()に着目した例でした。

複数(例としてここでは2つ)の変数のデータ比較をする際、
それら複数の変数の型が、それぞれプリミティブ型より、それぞれオブジェクト型である方が、
都合が良い、ということですよね?

オブジェクト型どうしの比較であれば、
equals()を使うことができ、これを使うことで簡単に比較結果を得られるからです。

比較対象にある複数の変数がそれぞれ、
プリミティブ型かつ同一の型(intどうしとか)ならば、
わざわざラッパークラスを出すまでもないのでしょうが、
このような、かなり限定されたケースは珍しく、
より汎用的に、複数の変数を比較することを考えた場合には、
ラッパークラスでもって、equals()を使い、目的を果たす方が楽、
ということなのでしょう。

データを、プリミティブ型からオブジェクト型に昇格(?笑)させることで、
より複雑な扱い方が可能になる、とも言えますでしょうか。

できることが広がったという意味で複雑になったように思いますが、
それを使うことで、単純な方法で、したいことができるようになったわけで、
そこに、このラッパークラスの真価(存在意義)があるのでしょう。

バラバラなプリミティブ型のデータを、
皆、オブジェクト型にラップすることで、
共通した扱い方が可能となる、そんなイメージがわいてきました。

プリミティブ型と、オブジェクト型がそれぞれどういう仕様で、
また、両者がどう異なるのか、を理解することが、
もしかしたら、本問の解決の近道なのかもしれません。

いやはや、おかげさまで、ゴールは近そうです。笑

お礼日時:2010/07/22 21:00

 #3です。



 長々と書いてしまいましたが、どちらかというと、

> プリミティブ型とオブジェクト型、型が違うからと言って、
>「文字の色」「太字か否か」「大きさ」などを別々の場所に
>格納するのはおかしな話です。
> すべてをオブジェクト型にしてしまえば、これらの意味情報を
>同列に扱うことでできるのです。

 こっちを言いたかったわけです。
 「文字の色」「太字」「大きさ」、これらは、文字列を修飾する情報という点で仲間です。
 できるなら、「文字列修飾情報」という一つの袋にまとめて入れておきたいわけです。
 それなのに、

「文字の色はColorクラスなのでオブジェクト袋に入れて、太字はboolean袋に入れて、大きさはinteger袋に入れよう」

 なんて事をやっていると、情報がバラバラになってしまいます。
 重要なのはデータの意味であって、型ではありません。
 すべてをオブジェクト型として、情報を透過的かつシンプルに扱うというのは、オブジェクト指向では、重要なのです。

 似たような考え方として、抽象クラスやインターフェースが存在します。
 これらも、なくてもプログラムは作れますが、使いこなせば、同じ意味を持つ違うクラスを透過的かつシンプルに扱えるようになります。
    • good
    • 0
この回答へのお礼

>どちらかというと、(中略)こっちを言いたかったわけです。

そっちでしたか、すみません。笑

>文字列修飾情報という一つの袋にまとめて入れておきたい
>なんて事をやっていると、情報がバラバラになってしまいます。

そういった概念をまず、頭に入れておきます。言わんとすることはよく分かります。

例えば、PHPという言語の配列では、データ型関係なく、
値を配列に格納していけます。
つまり、

arr = array();
arr[0] = 5;
arr[1] = "たこやき";
arr[2] = TRUE;

ということができます。
この場合、配列arr の中には、数値も文字列も真偽値も入っていることになります。

もし、このようなことができるのであれば、
arr[0] = 1;
arr[1] = "red";
arr[2] = "bold";
arr[3] = "24pt";

という風にすれば、
このarr1つで、文字列修飾情報を1箇所にまとめられたことになります。

で、これをJavaでするなら、
ラッパークラスを使うと便利ですよ、ということでしょうか?

ちなみに、

>すべてをオブジェクト型にしてしまえば、これらの意味情報を同列に扱うことでできるのです。

とありましたが、
この「同列に扱う」とは、どういった意味でしょうか?

プリミティブ型(int):ID情報
プリミティブ型(String):色情報
プリミティブ型(int):太さ情報
プリミティブ型(int):サイズ(pt)情報

オブジェクト型(object):ID情報
オブジェクト型(object):色情報
オブジェクト型(object):太さ情報
オブジェクト型(object):サイズ情報

こうすることで、何か良いことがあるのでしょうか?
(私は何か勘違いをしてそうですが、誤解を恐れずに質問させて頂きました。笑)

あえて、誇張して書いている部分もありますが、
それは問題箇所を明確にするためだったりします。(ほんとか。笑)

また宜しければ、アドバイスをお願い致します。

お礼日時:2010/07/22 19:56

まあ確かに「ラッパクラスの意義」って難しいと思う. 逆に考えれば「プリミティブ型を含めてすべて『オブジェクト』としておけば『ラッパクラス』そのものが不要」なので....


そういう意味では「最初の『アレ』な設計を覆い隠す」というのが意義なのかもしれない.
    • good
    • 0
この回答へのお礼

またしてもありがとうございます。

皆さんからアドバイスを受けてきて、今思うことは、
私の疑問というのは、つまり、

プリミティブ型を、オブジェクト型に変換する意義、

が分からん、ということなのでしょうね。

どうして、プリミティブ型のままじゃダメなのさー!!

え、なになにっ、
オブジェクト型じゃないと、受け付けないメソッド野郎が存在するからだと?

また、
オブジェクト型にすることで、便利なメソッドが使えるようになり、
プリミティブ型ではできなかったことが、できるようになるだって??

それは本当か!

というオチで、大雑把には、よろしいでしょうか。

と、今、どなたかに質問したいと思っているのですが…。

なお、もしまだ、隠されている意義が他にもあるようでしたら、
追加して頂けると嬉しいです。

お礼日時:2010/07/22 18:49

 #3です。



 ArrayListじゃあ納得できませんか。
 では、もっと、具体的に。
 サンプルコードをみてください。

public class Test extends JFrame {
  JTextPane textPane;
  DefaultStyledDocument document;

  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        Test frame = new Test();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);
        frame.setVisible(true);
      }
    });
  }

  public Test() {
    document = new DefaultStyledDocument();
    textPane = new JTextPane(document);

    try {
      //属性情報を作成
      SimpleAttributeSet attribute = new SimpleAttributeSet();

      //属性情報の文字色に赤を設定
      attribute.addAttribute(StyleConstants.Foreground, Color.RED);
      //属性情報に太字を設定
      attribute.addAttribute(StyleConstants.Bold, Boolean.TRUE);
      //属性情報に文字サイズ20を設定
      attribute.addAttribute(StyleConstants.FontSize, Integer.valueOf(20));

      //ドキュメントにその属性情報つきの文字列を挿入
      document.insertString(0, "あいうえお\n", attribute);
    } catch (BadLocationException ex) {
      ex.printStackTrace();
    }

    add(textPane, BorderLayout.CENTER);
  }
}

 属性情報の作成部分をみてください。
 文字色を赤、太字、サイズを設定しています。
 太字とサイズの第2引数に注目してみてください。
 ラッパークラスです。
 どうしてでしょう?
 それは、このメソッドの第2引数がObject型しか受け付けないから、致し方なくラッパークラスにせざるを得ません。

「いやいや、こんなのメソッドオーバーロードで対処可能でしょう。このメソッドを作った人が手抜きです」

 と、言うかもしれませんが、そんなに単純ではありません。
 SimpleAttributeSet クラスは、内部では Hashtable を使ってこれらの情報を格納しますので、結局、最終的にはラッパークラスにせざるを得なくなります。

 プリミティブ型とオブジェクト型、型が違うからと言って、「文字の色」「太字か否か」「大きさ」などを別々の場所に格納するのはおかしな話です。
 すべてをオブジェクト型にしてしまえば、これらの意味情報を同列に扱うことでできるのです。
    • good
    • 0
この回答へのお礼

わざわざ、私のために長いコードを書いて説明下さり、誠にありがとうございます。
こんなにして頂いたにも関わらず、
なんと、私はそれでもまだよく分からない状態なのです。苦笑

回答をまとめますと、
要するに、
「このメソッドの第2引数がObject型しか受け付けないから、致し方なくラッパークラスにせざるを得ません」
ということですよね。

つまり、オブジェクト型しか受け付けないメソッドがこの世には存在し、
そういう時には、プリミティブ型でデータを渡すことはできないので、
ラッパークラスで、そのプリミティブ型のデータをオブジェクト型に変換する必要がある、
ということなのでしょう。

nda23さんの回答にあったような意味合いですよね?、おそらく。

さて、具体例を書いて頂きましたが、
本件は、「もう、これでもかというほど、単純なコード」では、説明不可能な事例なのでしょうか。
もっとこう、なんと言いますか、
「すぱっ、うわっ、そっか! なるほどー。どひゃー。」的なコードを
実はこっそり期待しております。
もしよろしければ、また教えてください。^^

お礼日時:2010/07/22 18:42

ラッパークラスは、既存のライブラリを流用するときに力を発揮します。



似たような機能を提供するクラスAとクラスBがあり、
提供する機能の違いとかの理由で、
この二つのクラスを使い分けしたい場合を考えます。

(例えば、特殊な画像フォーマットに対する読み書きを行いたい場合とかで、
全形式を網羅するライブラリが無いから、画像フォーマットごとに複数のライブラリを使い分ける必要がある、とか)

ここでAとBは機能は似てますが、メソッド名などはてんでバラバラだったら…
そうなると、Aを使うコードとBを使うコードは別個に書く必要が出てきます。

そういうとき、同じインターフェースを持つラッパークラスを作り、
それを通してAとBを使うようにすると、
利用するコード側は共通化できますので、無駄がなくなりシンプルにできます。
    • good
    • 1
この回答へのお礼

うぬぉ? 今までの回答と、何か違うぞ。。。と思いながら、最後まで読み進めましたところ、
これは、自作ラッパークラスの意義、についての説明ということが分かりました。

誠に申し訳ありません。
そういうものもあるのですね、、、。

ここでは、ライブラリにある、
なんといいますか、プリミティブ型をオブジェクト型に変換する、
あの例のラッパークラスというやつについて、質問していたのでした。

しかし、頂いた回答は、それはそれで、いつかお役に立てたいと思います。
私のために回答下さり、ありがとうございました。

お礼日時:2010/07/22 17:32

 こんにちは。



>こんな私に、端的な例として、何か挙げて下さると
>大変有り難く思います。最も単純な例で結構です。

int n = 1;
ArrayList list = new ArrayList();

「ああ、ArrayListは、Object型しか入らない。どうしよう」
「えーい、包んじゃえー」

list.add(new Integer(n));
    • good
    • 0
この回答へのお礼

私にもう少し力があれば、おそらく、言わんとすることは理解できるのだと思います。

ここで理解を阻む壁となっているのは、ArrayListですね。
ArrayListなしの、端的な別の例を挙げて頂けると有り難いです。

この例ですと、
オブジェクト型のInteger(n)を使う前提で、
それを入れるのに、ArrayListを使っているように思えてしまいました。
つまり、ArrayListの方に目が行ってしまったのです。

ちょっとバカなことをここで書きますが、
int n = 1;
をオブジェクト型にしないで、
そのまま、int型で、配列にでも入れて使えば良いのでは?
と思えてしまうのです。

たぶんこのように書くと、
いやいや、きみ、そうではなくて、
この int型のnをだね、オブジェクト型にして、使いたいのだよ。
だから、Integer(n)としているのではないか。

と言われてしまいそうなのですが、

そこがそもそも、違っていて、
私が知りたいのは、

「この int型のnをだね、オブジェクト型にして、使いたいのだよ。」

の理由なんです。

なぜ、オブジェクト型に変換(つまり、ラッパークラスの利用)をしたいのか、
ということです。

その具体例で良さそうなものが、もし、ありましたら教えて下さい。

お礼日時:2010/07/22 17:15

ラッパー(wrapper)、要は「包む」ことですね。



何を包んでいるのかというと、「面倒な手続き一切合財」であるものがほとんどです。
ある機能を実現するのに必要な手続きを全てラッパー関数内に押し込めて、使う人はその関数を呼ぶだけにしておけば非常に楽ですし、間違いも起こりにくいですよね?

これについては、使う方よりも使わない方に壁がある事が多いです。
ないと面倒、ってところから来ているので。
    • good
    • 0
この回答へのお礼

「ないと面倒、ってところから来ている」

無いとどのくらい面倒なのでしょうね?
(有るとどのくらい楽なのでしょうね?)

JAVA超初心者の私からすると、
何が便利なのか、さっぱり分からないのです。

こんな私に、端的な例として、何か挙げて下さると大変有り難く思います。
最も単純な例で結構です。
もし可能でしたら、また色々と教えて下さい。宜しくお願い致します。

お礼日時:2010/07/22 16:45

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