JavaのC#の 'var'キーワードに相当するものは何ですか?


264

C#でのvarキーワードの1つの使用法は、暗黙の型宣言です。varの Java同等の構文は何ですか?


4
val(またはvar)特定の「Java置換」言語を使用する場合;-)

6
@pst:それはScalaでしょうか?ええ、そうです。
rsenna

IntelliJの場合、これを機能リクエストとして送信しました。youtrack.jetbrains.com / issue / IDEA-102808 IDEは、基になるコードにない場合でも、コードを折りたたんでvalまたはvarを表示する可能性があります。
Jon Onstott 2013年

@ジョンIntelliJのために一緒に何かをハッキングしました、私の答えを見てください。
balpha 2013

3
この機能はJavaで含まれるようにするために提案が用意されました- openjdk.java.net/jeps/286は
McGin

回答:


248

なにもない。悲しいかな、あなたは完全なタイプ名をタイプしなければなりません。

編集:投稿されてから7年後、ローカル変数の型推論(var)がJava 10に追加されました。

編集:投稿から6年後、下からいくつかのコメントを収集します。

  • C#にvarキーワードがあるのは、.NETで名前のないタイプが存在する可能性があるためです。例えば:

    var myData = new { a = 1, b = "2" };

    この場合、に適切なタイプを指定することは不可能myDataです。6年前、これはJavaでは不可能でした(たとえすべての型に名前が付けられていたとしても、それらは非常に冗長で扱いにくいものでした)。この間に変更されたかどうかはわかりません。

  • varと同じではありませんdynamicvariableは100%静的に型付けされています。これはコンパイルされません:

    var myString = "foo";
    myString = 3;
  • var型がコンテキストから明らかな場合にも役立ちます。例えば:

    var currentUser = User.GetCurrent();

    私は私が担当だと任意のコードでは、と言うことができcurrentUserているUserことや派生クラスを。明らかに、もしあなたの実装がUser.GetCurrentint を返すなら、多分これはあなたにとって有害で​​す。

  • これはとは関係ありませんがvar、メソッドを他のメソッドでシャドウする奇妙な継承階層がある場合(例:new public void DoAThing())で、非仮​​想メソッドがキャストされるタイプの影響を受けることを忘れないでください。

    これが優れたデザインであることを示す実際のシナリオは想像できませんが、期待どおりに機能しない可能性があります。

    class Foo {
        public void Non() {}
        public virtual void Virt() {}
    }
    
    class Bar : Foo {
        public new void Non() {}
        public override void Virt() {}
    }
    
    class Baz {
        public static Foo GetFoo() {
            return new Bar();
        }
    }
    
    var foo = Baz.GetFoo();
    foo.Non();  // <- Foo.Non, not Bar.Non
    foo.Virt(); // <- Bar.Virt
    
    var bar = (Bar)foo;
    bar.Non();  // <- Bar.Non, not Foo.Non
    bar.Virt(); // <- Still Bar.Virt

    示されているように、仮想メソッドはこれによる影響を受けません。

  • いいえ、var実際の変数なしでを初期化する不格好な方法はありません。

    var foo1 = "bar";        //good
    var foo2;                //bad, what type?
    var foo3 = null;         //bad, null doesn't have a type
    var foo4 = default(var); //what?
    var foo5 = (object)null; //legal, but go home, you're drunk

    この場合は、昔ながらの方法で実行してください。

    object foo6;

11
@Mike Caron:C#には[デフォルト]の非仮想呼び出しがあり、演算子は仮想でvar p = new X(); p.Z()はないSuperX p = new X(); p.Z()ため、すべてのXおよびSuperXと同じではありませんX : SuperX静的タイプでは常にあるが、常に、上記第1の実施例における第二の例です。認識しておく必要のある微妙だが重要な違い。しかし、あなたの答えは非常に正しいです:-)varpXSuperX

200
@ジョン・ハンナ:varコードをわかりにくくしません。私の意見ではむしろ反対です。たとえば、型を宣言してインスタンス化するときに、同じ行に型を2回(または3回)書き込むのはなぜRadioButton radioButton = new RadioButton();ですか()?var変数に名前を付けるときは、型ではなく機能に重点を置くため、よく考える必要があります(たとえば、 UserCollection collection = new userRepository.GetUsers();より自然にに変わりますvar users = userRepository.GetUsers();)。var分かりにくいと思ったら未使用だからというだけです。
Martin Odhelius、2007

4
@MartinOdheliusをvar使用すると、コードを明確に適切に使用できるようになりますが、不適切に使用することもできなくなります。多くのフォーマットオプションのように。バランスは、匿名オブジェクトとジェネリックをどれだけ使用するかによって異なります。どちらも.NET 1.0には存在しなかったため、C inの最初のバージョンでは仮想キーワードとしての有用性は低くなります。RadioButton radioButtonボタンについて重要なことはそれがであるということだけだったファクトリーまたはヘルパーメソッドの場合にのみ、名前を付けます。RadioButtonそれ以外の場合は、の有無にかかわらず狂気varです。
ジョンハンナ

6
@ジョン・ハンナ:私はかつてvarあなたと同じくらい批判的でしたが、私は私の意見を変えました、そしておそらくそれは異なる意見の質問と同じくらい簡単です匿名オブジェクトとジェネリックスをどれだけ使用しているかに関係なく;)ほとんどの場合、型宣言はコードノイズです。コードなしでコードを理解できない場合、どちらの場合もコードはおそらく不明確です。
Martin Odhelius

3
var匿名型を混同しているvarそれ自体は、割り当てから型を推測するようコンパイラーに要求するだけです。それは構文上の砂糖です。最初は懐疑的でしたが、信心深く使っていて、混乱するような時期はまだありません。インスタンス化時の冗長性を排除し、参照時にタイプをチェックする必要性を排除します。JAVA 9のように何のJAVA相当はありません
Robear

46

Lombokをプロジェクトに追加する場合、そのvalキーワードを使用できます。

http://projectlombok.org/features/val.html


1
@rightfold:参照がfinal不変であるとは限らないオブジェクト。検討してくださいfinal StringBuilder strB = new StringBuilder("My reference is final"); strB.append("I'm not immutable");
Matthias Braun 14年

1
lombok v1.16.12以降、の実験的なサポートもありvarます。projectlombok.org/features/experimental/var.html
Roel Spilker

@MatthiasBraunあなたの例は間違っています。この場合、StringBuilderクラス自体は不変であり、メソッドを使用して内部構造に文字列値を追加するだけで、これは完全に合法です。
Andzej Maciusovic 2017

27

JEP-JDKの機能拡張-提案

http://openjdk.java.net/jeps/286

JEP 286:ローカル変数の型推論

著者ブライアン・ゲッツ

// Goals:
var list = new ArrayList<String>();  // infers ArrayList<String>
var stream = list.stream();          // infers Stream<String>

Javaのバージョンは?10?
Peter Mortensen

@PeterMortensenはい。JEP 286は、JDK 10で承認および公開されています(openjdk.java.net/projects/jdk/10の「機能」の286を参照)。
ジャスティンアルバーノ

20

ある意味varでJavaで提供するIntelliJのプラグインを作りました。これはハックであるため、通常の免責事項が適用されますが、Java開発にIntelliJを使用して試してみたい場合は、https://bitbucket.org/balpha/varsityにアクセスしてください


現在のエディターで宣言型を折りたたむ/展開するためのキーボードショートカットがあると便利です。素晴らしいプラグインですが。
ホットキー2015

2
@hotkeyこれはIntelliJの組み込みコード折りたたみを使用するため、Ctrl-Shift-NumPadPlusですべてを展開できます。カーソルが折りたたみ変数宣言を含む行にある場合、Ctrl-NumPadPlusおよびCtrl-NumPadMinusを使用して、現在のメソッドで宣言を折りたたむ/展開することができます。すべての宣言を折り畳むのは少し厄介です。すべてを折りたたみ(Ctrl-Shift-NumPadMinus)、すべてをもう一度展開します(Ctrl-Shift-NumPadPlus)。
balpha 2015

18

3月20日のJDK 10のリリースにより、JEP 286でvar指定されているように、Javaには予約済みのタイプ名(キーワードではなく、以下を参照)が含まれるようになりました。ローカル変数の場合、Java 10以降では以下が有効になりました。

var map = new HashMap<String, Integer>();

varJavaでの予約型名はほぼ同じですvar両方(の重要な違いについては下記を参照)暗黙の型を可能という点で、C#でのキーワード。varJavaでは、次のコンテキストで暗黙的な型推論にのみ使用できます(JEP 286で列挙されているように、目標)。

  • 初期化子を持つローカル変数
  • 拡張されたforループのインデックス
  • 従来のforループで宣言されたローカル

したがって、フィールド、戻り値の型、クラス名、またはインターフェイス名には使用var できません。その根拠は、JEP 286 (Brian Goetz著作成)で述べられているように、ローカル変数を宣言および定義するときに長い型名を含める必要をなくすことです。

静的型の安全性に対するJavaの取り組みを維持しながら、開発者がローカル変数型の不必要なマニフェスト宣言を排除できるようにすることで、Javaコードの記述に関連する式を減らすことで、開発者のエクスペリエンスの向上を目指しています。

var Javaでのスコープ

ことに留意すべきであるvarJavaでのキーワードではなく、予約型の名前ではありません。JEP 286からの引用:

識別子varはキーワードではありません。代わりに、予約された型名です。つまり、変数、メソッド、またはパッケージ名としてvarを使用するコードは影響を受けません。クラス名またはインターフェース名としてvarを使用するコードは影響を受けます(ただし、これらの名前は通常の命名規則に違反しているため、実際にはめったにありません)。

varはキーワードではなく予約された型名であるため、パッケージ名、メソッド名、変数名(および新しい型干渉の役割)に引き続き使用できることに注意してください。たとえば、次はvarJava での有効な使用例です。

var i = 0;
var var = 1;
for (var i = 0; i < 10; i++) { /* ... */ }
public int var() { return 0; }
package var;

JEP 286からの引用:

この処理は、初期化子を含むローカル変数、拡張forループのインデックス、および従来のforループで宣言されたローカルに制限されます。メソッドフォーマル、コンストラクタフォーマル、メソッドの戻り値の型、フィールド、キャッチフォーマル、またはその他の種類の変数宣言では使用できません。

varJavaとCの違い

これはvar、C#とJavaの顕著な違いの1つです。C#ではvarタイプ名として使用できますが、Javaではクラス名またはインターフェイス名として使用できません。よると、C#のドキュメント(暗黙的に型指定されたローカル変数)

名前付きの型varがスコープ内にある場合、varキーワードはその型名に解決され、暗黙的に型指定されたローカル変数宣言の一部として扱われません。

varC#でタイプ名として使用できるため、複雑さが増し、複雑な解決ルールが導入されます。これはvar、Javaではvarクラス名またはインターフェース名として使用できないようにすることで回避されています。varC#での型名の複雑さについては、「暗黙的に型指定された変数の宣言に適用される制限」を参照してください。`var in Java 'のスコープを決定する根拠の詳細については、「JEP 286:スコープの選択」を参照してください。


varフィールドや戻り値の型に使用できないという点で、Javaとc#には違いがありますか?なぜ注意することが重要なのですか?
user1306322

@ user1306322そのコンテキストでは、いいえ。varJavaではフィールドまたは戻り値の型に使用できません。この制限により、var状況依存型になり、一部のコンテキスト(ローカル変数)でのみ使用でき、他のコンテキストでは使用できないため、これは重要です。これは、JavaとC#の違いに必ずしも注意する必要はありませんが、varJavaで使用する場合の一般的な重要な制限です。
ジャスティンアルバーノ2018

調べたところ、c#varではクラス名を作成してそのまま使用できるようです。技術的にはc#の場合は「コンテキストキーワード」ですが、Javaでは同じことはできないようです。私が間違っていたら訂正してください。
user1306322

1
あなたは正しいです。varJavaではクラス名またはインターフェース名として使用することはできませんが(いずれにしても一般的ではありません)、変数名、メソッド名、およびパッケージ名に使用できます。たとえば、var var = 1;は有効なJavaステートメントですが、クラスを宣言しようとするとpublic class var {}エラーが発生しますas of release 10, 'var' is a restricted local variable type and cannot be used for type declarations。上記の回答を更新してvar、Javaの背後にある理論的根拠とvar、C#との違いの詳細について説明します。
Justin Albano

11

JDK 10でサポートされる予定です。早期アクセスビルドで動作することを確認することも可能です。です。です。

JEP 286

Java言語を拡張し、初期化子を使用して型推論をローカル変数の宣言に拡張します。

だから今書く代わりに:

List<> list = new ArrayList<String>();
Stream<> stream = myStream();

あなたが書く:

var list = new ArrayList<String>();
var stream = myStream();

ノート:

  • var、予約型の名前
  • Javaはまだ静的型付けに取り組んでいます!
  • ローカル変数宣言でのみ使用できます

ローカルシステムにJavaをインストールせずに試してみたい場合は、JDK 10がインストールされたDockerイメージを作成しました。

$ docker run -it marounbassam/ubuntu-java10 bash
root@299d86f1c39a:/# jdk-10/bin/jshell
Mar 30, 2018 9:07:07 PM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
|  Welcome to JShell -- Version 10
|  For an introduction type: /help intro

jshell> var list = new ArrayList<String>();
list ==> []

3
あなたが提供したコード(前/後var)は同等ではありません。このvar例でlistは、タイプArrayListではなく、Listです。
ギリ

8

シンプルなソリューション(適切なIDEを使用していると想定)は、どこにでも「int」と入力し、それを使用してタイプを設定することです。

実際には「var」というクラスを追加しただけなので、別のタイプを入力する必要はありません。

コードはまだ冗長すぎますが、少なくともそれを入力する必要はありません!


「まともなIDE」と言うと、Eclipse *は除外されますか?-これはLunaでは機能しないようです(少なくとも私がで試した場合int)-何か不足していますか?(*:私はEclipseをまともなIDEと呼ぶことはありませんが、他の人を判断することはできません...)
BrainSlugs83

@ BrainSlugs83 dunno私はIDEAを使用しています。それはあなたのためにタイプを修正しませんか?私はそれが実際に正しく機能することを除いてIDEAのようなc#/ visual studio / resharperに慣れています!すべてのジェットブレインのエラーでは、エラーが発生したときにAlt-Enterキーを押して候補のリストを取得できます。そのため、typeをintに設定するとエラーが発生し、Alt-Enter
キーを押し

5

JetBrainsでKotlinを見ることができますが、それは重要です。変数ではありません。


4
Kotlinにはvalとvarがあります。valはjavaで変数finalを宣言するのと同じです。varは再割り当てを許可します。
samlewis 2017年

5

Java 10はローカル変数の型推論を得たのでvar、C#のものとほぼ同等になりました(私が知る限り)。

このことも非denotable種類(プログラマによってその場所に名前を付けることができなかった種類;かかわらず、推論どのタイプが非denotable異なります)。たとえば、匿名クラスを使用したトリックvar(職場では使用しないでください)を参照してください。

私が見つけた1つの違いは、C#では

varという名前の型がスコープ内にある場合、varキーワードはその型名に解決され、暗黙的に型指定されたローカル変数宣言の一部として扱われません。

Java 10 varでは、正当な型名ではありません。


@Liiはい、ここで私が何を意味するのか覚えていません、削除されました。
アレクセイロマノフ

すごい!コメントを削除して履歴を整理します!
Lii

4

Java 10以降、これに相当するものは...ですvar


違いはありますか?私はあなたがこのような短い回答を書くよりもよく知っていることを意味します。そして確かにいくつかの違いがあるはずです。
user1306322

@ user1306322それは完全に別の質問です!これの多くの側面が既に尋ねられているので、あなたはjava-10タグをチェックするかもしれません。
ブライアンゲッツ

さて、これは最初に来て、サイドバーのすべての関連する投稿にリンクされているので、これをグーグルするかどうかを調べるための質問です。だから、あなたがそれに答える別の質問を知っているなら、少なくともそれにリンクするか、またはその一部をあなたの答えに含めることができるかもしれません。
user1306322

3

私はこれが古いことを知っていますが、なぜvarクラスを作成してさまざまなタイプのコンストラクタを作成し、どのコンストラクタが呼び出されるかに応じて、さまざまなタイプのvarを取得します。あるタイプを別のタイプに変換するメソッドを組み込むこともできます。


3

Lombokvarをサポートしていますが、まだ実験段階に分類されています。

import lombok.experimental.var;

var number = 1; // Inferred type: int
number = 2; // Legal reassign since var is not final
number = "Hi"; // Compilation error since a string cannot be assigned to an int variable
System.out.println(number);

ここではそれを使用しようとすると回避するために落とし穴がありますIntelliJ IDEA。オートコンプリートとすべてを含めても、期待どおりに機能するようです。「ハックされていない」解決策があるまで(たとえば、JEP 286:Local-Variable Type Inferenceによる)、これが今の最善策かもしれません。

valによって支持されLombok変更または作成することなく、同様lombok.config


2

Java 10ではできるが、ローカル変数、つまり

あなたはできる、

var anum = 10; var aString = "Var";

しかし、できません

var anull = null; // Since the type can't be inferred in this case

詳細については、仕様を確認してください。


2
これは誤りです。 varキャプチャタイプ、交差タイプ、匿名クラスタイプなど、多くの形式の非分母タイプに使用できます。また、Java 11以降では、ラムダパラメータにも適用できます。
ブライアンゲッツ

0

一般に、任意の型にObjectクラスを使用できますが、後で型キャストを行う必要があります。

例えば:-

Object object = 12;
    Object object1 = "Aditya";
    Object object2 = 12.12;

    System.out.println(Integer.parseInt(object.toString()) + 2);

    System.out.println(object1.toString() + " Kumar");
    System.out.println(Double.parseDouble(object2.toString()) + 2.12);

Aditya、他のすべての回答を確認してください。それらの多くは-1であり、おそらく正当な理由によるものです。正しいかどうかわからない場合は、何も投稿しないでください。
user1306322

@ user1306322私の答えの問題は何ですか!詳しく説明できますか?すべてのデータ型にObjectクラスを使用できないのですか?
Aditya Kumar

オブジェクトオブジェクト= 12; オブジェクトobject1 = "Aditya"; オブジェクトobject2 = 12.12; System.out.println(Integer.parseInt(object.toString())+ 2); System.out.println(object1.toString()+ "Kumar"); System.out.println(Double.parseDouble(object2.toString())+ 2.12);
Aditya Kumar

問題はあなたが質問を理解していなかったことです。問題は「どうやって作るか」ではなく「こういうことはあるのか」だった。あなたは間違った質問に答えます。var正式言語の単語、あなたの答えは今も昔ながらの方法を参照しています。
user1306322

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.