プリミティブ型をラッパークラスで定義するメリットはありますか
解決済
回答 4
投稿
- 評価
- クリップ 0
- VIEW 9,619

退会済みユーザー
現在携わっている案件のコードにて、以下のようなコードを見かけます。
Integer i = 20;
//なんかする
if(i.equals(100)){
...
}
コード
や、
以下はメソッドの定義ですが、
private Boolean isSomething() {
...
return false;
}
コード
のようなコードです。
コードの全体像は載せられず恐縮ですが、
なんらかメリットや意義があるようでしたらお教えください。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+3
Javaのプリミティブ型はオブジェクト(ここではObjectを継承したなんらかのクラスのインスタンスであるということ)ではないため、次のような欠点があります。
- ジェネリックに使えない。(List<T>やOtinoal<T>等に使えない)
- synchronizedブロックに使えない。
- nullableでは無い。(未定義なら
null
とか、エラーの場合にnull
を返すと言うことができない)
1.についてはOptionalIntやIntStreamとか一部直接扱える物がありますが、int
、long
、double
しかなく、そして、なぜかArrayListIntのような物は存在しません。2.はnull安全を提供するという意味でむしろ利点です。
これを踏まえてラッパークラスを変数の型や返り値として使う利点を言うと、
- ジェネリックを使用するList<Integer>とかに入れていくときオートボクシングが発生しないから、速い。(その代わり、普通の四則演算とか、代入ではオートボクシングしまくりで遅い)
- synchronizedブロックに使える。(やってはいけません)
- エラーの時は
null
を返すといういけている(と本人は思っている)メソッドが作れる。(なぜ、例外を使わないかというと、例外は遅くなるからと言う最もらしいバカげた理由を付ける) - スタックに積まれない!(参照値はスタックに積まれるんだけどな)
- プリミティブ型が無ければ真のオブジェクト指向だ!!(C++的オブジェクト指向なのに真とかw)
すいません。私にはまったくもって利点がわかりませんでした。あえて言えば最後の5.でしょうが、Integer#add(Integer other)のようなメソッドが存在しない時点で凄い片手落ちだと思います。
つまり、私の結論はただ一つ。早くJava捨ててScalaやろうぜって事です。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+3
javaの言語仕様上の制約としてジェネリック型の要素としてプリミティブ型が使えないのでList,HashMap等々の要素にint,booleanを入れたい場合はInteger,Boolean等々を使わざるを得ません。そういう目的があるならやむをえずということになるでしょう。
前者のコードは、「なんかする」部分にiがIntegerでないと都合が悪い点があると考えられます。ただ比較はi==100としたほうがいいような気がします。見やすいですし、i.equals(100)と書くとboxingによりヒープが消費される可能性があります。i==100ならiがunboxingなのでヒープの消費はなく効率面からも少しよいコードと思います。
後者のfalseを返すコードはBoolean.FALSEと書いたほうが若干効率がよいかも知れません。なぜならfalseとかくとboxingのため暗黙的にBoolean.valufOf(false)が呼び出されるからです。しかし見やすさの点からいえばfalseと書きたいと自分は思います。高頻度で呼び出されるなら効率を気にするかもしれません。
最近別の質問の回答でも見かけましたが効率について気にするなら(中の仕組みを知っておくことに損はないものの)性能評価して実際の問題を見つけることのほうが大切なのだろうと思います。性能上問題ないことろでfalse/Boolean.FALSEのどちらがいいとかは時間のあるときに「やってみる」ならいいものの、これに拘泥しすぎないほうがよいかも知れませんね。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
前半のコードに関しては全く利点を見出せません。Integerに対して何かすることと言ったらたいてい計算になるわけですが、Integerは不変オブジェクトのため、計算に際して
アンボクシング→計算→ボクシング
という、非常に手間のかかることを強要されます。
尤も、ListなどのCollection系はプリミティブを使えないため、例えばMapである文字列の個数を数えたいというような場合はそうせざるを得ませんが、そういう状況でもなさそうなので、あえてラッパークラスで操作する意味はほとんどありません。Integer独自のメソッドを使いたいならその時だけボクシングすれば済みますし、その大概はプリミティブに対する演算子で十分カバーできます。
後半のコードも、通常はこんなことするのはまずないと思われますが、
親クラスで返り値がObjectまたはジェネリクスで定義されたメソッドを子クラスでオーバーライドし、返り値をbooleanにしたいとき
は例外になります。返り値が参照型で定義されたメソッドをオーバーライドで返り値をプリミティブにすることはできないため、ラッパークラス型で再定義することになります。
ただこちらも、子クラスでbooleanで返すメソッドを親でObject型で定義するということ自体変ですし、そうなったら構造から考え直したほうがよさそうに思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
-1
プリミティブのラッパクラスですが、型変換のメソッドはよく利用します。
たとえば、
valueOf()やto***()などは、
値となるインスタンスの変数名そのままに型変換するコードが記述できることは、
変数が主語となり、コードの文脈が追いやすくまたメソッド名が表す文字表記上の意味合いもわかりやすいです。
また、Javaのラッパークラスには、
ラップ対象となったプリミティブ型に適した処理をしてくれるメソッドが定義されていたりするので便利だと思います。
例)
Integer.signum() : 対象オブジェクトの符号(+/-)を数値で返却。
また下記ですが、
プリミティブになるreturn値をクラスメソッドでくるんでいる点についての観点で記載させていただきます。
private Boolean isSomething() {
...
return false;
}
コード
この形式のメリットは、
メソッド名によって論理的な意味合いを持せられることが最大の理由だと思います。
returnに至る前のコードで、メソッド名の意味に対応する処理を行うことで、
・メソッドの機能に対する透過性
・部品の再利用性
・コードの保守性
・複数人数による開発時の責務の分割と効率性
を向上させる効果があります。
もちろん、APIの持つ論理的な構成が適切であることが重要な前提となりますが、
ラップというワンクッションをはさむことは、
プログラムのコード間が疎結合となり開発プロジェクトでは大きなメリットをもたらします。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.10%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/12/18 21:20
Scalaにもちょっと手を出してみます。