Javaには、Integer、Float、Double、Longの可変型がありますか?


81

Integerなどの可変バージョンを使用したい状況にあります。これらのクラス(下記)を使用する必要がありますか、それともJavaに何かが組み込まれていますか?

http://www.java2s.com/Code/Java/Data-Type/Amutableintwrapper.htm


8
問題は、なぜこれをしたいのかということです。
helpermethod 2010

2
場合によっては(たとえば、ゲーム、nカロリーを運ぶ食品を保存する、枯渇/追加することができる)、使用にちなんで名付けられたクラスを使用する方が良い場合があります(たとえばclass FoodItem { int calories; }、より明確でメソッドができるため)後で必要に応じて追加すること。
GKFX

7
Java 8ラムダは、効果的に最終変数でのみ機能します。この制限を回避するには、可変整数が必要です。
アレックス

メソッド間で渡す必要のあるカウンターが必要な場合があります。を渡すと、int一方のメソッドでインクリメントされたかのようには機能せず、値はもう一方のメソッドに反映されません。
AdamBurley20年

回答:


51

いいえ、Javaにはこれらが組み込まれていません。それが理由です。可変タイプを使用すると、誤用されやすいため危険です。さらに、それを実装するのは本当に簡単です。たとえば、commons-langにはMutableInt。があります。


5
私の推測では、Java開発者が望んでいた整数はintのように「動作」します。つまり、一度参照すると、変更されることはありません(混乱を避けてください)。しかし..私には、どういうわけか変更可能なオプションがないのはまだ奇妙に思えます...
rogerdpack 2013

35
「可変型を使用すると、誤用されやすいため危険です。」ほとんどのものは誤用される可能性があります。安全性が重要な場合には不変型が存在しますが、反射によって変更することもできます。これらのケースが邪魔にならないので、人々が必要なときに可変型を使用することを妨げる理由はありません。
GKFX 2014

2
より良い言い方をすれば、不変の型は、マップやセットなどで混乱を少なくします。可変整数があり、それがキーとして機能する場所でその値を変更した場合、コレクションが台無しになります。ただし、整数の可変実装が必要な場合は、内部にint値を持つクラスを作成するよりも簡単なことはありません。そして、あなたはそこで創造的になることができます-それを例えばカウンターやカウントダウンにするだけでなく、まったく何でも可能にする単なるintではありません。ロジックを与えます(ボトムアップで動作するJava EEで開発する場合を除く)。
vlasec 2014

確かに古い質問ですが、うまくいけば、誰かが誤用される可能性がある方法に答えることができます。それらを使用することの何がそんなに危険ですか?
ふわふわロボット

@ user1175807 Vlasecがコメントしたように、他の場所で使用した変数を誤って変更すると、奇妙なバグが発生します。さらに悪いことに、クライアントのコードと連携して動作するプログラムを作成しているとしましょう。可変整数型のパラメーターを持つメソッドを実装する必要があります。これで、何らかの理由で可変整数を変更すると、クライアントのプログラムでも変更されますが、これはまったく予期しないことであり、見つけるのが難しいバグが発生します。
gregT 2017年

90

int[] mutable = {1};可変ラッパークラスのコードを含めるのが面倒な場合のように、いつでも値を配列でラップできます。


30
賢く、罪のように醜いバグ。
gvlasov 2014年

2
これは非常に賢く、ほとんどスペースを取りません。さらに、AtomicIntで行われる同期を回避します。
compEng88 2018年

53

JDK 1.5以降、Javaには java.util.concurrent.atomic.AtomicInteger

これはスレッドセーフな可変整数であり、使用例は次のとおりです。

final AtomicInteger value = new AtomicInteger(0);

その後:

value.incrementAndGet();

13
このヘッダーの安全性にはパフォーマンスコストが伴いますが、多くの場合、これは必要ありません。たとえば、私にとっての一般的な使用例は、ラムダによってキャプチャされたカウンタをインクリメントすることです。アトミックを使用するのはやり過ぎです。
ミナスミナ

12

これが私が可変整数のために作った小さなクラスです:

public class MutableInteger {
    private int value;
    public MutableInteger(int value) {
        this.value = value;
    }
    public void set(int value) {
        this.value = value;
    }
    public int intValue() {
        return value;
    }
}

これを他のプリミティブに簡単に拡張できます。もちろん、他のみんなが言っているように、あなたはそれを注意深く使うべきです。


1
IMHOの最良のオプションは、アトミックインターガーを使用する場合のように、並行性について誤った手がかりを与えないことです。そして配列、本当に私は私のコードでそのような悪いことをすることは決してないだろう..;)
Snicolas 2015年

あなたがで終わるしないように、代わりに単一の汎用ラッパークラスを提供することをお勧めすることができMutableIntegerMutableDoubleMutableStringなどではなく、持っているMutable<Integer>Mutable<Double>、...使用のメモリオーバーヘッド(Integerオーバーはint通常考慮に落ちることはありません。しかし、あなたは(あなたがあなたの整数かかわらず、あなたはまだサブクラスに必要に匹敵または類似のものになりたい場合は)ほとんどのケースを扱うことができるクラスを使用する準備ができて、単一の取得。
Qw3ry

Numberを拡張することをお勧めします。
Stijn de Witt 2017

7

@Alexandreが示唆するように、nnnn []を任意のプリミティブ型の可変オブジェクトとして使用できます。Javaには、AtomicIntegerとAtomicLongもあります。

IMHO intは通常、整数よりも適切な選択であり、変更可能です。

複数のオブジェクトが必要な理由の詳細を教えてください。おそらく、同じことを実現する別の方法があります。


7
intそれ以外の場合は常に変更可能ですfinal
Peter Lawrey 2012年

18
プリミティブ型が可変であると言うのは実際には有効ではありません。変更することはできますが、新しいオブジェクトをポイントするだけで、すべての非最終オブジェクトも変更できます。たとえばInteger a = 4;a = 5;は有効なコードですが、Integer変更することはできません。
mjaggard 2012

Integerインスタンスへの参照が変更可能であっても、インスタンスは変更可能ではないことに同意しますが、それは別のタイプです。
Peter Lawrey 2012

これは、参照intパラメーターを持つための良い方法ではありませんか?たとえば、(データベースから)ページ付けされたアイテムのリストだけでなく、レコードの総数も返す関数。このような場合、AtomicIntegerまたはMutableIntegerが役立つようです。もちろん、他の方法は、同じメソッドで返すのではなく、getTotalRecordsプロパティを持つことです。
msanjay 2012

1
intメソッドに渡すと、メソッドがその値を変更して、呼び出し元のメソッドに新しい値を反映させる方法がないため、は変更できません
AdamBurley20年

5

AtomicIntegerすでに言及されています。可変DoubleはでエミュレートできますAtomicReference<Double>。すでに述べた警告が適用され、それは悪いスタイルですが、時々あなたはこのようなコードを持っています

double sum=0
for (Data data:someListGenerator())
  sum+=data.getValue()

関数型Java8スタイルでリファクタリングしたい。コードがこのパターンに従っているが、かなり複雑になっている場合、最も賢明な変換は次のようになります。

AtomicReference<Double> sumref=new AtomicReference<>(0d);
someStreamGenerator().forEach(data->
  sumref.set(sumref.get().doubleValue()+data.getValue()));
double sum=sumref.get().doubleValue();

もちろん、これは少なくとも疑わしいスタイルです。しかし、私は、ResultSetコンピューティング上でねじれたループがあり、そこから3つの異なる情報を部分的に蓄積している状況に何度も気づきました。これにより、コードを適切な機能スタイルに変換することが非常に困難になります。上記のパターンに従って累積パーツを変換することは、クリーンなコードと過度に単純化されたリファクタリングの間の合理的なトレードオフのように思えました。


言葉遣いについて本当に考える必要があります。ラムダを使用しても、副作用が禁止されているため、例は機能しません。あなたが本当にそれを機能的に書くなら、あなたは可変物を必要としません:someStreamGenerator().mapToDouble(Data::getValue).sum()。3つの異なる情報を累積する場合でも、またはを使用する機能的な方法があります。すべてのループを関数型コードフラグメントにリファクタリングする理由はわかりませんが、そのようにしたい場合は、最後まで実行する必要があります。Stream.reduceStream.collect
Tobias Liefke 2018年

私が書いたように:これは適切なスタイルではなく、新しいコードごとにこれを使用するべきではありません。しかし、15年以上以内に進化した400.000行以上のコードをリファクタリングすると、真に機能的な構造に適切に書き直すことが非常に困難になる可能性がある構造が見つかります。次に、このようなハイブリッドスタイルに書き直すことは、少なくとも基本構造を調整するため、賢明なトレードオフになる可能性があります。forまたforeach、機能的に書き直された複雑なフレームワークの一部になる可能性があるため、コードの残りの部分を何らかの方法でそれらの周りに配置する必要があります。
DirkHillbrecht18年

ラムダと関数型プログラミングを混同しています。あなたの例では、それを「機能的」に書き直していません。そして、読みやすさを失ったが関数型プログラミングの利点が得られなかったときに、すべてをラムダで書き直すことのポイントは何ですか?そのようなハイブリッドを使用して、複雑なフレームワーク内のすべてのループを取り除こうとする必要があるのはなぜですか?
TobiasLiefke18年

コードに特定のイディオムを持つ1000の場所があります。このイディオムは、ライブラリまたはその他のグローバル構造によって駆動されます。そのグローバル構造を、関数型アプローチとラムダに基づいた新しい構造に置き換えます。1000か所のうち998か所をきれいに機能的なスタイルに変えることができます。残りの2つは、適切に変換するのが非常に困難です。そのような場合、私は常にそのようなハイブリッド構造で新しいスタイルに変換することを義務付けています。そうして初めて、コードに含まれていた古いグローバル構造を取り除くことができます。完璧ではありませんが、全体的なコード品質は向上します。
DirkHillbrecht18年

2

org.omg.CORBAパッケージ(または必要なクラスのみ)をインポートして、Holderクラスを使用できます。

たとえば、整数を格納するフィールドがパブリックである「IntHolder」があり、それを変更するためのアクセス権を与えます。

public static void triple(IntHolder x){
    x.value = 3 * x.value;
}

IntHolder mutableInt = new IntHolder(10);
triple(mutableInt);     
System.out.println(mutableInt.value);

また、「LongHolder」や「DoubleHolder」など、たくさんの使い方ができます。注意して使用してください。

これがそのAPIです:https//docs.oracle.com/javase/7/docs/api/org/omg/CORBA/package-summary.html


2
この問題を解決する非常に賢い方法ですが、Java9が登場するので、おそらくこれを使用したくないでしょう。これは、intホルダーのためだけにCORBAモジュール全体をインポートします。
Agoston Horvath 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.