web-dev-qa-db-ja.com

JavaのC#「var」キーワードと同等のものは何ですか?

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

249
Arturo

なにもない。残念ながら、完全なタイプ名を入力する必要があります。

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

編集:投稿から6年後、以下からコメントの一部を収集します。

  • C#にvarキーワードがあるのは、.NETで名前のないタイプを使用できるためです。例えば:

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

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

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

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

    var currentUser = User.GetCurrent();
    

    私が担当するどのコードでも、currentUserにはUserまたは派生クラスが含まれていると言えます。明らかに、User.GetCurrentの実装がintを返す場合、これはあなたにとって有害かもしれません。

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

    これが良いデザインを示す現実の世界のシナリオを想像することはできませんが、これはあなたが期待するように機能しないかもしれません:

    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;
    
239
Mike Caron

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

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

43
darthtrevino

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>
26
blueberry0xff

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

20
balpha

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

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

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

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

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

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

var Javaのスコープ

varはJavaのキーワードではなく、予約された型名であることに注意してください。 JEP 286から引用したとおり:

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

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

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

JEP 286から引用したとおり:

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

JavaとC#varの違い

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

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

C#でvarを型名として使用すると、複雑さが増し、複雑な解決規則が導入されます。これは、varをクラス名またはインターフェイス名として禁止することで、Javaのvarによって回避されます。 C#のvar型名の複雑さについては、「 制限が暗黙的に型指定された変数宣言に適用される 」を参照してください。 Javaでの `varのスコープ決定の背後にある理論的根拠の詳細については、 JEP 286:Scoping Choices を参照してください。

13
Justin Albano

JDK 10でサポートされる予定です。 early access build で動作を確認することもできます。

JEP 286

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

だから今書く代わりに:

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

あなたが書く:

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

ノート:

  • var予約済みの型名 になりました
  • Javaはstill静的型付けへのコミットメントです!
  • local変数宣言でのみ使用できます

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

$ 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 ==> []
11
Maroun

簡単な解決策(まともなIDEを使用していると仮定)は、あらゆる場所に 'int'を入力し、タイプを設定するだけです。

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

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

8
JonnyRaa

Java 10はローカル変数型の推論を取得したため、C#のものとほぼ同等のvarを持っています(私が知っている限り)。

また、非表示型(プログラマがその場所に名前を付けることができなかった型。ただし、which型は非表示型とは異なります)たとえば、JavaにはC#の匿名型に相当するものはありません)。

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

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

Java 10では、varは有効な型名ではありません。

5
Alexey Romanov

JetBrainsによる Kotlin を見ることができますが、それはvalです。 varではありません.

5
Artiom

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

3
Sebastian Zaba

Java 10現在、同等のものは... varです。

3
Brian Goetz

Lombokはvarをサポートしています しかし、まだ実験的として分類されています:

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.configを変更または作成せずに、Lombokでもサポートされていることに注意してください。

3
BullyWiiPlaza

Java 10では、Local変数に対してのみ、つまり、

あなたはできる、

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

しかし、できません、

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

詳細については、 spec をご覧ください。

2
Antho Christen

一般に、任意の型に対して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);
0
Aditya Kumar