Ch1. Javaプログラミングの基礎

リテラル

2進数、8進数、10進数の書き方は以下の通り。

public class Ch1 {
    public static void main(String args[]) {
        System.out.println(100);  // '100' decimal
        System.out.println(0b100);// '4'   binary
        System.out.println(0100); // '64'  octal
        System.out.println(0x100);// '256'hexadecimal
    }
}

大きな数字を扱う際に可読性を良くするため、アンダースコアを利用できる。 ただし、先頭・末尾・小数点やF/L(float,long)などの記号の前には利用できない。

public class Ch1 {
    public static void main(String args[]) {
        System.out.println(1000_00);//100000
        System.out.println(0x1_0000);//65536
        //System.out.println(1000._00);// NG:記号の前後
        //System.out.println(0x_10000);// NG:記号の前後
        System.out.println(10_000L);//10000
        System.out.println(10_000f);//10000.0
        //System.out.println(10000_f);//  NG:記号の前後
        System.out.println(1______0);//10
        //System.out.println(_10);//NG:先頭
        //System.out.println(_1______0);// NG:先頭
        System.out.println(0_10);//8 
        System.out.println(010);//8
        System.out.println(0xfeea);//65258
    }
}

アンダーバーを使えないのはあくまで先頭や記号の前後であり、Octalを表す先頭のゼロの後には利用できる。

変数名の先頭には$_も利用できる。@や数字は利用できない。 なお、(Javaにそれ相当の機能が存在しないにも関わらず)【goto】は予約語として扱われてるという謎がある。

       int _100 = 100;
        int $100 = 100;
        //int 100  = 100;
        //int @100 = 100;
        //int 100@ = 100;
        int A00_00 = 100;

リテラルを変数代入するときはデフォルトの型について注意する必要がある。

       int  normal  = 100000;
        long normalLong = 100000;
        //long veryLong   = 1000000000000;
        long veryLong   = 1000000000000l;

代入の右辺が整数ならば、defaultでまずは【int型】として認識される。 しかし、右辺がintで扱うには大きすぎる値の場合はコンパイルエラーとなってしまう。 そのため、右辺の整数を最初から【Long型】として認識させるためにLまたはlの記号が使われる。

小数点についても似たような約束がある。 代入の右辺が小数ならば、defaultでまず【double型】(より精度が細かい)として認識される。 そのため、そのまま【float型】(より精度が荒い)に代入しようとすると、(情報が失われてしまうため)コンパイルエラーとなる。 floatへの代入はFfを明示する。

       double variable1 = 0.1;
        // float  variable2 = 0.1;
        float  variable2 = 0.1f;

変数スコープ

前々からメソッド内でやたらと{}を利用するコードを見てきてどういう意図があるのか不思議に思っていたが実は次のような事だった。

       int variable12 = 100;
        {
            System.out.println(variable12);
            int variable13 = 200;
        }
        //System.out.println(variable13);

実は{}で囲まれたブロックで宣言した変数は、その括弧をスコープとしてそれ以外からは参照が出来ないのだ。 このようなスコープを敢えて作る理由はよくわからないが、このようにスコープを持つブロックを自由に作れるとは知らなかった。

パッケージ

【クラスのカプセル化】の話でも少し触れたが、パッケージを利用しつつ、public修飾子を付けないことで【外部で利用されたくないクラス】を設定することが可能になった。パッケージの役割の一つとして掲げられている

アクセス修飾子と組み合わせてアクセス制御を可能にする

とは、このことである。

同じパッケージに属するpublicクラスにのみアクセスできる。他のパッケージに属するクラスは明示的にimportしたクラス以外は利用できない。例外としてjava.lang.*のクラスはわざわざ書かなくても勝手にインポートしてくれる。そのクラスに対するpackage宣言がされていない場合は【無名パッケージ】として扱われ他の無名パッケージにも(import宣言なしに)アクセスできる。

逆にいば、packageに属するクラスからだとimportの指定方法がないため無名パッケージをインポートすることは出来ない。

staticインポート

staticなクラスやメソッドにアクセスする方法。 staticなクラスなので、当然クラス名.クラスメソッド名のようなアクセスをすることになるがそれをクラスメソッド名だけでアクセスしたいときがあるようだ(そんなことあるかなぁ)。

パッケージ名の指定方法がないので、無名パッケージ内に宣言されたクラスメソッド(変数)をstaticインポートすることは出来ない。 しかし、名前のあるパッケージにさえ属していれば、同じパッケージ内に宣言されているクラスのクラスメソッドをstaticインポートに指定することは出来る。

メソッドのimportであっても、括弧を指定したり引数を指定したりしない。オーバーロードされているメソッドは全てがimport対象となる。

package test;
import static test.Company.variable;
import static test.Company.method1;
import static test.Company.method2;

class Company{
    static int variable = 100;
    static int variable1 = 110;
    static void method1() {
        System.out.println("method1");
    }
    static void method1(int a) {
        System.out.println("method1");
    }
    static void method2() {
        System.out.println("method2");
    }
}
public class Ch1New {
    public static void main(String[] args) {
        // TODO 自動生成されたメソッド・スタブ
        method1();   //'method1'
        method1(100);//'method1'
        method2();   //'method2'
        System.out.println(variable);//'100'
    }
}

static importされたメソッドや変数名と自クラスのクラスメソッド・クラス変数との名前衝突が発生しても、特にエラーは起こらず自クラスのクラスメソッド・クラス変数が優先される。