@blog.justoneplanet.info

日々勉強

Javaのジェネリックス

ジェネリックスとは、型を指定することなく、パラメータ化することにより型を定義できるようにすること。

■通常のクラスとクライアントコード

まずは、一般的なコードを見てみる。

クラス

public class Dog
{
    private String _name;
    public Dog(String name)
    {
        this._name = name;
    }
    public String cry()
    {
        return this._name + ", bow!";
    }
}

クライアントコード

上述の場合、以下のようにして使用することができる。

public class HelloWorld
{
    public static void main(String[] args)
    {
        Dog pochi = new Dog("pochi");
        System.out.println(pochi.cry());
    }
}

しかし、以下のようにして使用することはできない。

public class HelloWorld
{
    public static void main(String[] args)
    {
        Dog pochi = new Dog(123);
        System.out.println(pochi.cry());
    }
}

クラス

以下のように、全てのクラスと互換性があるObjectとすることで使用することができるようになる。

public class Dog
{
    private Object _name;
    public Dog(Object name)
    {
        this._name = name;
    }
    public String cry()
    {
        return this._name + ", bow!";
    }
}

■ジェネリックスを用いたコード

インスタンス化する時に使用する型を指定する。

クラス

public class Dog<T>
{
    private T _name;
    public Dog(T name)
    {
        this._name = name;
    }
    public String cry()
    {
        return this._name + ", bow!";
    }
}

クライアントコード

public class HelloWorld
{
    public static void main(String[] args)
    {
        Dog<String> pochi = new Dog<String>("pochi");
        System.out.println(pochi.cry());
        Dog<Integer> shiro = new Dog<Integer>(123);
        System.out.println(shiro.cry());
    }
}

これはデータ構造などのクラスにおいて多用される。

■コレクション

List

List自体はインターフェースである。

ArrayList

可変長配列を表す。

ArrayList<String> ary = new ArrayList<String>();
ary.add("hoge");
ary.add("fuga");
for(int i = 0; i < ary.size(); i++){
    Log.e("", "ary[" + String.valueOf(i) + "] = " + ary.get(i));
}

ちなみに以下のようにするとエラーになる。

ArrayList<String> ary = new ArrayList<String>();
ary.add("hoge");
ary.add(2, "fuga");
for(int i = 0; i < ary.size(); i++){
    Log.e("", "ary[" + String.valueOf(i) + "] = " + ary.get(i));
}

Cとか本来の配列に可変長を持たせたものであり、JavaScriptやPHPの配列とは異なる。

LinkedList

連結リストを表す。

LinkedList<String> ary = new LinkedList<String>();
ary.add("hoge");
ary.add("fuga");
ary.add(1, "piyo");
for(int i = 0; i < ary.size(); i++){
    Log.e("", "ary[" + String.valueOf(i) + "] = " + ary.get(i));
}

配列の途中への追加や削除がO(1)のコストでできるデータ構造。

Set

集合。要素の重複を許容しない。

HashSet

任意の順序で要素を保持する。

HashSet<String> hash = new HashSet<String>();
hash.add("hoge");
hash.add("hoge");
hash.add("hoge");
Log.e("hash", hash.toString());
// [hoge]
LinkedHashSet

HashSetとは異なり要素の順序を保持する。

Queue

PriorityQueue

優先順位つきキュー。探索とかでよく使う。

Map

HashMap

連想配列。但し格納順書は保持しない。

HashMap<String, Object> map = new HashMap<String, Object>();
HashMap<String, HashMap<String, String>> map = new HashMap<String, HashMap<String,String>>();
LinkedHashMap

HashMapと違って格納順序を保持する。

メソッドのオーバーロード

以下のように、Javaでは同名のメソッドを同一クラス内で定義できる。

public class HelloWorld
{
    private static String plus(int x, int y)
    {
        String result = Integer.toString(x + y);
        return "合計は「" + result + "」です";
    }
    private static String plus(String str1, String str2)
    {
        return "文字列をつなげると「" + str1 + str2 + "」です";
    }
    public static void main(String[] args)
    {
        System.out.println(plus(3, 5));
        System.out.println(plus("Hello, ", "World"));
    }
}
/*
合計は「8」です
文字列をつなげると「Hello, World」です
*/

上述のように引数の型の異なったメソッドが存在する場合は、各々が別のメソッドとして処理される。但し、同名で引数の型も数も全く同じメソッドはオーバーロードできない。

Javaの演算子

■文字列の結合

以下のようにして文字列を結合することができる。

public class HelloWorld
{
    public static void main(String[] args)
    {
        System.out.println("Hello" + "World" + "!");
    }
}
// HelloWorld!

意外だが以下のように、数値を文字列として結合することもできる。

public class HelloWorld
{
    public static void main(String[] args)
    {
        System.out.println("Hello " + 1192 + " World" + "!");
    }
}
// Hello 1192 World!

その他の演算子は他のプログラミング言語と大体同じだから適宜まとめることにする。

Javaの変数

■宣言

Javaでは変数を使用する前に、以下のように型を指定して宣言する必要がある。

public class HelloWorld
{
    public static void main(String[] args)
    {
        String greeting = "Hello World";
        System.out.println(greeting);
        greeting = 1;// error
    }
}

上述のように、指定した型以外の型の値を代入することはできない。

また、以下のように何も入っていない変数を使用することはできない。

public class HelloWorld
{
    public static void main(String[] args)
    {
        String greeting;
        System.out.println(greeting);// error
    }
}

■スコープ

Javaにはブロックスコープが存在する。従って以下のように{}で区切られた箇所にスコープが生成される。

public class HelloWorld
{
    public static void main(String[] args)
    {
        {
            String greeting1 = "Hello World";
            {
                String greeting2 = "Hello World";
            }
            System.out.println(greeting1);
            System.out.println(greeting2);// error
            System.out.println(greeting3);// error
            String greeting3 = "Hello World";
        }
        System.out.println(greeting3);// error
    }
}

■型変換

以下のように、Javaでは型変換することができる。

public class HelloWorld
{
    public static void main(String[] args)
    {
        double pi = 3.1415;// double型で宣言
        int x = (int) pi;// double型をint型に変換...(a)
        String number = Integer.toString(x);// int型をString型に変換
        System.out.println(number);
    }
}

上述(a)を見るとPHPと同様であるように思える。しかし、以下のようにする事はできない。

public class HelloWorld
{
    public static void main(String[] args)
    {
        int x = (int)"1192";// error
        System.out.println(x);
    }
}

以下のようにすることで、上述の操作を達成することができる。

public class HelloWorld
{
    public static void main(String[] args)
    {
        int x = Integer.parseInt("1192");
        System.out.println(x);
    }
}

■定数

以下のように、finalを使用して定数を宣言することができる。

public class HelloWorld
{
    private static final String GREETING = "Hello World";
    public static void main(String[] args)
    {
        System.out.println(GREETING);
    }
}

定数なので当然、代入はできない。

public class HelloWorld
{
    private static final String GREETING = "Hello World";
    public static void main(String[] args)
    {
        GREETING = "";// error
        System.out.println(GREETING);
    }
}

■列挙型

public class HelloWorld
{
    enum Week {
        Monday,
        Tuesday,
        Wednesday,
        Thursday,
        Friday,
        Saturday,
        Sunday,
    }
    public static void main(String[] args)
    {
        System.out.println(Week.Monday);// Monday
    }
}

MySQLとかであるようなやつだね。

Javaの基本

■Hello World

なんだかんだでHello Worldからまとめてみる。

public class HelloWorld
{
    /**
     * @param args
     */
    public static void main(String[] args)
    {
        System.out.println("Hello World");
    }
}

■コメント

コメントは以下の2種類が存在する。#はコメントとして扱われない。

public class HelloWorld
{
    public static void main(String[] args)
    {
        // this is a comment
        /* this is a comment */
        System.out.println("Hello World");
    }
}

■文末

セミコロンが必須である。PHPに近くてJavaScriptやPythonとは違う。

public class HelloWorld
{
    public static void main(String[] args)
    {
        System.out.println("Hello World");// OK
        System.out.println("Hello World")// NG
    }
}

■命名規則

以下のように関数名やクラス名に日本語を使用することができる。

public class HelloWorld
{
    public static void main(String[] args)
    {
        System.out.println(げっと文字列());
    }
    
    private static String げっと文字列()
    {
        return "Hello World";
    }
}

はっきり言ってダサいし見づらいので日本語は使用しないこと。

  • アルファベット、数字、アンダースコア、$を使用できるが、数字で始めることはできない。
  • 長さに制限はない
  • 大文字と小文字は区別される。