Java 入門
Chapter1 プログラムの書き方
基本コード
public main Example {
public static void main(String[] args) {
}
}
基本事項
- 拡張子:.java
- コンパイル後:.code
- 文(statement)ごとに ’ ; ’ が必要
- 基本的にキャメルケースで命名定義する
変数型
- byte:1 byte
- short:2 byte
- int:4 byte
- long:8 byte
- float:基本使わない
- double:浮動小数点
- boolean:true or false
- char:1文字(漢字なども可), シングルクォーテーションのみで定義可能
- String:複数文字, ダブルクォーテーションのみ.メソッド length()を持つ
- final:定義範囲で変更がない定数には原則付与すること
Chapter2 式と演算子
オペランドと演算子
- リテラル:具体的な値のこと
- エスケープシーケンス\:特殊記号の出力
- 三連続のダブルクォーテーション”””(テキストブロック):文字列の改行状態をそのまま維持する
- 演算優先度:()>*>+
- キャスト演算子: int age = (int) 3.2;
基本的な命令文
- 標準出力:System.out.println();
- 大小比較:int m = Math.max(a, b);
- 文字列の数値型変換:int n = Integer.parseInt(a);
- 乱数生成:int r = new java.util.Random().nextInt(max_number);
- 文字列の標準入力:String a = new java.util.Scanner(System.in).nextLine();
Chapter3 条件分岐・ループ
if文
if (a == true) {
} else if {
} else {
}
While文
while(a == true) {
}
do {
}
while(a == true);
文字列の論理演算の場合
- str == "こんにちは":←比較演算に失敗の可能性がある
→ str.equals("こんにちは"):←正確 - 演算子and, or :&&, ||
- if (xは10より大きく、20より小さい): if(10 < x && x < 20) {
同一処理の記述:switch文
switch (x) {
case 1 -> {
}
case 2, 3 -> {
}
default -> {
}
}
三項条件演算子
- 変数に対して2つの分岐を1行で記述
String s = age >= 18 ? "成人" : "未成年";
for 文
for (int i = 0; i < 10; i++) {
}
Chapter4 配列
配列の作成
- int型の要素を持つ配列scoresを宣言.要素数を定義して配列を作成
int[] scores;
scores = new int[5];
- 配列はlengthメソッドを持つ
- 配列作成時には,すべての要素が0で初期化される(boolean:false, String:null)
- 初期値を定める場合: new int[] {1, 2, 3, 4, 5};
- for文による値の取り出し方
for (int value : scores) {
System.out.print(value);
}
- 配列は参照型.scoresには配列の先頭要素のアドレスが代入される
- ガベージコレクション
- 配列定義の有効範囲を出たとき,変数は保持されない
- 一方で,"new int[] {1, 2, 3}"など定義した要素はメモリ内に残ってしまうが,Javaでは自動的に排除してくれる
- null:参照型の変数にのみ代入可能.代入することで参照先のアドレスを削除する
- 2次元配列の場合
int [][] scores = new int[2][3];
int [][] scores = new int[][] {{1, 2, 3}, {4, 5, 6}};
Chapter5 メソッド
- 複数行の処理をまとめた部品の最小単位
- 可読性・保守性
定義
public class Main {
public static void main(String[] args) {
hellow("たろう");
{
public static void hello(String name) {
System.out.print("こんにちは!" + name)
}
}
- mainメソッドから開始される
- メソッドの記述順は影響しない
- 戻り値がある場合は、メソッドの型名を適当なものに変更
- 同一名のメソッドはクラス内に1つだが、引数の個数や型が異なる場合は可能(:オーバーロード)
- 引数をまとめて、メソッドのシグネチャと呼ぶ
値渡しと参照渡し
- 配列を引数とするような参照渡しでは、メソッド内での配列操作が元の配列の要素に影響を与える
Chapter6 複数クラスを用いた開発
別クラスのメソッド呼び出し
- クラス名.メソッド名で呼び出す
int a=5; int b=6;
int total = CalcLogic.tasu(a, b);
- javaプログラムの完成品は、複数のクラスファイルの集合体
- 実行は、mainメソッドがあるクラスファイルを用いる
- .jar:javaファイルをまとめるファイル形式
packageによるクラス管理
- ソースコードの先頭で宣言する. パッケージごとに関連性はもたない
- 開発環境におけるソースコードの階層関係と同一のパッケージ名を付けること(後述)
package clacapp.main;
public class Calc{
}
- packageによる管理を行う場合、別クラスの呼び出し方は、クラス名の前にパッケージ名を明記する(:完全限定クラス名, FQCN)
- 明記しない場合は、defaultパッケージとして認識される
int total = calcapp.logics.CalcLogic.tasu(a, b);
- FQCNを省略する場合、import文を用いる
package calclogic.main;
import calcapp.logics.ClacLogic;
~
int total = ClacLogic.tasu(a, b);
- packageを利用した場合、javaコードの実行時のクラス指定は、FQCNでmainメソッドがあるクラス名を指定する必要がある.
- JVMを用いたjavaコードの実行では、クラスパスとして設定したディレクトリ配下で、クラス名を指定して実行される
- さらに、packageで記述した階層構造と、ソースファイルの階層を一致させる必要がある
- JavaAPI reference:https://docs.oracle.com/javase/jp/11/docs/api/index.html
Chapter7 オブジェクト指向
- 処理そのものの構造に着目し、個々の部品をオブジェクトとして作成する
- オブジェクト:データと処理をひとまとめにするまとめ方
- オブジェクト同士のやり取りによって結果が得られる
Chapter8 インスタンスとクラス
- インスタンス:クラスによって定義した動作を実態として持つモノ
- 各インスタンスへの実行命令はmainメソッドで記述される. Mainクラスなどを用意して、ファイルを分けることが推奨
- UML クラス図:オブジェクトが持つ属性・操作を図で可視化する
クラスの定義
- クラス内には属性'(field)と操作(method)を記述する
- クラスの属性として定義した変数を指定する場合、"this."を用いる
public class Hero {
// 属性
String name;
int hp;
// 操作
pubilc void sleep() {
this.hp = 100;
System.out.print(this.name + "は眠って回復した")
}
}
- 定義したクラスを基に、クラス型変数としてインスタンスが作成される. (←同一オブジェクトの識別が可能になる)
public class Main{
public static void main(String[] args){
// インスタンスを生成
Hero momo = new Hero();
momo.name = "太郎";
momo.hp = 100;
momo.sleep();
}
}
Chapter9 クラス機構
- クラス型も参照型. 変数momoには、インスタンスHeroのアドレスが渡されている
Hero momo = new Hero(); - 属性にクラス型を定義することや、メソッド引数・戻り値に定義することもできる
public class Sword {
String name;
int damage;
}
public class Wizard {
String name;
int hp;
Sword sword;
public void heal(Hero h) {
h.hp += 10;
}
}
コンストラクタ
- インスタンス作成時に行われる、属性の初期化を記述する
- 記述形式
- メソッド名がクラス名と完全に等しい
- メソッド宣言に戻り値の型が記述されていない. voidも記述しない
- インスタンス作成時に、属性の初期値を引数として与えられる
- 引数の違いによる処理を変更するために、同名のコンストラクタの定義が可能(オーバーロード)
- 別コンストラクタをコンストラクタで呼び出すには this(引数);
public class Hero() {
String name;
int hp;
// コンストラクタ
public Hero(String name) {
this.hp = 100;
this.name = name;
}
// オーバーロードして、Hero(String name)を利用
public Hero() {
this("ダミー")
}
public void attack(Monster m) {
}
}
Chapter10 11 継承
- Heroクラスを継承するSuperHeroクラス
- Heroクラスと同じメンバの定義を省略. Heroクラス(スーパークラス)で定義したフィールドやメソッドは利用可能
- 複数のスーパクラスを継承する多重継承は禁止
- 継承したメソッドを再定義可能(オーバーライド). フィールドは同名で宣言しないこと.
- 定義したクラスの継承を禁止する場合、finalをつけてクラス宣言する
public class SuperHero extends Hero {
boolean flying;
public void flying() {
~
}
public void attack(Monster m) {
System.out.println("スーパー攻撃");
}
}
インスタンスの構造
- 子クラスで再定義されたメソッドは、親クラスよりも優先される
- スーパクラスで定義したメソッドを子クラスで呼び出す
- 子クラスは自身の直接のスーパクラスのみを呼出し可能(super.)
public class SperHero extends Hero {
public void attack(Monster m) {
super.attack(m); // スーパクラスのメソッド利用
if (this.flying) {
super.attack(m);
}
}
}
継承とコンストラクタ
- コンストラクタでは、必ずスーパクラスのコンストラクタが先に呼び出される
- スーパクラスのコンストラクタにおいて、引数が必要な場合は super()に引数を明示する
public class SuperHero extends Hero {
public SuperHero() {
super(); // 明示されなくとも、先にスーパクラスのコンストラクタが呼ばれる
System.out.println("SuperHeroクラス");
}
}
継承のルール
- 正しい継承関係:子クラス is a スーパクラス
- スーパクラス→子クラス:特化
- 子クラス→スーパクラス:汎化
抽象クラスとインターフェイス
抽象クラスをつくる上での留意点
- 実体を持つクラスをつくる前に、必要なフィールド・メソッドを定義するのは難しい
- オーバライド忘れや、記述ミスに対して、エラーであることを明示的に理解できるべき
- クラス定義の利用方法は大きく2つあり、使い方は指定されていない
- インスタンス(実体)を生み出す
- 継承元としてスーパクラスを定義する
抽象クラスにおける対処法
- 詳細未定のメソッドの宣言:abstract
public abstract void attack(Monster m);
- 抽象クラスであることの宣言:abstract → インスタンス化に利用不可
public abstract class Charactor {
String name;
public abstract void attack(Monster m);
}
- 抽象クラスが継承されたとき、abstract で宣言されたメソッドがある場合、子クラスで記述(オーバライド)しなければエラーが出る(:実装)
インターフェイス
- 抽象クラスの中の抽象クラス
- 定義条件
- すべてのメソッドが抽象メソッド(default宣言した抽象メソッドは可)
- フィールドを1つも持たない(定数のみ可 "public static final" )
public abstract class Creature {
public abstract void run();
}
↓
public interface Creature {
double PI = 3.14;
void run();
}
- interfaceを継承したクラスの定義 implements
- 実装することになったとき、抽象メソッドをすべて定義しなければならない
public class Monster implements Creature {
public void run() { // 抽象メソッドをオーバライドする
~
}
}
- 複数のinterfaceとして定義された抽象クラスは、多重継承して利用可能
- interfaceを継承してinterfaceを定義する場合は、extends
public class PrincessHero implements Hero, Princess, Charactor {
}
Chapter 12 多態性・ポリモーフィズム
多態性
- 物事をざっくりと捉えて定義する
- インスタンスを作成するとき、代入する変数の型によってとらえ方が変化する
- スーパクラス・抽象クラス・インターフェイスの型でインスタンスを作成可能(is a関係)
SuperHero h = new SuperHero();
Character c = new SuperHero();
利用時の挙動
-
変数定義の型(Character):どのメソッドを実行可能かを決定する
- 親クラス側からは、親クラスで定義したメソッドが継承されていることはわかるが、子クラスの独自のメソッドは把握できない
-
インスタンスの型(SuperHero):呼ばれたメソッドで、何を実行するかを決定する
- また、継承されているメソッドを実行したときには、子クラスで定義したメソッド内容が実行される
-
もし、継承ではないSuperHero独自のメソッドを利用したい場合(:ダウンキャスト)
-
キャスト可能かを確認して実行するには、"instanceof"
Character c = new SuperHero();
SuperHero h = (SuperHero) c;
利点
- ざっくりと同じカテゴリに属するクラスから生成されるインスタンスをまとめられる
- 同一種類として配列で扱うことが可能
public class Main { public staic void main(String[] args) { Character[] c = new Character[5]; c[0] = new Hero(); c[1] = new Thief(); c[2] = new Wizard(); // 一括で回復処理がかける for (Character ch : c) { ch.hp += 50 } } }
- 呼び出し側はインスタンスを同一視して呼び出すが、実行されるメソッドは個々のインスタンスに基づいて動作する
Chapter13 カプセル化
- フィールドへの読み書き、メソッドの呼び出しを制限する機能
フィールド・メソッドに対する4つのアクセスレベル(アクセス就職子)
-
private(pricate):定義したクラスのみ
-
package private(なし):同じpackageに属するクラスのみ
-
protected(protected):同じpackageもしくは、自身を継承した子クラスのみ
-
public(public):すべてのクラス
-
基本的に、フィールドはprivate. メソッドはpublic
-
privateのフィールドには他クラスは直接操作できないが、メソッドを経由して更新することはできる
public class Hero {
private String name;
// 直接nameにはアクセスさせないが、nameを取得できるようメソッドを定義する(:ゲッター)
public String getName() {
return this.name;
}
// 値設定用のメソッド(:セッター)
public String setName(String n) {
this.name = n;
}
}
public class King {
void talk(Hero h) {
System.out.println(h.getName() + "よ");
System.out.println("今日からお前は" + h.setName("ヨシヒコ").getName());
}
}
- ゲッター・セッターのメリット
- 変数に対するRead only, Write onlyの設定が可能
- 定義しているクラスの内部設計は自由に変更可能
- セッターに対して、入力値ごとの動作確認が可能
クラスに対するアクセス制御(2種類)
-
package private(なし):同じpackageクラスのみ
-
public(public)すべてのクラス
-
非publicクラスについて
- クラス名はソースファイル名と異なってよい
- 1つのソースファイルに複数の非publicクラスを宣言してもよい
Appendix Java API➀
java.lang.Object
- 継承を定義しないクラスは、すべてObjectクラスを暗黙的に継承している。
- メリットの1つとして、最低限のメソッドが定義されていること
- toString()をオーバーライドして、文字列表現を定義できる
- 等価の判定equals の判定基準を定義できる
静的メンバ static
-
インスタンスの独立性の原則によらず、各インスタンス間で共有したい情報を定義する
-
静的フィールド
- 個々のインスタンスごとに変数を持つのではなく、クラス単位で値を保持する。(クラス共有の変数)
- インスタンスを生成していない状態でも、代入・呼び出しが可能
- 定数を共有するための利用
public static final double RATE = 1.413;
-
静的メソッド
- メソッドはクラス名で呼び出せる
- インスタンス変数からも呼び出せる
- インスタンスを生成していない状態でも、呼び出せる
- 静的メンバでないフィールド・メソッドを利用できない
public static void setRandomMoney() { ~ }
-
メリット
- インスタンス生成せずに、メソッドを呼び出せる
文字列の処理
- 内容の等価:equals(Object o)
- 大小文字を区別せずに、内容の等価:equalsIgnoreCase(String s)
- 空文字か:isEmpty()
- 1部に文字列sを含むか:contains(String s)
- 文字列sで始まるか:starsWith(String s)
- 前後の空白を除去する:trim()
- 文字の置換:replace(Strinf before, String after)
StringBuilder:文字列の連結
- メモリ領域を利用し、可変なクラスとして文字列を保持する
public cals Main { public staic void main (String[] args) { String Builder sb = new StringBuilder(); for (int i = 0; i < 100; i++) { sb.append("Java"); } String s = sb.toString(); } }
Appendix Java API➀
正規表現
- パターンマッチング:正規表現による文字列の形式判定
name.match("[A-Z][A-Z0-9]{7}");
- . : 任意の一文字
- :直前文字の0回以上の繰り返し(AB →A, AB, ABBBBB)
- ?:直前文字の0もしくは1回の繰り返し
- ^:文字列の先頭
- $:文字列の末尾
文字列の処理
- split("[,:]"):,か:で分割
- replaceALL("[abc]", "X"):a, b, cのいずれかに当てはまる場合に"X"に変換
日時・時刻
- long型:ミリ秒で表現(基準日時 1970/1/1/0:00:00)
- Date型:java.util.Dateクラス。インスタンス生成で利用
現在時刻:new Date(); - Calendar型
public class Main {
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
c.set(2023, 1, 1, 12, 00, 00); // 値を設定
c.set(Calendar.MONTH, 9);
Date d = c.getTime(); // 時刻を取得
}
}
-
SimpleDateFormat:書式指定した形で表示
SimpleDateFormat f = new SimleDateFormat("yyyy/MM/dd HH:mm:ss"); -
java.time:メジャーな日時関連のクラス
Appendix ②
コレクション
- インスタンスしか格納できない
- intなどのデータ型を保持するには、データを保管するためのラッパークラスを利用する
- java.lang.Integerクラス
- オートボクシング
ArrayList 配列
-
ArrayList<String> names = new ArrayList<String>();
- add:最後尾に格納
- set(int a):位置aの要素を上書き
- get(int a):位置aの要素を取得
- remove(int a):除去
-
イテレータ Iterator
- hasNext(), next()の二つのメソッドを持つ
public class Main {
public staic void main(String[] args) {
ArrayList<String> names = new ArrayList<String>();
names.add("aa");
Iterator<String> it = names.iterator();
While (it.hasNext()) {
String e = it.next();
System.out.println(e);
}
}
}
- LinkedList:連結リスト
java.util.HashSetクラス
- 重複なし、順序なしの集合データ
HashMap
- key, valueのペアデータ構造
Map<String, Integer> prefs = new HashMap<String, Integer>();
prefs.put("京都", 255);
int kyoto = prefs.get("京都");
// 取り出し方
for (String key : prefs.keySet()) {
int value = prefs.get(key);
}
Appendix③
例外処理
3種類のエラーと対処法
-
文法エラー(記述ミス)→コンパイラの指摘を解決する
-
実行時エラー(想定外の動作、0割り算)→エラーに対する回避策を用意しておく
-
論理エラー(想定と異なる結果の出力)→コード修正
-
基本的な例外処理方法
FileWriter fw = null; // コード全体のスコープで利用
try {
// 実行したい処理
fw = new FileWriter("data.text");
fw.writer("hello");
} catch(IOException | NullPointerException e) {
// 例外時の処理
System.out.println("error" + e.get.Message());
} finally {
// 例外時・正常時問わずに実行される処理
if (fw != null) {
try {
fw.close();
} catch (IOException e){
;
}
}
-
javaでは、Exception系の例外が発生しそうな処理を行うとき、try-catch文を記述しなければ、コンパイルエラーが生じる(チェック例外)
-
呼び出すメソッド・APIにおいて、発生しうる例外はリファレンスにある
- すべての例外は、getMessage()とprintStackTrace()をもつ
-
例外が発生する可能性があるメソッドについて、呼び出し元側で例外処理を行うことを宣言できる(throw宣言)
public static void sub() throw IOException {
FileWriter fw = new FileWriter("data.txt");
}
// 基本構造: クラスの定義
public class BasicJavaExample {
// mainメソッド(プログラムの入口)
public static void main(String[] args) {
System.out.println("Hello Java!");
// 変数とデータ型
int number = 10;
double decimal = 5.5;
String text = "Java";
boolean flag = true;
System.out.println("Number: " + number);
System.out.println("Decimal: " + decimal);
System.out.println("Text: " + text);
System.out.println("Boolean: " + flag);
// 演算子
int sum = number + 5;
System.out.println("Sum: " + sum);
// if文(条件分岐)
if (number > 5) {
System.out.println("numberは5より大きい");
} else {
System.out.println("numberは5以下");
}
// for文(繰り返し)
for (int i = 0; i < 3; i++) {
System.out.println("forループ: " + i);
}
// while文(繰り返し)
int count = 0;
while (count < 2) {
System.out.println("whileループ: " + count);
count++;
}
// 配列
int[] numbers = {1, 2, 3};
for (int num : numbers) {
System.out.println("配列要素: " + num);
}
// メソッドの呼び出し
greet("Alice");
// オブジェクト指向の基本
Person person = new Person("Bob", 25);
person.introduce();
// 継承の例
Student student = new Student("Charlie", 20, "Math");
student.introduce();
// 例外処理の例
try {
int result = divide(10, 0);
System.out.println("割り算の結果: " + result);
} catch (ArithmeticException e) {
System.out.println("エラーが発生しました: " + e.getMessage());
}
}
// メソッドの定義
public static void greet(String name) {
System.out.println("Hello, " + name);
}
public static int divide(int a, int b) {
return a / b;
}
}
// クラスの定義(オブジェクト指向の基本)
class Person {
String name;
int age;
// コンストラクタ
Person(String name, int age) {
this.name = name;
this.age = age;
}
void introduce() {
System.out.println("私は " + name + " です。年齢は " + age + " 歳です。");
}
}
// 継承の例(StudentはPersonを継承)
class Student extends Person {
String major;
Student(String name, int age, String major) {
super(name, age); // 親クラスのコンストラクタを呼ぶ
this.major = major;
}
// メソッドのオーバーライド
@Override
void introduce() {
System.out.println("私は学生の " + name + " です。専攻は " + major + " です。年齢は " + age + " 歳です。");
}
}