「Java SE 7 リリース」 言語拡張メモ

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

毎度お世話になっております。クラスメソッドの稲毛です。

今回は先日リリースされた「Java SE 7」について、新たに追加された言語拡張についてまとめておきたいと思います。

リファレンスはオラクル社の下記サイトとなります。

http://download.oracle.com/javase/7/docs/technotes/guides/language/enhancements.html#javase7

Javaプログラミング言語の拡張

Binary Literals

バイナリのリテラル表現

バイナリ値の接頭辞に「0b」または「0B」を追加することで、整数型(byte, short, int, long)の値をリテラルで表現できるようになりました。

// An 8-bit 'byte' value:
byte aByte = (byte)0b00100001;

// A 16-bit 'short' value:
short aShort = (short)0b1010000101000101;

// Some 32-bit 'int' values:
int anInt1 = 0b10100001010001011010000101000101;
int anInt2 = 0b101;
int anInt3 = 0B101; // The B can be upper or lower case.

// A 64-bit 'long' value. Note the "L" suffix:
long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;

http://download.oracle.com/javase/7/docs/technotes/guides/language/binary-literals.html

Underscores in Numeric Literals

アンダースコアを含んだ数値リテラル

数値リテラルにアンダースコア「_」を含める事ができるようになりました。数値リテラルの可読性向上等に利用することができます。

long creditCardNumber = 1234_5678_9012_3456L;
long socialSecurityNumber = 999_99_9999L;
float pi = 3.14_15F;
long hexBytes = 0xFF_EC_DE_5E;
long hexWords = 0xCAFE_BABE;
long maxLong = 0x7fff_ffff_ffff_ffffL;
byte nybbles = 0b0010_0101;
long bytes = 0b11010010_01101001_10010100_10010010;

ただし、アンダースコアを挿入する位置に注意する必要があります。

float pi1 = 3_.1415F;      // Invalid; cannot put underscores adjacent to a decimal point
float pi2 = 3._1415F;      // Invalid; cannot put underscores adjacent to a decimal point
long socialSecurityNumber1
  = 999_99_9999_L;         // Invalid; cannot put underscores prior to an L suffix

int x1 = _52;              // This is an identifier, not a numeric literal
int x2 = 5_2;              // OK (decimal literal)
int x3 = 52_;              // Invalid; cannot put underscores at the end of a literal
int x4 = 5_______2;        // OK (decimal literal)

int x5 = 0_x52;            // Invalid; cannot put underscores in the 0x radix prefix
int x6 = 0x_52;            // Invalid; cannot put underscores at the beginning of a number
int x7 = 0x5_2;            // OK (hexadecimal literal)
int x8 = 0x52_;            // Invalid; cannot put underscores at the end of a number

int x9 = 0_52;             // OK (octal literal)
int x10 = 05_2;            // OK (octal literal)
int x11 = 052_;            // Invalid; cannot put underscores at the end of a number

http://download.oracle.com/javase/7/docs/technotes/guides/language/underscores-literals.html

Strings in switch Statements

switch文で文字列を

switch文の条件式でStringオブジェクトが使用できるようになりました。Javaコンパイラは一般的に、「if-then-else文よりもStringオブジェクトを用いるswitch文のほうが効率的なバイトコードを生成する。」とされています。

public String getTypeOfDayWithSwitchStatement(String dayOfWeekArg) {
     String typeOfDay;
     switch (dayOfWeekArg) {
         case "Monday":
             typeOfDay = "Start of work week";
             break;
         case "Tuesday":
         case "Wednesday":
         case "Thursday":
             typeOfDay = "Midweek";
             break;
         case "Friday":
             typeOfDay = "End of work week";
             break;
         case "Saturday":
         case "Sunday":
             typeOfDay = "Weekend";
             break;
         default:
             throw new IllegalArgumentException("Invalid day of the week: " + dayOfWeekArg);
     }
     return typeOfDay;
}

http://download.oracle.com/javase/7/docs/technotes/guides/language/strings-switch.html

Type Inference for Generic Instance Creation

ジェネリックインスタンス生成時の型推論

従来、このように記述していたものを

Map<String, List<String>> myMap = new HashMap<String, List<String>>();

このように記述することができるようになりました。

Map<String, List<String>> myMap = new HashMap<>();

「<>」を付与しないと警告が出力されますのでご注意ください。

Map<String, List<String>> myMap = new HashMap(); // unchecked conversion warning

http://download.oracle.com/javase/7/docs/technotes/guides/language/type-inference-generic-instance-creation.html

Improved Compiler Warnings and Errors When Using Non-Reifiable Formal Parameters with Varargs Methods

型パラメータを可変長引数で使用時のコンパイラ警告およびエラーの改善

ジェネリクスにより型の安全性が保証されているのにも関わらず、保証されていない型のオブジェクトが扱われてしまうようなケースが「ヒープ汚染」と呼ばれます。

    List l = new ArrayList<Number>();
    List<String> ls = l;       // unchecked warning
    l.add(0, new Integer(42)); // another unchecked warning
    String s = ls.get(0);      // ClassCastException is thrown

Java SE 7ではコンパイル時にヒープ汚染が起こる可能性がある場合、警告を出力するようになりました。

warning: [varargs] Possible heap pollution from parameterized vararg type T

この警告を出力しないようにするには、以下の方法があります。

  • staticおよび非コンストラクタメソッドの宣言に次のアノテーションを追加します。
    • @SafeVarargs
  • メソッドの宣言に次のアノテーションを追加します。
    • @SuppressWarnings({"unchecked", "varargs"})
    • メソッド呼び出し側で生成される警告は抑制できません。
  • コンパイラオプションに -Xlint:varargs を指定します。

http://download.oracle.com/javase/7/docs/technotes/guides/language/non-reifiable-varargs.html

The try-with-resources Statement

リソースを含めたtry文

プログラムが終了した際にクローズされていなければならないリソースをtry文に含めることができるようになりました。これらのリソースはステートメント終了時にクローズされることが保証されます。

static String readFirstLineFromFile(String path) throws IOException {
  try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
  }
}

http://download.oracle.com/javase/7/docs/technotes/guides/language/try-with-resources.html

Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking

複数例外型キャッチと型チェックの改善による例外の再スロー

複数例外型をキャッチすることが可能となりました。このようなケースが

catch (IOException ex) {
     logger.log(ex);
     throw ex;
catch (SQLException ex) {
     logger.log(ex);
     throw ex;
}

このように記述できます。

catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}

キャッチした例外を再度スローする際、メソッド宣言のthrow節に、より特定の例外型を指定することができるようになりました。従来は、メソッド宣言のthrow節に「FirstException」と「SecondException」を指定することができませんでしたが(双方の親クラスである「Exception」を指定していた。)

  static class FirstException extends Exception { }
  static class SecondException extends Exception { }

  public void rethrowException(String exceptionName) throws Exception {
    try {
      if (exceptionName.equals("First")) {
        throw new FirstException();
      } else {
        throw new SecondException();
      }
    } catch (Exception e) {
      throw e;
    }
  }

throw節に「FirstException」および「SecondeException」を指定することができます。

  public void rethrowException(String exceptionName)
  throws FirstException, SecondException {
    try {
      // ...
    }
    catch (Exception e) {
      throw e;
    }
  }

http://download.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html

まとめ

Java SE 7では、言語拡張以外にも様々な改良が施されています。

http://download.oracle.com/javase/7/docs/

OracleによるSunの買収や、「Javaの父」ことジェームズ・ゴスリン氏のGoogle移籍など、Javaプラットフォームを取り巻く環境は大きく変化しましたが、「Scala」や「Groovy」などのJVM言語や心機一転したJavaFX 2.0など面白そうな話題もまだまだあるので、今後もチェックを続けていこうと思います。