はじめに
今年度から大手シンクタンクでエンジニアとして働いているAmayです。研修の一環としてJavaを2週間学習し、未経験から簡単なWebアプリを作成することができました。Javaの基本的な文法とオブジェクト指向の考え方を学ぶ中で、特に重要だと感じたポイントを共有したいと思います。
この記事では、初心者の私が短期間で効果的にJavaを学習できた方法や、押さえておきたい基礎知識について詳しく解説します。これからJavaを学び始める方や、効率的な学習方法を探している方にとって、少しでも役立つ内容になれば幸いです。
学習方法
実際に利用した教材は以下の通りです。
- 弊社研修資料(非公開)
- スッキリわかるJava入門第4版
研修資料を中心に学習を進め、その中で開発を経験しました。スッキリJavaは研修中や復習の際に補足資料として使用しました。初学者がつまずきやすいポイントを簡潔にまとめてあって、とても使い勝手が良かったです。
今回はスッキリJavaのステップに合わせてまとめました。より詳しい内容が知りたい場合は、購入して一読することをお勧めします!
以下、Java入門編のまとめになります。
Java入門編 つまずきポイント
「第1部 ようこそJavaの世界へ」より
宣言と初期化・代入
- 宣言:変数が入る箱を作ること。宣言だけでは中身がないためそのまま使えない場合がある
- 生成:指定された型の要素を生成する。生成にはnew演算子を用いる。
- 生成(new)後の各要素にはデフォルト値が代入される(Object型、配列型はnull)
- 代入:作成した要素を箱の中に入れる。
値(プリミティブ)型と参照型
-
値型:全て変数のサイズ(bit)が決まっている。
- 規定のサイズを超える値を格納することはできない。逆に言うと適切な型を使わないと無駄にメモリを使うことになる。
-
参照型:String型やオブジェクト型が当たる。
- 参照型の特徴は、変数に格納されているのは「値」そのものではなく、値がメモリのどこに格納されているかを示す「参照値」ということ。
-
値渡しと参照渡し
- 値渡しは変数の値を伝えるだけ。中身の変更は×
- 参照渡しは変数の参照先ごと伝えちゃうから、何でも変更できちゃう
スタック領域とヒープ領域
-
スタック領域
- 読み込みが早く管理がしやすいが、大きなデータの格納には向いてない
- ローカル変数、ローカル参照変数、メソッド呼び出し
- 読み込みが早く管理がしやすいが、大きなデータの格納には向いてない
-
ヒープ領域
- 大きなデータ、スコープがはっきりしないもの、静的なデータの格納に向く
- オブジェクトのインスタンス、実際の値やメソッド
- 大きなデータ、スコープがはっきりしないもの、静的なデータの格納に向く
「==」 vs 「equals」
まずは、等値(equality)と等価(equivalance)の理解が必要!
等値:同一の存在であること(同じアドレスを指しているかどうか)
等価:同じ内容であること(同じアドレスを示していなくてもよい)
- 「==」はスタック領域の、「equals」はヒープ領域の比較をおこなう。
- 値型の変数は、「==」で値の比較ができる。一方で、「equals」では値の比較ができない。なぜなら、値型の変数はスタック領域にしか値を持っていないから。
- 参照型の変数は、「==」, 「equals」ともに比較できるが、「==」の場合は、スタック領域にある参照値(実際の値とは異なる)を比較することになる。
// 「==」と「equals」の違いを表したコード例
public class ComparisonExample {
public static void main(String[] args) {
// 結果を格納する変数
String result = "";
// 2つの整数配列を定義
int[] numbers1 = {7, 8, 9};
int[] numbers2 = {7, 8, 9};
// 配列を==で比較(メモリアドレスの比較)
if (numbers1 == numbers2) {
result = "==で同じです";
} else {
result = "==で違います";
}
// 結果を表示:==で違います
System.out.println(result);
// 配列のメモリアドレスを表示
System.out.println(numbers1); // 例: [I@5e91993f
System.out.println(numbers2); // 例: [I@1c4af82c
// 次に文字列を使って比較を説明します
String text1 = new String("こんにちは");
String text2 = new String("こんにちは");
// 文字列を==で比較(メモリアドレスの比較)
if (text1 == text2) {
result = "==で同じです";
} else {
result = "==で違います";
}
// 結果を表示:==で違います
System.out.println(result);
// 文字列をequalsで比較(内容の比較)
if (text1.equals(text2)) {
result = "equalsで同じです";
} else {
result = "equalsで違います";
}
// 結果を表示:equalsで同じです
System.out.println(result);
// 文字列の内容を表示
System.out.println(text1); // こんにちは
System.out.println(text2); // こんにちは
}
}
- このコードで以下のポイントを説明している:
- numbers1とnumbers2は同じ数値を含む別々の配列であり、==を使って比較するとメモリアドレス(どこに保存されているか)の比較になるため、結果は「違います」となる。
- text1とtext2は同じ文字列「こんにちは」を含む別々のオブジェクトであり、==を使って比較するとやはりメモリアドレスの比較になるため、「違います」となる。
- しかし、equalsメソッドを使って文字列の内容を比較すると、内容が同じなので「同じです」となる。
- よって、文字列の比較を行う場合には「equals」が用いられる(等価であれば十分)。
for文
- ()内の初期値、条件文の設定を忘れないように!
- (ex) for (int i = 0; i < 5; i++) {}
return
- return文は値を戻すだけでなく、メソッドの終了を指示する。
オーバーロード
- オーバーロードは「シグネチャ」が重複しない場合のみ許される。引数が同じで、戻り値の型だけが異なるものは定義できない。
シグネチャ:メソッドにおいては、メソッド名、引数の個数や型とその並び順の情報をまとめたもの(戻り値の型は含まれない)。
第2部 スッキリ納得オブジェクト指向
オブジェクト指向
-
日本語とオブジェクト指向
- 個人的には、上記サイトを一読するだけでオブジェクト指向とはなんぞや?がはっきりするだろう
- オブジェクト指向とは、「ユーザーにオブジェクトを先に選ばせることにより選択の幅を狭くして使いやすくする」こと。
ウィンドウズにおいて、文書ファイルをダブル・クリックすると自動的に「編集する」が選ばれ、音楽ファイルをダブル・クリックすると「演奏する」が選ばれるのは、まさにこの例である。つまり、ウィンドウズ・ユーザーが日々何気なく使っているダブル・クリックには、「私がこのオブジェクトに対してやりたいだろうことを類推して実行してくれ」という意味が含まれているのである。
String
- 文字列は String型のインスタンスとして扱われる。
- String型は、二重引用符で囲うだけで、事実上、String型インスタンスが生成されている点に注意
- 空文字("")はインスタンスがある、nullはインスタンス自体がない。よって、空文字を判定するにはisEmpty()を用いる。
特化と汎化
- ある機能を作りたいと思ったとき、その機能に根源的になくてはならないものを、スーパークラスとして定義する。
- (ex)自動販売機を実装したい時、商品である缶やペットボトルが根源となり、飲食店を実装したい時、料理が根源となるので、それらがスーパークラスになる。
オーバーライド
- オーバーライドは、スーパークラス(親クラス)で定義されたメソッドをサブクラス(子クラス)で再定義すること。これにより、サブクラスでスーパークラスのメソッドの振る舞いを変更できる。
- 以下、基本的な法則。
- メソッド名が同じ。
- 引数の型と数が同じ(シグネチャが同じ)。
- 戻り値の型が同じ。
- オーバーライドするメソッドのアクセス修飾子は同じかより広い。
- スーパークラスのメソッドに付いている例外は、同じかより少ない種類の例外にする。
- より外側のインスタンスに属するメソッドが優先的に動作する
コンストラクタ
- 全てのコンストラクタは、先頭で、親インスタンスのコンストラクタを呼び出す必要がある。
- コンストラクタもメソッドの一つであることを忘れない。
抽象クラス
- 抽象クラスの特徴
- インスタンス化できない:抽象クラスそのものからはオブジェクトを作成できない。
- 抽象メソッドを持つ:抽象クラスは抽象メソッドを持つことができる。抽象メソッドは具体的な実装を持たないメソッドで、サブクラスで必ずオーバーライドしなければならない(オーバーライドの強制)。
- 具体的なメソッドも持てる:抽象クラスは抽象メソッドだけでなく、具体的なメソッドも持つことができる。
- コンストラクタを持てる:抽象クラスもコンストラクタを持つことができるが、サブクラスのコンストラクタから呼び出される。
インターフェイス
- 抽象クラスの抽象クラスと考えていてもよい。
- インタフェースは使用部を決め、抽象クラスはその中の共通処理部分を実装し、具象クラスで個別の処理を記述する。
- Factoryクラスを作る目的は、インスタンスの型の違いをmain関数が意識しなくてもよいプログラムを作成するため。
第3部 もっと便利にAPI活用術
API
- java.langパッケージに属するクラスは自動的にインポートされる
コレクション
- Listは要素の挿入順序を保持し、要素の重複を許可するが、setは順序非保証・重複不可である。
オート(アン)ボクシングとキャスト
- Auto(Un)Boxingは、ラップにくるむことで対象に機能を拡張するイメージ、対象のみが使用できるメソッドを付与する。Castは対象の型そのものを変換する。
例外処理3原則
- 例外は投げたら必ずキャッチする
- キャッチしたうえで再度投げれる
- メインクラスはキャッチ専門。誰にも投げられない。
例外種類3種
-
Error系例外:回復飲み込みがなく、致命的な状況なので、プログラムではどうしようもない。
- OutOfMemoryErrorやClassFormatErrorなど
-
Exception系例外:その発生を十分に想定して対処を考える必要がある状況でtry~catchすべき
- IOExceptionやDataValueExceptionなど
-
RuntimeException系例外:回復が必須ではない状況でtry~catchしなくても良い
- NullPointerExceptionやArrayIndexOutOfBoundsExceptionなど
終わりに
今回の記事では、私が新卒エンジニアとしてJavaを学び始めた際に効果的だった学習方法や、押さえておきたい基礎知識について共有しました。短期間で効率よくJavaの基礎を習得するためには、適切な教材の選択と実践的な経験が重要です。特に、「スッキリわかるJava入門第4版」は、初学者のつまずきやすいポイントをしっかりとカバーしてくれる優れた参考書です。
Javaを学び始めるのは少し敷居が高いと感じるかもしれませんが、今回紹介した方法を参考に、まずは基本的な文法やオブジェクト指向の考え方をしっかりと身につけることから始めてみてください。実際の開発経験を積みながら学習を進めることで、理解がより深まるはずです。
今後も、私が学んだことや新たに発見した効率的な学習方法について共有していきたいと思っています。次回の記事では、さらに進んだJavaの技術や、Webアプリ開発の具体的な手法について解説できればいいなと思っております。皆さんの学習の一助となれば幸いです。