第0講 Java言語の基礎1

この講で利用するプログラム

第0講 Java言語の基礎1のサブセクション

基礎の基礎

Hello World

Java言語で Hello World を書いてみましょう. 以下のプログラムを書き,HelloWorld.java に保存してください(//の後ろは書かなくても構いません). ファイル名とclassの後ろにある名前(クラス名)は必ず一致させていなければいけません. 一致していない場合は,コンパイルエラーが発生します.

public class HelloWorld { // <= クラス宣言の開始
    public static void main(String[] args){ // <= mainメソッドの開始
        System.out.println("Hello World");
    } // <= mainメソッドの終了
} // <= クラス宣言の終了

コンパイル方法

コンパイルには,javac コマンドを利用します.ターミナルで以下のコマンドを入力してください($はプロンプトを表していますので,入力不要です).

$ javac HelloWorld.java # Javaプログラムをコンパイルする

上記のように javacHelloWorld.java を渡して実行してください. コンパイルが行われます.コンパイルに成功すると,HelloWorld.class というクラスファイルが出力されます. a.out のようなファイルは出力されないことに注意してください.

コンパイルのイメージ コンパイルのイメージ

コンパイルに失敗すると,コンパイルエラーがコンパイラにより示されます. 代表的なコンパイルエラーは次の通りです.

  • シンボルが見つかりません.
    • 宣言されていない変数を使おうとしたときに指摘されます.
      • 変数は参照できる場所に宣言されていますか.
      • 綴りは間違っていないか確認しましょう.
  • クラスXxxxはpublicであり,ファイルXxxx.javaで宣言しなければなりません
    • Javaではクラス名とファイル名は必ず一致させておかなければいけません.
      • クラス名とファイル名が一致しているか確認しましょう.
  • <identifier>がありません.
    • publicstaticclassなどの綴り間違いが疑われます.
      • public static void main(String[] args)は間違いなく書かれていますか.
      • 一番外側に,public class Xxxxのように囲んでいますか.
      • カッコの対応は合っていますか.
  • \12288は不正な文字です.
    • 全角スペースが入っていないか確認してください.全角スペースはC言語と同じく文字列以外での利用が許されていません.

実行方法

実行するには,java コマンドを利用します. 先ほどコンパイルして得られた HelloWorld.class を実行するには,以下のようなコマンドを入力しましょう.

$ java HelloWorld # Javaプログラムを実行する
Hello World

実行するときには,拡張子(.class)はつけないことに注意してください.

プログラムの解説

一番外側

Javaプログラムは必ず一番外側が public class Xxxx で囲まれている必要があります.この一番外側の囲みをクラス宣言と呼びます. 変数も関数も必ずこのクラス宣言に囲まれた部分でしか定義できません.

また,Xxxx の部分をクラス名と呼び,ファイル名とクラス名は一致させる必要があります. 上の例の場合では,public class HelloWorld{ ... } ですから,HelloWorld.java に保存しなければいけません. それ以外のファイル名に保存すると,コンパイルできません.

mainメソッド

C言語における関数は,Javaでは,メソッド(method)と呼びます. main メソッドは,Javaプログラムを実行した時に一番最初に呼び出されるメソッドです.

main メソッドは,必ず public static void main(String[] args){ ... } であり, なんらかのクラス宣言に含まれています. 大文字小文字も区別されますので,一言一句間違えずに入力してください. なお,mainメソッドは必ずクラス宣言の括弧の内側に書かれる必要があります

public class ClassName {
    // mainメソッドはこの部分に書く.
    public static void main(String[] args) {
        // メソッドの中にメソッドは定義できない.コンパイルエラーが起こる.
        // public static void main(String[] args) {
        // }
    }
}
// ここにmainメソッドを書くとコンパイルエラーが起こる.
// public static void main(String[] args) {
// }

画面に出力する方法(printf)

Java言語で標準出力(ターミナルの実行画面)に文字を出力するには,System.out.printlnを利用します. 改行を伴って出力されます.改行したくない場合は,System.out.print を用いてください.

ただし,上記のメソッド(printlnもしくはprint)では,%dのような書式付きでは出力できません. C言語のように(printfのように)書式付きで出力したい場合,System.out.printf を利用してください. ただし,改行は \n ではなく,%n を利用してください. 改行はプラットフォーム依存であるためです. 詳しくは FAQ なぜ\nではなく,%nを利用するのでしょうかを参照してください.

なお,%dなどのフォーマット記述子には対応する型が存在します.対応しない型を指定すると実行時エラーが発生します. 対応については,FAQ フォーマット記述子とは何ですかを参照してください.

文字列

C言語と同じく,文字列は,"mojiretu"のように,""(ダブルクォート)で囲んで表します. Hello Worldのサンプルプログラムで言えば,3行目の"Hello World"部分が文字列です. ダブルクォートの内側は自由に変更しても,コンパイルエラーにはならず,実行結果が変わります.

基礎文法

条件分岐

概要

条件分岐は,if もしくは switch を用います. 文法は,C言語と同じです.典型的な例を次に示します.

if(条件式1){
    // 条件式1が成り立ったときに実行される文.
}
else if(条件式2){
    // 条件式2が成り立ったときに実行される文.
}
else{
    // 条件式1も条件式2も成り立たなかったときに実行される文.
}

C言語の場合,条件式は int 型で表現しましたが,Java言語の場合, Boolean 型となります. Boolean 型は,true もしくは false の2値で表される型です. C言語のようにプログラムを書くと,Boolean型になりますので,あまり気をつけなくとも良いようになっています.

Boolean型による条件分岐

if(value = 10){
    // この場合,if文の条件が Integer 型になるため,コンパイルエラーになる.
}
if(value == 10){
    // こう書くと,value == 10 の結果は Boolean になるため,Javaのif文として成り立つ.
    // 厳密に書けば,(value == 10) == true という条件であるが,
    // 冗長であるため,value == 10 と書くほうが望ましい.
}

例題

整数型である Integer 型の値が正負のどちらかであるかを if 文を使って判定しましょう. 以下のプログラムの.....部分を埋めて完成させてください.

public class PositiveChecker{
    public static void main(String[] args){
        Integer value = 5;
        if(.....){
            System.out.printf("与えられた数値は正の値です: %d%n", value);
        }
        else if(.....){
            System.out.printf("与えられた数値は0です: %d%n", value);
        }
        else{
            System.out.printf("与えられた数値は負の値です: %d%n", value);
        }
    }
}

完成すれば,value の値をいろいろと変更して,実行してみましょう. その際,全ての分岐が網羅するには,valueをどのような値にして,何度変更すれば良いかを考えてみましょう.

出力例

$ java PositiveChecker
与えられた数値は正の値です: 5
$ java PositiveChecker
与えられた数値は負の値です: -9
$ java PositiveChecker
与えられた数値は0です: 0

3回変更すれば,条件分岐を網羅できます.

  1. valueを0にする.
  2. valueを正の値(例:1, 2, 3, …, 2,147,483,647 (Integerの最大値))のいずれかの値にする.
  3. valueを負の値(例:-1, -2, -3, …, -2,147,483,648 (Integerの最小値))のいずれかの値にする.
        ....
        if(value > 0){
            System.out.printf("与えられた数値は正の値です: %d%n", value);
        }
        else if(value == 0){
            System.out.printf("与えられた数値は0です: %d%n", value);
        }
        ....

繰り返し

概要

繰り返しは,for もしくは while を利用します.文法はC言語と同じです. 典型的な例を次に示します.

// 初期化式,継続条件式,反復式をセミコロン(;)で区切る.
for(Integer i = 0; i < 10; i++){
    // iが0から9までこの文を繰り返す.
}
// for(初期化式; 継続条件式; 反復式)

Integer loop = 0;
// 継続条件式を while に指定する.
while(loop < 10){
    // loopが0から9までこの文を繰り返す.
    loop++;
}
// while(継続条件式)

ループ制御には,Integer型を利用することが多いです.if 文と同じく,繰り返し文の継続条件はBoolean型で表現されます.

また,for文の初期化式で変数宣言が行えるようになっています. ループを途中で抜けるには,break,そして, ループを途中で中断し,次の繰り返しに移行するには continueを使うのも C言語と同じです.

例題

for 文を使って,1以上,100未満の奇数の値を出力しましょう.

public class OddPrinter {
    public static void main(String[] args) {
        // for文を使って繰り返し.
    }
}

出力例

$ java OddPrinter
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99

完成すれば,1以上,100未満の偶数値を出力する EvenPrinter を作成してください.

public class OddPrinter{
    public static void main(String[] args){
        // 正攻法
        for(Integer i = 1; i < 100; i++){
            // iを割った余りが1であれば,奇数.
            if(i % 2 == 1){ // i % 2 != 0 の条件でも可.
                System.out.print(i);
                System.out.print(" ");
            }
        }
        System.out.println();

        // 解2: 2づつ増加させる方法.
        for(Integer i = 1; i < 100; i += 2){
            System.out.print(i);
            System.out.print(" ");
        }
        System.out.println();
    }
}

例題 改1

OddPrinterEvenPrinter それぞれで,20個の数値を出力するごとに改行してください.

出力例

$ java EvenPrinter
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40
42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80
82 84 86 88 90 92 94 96 98
public class EvenPrinter {
    public static void main(String[] args) {
        // 正攻法:出力した回数を数え,20個出力したら改行する.
        Integer printedCount = 0;
        for(Integer i = 1; i < 100; i++){
            // iを割った余りが1であれば,偶数.
            if(i % 2 == 0){
                System.out.printf("%2d ", i);
                printedCount++;
                if(printedCount == 20){
                    System.out.println();
                    printedCount = 0;
                }
            }
        }
        System.out.println();

        // 解2: 改行する位置は決まっているので,3つのループで実現する.
        for(Integer i = 2; i <= 40; i += 2){
            System.out.printf("%2d ", i);
        }
        System.out.println();
        for(Integer i = 42; i <= 80; i += 2){
            System.out.printf("%2d ", i);
        }
        System.out.println();
        for(Integer i = 82; i < 100; i += 2){
            System.out.printf("%2d ", i);
        }
        System.out.println();
    }
}

Java言語は,C言語に比べて,非常に多彩な型が存在します(標準で約4,000の型が用意されている). 型がわからなければ,プログラムが読めなくなりますので,C言語のとき以上に型に気をつけてください.

この講義では,とりあえずは,次の型さえ区別できていれば良いです. 講義が進むと,さらに扱う型が増え,最終的に標準で用意されている型では,20 程度の型を使うことになります.

変数の宣言方法

C言語と同じく,型名の後ろに変数名を書いて変数を宣言します. 先にも述べたように,C言語と比べて非常に多彩な型が出てきます. 変数がどんな型であるのかを把握しなければプログラムがわからなくなりますので, 変数の型に気をつけてプログラムを読むようにしましょう.

Integer intValue; // Integer型の変数 intValue を宣言した.
intValue = 10;    // intValue に10を代入した.

// Double型の変数 pi を宣言し,初期値として3.14 を代入した.
Double pi = 3.14;

// String型の変数 name を宣言し,初期値として"Tamada"を代入した.
String name = "Tamada";

// Boolean型の変数 flag を宣言し,初期値として,true を代入した.
Boolean flag = true;

// Character型の変数 character を宣言し,
// 'a' という値を代入した.文字は''で囲む.
Character character = 'a';

代表的な型

  • 整数型
    • Integer 型,(Long型,Short 型,Byte型)
    • ほとんどの場合,Integer型を利用する.
  • 浮動小数点型
    • Double 型,(Float 型)
    • ほとんどの場合,Double型を利用する.
  • 真偽値型
    • Boolean 型(true もしくは false
  • 文字型
    • Character 型.
  • 文字列型
    • String 型.

各型の取りうる値

  • Boolean
    • trueもしくは false のどちらか.
  • Character
    • 16ビット Unicode 文字(\u0000\uffff
  • Byte
    • 8ビット整数(-128127$-2^7$〜$2^7-1$))
  • Short
    • 16ビット整数(-32,76832,767$-2^{15}$〜$2^{15}-1$))
  • Integer
    • 32ビット整数(-2,147,483,6482,147,483,647$-2^{31}$〜$2^{31}-1$))
    • 最大値は,Integer.MAX_VALUE
  • Long
    • 64ビット整数(-9,223,372,036,854,775,8089,223,372,036,854,775,807$-2^{63}$〜$2^{63}-1$))
  • Float
    • 32ビット単精度浮動小数点数
  • Double
    • 64ビット倍精度浮動小数点数

各型の相互変換

String型への変換

次の2通りの方法があります.

  • 実体に対して,toStringメソッドを呼び出す方法.
  • 他のString 型と連結する方法.

処理速度は,toStringメソッドを呼び出す方が早いです. 以下の例も参考にしてください.

Integer intValue = 10;
Double doubleValue = 3.141592;
String string1 = intValue.toString(); // もちろん,"" + intValue でも可.
String string2 = "" + doubleValue;    // doubleValue.toString() でも可.

// 次のような代入方法では,コンパイルエラーが起こる.
String string3 = intValue;  // 型が違う.
String string4 = (String) doubleValue; // 暗黙的な型変換が行えない

String型から各種数値型への変換

必要になった時に改めて説明しますが,次の原則を覚えておくと役に立つでしょう. 数値型(Integer型やDouble型など)にvalueOfというメソッドが定義されています.

練習問題

本日の残りの時間で,次に挙げる練習問題を順に作成してください.

1. Big & Small

0から1までの Double 型の乱数を発生させ,その値が0.5より小さければ Small,0.5以上であれば Big と出力するプログラムを作成してください. 0以上1未満の Double 型の乱数は,次のコードで得られます.

public class BigAndSmall{
    public static void main(String[] args){
        Double value = Math.random();
        // valueには0から1の乱数が代入されている.
        System.out.printf("value: %f: ", value);

        // ここに判定のプログラムを書いていく.
    }
}

実行すると,そのときの value の値と Big もしくは Small の文字列が出力されます.

乱数発生方法

0以上1未満の Double 型の乱数は,次の1行で得られます.

Double value = Math.random();

出力例

以下の出力例と同じ結果は出ませんが,条件に示したように,value の値が0.5より小さいか,以上かで判定できているかを確認してください.

$ java BigAndSmall
value: 0.327039: Small
$ java BigAndSmall
value: 0.582704: Big
$ java BigAndSmall
value: 0.239037: Small
$ java BigAndSmall
value: 0.304460: Small

2. うるう年の判定

与えられた年がうるう年であるか否かを判定しましょう. うるう年は,次のように判定します.

  • 西暦で表される年が 4 で割り切れたらうるう年である.
  • ただし,そのうち,100で割り切れる年はうるう年ではない.
  • ただし,さらに,400で割り切れる年はうるう年である.

次のようなフローチャートになります.

graph LR
    id1{4で割り切れる}
    id2{100で割り切れる}
    id3{400で割り切れる}
    leap(うるう年)
    ordinal(平年)
    id1 -->|true|id2
    id1 -->|false|ordinal
    id2 -->|true|id3
    id3 -->|false|ordinal
    id3 -->|true|leap
    id2 -->|false|leap
public class LeapYear{
    public static void main(String[] args){
        Integer year = 2016;
        Boolean leapYear = false;
        // ここに判定処理を書いていく.
 
        if(leapYear){ // leapYearがtrueの場合.
            System.out.printf("%d年はうるう年です.%n", year);
        }
        else{
            System.out.printf("%d年はうるう年ではありません.%n", year);
        }
    }
}

完成すれば,year の値を変更して実行結果を確認してください. なお,2000, 2004, 2016年はうるう年,2100,2015, 1900年はうるう年ではありません.

条件文の AND, OR, NOT

  • 2つの条件の両方を満たしたときに処理を行いたい場合は,次のように,AND(&&)で2つの条件式を結ぶ.
if(条件式1 && 条件式2){
    // 条件式1, 条件式2の両方を満たした時に実行される.
}
  • 2つの条件のどちらか一方を満たしたときに処理を行いたい場合は,次のように,OR(||)で2つの条件式を結ぶ.
if(条件式1 || 条件式2){
    // 条件式1,条件式2のどちらかを満たすときに実行される.
}
  • ある条件を満たさないときに処理を行いたい場合は,次のように,条件式の前に NOT(!)をつける.
if(!条件式1){
    // 条件式1を満たさないとき(falseの場合)に実行される.
}

出力例

以下のように,判定する年を変更して実行結果を確認してみましょう. 以下の例では省略していますが, year に代入する値を変更するたびにコンパイルしてください.

$ java LeapYear
2016年はうるう年です.
$ java LeapYear
2000年はうるう年です.
$ java LeapYear
2004年はうるう年です.
$ java LeapYear
2100年はうるう年ではありません.
$ java LeapYear
2015年はうるう年ではありません.
$ java LeapYear
1900年はうるう年ではありません.

3. 総和を求める.

ループを用いて,1から10までの総和(10を含む)を求めましょう.次の手順で作成していきましょう.

  1. クラス名をGrandTotal とする.
  2. main メソッドを用意する.
  3. main メソッド内で Integer 型の変数 result を宣言する.
    • result は初期値として0を代入しておく.
  4. main メソッド内で Integer 型のループ制御変数 i を宣言する.
  5. ループ制御変数 i を用いて1から10までループを作成する.
  6. 繰り返しごとに,resulti の値を加算していく.
  7. ループ終了後,result の値を出力する.

ループはC言語と同じように書けます. forwhile のどちらも利用できますので,試してみましょう.

完成すれば,範囲を変更して,総和を求めましょう.

出力例

$ java GrandTotal
1から10までの総和は55です.
$ java GrandTotal
1から100までの総和は5050です.
$ java GrandTotal
1から1000までの総和は500500です.

4. 九九を表示する.

出力例のように,九九を表示するプログラムを作成しましょう. クラス名を Multiplication とします.

出力するとき,System.out.printf のフォーマット記述子に%d ではなく,%2dとすると,1桁の数字でも2桁として出力してくれます. なお,%02dとすると,足りない桁は0で埋めてくれます.

出力例

$ java Multiplication
   1  2  3  4  5  6  7  8  9
1  1  2  3  4  5  6  7  8  9 
2  2  4  6  8 10 12 14 16 18 
3  3  6  9 12 15 18 21 24 27 
4  4  8 12 16 20 24 28 32 36 
5  5 10 15 20 25 30 35 40 45 
6  6 12 18 24 30 36 42 48 54 
7  7 14 21 28 35 42 49 56 63 
8  8 16 24 32 40 48 56 64 72 
9  9 18 27 36 45 54 63 72 81 

5. Xの描画

繰り返しを利用し,出力例の模様を出力してください. クラス名は XPrinter としてください.

出力例

$ java XPrinter
X........X
.X......X.
..X....X..
...X..X...
....XX....
....XX....
...X..X...
..X....X..
.X......X.
X........X

まとめ

まとめ

if(条件式1 && 条件式2){
    // 条件式1,条件式2の両方を満たすときに実行される.
}
if(条件式1 || 条件式2){
    // 条件式1,条件式2のどちらかを満たすときに実行される.
}
if(!条件式1){
    // 条件式1を満たさないときに実行される.
}