【Java Silver黒本】6章のつまづいたところまとめ。

可変長引数

  • メソッド内では配列として扱われる
  • 可変長引数は引数リストの最後に記述する
  • 可変長引数は各メソッドに最大ひとつまで
public class Main {
  // メソッド内では配列として扱われる
  public static void sampleMethod1(String text, int... numbers) {
    System.out.println(numbers instanceof int[]); // => true
  }

  // 可変長引数は引数リストの最後に記述する
  // 次のメソッドはコンパイルエラーになる
  public static void sampleMethod2(int... numbers, String text) {

  }

  // 可変長引数は各メソッドに最大ひとつまで
  // 次のメソッドはコンパイルエラーになる
  public static void sampleMethod3(int... numbers, String... texts) {

  }
}

return文

  • return文の使用で明らかに到達不可能なコードがある場合、コンパイルエラーになる
public class Main {
  public static void main(String[] args) {
    return;

    // コンパイルエラー
    System.out.println("Hello");
  }
}

オーバーロード

public class Main {
  public static void main(String[] args) {

  }

  // 元のメソッド
  public static void sampleMethod(int number) {

  }

  // 引数だけ変える
  // 次のメソッドは元のメソッドのオーバーロードとして動作する
  public static void sampleMethod() {

  }

  // 戻り値だけ変える
  // 次のメソッドはコンパイルエラーになる
  public static String sampleMethod(int number) {
    return "hello";
  }

  // アクセス修飾子だけ変える
  // 次のメソッドはコンパイルエラーになる
  private static void sampleMethod(int number) {

  }
}

あいまいなメソッド呼び出し

  • オーバーロードした複数のメソッドがあり、呼び出し時の実引数指定でどちらのメソッドを使用するか特定できない場合、コンパイルエラーとなる
public class Main {
  public static void main(String[] args) {
    // コンパイルエラー
    sampleMethod(1, 2);
  }

  public static void sampleMethod(int a, double b) {

  }

  public static void sampleMethod(double a, int b) {

  }
}

コンストラクタ定義ルール

  • メソッド名をクラス名と同じにする
  • 戻り値型は記述しない
  • newと一緒にしか使えない

※戻り値型を記述すると、メソッドとして扱われる。

public class Main {
  public static void main(String[] args) {
    Item item = new Item();

    item.Item(); //=> hello
  }
}

class Item {
  // コンストラクタを明示的に記述しない場合、
  // コンパイル時に引数なしのコンストラクタが自動で追加される

  // 次のItem()は戻り値型の記述があるため
  // コンストラクタではなくメソッドとして解釈される
  void Item() {
    System.out.println("hello");
  }
}

privateにすることも出来る。

public class Main {
  public static void main(String[] args) {
    Item item1 = Item.createInstance();
    Item item2 = Item.createInstance();

    System.out.println(item1 == item2); // => true
  }
}

class Item {
  public static Item instance;

  private Item() {

  }

  public static Item createInstance() {
    if(Item.instance == null) {
      Item.instance = new Item();
    }

    return Item.instance;
  }
}

初期化ブロック

  • クラス宣言の中にブロックだけを記述すると、初期化ブロックとなる
  • 初期化ブロックは全てのコンストラクタの実行前に実行される
public class Main {
  public static void main(String[] args) {
    Item item = new Item();
    // => hello
    // => world
  }
}

class Item {
  public Item() {
    System.out.println("world");
  }

  // 初期化ブロック
  {
    System.out.println("hello");
  }
}

コンストラクタのオーバーロード

  • コンストラクタのオーバーロードの際、別のコンストラクタ呼び出しは処理の最初でなければならない
public class Main {
  public static void main(String[] args) {
    Item item = new Item();
  }
}

class Item {
  public Item(String text) {

  }

  public Item() {
    // 別のコンストラクタ呼び出しthis("fuga")より前に処理があるので
    // コンパイルエラーとなる
    System.out.println("hoge");

    this("fuga");
  }
}

アクセス修飾子によるアクセス制御

アクセス修飾子 アクセス可能範囲
public 全てのクラスからアクセス可
protected 同パッケージ、
もしくは継承クラスからのみアクセス可
記述なし 同パッケージからのみアクセス可
private クラス内からのみアクセス可
  • クラス宣言にはpublicと記述なしのみ使用可
  • インナークラスにはprivateも使用可
  • 記述なしはpackage privateとも表現される

実引数と仮引数

  • 実引数はコピーされて仮引数へ渡されるため、仮引数が変更されても実引数に影響はない
public class Main {
  public static void main(String[] args) {
    int number = 1;

    sampleMethod(number);

    System.out.println(number); // => 1
  }

  public static void sampleMethod(int number) {
    number = 10;
  }
}

【Java Silver黒本】5章のつまづいたところまとめ。

for文

  • 初期化文で複数の変数を宣言する場合、変数は同じ型でなければならない。
  • 更新文には複数の処理を記述できる。
public class Main {
  public static void main(String[] args) {
    // 初期化時に複数の変数を宣言できる
    for(int i = 0, j = 0; i < 10; i++) {

    }

    // 初期化時には違う型の変数を複数宣言することは出来ない
    // 次のfor文はコンパイルエラーになる
    for(int i = 0, double d = 0.0; i < 0; i++) {

    }

    // 更新時に複数の処理を記述できる
    for(int i = 0; i < 10; i++, System.out.println(i)) {

    }
  }
}

拡張for文

  • 拡張for文の一時変数には、集合の各要素への参照が入っている。そのため、一時変数に別の値を代入しても集合に変化はない。
public class Main {
  public static void main(String[] args) {
    int[] array = { 1, 2, 3 };

    for(int i: array) {
      i = 0;
    }

    // array: { 1, 2, 3 }
  }
}

ラベル

  • Javaでは変数宣言以外の文やブロックなどにラベルをつけることが出来る。ラベルはループ制御に使用することが出来る。
public class Main {
  public static void main(String[] args) {
    loopI: for(int i = 0; i < 5; i++) {
      loopJ: for(int j = 0; j < 3; j++) {
        if(j > 1) {
          continue loopI;
        }

        if(i > 1) {
          break loopJ;
        }

        System.out.println(i + ", " + j);
      }
    }
  }
}

実行結果

0, 0
0, 1
1, 0
1, 1

VPSにMariaDBをインストールしてデータベースを作ってみる。【ver.5.2】

参考サイト

centossrv.com

MariaDBインストー

$ sudo yum -y install mariadb-server

MariaDB設定

$ sudo vi /etc/my.cnf.d/server.cnf

server.conf

# 略
[mysqld]
character-set-server = utf8
# 略

MariaDB起動

$ systemctl start mariadb
$ systemctl enable mariadb

MariaDB初期設定

$ sudo mysql_secure_installation

基本Enterを押して進めていく。

New password:と聞かれたときにrootユーザーログイン用のパスワードを入力する。

以降もEnter連打。

接続コマンド

$ mysql -u [USERNAME] -p [PASSWORD]

作成したデータベース

認証もしたほうがいいっぽいので認証用テーブルとメッセージ保存用テーブルを分けた。

users

COLUMN DATA TYPE
id INTEGER PRIMARY KEY
name VARCHAR(255) UNIQUE
token VARCHAR(255) UNIQUE

messages

COLUMN DATA TYPE
id INTEGER PRIMARY KEY
channel VARCHAR(255) NOT NULL
text VARCHAR(4095) NOT NULL
is_admin BOOLEAN DEFAULT 0
created_at TIMESTAMP

メッセージ投稿用のエンドポイントを作成してみる。【ver.5.1】

ポートフォリオに追加するメッセージツール用のエンドポイントを作成してみた。

kazmaarakaki.hatenablog.com

Expressを使えばめちゃくちゃ簡単、と思いきやPOSTでクライアントからデータを送るときには追加のモジュールが必要。

body-parserをインストー

github.com

ファイルアップロード用のmulterっていうモジュールもあるみたい。今回は使わないけど。

github.com

npm install body-parser --save

リクエスト処理をサーバーファイルに追加

エンドポイントのURLは少し変えた。

server.js

import express from "express";
import bodyParser from "body-parser";

const app = express();

app.use(bodyParser.json());

app.use(express.static(__dirname + "/build", {
  "setHeaders": (response, path, stat) => {
    switch(path.substr(path.lastIndexOf("."))) {
      case ".html":
      case ".js":
      case ".jpg":
        response.set("Content-Encoding", "gzip");
    }
  }
}));

app.get("/api/portfolio/message/get_all/:channel", (request, response) => {
  console.log(request.params.channel);
});

app.post("/api/portfolio/message/send", (request, response) => {
  console.log(request.body.channel);
  console.log(request.body.text);
});

app.listen(3000, () => {
  console.log("Server is running...");
});

テスト用スクリプト

ブラウザからリクエストを投げるスクリプト

GET /api/portfolio/message/get_all/:channel

fetch("/api/portfolio/message/get_all/hoge").then(response => {
  return response.text();
}).then(data => {
  console.log(data);
});

POST /api/portfolio/message/send

fetch("/api/portfolio/message/post", {
  "method": "POST",
  "headers": (function(headers) {
    headers = new Headers();
    headers.append("Content-Type", "application/json");
    return headers;
  })(),
  "body": JSON.stringify({
    "channel": "hoge",
    "text": "fuga"
  })
}).then(response => {
  return response.text();
}).then(data => {
  console.log(data);
});

【Java Silver黒本】4章のつまづいたところまとめ。

多次元配列の宣言

宣言 次元数
int[][] array; 2次元
int[][] array[]; 3次元
int[] array[][]; 3次元
int array[][]; 2次元

配列のデフォルト値

デフォルト値
整数型 0
浮動小数点数 0.0
真偽型 false
文字型 \u0000
オブジェクト型 null
public class Main {
  public static void main(String[] args) {
    Item[] items = new Item[3]; // => { null, null, null }
  }
}

class Item {

}

配列の初期化

  • 初期化時に配列の要素数を指定しなければならない(array1
  • 初期化演算子{}は、配列の要素数を自動計算する(array3
  • 初期化演算子を使用する場合、new int[]のブラケット内に要素数を書いてはいけない(array5
  • 初期化演算子を使用する場合、new int[]は省略できる(array6
  • new int[]を省略して初期化演算子のみで初期化できるのは変数宣言時のみ(array7
  • 宣言部分の次元数と、初期化部分の次元数は同じでなければならない(array10
public class Main {
  public static void main(String[] args) {
    int[] array1 = new int[2];
    int[] array2; array2 = new int[2];
    int[] array3 = new int[]{ 1, 2 };
    int[] array4; array4 = new int[]{ 1, 2 };
    int[] array5 = new int[2]{ 1, 2 }; // コンパイルエラー
    int[] array6 = { 1, 2 };
    int[] array7; array7 = { 1, 2 }; // コンパイルエラー
    int[] array8 = {};
    int[] array9; array9 = {}; // コンパイルエラー
    int[][] array10 = new int[2]; // コンパイルエラー
    int[][] array11 = new int[2][3];
    int[][] array12 = new int[2][];
    int[][] array13 = new int[][]{ { 1, 2 }, { 3, 4 }, { 5, 6 } };
    int[][] array14 = new int[][]{ { 1 }, { 2, 3 }, { 4, 5, 6 } };
    int[][] array15 = { { 1, 2 }, { 3, 4 }, { 5, 6 } };
    int[][] array16 = {};
  }
}

cloneメソッド

cloneメソッドはインスタンスのコピーを作るが、配列の要素として参照を持っている場合、参照先のインスタンスはコピーされない。

つまり、同じ参照の配列を持つ別インスタンスが作られる。

public class Main {
  public static void main(String[] args) {
    int[][] array1 = { { 1, 2 }, { 3, 4 } };
    int[][] array2 = array1;
    int[][] array3 = array1.clone();

    System.out.println(array1 == array2); // => true
    System.out.println(array1 == array3); // => false
    System.out.println(array1[0] == array3[0]); // => true
  }
}

System.arraycopyメソッド

配列のコピーを行う。

public class Main {
  public static void main(String[] args) {
    int[] array1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    int[] array2 = new int[array1.length];

    Object fromArray = array1;
    int fromIndex = 3;
    Object toArray = array2;
    int toIndex = 1;
    int copyLength = 2;

    System.arraycopy(
        fromArray,
        fromIndex,
        toArray,
        toIndex,
        copyLength
    );

    // array1のインデックス番号3から2つ分の要素を
    // array2のインデックス番号1以降にコピーする
    //
    // array2: { 0, 4, 5, 0, 0, 0, 0, 0, 0 }
  }
}
引数
fromArray コピー元の配列インスタンス
fromIndex コピー元のコピー開始インデックス
toArray コピー先の配列インスタンス
toIndex コピー先のコピー開始インデックス
copyLength コピーする要素数

【Java Silver黒本】1章から3章までのつまづいたところまとめ。

はじめて知る知識が多いが、特に難しいというわけではない。

知らなかったことを学んでいけば受かりそう。

1章

  • パッケージの目的

パッケージ名を省略すると「無名パッケージ」として解釈される。つまり全てのクラスはなんらかのパッケージに属している。

  • 自動インポートされるクラス

    • java.langパッケージに属するクラス
    • 自クラスと同じパッケージに属するクラス
  • 同名フィールド、同名メソッドのstaticインポート

    • インポートしたものと、クラス内で定義したものの変数名が重複した場合、インポートしたものが無視される
    • 同名フィールドや同名メソッドをインポートした場合、コンパイルエラーとなる

2章

10進数 2進数 8進数 16進数
63 077 0x3F 0b00111111

3章

public class Main {
  public static void main(String[] args) {
    int a = 10;

    int b = a++ + a + a-- - a-- + ++a;
    // (10) + (10 + 1) + (11) - (11 - 1) + (10 - 1 + 1)
    //  10  +  11      +  11  -  10      +  10
    // => 32
  }
}
  • Object.equals(Object o)

    • Objectクラスのequalsメソッドは同一性のチェックのみを行うので、同値性のチェックを行うためには継承先の各クラスでオーバーライドしなければならない。
  • コンスタントプール

    • 定数やシンボルを保存する領域。ヒープ内に存在し、全てのスレッドから共有される。コンスタントプールに置く定数値の定義は、各クラスの中に存在し、クラスの読み込み時にメソッドエリアにコピーされる。
  • else if文

    • elseとifの間では改行できない。
  • switch文

    • switch(ARG)ARG部分
      • longを除く整数型
      • 文字、文字列
      • 列挙型
    • case VALUEVALUE部分
      • 条件式が戻す値と同じ型か、もしくは互換性のある型か
      • final宣言された変数かリテラル
      • nullではないこと
  • 整数型、浮動小数点数型のキャスト

    • より小さい範囲の型へ非明示的にキャストすることはできない。
    • 明示的なキャストで範囲外の数値(byte型に257など)を与えると、最大ビットを超えた分が切り捨てられるがエラーにはならない。

下のコードは非明示的キャストでコンパイルエラーになる例である。

public class Main {
  public static void main(String[] args) {
    int i = 1;

    long l = i;
    short s = i; // => コンパイルエラー
    byte b = i; // => コンパイルエラー
  }
}

でもこれ↓はエラーにならない。

public class Main {
  public static void main(String[] args) {
    int i = 1;

    long l = 1;
    short s = 1;
    byte b = 1;
  }
}

これ↓はエラーになる。

public class Main {
  public static void main(String[] args) {
    long l = 1L;
    int i = 1L; // => コンパイルエラー
    short s = 1L; // => コンパイルエラー
    byte b = 1L; // => コンパイルエラー
  }
}

また、浮動小数点数値を使うと、

この例↓ではエラーにならないが、

public class Main {
  public static void main(String[] args) {
    double d = 1;
    float f = 1;
  }
}

これ↓だとコンパイルエラーになる。

public class Main {
  public static void main(String[] args) {
    double d = 1.0;
    float f = 1.0; // => コンパイルエラー
  }
}

257を2進数で表すと0b1_0000_0001だが、9ビットの数値となるので、一番左のビットが切り捨てられ、0b0000_0001と同値になる。

public class Main {
  public static void main(String[] args) {
    byte b = (byte)257; // => 1
  }
}

Oracle Certified Java Programmer, Silver SE 8 認定資格を取りたい。

7月末にOracle Java Programmer Iの試験を受けようと思っている。合格したらJava Silverの資格がもらえる。

Java Silverとは

Oracle Certified Java Programmer, Silver SE 8 認定資格は、Javaアプリケーション開発に必要とされる基本的なプログラミング知識を有し、上級者の指導のもとで開発作業を行うことができる開発初心者向け資格です。

Java SE 8 認定資格 | オラクル認定資格制度 | Oracle University

試験概要

Java SE 8 Programmer I | Oracle Certification Exam

試験時間 150 分
出題数 77 問
合格ライン 65%
受験料 26600 円(税別)
会場 ピアソンVUE

その他リンク