第1章 Javaクラス設計
- switch文
case文で使用できるデータ型が
・byte
・char
・short
・int
・enum
・String
・Character
・Byte
・Short
・Integer
上記の基本データ型とそのラッパークラス。
と言っても、実際enum、String、char、intくらいしか使わないと思われる。
- 拡張されたリテラル
10進数、8進数、16進数、2進数、アンダースコア(_)が使用可能。
public class Sample {
public static void main(String[] args) {
int v1 = 10; // 10進数
int v2 = 072; // 8進数
int v3 = 0x1a; // 16進数
int v4 = 0b1111; // 2進数
int v5 = 100_000; //可読性を上げるため
}
}
アンダースコアは、リテラルの先頭・末尾・記号の前後は使用できないことを覚えておこう。
- アクセス修飾子とカプセル化
Javaにはアクセス範囲、いわゆるスコープを定めるための修飾子が以下のモノがある。
修飾子 | 適用場所 | 説明 |
---|---|---|
public | クラス、メソッド、変数、コンストラクタ | どのクラスからも使用可能 |
protected | メソッド、変数、コンストラクタ | 同一パッケージ及び、継承したのクラスのみ使用可能 |
デフォルト(指定なし) | クラス、メソッド、変数、コンストラクタ | 同一パッケージからのみ使用可能 |
private | メソッド、変数、コンストラクタ | 同一クラス内のみ使用可能 |
publicにつて
以下の様に一つのファイルにはpublicクラスは一つしか作れない。
public class Sample { // これOK
public static void main(String[] args) {
System.out.println("Sample");
}
}
public class Sample2 { // これはコンパイルエラーになる
public static void main(String[] args) {
System.out.println("Sample2");
}
}
protectedとprivateについて
protectedは、同一パッケージ及び、サブクラスからしか使用できないという制限から、
慣例的に「オーバーライドして欲しいメソッド」に対して付けることが多いらしい。
privateは、カプセル化で使用する事が多いらしい。
カプセル化の目的は、無作法的にフィールドを変更されないようにすることを目的としているらしい。
あとは、どこで値をセットしているか、取得しているのかがわかりやすくなるのは良いかなって思う。
ソースにするとこんな感じかな?
public class Sample {
public static void main(String[] args) {
Cat zakiyama = new Cat();
zakiyama.setName("ザキヤマ");
System.out.println(zakiyama.getName());
}
}
abstract class Animal {
private String Name;
protected abstract String getName();
protected abstract void setName(String newName);
}
class Cat extends Animal {
private String Name;
@Override
protected String getName() {
return this.Name;
}
@Override
protected void setName(String newName) {
this.Name = newName;
}
}
- final修飾子とstatic修飾子
final修飾子は変数、メソッド、クラスに適用できる。
それぞれ適用した時に動きは以下になる。
適用場所 | 説明 |
---|---|
クラス | そのクラスを継承できなくなる |
メソッド | そのメソッドをオーバーライドできなくなる |
変数 | その変数の中身を変更できなくなる(定数化) |
・finalについて
javaの標準クラスの一つで、Stringクラスはfinalクラスである。(JavaDoc参照)
どういうときにfinalをつけるかということ、継承が不要な時につける。
それによって設計崩れを防げるのは大きいね。
本当は継承して拡張するクラスじゃないのに、
継承してしまったら本来もつべき役割の意味がなくなってしまう。
こちらの記事に、finalをつけるメリットなどが書かれているので、結構参考になる。
・staticについて
staticをつけた変数とメソッドはインスタンスとはメモリ領域が異なる。
インスタンス化しなくても、その変数とメソッドを使用することができる。
こんな感じ。
public class Sample {
public static void main(String[] args) {
Animal zakiyama1 = new Animal();
Animal zakiyama2 = new Animal();
zakiyama1.SetName("ザキヤマ1だよ");
System.out.println(zakiyama1.getName());
System.out.println(zakiyama2.getName());
zakiyama2.SetName("ザキヤマ2だよ");
System.out.println(zakiyama1.getName());
System.out.println(zakiyama2.getName());
}
}
class Animal {
private static String Name;
public String getName() {
return Animal.Name;
}
public void SetName(String newName) {
Animal.Name = newName;
}
}
実行結果
ザキヤマ1だよ
ザキヤマ1だよ
ザキヤマ2だよ
ザキヤマ2だよ
static変数は、クラスに対して持つものなので、
インスタンス変数毎に中身を持っていない。
だから、zakiyama1で変数を変更するとzakiyama2で呼び出すときに中身が変更されている。
インスタンス毎に変数の中身が保持されていた場合は、変数は複数のインスタンスから影響を受けない。
インスタンス変数の場合はこんな感じ。
public class Sample {
public static void main(String[] args) {
Animal zakiyama1 = new Animal();
Animal zakiyama2 = new Animal();
zakiyama1.SetName("ザキヤマ1だよ");
System.out.println(zakiyama1.getName());
System.out.println(zakiyama2.getName());
zakiyama2.SetName("ザキヤマ2だよ");
System.out.println(zakiyama1.getName());
System.out.println(zakiyama2.getName());
}
}
class Animal {
private String Name;
public String getName() {
return this.Name;
}
public void SetName(String newName) {
this.Name = newName;
}
}
結果
ザキヤマ1だよ
null
ザキヤマ1だよ
ザキヤマ2だよ
続きはまた。