18
12

More than 1 year has passed since last update.

Javaの隠された (しかも、ちょっと面白い) 文法 3選

Last updated at Posted at 2022-10-15

この記事は?

この記事は知名度がかなり低そうなJavaの文法を、独断で3つ選んで紹介するものです。

動作確認したJavaのバージョンは OpenJDK19 ですが、Java8 の時にはこれらの文法が既にありました。

では、早速行ってみましょう。

1. ラベル

文(といっても専らforやwhile文)には、 ラベル をつけることができます。
for文の中のbreakやcontinueで参照することで、ラベルがついたループを抜けたり、もう一回やり直すことができます。

var list = new ArrayList<List<Integer>>();
        
// マス目を x + y で埋めていくが、 x + y が6以上になった時点でやめる
label:
for(int y=0; y<5; y++){
  list.add(new ArrayList<Integer>());
  for(int x=0; x<5; x++){
    list.get(y).add(x+y);
    if(x + y >= 6){
      // 外側のループを抜ける
      break label;
    }
  }
}

//表示
list.forEach(elm->{
  elm.forEach(str->System.out.print(str));
  System.out.println();
});

出力:

01234
12345
23456

6になった瞬間にy方向への数値追加もやめたことが分かるでしょうか。

2. 小数 リテラル

16数小数リテラル

image.png
!?

小数は10進数だけでなく16進数で書くことも可能です。 (いつ使うんだろう...)
小数を 5e-3 (=$5*10^{-3}$) などと書けることは良く知られていると思いますが、eは16進数の桁に用いられるので、16進数の時はPを使います。pは16進小数には必須で、指数部はなぜかBinary(2の累乗)です。

System.out.print(0x1p-1) // 0.5
System.out.print(0x.1p-2) // 0.015625

System.out.print(0x.1) // コンパイルエラー!
System.out.print(0x.1p0) // OK! 0.0625

0x1p-1 = $1 * 2^{-1} = 0.5$
0x.1p0 = ${16}^{-1} * 2^{0} = 0.0625 * 1 = 0.0625$
0x.1p-2 = ${16}^{-1} * 2^{-2} = 0.0625 * 0.25 = 0.015625$

(...ハイライトが上手く適用されてない件...)

float リテラル

おまけで紹介すると、数値には以下の表記法があって、型を書き分けることができます。

int    i  = 6; // int型
float  i2 = 6f; // float型
float  i3 = 6.0f; // float型
double i4 = 6d; // double型
double i5 = 6.0d; // double型
double i6 = 6.0; // double型

(float)3.14 よりも 3.14f の方がスマートな感じがしませんか、ね?

3. マルチキャッチ

Javaでは、try-catch文において、複数の例外についてまとめて同じ処理を書くことができます。
これを マルチキャッチ(multi-catch)1 といいます。

import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args) throws Exception {
      for(int i=0;i<3;i++){
        try {
          someMethod(i);
        } catch(IOException | IllegalArgumentException e){ // マルチキャッチ
          System.out.println(e.toString() + "; もしかして変な要求を送った?");
        } catch(NullPointerException e){
          System.out.println("ぬるぽ。多分APIのエラー。");
        }
      }
    }
    
    public static void someMethod(int i) throws IOException{
      switch(i){
        case 0 -> throw new IOException();
        case 1 -> throw new IllegalArgumentException();
        case 2 -> throw new NullPointerException();
      }
    }
}

出力:

java.io.IOException; もしかして変な要求を送った?
java.lang.IllegalArgumentException; もしかして変な要求を送った?
ぬるぽ。多分APIのエラー。

違う例外で同じ処理をするならできるだけマルチキャッチを使いましょう!
そうするとコンパイル後のクラスファイルも小さくなります2。読みやすさも多少上がるでしょう。

終わりに

いかがでしたか?

Minecraftのジグソーブロック並み3に誰も使わないような文法ですが、知っているとちょっと面白い...はずです。

読むと楽しい

  1. れっきとした公式用語。逆に、普通のcatch節は "uni-catch" という。

  2. 詳しいことは省きますが、コンパイラはマルチキャッチ節をuni-catchに分解せずともそのまま理解できるためです。

  3. データパックなどにて構築物のランダムな生成を可能にするブロック。カスタムディメンションを作るような人しか使わない。

18
12
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
12