Help us understand the problem. What is going on with this article?

プログラミングド素人のデザイナーがJava入門してみた_その6

More than 3 years have passed since last update.

前回までのあらすじ

プログラミングド素人のデザイナーがJava入門してみた_その5

static修飾子

  • インスタンス化しなくても使えるフィールドやメソッドを登録できる
private static  変数名 = ;
  • staticのついたフィールドやメソッドを、クラス変数クラスメソッドという
  • クラス変数の値はインスタンスではなくクラスに紐づく
    • インスタンス化された数とかを保持できる
  • クラス変数はクラスに紐づくので、アクセスする場合はクラス名.フィールド名とする
Hoge.huga //this.hugaではだめ

インスタンス化された回数を表示してみる

class User{
  private String name;
  //★インスタンス化された回数を保持するstaticフィールド
  private static int count = 0;

  public User(String name){//コンストラクタ
    this.name = name;
    //★クラス内からstaticフィールドにアクセスするときは[クラス名].[フィールド名]とする
    User.count++;//インスタンス化されるたび(正確にはコンストラクタが実行されるたび)+1する
  }

  //★インスタンス化された回数を表示するstaticメソッド
  public static void getInfo(){
    System.out.println(User.count);
  }
}


public class HelloWorld {
  public static void main(String[] args) {

  //staticメソッドなのでインスタンス化せずに使える
  User.getInfo();//0
  User bob = new User("Bob");//インスタンス化
  User.getInfo();//1

  }
}

  • 起点となるmain()staticとなっているのは、javaの仮想マシンがインスタンス化せず直接実行できるようにするため
public class HelloWorld {
  public static void main(String[] args) {//main()もstaticメソッド
    処理  
  }
}

イニシャライザ

  • インスタンスに対するコンストラクタのように、クラスを使う前に実行されるメソッドを定義できる
staticイニシャライザ インスタンスイニシャライザ コンストラクタ
クラス宣言に伴い、最初に1度だけ実行される newされる度、インスタンス化される前に実行される newされる度、インスタンス化された後に実行される
  • 実行順はstaticイニシャライザ→インスタンスイニシャライザ→コンストラクタの順

staticイニシャライザ

  • 主にクラス変数の初期化に使う
static{
  処理
}

インスタンスイニシャライザ

  • コンストラクタがオーバーロードされていて複数あったりする場合(newするときの引数によってコンストラクタの挙動が異なる場合?)共通処理を行ったりする
{//{から初めて処理を記述する
  処理
}

記述例

class User{
  private String name;
  private static int count;

  //staticイニシャライザ
  static { //主にクラス変数の初期化に使う
    User.count = 0;
    System.out.println("staticイニシャライザが実行された");
  }

  //インスタンスイニシャライザ
  {
    System.out.println("インスタンスイニシャライザが実行された");
  }

  public User(String name){//コンストラクタ
    this.name = name;
    System.out.println("コンストラクタが実行された");
  }

}

public class HelloWorld {
  public static void main(String[] args) {

    User bob = new User("Bob");

  }
}

final修飾子

  • クラスやフィールド、メソッドなどの変更を不可にする
クラス フィールド メソッド
継承不可 staticと合わせて定数とする(書き換え不可) オーバーライド不可
  • 修飾子の記述順に決まりはないが、アクセス修飾子→static→finalの順が一般的
final class User{//★finalで継承不可に
  protected String name;
  //staticとfinalを付与して定数とする
  private static final double VERSION = 1.1;//★finalで変更不可に

  public User(String name){//コンストラクタ
    this.name = name;
    User.VERSION = 1.2;//☆VERSIONは変更不可(定数)なのでコンパイルエラー
  }

  public final void sayHi(){//★finalでオーバーライド不可に
    System.out.println("Hi! " + this.name);
  }
}

class AdminUser extends User{//☆Userは継承不可なのでコンパイルエラー
  public AdminUser(String name){//コンストラクタ
    super(name);
  }

  @Override
  public void sayHi(){//☆sahHiはオーバーライド不可なのでコンパイルエラー
    System.out.println("[AdminUser]Hi! " + this.name);
  }
}

public class HelloWorld {
  public static void main(String[] args) {

    User bob = new User("Bob");

  }
}

定数

  • 値の変更ができない変数
  • 宣言時にかならず初期化(値をいれる)
  • 定数名は慣習的にすべて大文字にする
  • finalとあわせてstaticを付与するのは、変更不可であるためインスタンスごとに持たせる意味がなく、クラスで一元管理した方が効率がいいから(?)

抽象クラス

  • 他のクラスに継承されることが前提のクラス
  • これ単体をインスタンス化することは不可
  • 抽象クラスを継承するクラスを具象クラスという
abstract class User{ //★abstractで抽象クラスとして宣言
  //★メソッドの定義だけしておいて、実装は具象クラスに任せる
  //★メソッドにabstractをつけることで、具象クラスでの実装(オーバーライド)を義務付ける
  public abstract void sayHi();//抽象メソッド
}

class JapaneseUser extends User{//具象クラス
  @Override
  public void sayHi(){//抽象クラスで実装を義務付けられたメソッドを実装(オーバーライド)
    System.out.println("こんにちは!");
  }
}

class AmericanUser extends User{//具象クラス
  @Override
  public void sayHi(){//抽象クラスで実装を義務付けられたメソッドを実装(オーバーライド)
    System.out.println("Hi!");
  }
}

public class HelloWorld {
  public static void main(String[] args) {
    JapaneseUser tarou = new JapaneseUser();
    AmericanUser john = new AmericanUser();
    tarou.sayHi();//こんにちは!
    john.sayHi();//Hi!
  }
}

抽象メソッド

  • 抽象クラス内で宣言のみ行い、具象クラスでの実装(オーバーライド)が義務付けられたメソッド

インターフェース

  • クラスを拡張するための追加機能郡(クラスの簡易版みたいなもの?)
  • 継承と異なりいくつでもくっつけることができるので、柔軟な機能追加ができる
  • インターフェースには下記の要素が盛り込める
定数 抽象メソッド defaultメソッド staticメソッド
private,static,finalを省略可 public,abstructを省略可 インターフェース自体に実装するメソッド defaultメソッドが複雑になった場合に処理をまとめたりするヘルパー的存在のメソッド
interface CanSayBye {//★interfaceを付与し、インターフェースとして宣言
  //定数
  double VERSION = 1.1;//private,static,final省略可
  //抽象メソッド
  void sayBye();//public,abstract省略可
  //defaultメソッド
  public default void getInfo(){
    System.out.println("version " + CanSayBye.VERSION);
  }
}

interface CanJump {//★もうひとつインターフェースを定義
  void jump();
}

class User implements CanSayBye,CanJump{//★implementsを付与し、インターフェースをくっつける
  @Override
  public void sayBye(){
    System.out.println("Bye...");
  }
  @Override
  public void jump(){
    System.out.println("JUMP!");
  }
}

public class HelloWorld {
  public static void main(String[] args) {
    User bob = new User();
    bob.sayBye();//bye...
    bob.jump();//JUMP!
  }
}

教科書

ドットインストールさまさま

@iwashi0830はこう思った

  • クラス変数やクラスメソッドがあるなら、変数やメソッド単体で記述するケースはほぼない?
  • イニシャライザの恩恵は、複雑な処理をする必要性がでてくるまで感じられなさそう
  • 定数にstaticを付与する考え方は合理的でおもしろいとおもった
  • わざわざ抽象クラスにする意味がよくわからん...
  • インターフェースはあとから機能を付けたくなった時さくっと使える便利な技?
    • のちのち機能を統合したほうがいい?
iwashi0830
都内のIT企業でデザイナーという名の雑用をしています。 エンジニアの仕事っぷりを見ていて、自分でも動くものを作りたくなってきたこの頃です。
http://sardine-can.site/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away