【Java学習】09 参照型の型変換 [Java SE 11 Silver 紫本]

スーパークラス型の変数にサブクラスのオブジェクトを代入すると、インスタンスメンバはスーパークラス、インスタンスメソッドはstatic修飾子を付けない限りサブクラスのメンバが呼び出されます。

Amazonのブラックフライデーセールが明日までなので、Goldの紫本も購入しました。来年1月末までにSilver本とGold本を読破したいです。

前にも書きましたがオラクルの検定は受けません。苦痛でしかない練習問題を解く代わりにサンプルコードをいじって色々動作検証しています。その方が楽しいですし、スキルが身に付きやすいと思います。

class Super {
  String x = "Super : x";
  String y = "Super : y";
  void methodA() { System.out.println("Super : methodA()"); }
  static void methodB() { System.out.println("Super : methodB()"); }
}
class Sub extends Super {
  String x = "Sub : x";
  String y = "Sub : y";
  void methodA() { System.out.println("Sub : methodA()"); }
  static void methodB() { System.out.println("Sub : methodB()"); }
}
public class Main2 {
  public static void main(String[] args) {
    Super obj = new Sub();
    System.out.println(obj.x);
    System.out.println(obj.y);
    obj.methodA();
    obj.methodB();
  }
}
--------------------------------------------------
出力
--------------------------------------------------
Super : x
Super : y
Sub : methodA()
Super : methodB()

【Java学習】08 interface [Java SE 11 Silver 紫本]

これまでいくつかJavaコードを書いてきましたが、interfaceは全くの初見でした。

本にはサンプルコードがなかったのでネットから適当に探してきました。

下記サンプルコードではinterfaceを使うメリットがよく分かりません。interfaceを使わない方がスッキリ書けます。開発者が初期値をinterfaceで設定しプログラマがそれに従ってコードを作成するというイメージで覚えることにしました。

以下2つのコードの内容は同じ
--------------------------------------------------
interface Calc {
    int NUM1 = 10;
    int NUM2 = 50;
 
    void calc();
}

class Add implements Calc {
    public void calc() {
        System.out.println(NUM1 + NUM2);
    }
}
 
class Sub implements Calc {
    public void calc() {
        System.out.println(NUM1 - NUM2);
    }
}
 
public class Main {
    public static void main(String[] args) {
        Add add = new Add();
        add.calc();
 
        Sub sub = new Sub();
        sub.calc();
    }
}
--------------------------------------------------
class Calc {
    int NUM1 = 10;
    int NUM2 = 50;
    public void add() {
        System.out.println(NUM1 + NUM2);
    }
    public void sub() {
        System.out.println(NUM1 - NUM2);
    }
}
 
public class Main {
    public static void main(String[] args) {
        Calc cal = new Calc();
        cal.add();
        cal.sub();
    }
}
--------------------------------------------------
出力
--------------------------------------------------
60
-40

【Java学習】07 抽象クラス abstract [Java SE 11 Silver 紫本]

abstractの役割が今一つピンときませんでしたが、具象クラスであるサブクラスを作成する際にオーバーライドを強制する、つまり開発者が設定した抽象クラスをプログラマがサブクラス作成時に必ず記述しなければならない、という説明で理解できました。

全てではないでしょうが開発者の意図通りにコーディングさせる手段の一つという解釈でそんなに外していない様です。

abstract class X {                // 抽象クラス
  protected abstract void methodA();     
}
abstract class Y extends X { }    // 抽象クラス
class Z extends Y {               // 具象クラス
  protected void methodA() { }    // 具象クラスではオーバーライドは必須
}

【Java学習】06 thisとsuper [Java SE 11 Silver 紫本]

サブクラス実行の際はsuperクラスのコンストラクタはかならず実行されますが、特に明示しない限り引数なしのコンストラクタが呼び出されます。

以下のコードは動作確認のためだけに作成されたものです。意味は分かりますが実用に寄与しない内容でもやもやします。

class SuperA {
  public SuperA() { System.out.println("SuperA()"); }
  public SuperA(int a) { System.out.println("SuperA(int a)"); }
}
class SubA extends SuperA {
  public SubA() { System.out.println("SubA()"); }
  public SubA(int a) { 
    super(a); // 引数付きコンストラクタを呼び出すのに必要な記述
    System.out.println("SubA(int a)"); }
}
public class Main {
  public static void main(String[] args) {
    SubA obj1 = new SubA();
    SubA obj2 = new SubA(10);
  }
}
--------------------------------------------------

出力
--------------------------------------------------
SuperA()
SubA()
SuperA(int a)
SubA(int a)

【Java学習】05 Overrideアノテーション [Java SE 11 Silver 紫本]

サブクラスにおいて同じメソッド名で異なる機能にする場合はオーバーライドのルールに従います。`@Overrideを記述するとメソッド名が違っていないかチェックしてくれます。

オーバーライドを多用するとロクなことにならない様な気がするのですが、大規模開発では必要な機能なのでしょうか。

class SuperA { 
  public void print(String s) {
    System.out.println("SuperA print : " + s);
  }
  public void method() { }
}
class SubA extends SuperA { 
  @Override
  public void Print(String s) { // printがPrintになっているのでコンパイルエラーになります
    s = "渡された文字列は " + s + " です";
    System.out.println("SubA print   : " + s);
  }
}
public class Main {
  public static void main(String[] args) {
    SuperA obj1 = new SuperA();
    obj1.print("Java");
    SubA obj2 = new SubA();
    obj2.print("Java");
  }
}
--------------------------------------------------

出力
--------------------------------------------------
Main.java:8: エラー: メソッドはスーパータイプのメソッドをオーバーライドまたは実装しません

【Java学習】04 継承 [Java SE 11 Silver 紫本]

extendsがないクラスは全てjava.lang.Objectクラスのサブクラスです。

以下のコードではObjectクラスのメソッドを使っています。

class Member extends Object{
  private String id = "1000";
  public String getId() {
    return id;
  }
}
class Sales extends Member {
  private String clientName = "ABC";
  public String getClientName() {
    return clientName;
  }
}
public class Main {
  public static void main(String[] args) {
    Sales s = new Sales();
    System.out.println("clientName : " + s.getClientName());
    System.out.println("id         : " + s.getId());
    System.out.println("String : " + s.toString()); // ObjectクラスのtoStringメソッド
    System.out.println("hashCode : " + s.hashCode()); // ObjectクラスのhashCodeメソッド
  }
}
--------------------------------------------------

出力
--------------------------------------------------
clientName : ABC
id         : 1000
String : Sales@6b95977
hashCode : 112810359

【Java学習】03 コンストラクタのオーバーロード [Java SE 11 Silver 紫本]

コンストラクタの引数の構成を変えると同じコンストラクタ名を使えます。これをオーバーロードと呼びます。メソッドもオーバーロード可です。

以下のコードには特に意味はありません。単にコンパイルエラーの有無を検証しただけです。

class Employee {
  int id; String name;
  Employee() { System.out.println("Employee()エラーなし"); }
  Employee(String name) { System.out.println("Employee(String name)エラーなし"); }
  Employee(int id) { System.out.println("Employee(int id)エラーなし"); }
  Employee(int id, String name) { 
    System.out.println("Employee(int id, String name)エラーなし"); }
  Employee(int id, String country) { 
      System.out.println("Employee(int id, String country)エラーなし"); }
}
public class Main {
  public static void main(String[] args) {
    Employee a = new Employee();
    Employee b = new Employee("sato");
    Employee c = new Employee(100);
    Employee d = new Employee(100, "sato");
  }
}
--------------------------------------------------

出力
--------------------------------------------------
Main.java:8: エラー: コンストラクタ Employee(int,String)はすでにクラス Employeeで定義されています
  Employee(int id, String country) { 

【Java学習】02 For文 [Java SE 11 Silver 紫本]

Java SE 11 Silver 紫本はChapterを読み終えたら章末の練習問題を解いていましたが、敢えてとは言えども不完全なコードを読まされるのはかなり苦痛です。

そもそも実行して出力させれば分かることですし、実務で遭遇しない限り自力でデバッグしようとは思わないです。

Java SilverやGoldを受けることは絶対にないと確信させられた章でした。まあ一応最後まで読みますが練習問題には一切手を付けません。

下記のコードなんかを読まされたときの徒労感は半端ではありません。不具合の内容もそうですが、コード自体が不毛すぎます。こんなの読んでたら感性がおかしくなります。

public class Main {
  public static void main(String[] args) {
    int[] ary = {10, 20, 30, 40, 50};
    int i = 5;
    for(int a : ary){
      while(i < ary.length){
        i++;
        System.out.print(i + " ");
      }
    }
  }
}
--------------------------------------------------
最初のループですでにiが配列の要素数5未満ではないので出力はなし

【Java学習】01 StringとStringBuilder [Java SE 11 Silver 紫本]

Java SE 11 Silver 紫本のChapter3まで読了しました。よく出来た本ですが紙幅が限られているためか総じて説明が足りないです。

例えばこの方法ではこれができないので別の方法になります、という説明に終始しています。いや一工夫したら別の方法じゃなくてもできるでしょというケースもあるのですが、説明が先に進まないので仕方ない面はあります。せめて注釈でその一工夫に言及してほしかったです。

StringとStringBuilderの違いについては、Pythonの”sortedとsort”と同様に可逆的、不可逆的(あるいは非破壊的、破壊的)の対比と考えれば理解しやすいです。

最後まで読み通して理解し修得できたら、取りあえずJava初心者を脱してJava初級者を名乗れるでしょうか。

public class Main {
  public static void main(String[] args) {
    String str = new String("Hello");
    StringBuilder sb = new StringBuilder("Hello");
    String str2 = str.concat(" dear"); // 可逆的変更なので新たに変数設定して戻り値を捕捉する。
    sb.append(" dear"); // 不可逆的変更なので新変数の設定不要
    System.out.println("str: " + str + ", str2: " + str2 + ", sb: " + sb);
  }
}
--------------------------------------------------

出力
--------------------------------------------------
str: Hello, str2: Hello dear, sb: Hello dear