【Pythonエンジニア向け】Java入門
プログラミング言語によって記述方法や利用できるライブラリは異なります。
私が業務として主に扱ってきた言語はPythonとRubyなのですが、フリーランスを始めるにあたって初めて受注した案件で利用する言語がJavaでした。
案件に入る前に自己学習を進めていたのですが、その中でPythonやRubyと異なり特に重要だと思った部分について本記事にまとめましたので、PythonもしくはRubyエンジニアで新たにJavaを勉強しようと考えている方は参考にしてみてください。
勉強に利用した書籍は以下です。
私は大分昔に買っていたので第2版で勉強しましたが、何かとややこしいオブジェクト指向などを背景から詳しく分かりやすく説明してくれている良書です。
基本
- JavaはC言語を元にしてできたコンパイラ言語
- ソースコードをコンパイルしてバイトコードにしたのちに、インタープリタによってマシン語に解釈され実行する
- Javaのソースコードを実行するためにはコンパイラとインタープリタが必要
- Javaは関数型ではなくオブジェクト指向型
- 関数を単体で作ることはできず、必ずクラスを作成した上で、そのなかのメソッドとして記述する
- ファイル名とクラス名は一致させる必要がある
- 大文字小文字も一致させる必要がある
- ただしPublicではないクラスであれば一致していなくてもOK
- 1ファイルに複数のクラスを作ることも可能
- Publicなクラスは1ファイルに複数作ることは不可
- クラスやメソッドなどのブロックを形成するための行以外には一行ごとにセミコロンが必要
- ブロックの形成には{}が使われる(Pythonはインデントでブロック)
コード具体例
Javaの基本的な書き方についてコード例で解説します。
各種設定の配置箇所は以下です。
公開度合い class クラス名 extends 継承元クラス名 {
公開度合い 動的or静的 戻り値の型 メソッド名(引数の型1 引数名1, 引数の型2 引数名2) {
処理内容;
}
}
上記の記法に従って書いたコードの例を載せます。
public class App {
public static void main(String[] args) throws Exception {
System.out.println("Hello, World!");
this.sampleMethod(2, 'あ');
}
private void sampleMethod(int num, char moji) {
System.out.plintln(num);
System.out.plintln(moji);
}
}
変数
- 変数の宣言時には型を指定する必要がある(Pythonは型指定が不要で代入される値を元に型決定)
- 1文字(char型)の時はシングルクオート、複数文字(String型)の時はダブルクオートで囲んだ文字を代入できる
- 上書きされたくない変数はfinalをつけて宣言
- finalで宣言された変数は一度しか代入できない
- 整数リテラルにはアンダースコアを含めても良い(リテラルは"値"のようなイメージでOK)
- 例えば1_000という値は1000として解釈される
- メソッドの引数は基本的に値渡しだが、配列の場合は参照渡しになる。
演算
- 計算処理は優先順位にしたがって行われる。必ずしも左からされるわけではない
- =演算子は右から左に向かって評価される
- 例:a=b=10;という記述の場合、まず右側の=演算子が評価され、bに10が代入された後にaにbが代入される
- =演算子は右から左に向かって評価される
- 異なる型の演算時には意味的に大きな型に統一されてから演算される
- 例えばdoubleとintの演算なら、doubleとdoubleに統一されて演算されて、double型で演算結果が出る
ロジック
- if文やwhile文などで利用される条件式はboolean型に変換できる結果しか不可
- Pythonだったらint型でも値があればtrueという判定になっていたが、そのような判定はせずtrue, falseのみで判定
- 文字列の比較の際はequalsメソッドを利用する。==は利用しない。
- stringは参照型のために別のメモリアドレスに保管されている値の"参照値"を変数に格納している。==で比較したときにjavaは変数がもつメモリアドレスを比較するので、仮に同じ文字列を指していてもメモリアドレスが異なることにより比較結果がfalseになる。文字列同士の比較をする場合、メモリアドレスではなく実際の文字列で比較したいはずなので、equalsメソッドを利用する。メモリアドレスを比較したいなら==でOK
- switch文は利用可能(Pythonにはない)
- 拡張for文なるものがあり、シンプルなfor文を記載することが可能
- 記法:for (型 変数: for文で回したい配列が格納された変数){.処理 }
クラス
- インスタンス化しなくても他クラスのstaticメソッドは利用できる
- パッケージを設定した場合にはそれに準じたフォルダ構成にしてしかるべき位置にクラスファイルを配置する必要がある
- 静的フィールドはすべてのインスタンスで値が共通になる
- staticを先頭につけて宣言すれば、静的フィールドになる
- インスタンス1で静的フィールドの値を設定したら、インスタンス2でも同じ静的フィールドを利用できる
- 静的メソッドはインスタンス化しなくてもクラスから直接呼び出すことができる。
- Pythonでいうクラスメソッドのような形
- クラスのメンバ変数は基本的にprivateにし、getter、setterを使って操作する
- メリット1:readonlyもしくはwriteonlyの変数を作成できる
- メリット2:メンバ変数名変更の際に別ファイルからの呼び出し文の変更をしなくて済む→getter setter名には名前の付け方に風習があるから、あまりメリットにはならなさそう。
- メリット3:設定される値が妥当かどうかチェックを入れることが可能になる。→一番重要なメリットだと思う。
- 複数のクラスを継承元にすることは規約として不可
オブジェクト指向
- メソッドにfinalをつけると継承先でのオーバーライドが不可になる
- 親クラスを持つクラスのインスタンス化時に動作するコンストラクタでは、必ず最初に親クラスのコンストラクタが動作する。これを明示的に行うために、子クラスのコンストラクタの先頭でsuper();を記述するのが慣習。
- abstractで作成できる抽象クラスは継承されることを前提としたクラスで、newでインスタンス化は不可
- abstractメソッドは継承先で必ずオーバーライドしないといけない
- インターフェイスとは、抽象メソッドだけが定義された抽象特化型クラスと考えればOK
そのほかJavaの特徴
- ガベージコレクションは勝手にやってくれる(PythonやRubyと一緒)
- 複数のファイルで構成されたJavaプログラムはjavaコンパイルにより複数のクラスファイルになるが、これらの複数のクラスファイルを一つにまとめたファイルをJARファイルと呼ぶ(JavaArchive)
- Javaにおけるimport文は別のファイルの関数やメソッドを利用できるようにするためではなく、利用する際に省略して記述できるようにするための目的しかない。importしなくてもJVMが勝手に参照できるようにしてくれる。
- Exceptionが発生する可能性がある処理をするときには例外処理を入れないとコンパイルエラーになる。(例外処理の強制→初心者プログラマに向いている仕様やね)
- ただし処理を記載しているクラスでスロー宣言をしている時には呼び出し元で対処することが約束されているので、コンパイルエラーにならない(逆に呼び出し元はその処理の呼び出し時にtry-exceptする必要がある)