Shoeisha Technology Media

CodeZine(コードジン)

記事種別から探す

varを使って型指定をせずにプログラミング! さらにお手軽になったJava 10

初めての6カ月定期アップデートで変わったJava 10、ポイントを押さえよう 第1回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2018/06/11 14:00

 Java 9が2017年9月にリリースされ、その半年後の2018年3月にJava 10がリリースされました。さらに6カ月後の2018年9月には次のJava 11のリリースが控えています。また、Java 10のリリースと同時にJava 9のサポートが終了するうえ、Java 11がリリースされるとJava 10のサポートも終了します。ただし、Java 11はTLS版(長期サポート)になります。従って、Java 9以降の機能の長期利用を想定したバージョンが次のJava 11ということになります。Java 10はJava 9ほど大きな違いはありませんが、2回にわけて変更点を紹介します。今回は主にAPIに関する変更点、次回は環境面、サポート面などについて紹介します。  

目次

Java 10の主な変更点

 Java 10では主に以下の変更が行われています。

  • ローカル変数時のvarを用いた型推論
  • Optionalクラス・コレクションクラスなどのAPI変更
  • ガベージコレクションに対する改善とインターフェースの提供
  • アプリケーションクラスも含めたクラスデータ共有(CDS)
  • ルート証明書の提供(OpenJDK)
  • Docker環境下での改善
  • javahコマンドの廃止
  • JavaベースのJITコンパイラ
  • バージョン表記方法の変更

 OpenJDKとOracleJDKの違いにより、細かい差異は他にも多少あります。ただし、Oracleからの無償版JDKの提供はこのJava 10で終了するので、Java 11以降、多くの開発者がOpenJDKを利用することになると思われます。

 そのため、今までOracleJDKでは標準で提供されていた機能がOpenJDKに統合される流れになっています。例えば、ルート証明書の問題などはOpenJDKでよく生じる問題でしたが、それらが改善されています。

 また、開発者にとって最も大きな変更点であり、注目しているポイントは「ローカル変数時のvarを用いた型推論」だと思います。今回はその変更点を中心に、その他のAPIの変更点も説明します。

ローカル変数時のvarを用いた型推論(1)

 「型推論」というと少々堅苦しいイメージがありますが、簡単に言えば、変数利用時に型を意識せずにvarを使って型宣言ができる機能です。同様な機能はC#でもC++でもあったので、多くの方にとっては「Javaでもやっと使えるようになった」という印象だと思います。

 また、基本的に型宣言をせずに利用できるJavaScriptやPHPといったスクリプト言語系を中心に使っている方であれば、Javaのコードは多少面倒と感じる部分もあったと思います。

 型推論、もしくは暗黙的な型指定の機能は時にプログラマの勘違い等により危険なコードにもなりやすいため、スクリプト言語系ではTypeScriptなど、型宣言の機能強化を図る方向性もあるので、実際の利用では意見が分かれる部分ではあります。ただし、メリット・デメリットを理解して利用すれば、大変便利な機能です。

基本的な使い方

 varで型宣言をする方法をリスト1に示します。

[リスト1]varを使った基本的な型宣言の例( com/coltware/sample/BasicVar.javaの抜粋 )
// (1)プリミティブな型の場合
var bl = true;  // bool型
var chr = 'a';  // char型

var num1 = 10;  // int型
var num2 = 10L; // long型
var num3 = 1.0; // double型
var num4 = 1.0F; // float型

// (2)オブジェクトの場合
var str = "Hello Java"; // String型
var list = new ArrayList<String>();
var fis  = new FileInputStream(new File("/tmp/dummy.txt"));

// (3)varでは記述できないもの
List<String> list1 = new ArrayList<String>();
FileInputStream fis1 = null;

// (4)varを使って(3)相当のことをやりたい場合の記述
var list2 = (List<String>)(new ArrayList<String>());
var fis2  = (FileInputStream)null;

 プリミティブな型の基本的なものの場合には、(1)のようにそのまま値を右辺に設定します。ただし、数値型の場合にはリテラル表示を正しくしないと、正しい型にならないので注意が必要です。

 わかっていてもうっかり間違ってしまいがちな部分であり、プリミティブな型に関してはそれほど面倒でもないので、型宣言をした方が確実かと思います

 一方(2)のように、オブジェクト型に関しては、型宣言、そしてインスタンスの作成でも同じ記述をしなければいけませんでしたが、varを用いることで右辺だけ指定すればよくなります。

 ただし、(3)のような記述を、varを使って記述することはできません。無理やり記述すれば、(4)のようにも記述できますが、あまりvarを使う必要性もなくなります。

 varを使った型推論は、コンパイル時に型が右辺から特定できる場合に利用できる略式記述(シンタックス・シュガー)なので、この書き方をすることでこれまで実現できなかったことができるわけではありません。

 また、初期値をともなったListやMapインターフェースを使った変数を定義したい場合には、リスト2のようにList/MapのofメソッドがJava 9から記述できます。

[リスト2]varを使った基本的な型宣言の例( com/coltware/sample/BasicVar.javaの抜粋 )
var list3 = List.of(1,2,3,4,5,6,7,8,9,10);
var list4 = Map.of("key1","val2","key2","val2");

 ただし、List/Mapのofメソッドにて作成されたオブジェクトは変更できません。

 また、1行で記述されていて何をしているのか少々わかりにくいコードを分割してデバッグする際に、varを利用すると便利です。

 例えば、リスト3の(1)のように何をしているのかわかりにくい1行コードがあり、それらを分割してデバッグ等を行いたい場合、それぞれの戻り値について型宣言をする必要がないため、import文も記述しなくてよくなります。

 ただし、恒久的に記述したい場合には、右辺の戻り値の型がわかりにくくなるので、型宣言をした方がよいでしょう。

[リスト3]1行コードを分割する際の利用例( com/coltware/sample/BasicVar.javaの抜粋 )
//  (1) わかりにくい1行で記述されたコード例
var total = List.of(1,2,3,4,5,6,7,8,9,10).stream().mapToInt(num -> num).sum();

//  (2) 何をしているのかを理解するために、デバッグしやすいように分割した例
var list = List.of(1,2,3,4,5,6,7,8,9,10);
var st1 = list.stream();
var st2 = st1.mapToInt(x -> x);
var total2 = st2.sum();

  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2017年5月時点での登録メンバは52名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XMLD...

All contents copyright © 2005-2018 Shoeisha Co., Ltd. All rights reserved. ver.1.5