0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Java入門】第8章 クラスとオブジェクト

0
Last updated at Posted at 2026-10-31

第7章までは、社員の名前と年齢を別々の変数や配列に入れていました。この章では、「社員」という1つのまとまりを表す クラス を自分で定義し、そこから社員1人1人の オブジェクト を作って使います。Java のプログラムの中心になる考え方です。

この章で学ぶこと

  • クラスの定義とフィールド
  • new でオブジェクトを作り、. でフィールドやメソッドを使う
  • static の付かないメソッド
  • コンストラクタと this
  • 変数に入っているのはオブジェクトの「参照」であること
  • null と NullPointerException

8.1 この章で作るもの

この章では、ch08 パッケージに、社員を表すクラス Employee と、それを使うクラス Main を作ります。章の最後には、Main を実行するとコンソールに次のように表示されるようになります。

コンソール
雷禅 海皇(26歳)
院照 心愛(27歳)
雷禅 海皇(27歳)
e1 と e3 は同じオブジェクトか:true
e1 と e2 は同じオブジェクトか:false
ファイル 作業 内容
ch08/Employee.java 新規 社員を表すクラス(main なし)
ch08/Main.java 新規 Employee を使うクラス(main あり)

8.2 クラスを定義する

【便利な使い方】補完で入力する

補完を使っていますか? この章からは、自分で作ったクラスを使います。名前の一部を入力して Ctrl + Space キーを押すと、続きの候補が表示されます。自分で作ったクラスの名前や、そのクラスのフィールド・メソッドも補完できるので、打ち間違いが減り、入力も速くなります。

入力して Ctrl + Space 入るもの
Emp Employee(この章で作るクラス)。↑ ↓ キーで選んで Enter キー
e1. name、age、print() など、e1 で使えるフィールドやメソッドの候補
sysout System.out.println();

くわしくは、第3章の「補完で入力する」で説明しています。

  1. src を右クリックし、新規 → パッケージ で ch08 パッケージを作ります。

  2. ch08 パッケージを右クリックし、新規 → クラス で、名前 Employee と入力し、「public static void main(String[] args)」の チェックを入れずに クラスを作ります。

  3. 緑の行を入力します。

    ch08/Employee.java
    package ch08;
    
    /** 社員を表す */
    public class Employee {
    
        String name;
        int age;
    
        /** 一覧に表示するために、名前と年齢を1行にして表示する */
        void print() {
            System.out.println(name + "(" + age + "歳)");
        }
    
    }
    
  4. 保存します。

  5. もう一度 ch08 パッケージを右クリックし、新規 → クラス で、名前 Main、「public static void main(String[] args)」に チェックを入れて クラスを作ります。

  6. // TODO の行を消し、緑の行を入力します。

    ch08/Main.java
    package ch08;
    
    public class Main {
    
        public static void main(String[] args) {
            Employee e1 = new Employee();
            e1.name = "雷禅 海皇";
            e1.age = 26;
            Employee e2 = new Employee();
            e2.name = "院照 心愛";
            e2.age = 27;
            e1.print();
            e2.print();
        }
    
    }
    
  7. 保存して、Main.java を実行します。

    コンソール
    雷禅 海皇(26歳)
    院照 心愛(27歳)
    

8.3 クラスとオブジェクト

Employee クラスは、「社員は名前(name)と年齢(age)を持ち、表示する処理(print)ができる」ということを定義しています。クラスは、どんなデータと処理を持つかを決めたもの で、クラスを定義しただけでは、社員は1人もいません。

new Employee() と書くと、Employee クラスの定義どおりのデータの入れ物が、メモリの上に1つ作られます。これを オブジェクト(またはインスタンス)といいます。Main では、new を2回書いたので、オブジェクトが2つ作られ、e1 と e2 という変数に入りました。2つのオブジェクトは、それぞれ別の name と age を持っています。

Employee クラスの定義(name、age、print)から、new で2つのオブジェクトが作られている。e1 のオブジェクトは name が雷禅 海皇、age が 26。e2 のオブジェクトは name が院照 心愛、age が 27
図8-1 1つのクラスから、複数のオブジェクトを作る

コード 意味
Employee e1 = new Employee(); Employee のオブジェクトを新しく作り、Employee 型の変数 e1 に入れる。クラス名は、そのまま型の名前になる
e1.name = "雷禅 海皇"; e1 のオブジェクトの name に値を入れる。. は「〜の」
e1.print(); e1 のオブジェクトの print メソッドを呼ぶ。e1 の name と age が表示される

第4章で学んだ String も、こうしたクラスの1つです。"雷禅 海皇" と書くと String のオブジェクトが作られ、name.length() はそのオブジェクトのメソッドを呼んでいます。

8.4 フィールドとメソッド

フィールド

クラスの { } の直下(メソッドの外)に宣言した変数を フィールド といいます。name と age がフィールドです。

  • フィールドはオブジェクトごとに持つ。e1.age と e2.age は別の値
  • フィールドは、そのクラスのどのメソッドからも使える(print メソッドの中で、引数で受け取っていない name・age を使えている)
  • 値を入れていないフィールドには、型ごとの初期値が入っている。int は 0、boolean は false、String などのクラスの型は null

static の付かないメソッド

print メソッドには static を付けていません。static の付かないメソッドは、e1.print() のように オブジェクトに対して呼び出し、そのオブジェクトのフィールドを使って動きます。第7章の static なメソッドは、AgeChecker.isValid(age) のようにクラスに対して呼び出し、オブジェクトを作らなくても使えるものでした。

クラスの中で「そのオブジェクト自身のデータ」を使う処理は、static を付けずに書きます。この教材でこの後に作るメソッドは、Main クラスの中のもの以外は static を付けません。

【ご注意】main メソッドからフィールドを直接使えない

Employee クラスに main メソッドを書いて、その中で name と書くと、「非 static フィールド name を static 参照できません」というエラーになります。main は static なので、どのオブジェクトの name なのかが決まらないためです。new でオブジェクトを作り、e1.name のようにオブジェクトを指定して使います。

8.5 コンストラクタと this

new Employee() でオブジェクトを作ってから、name と age を1つずつ入れるのは手間です。オブジェクトを作るときに、同時に値を入れられるようにする仕組みが コンストラクタ です。

  1. Employee.java に、緑の行を書き足します。

    ch08/Employee.java
    package ch08;
    
    /** 社員を表す */
    public class Employee {
    
        String name;
        int age;
    
        /** 名前と年齢を決めて社員を作る
         * @param name 名前
         * @param age 年齢 */
        Employee(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        /** 一覧に表示するために、名前と年齢を1行にして表示する */
        void print() {
            System.out.println(name + "(" + age + "歳)");
        }
    
    }
    
  2. 保存します。Main.java の new Employee() の行に赤い「×」が付きます。「コンストラクター Employee() は未定義です」という意味です(理由は後で説明します)。

  3. Main.java の main メソッドを、緑の行のように書き換えます。

    ch08/Main.java
    package ch08;
    
    public class Main {
    
        public static void main(String[] args) {
            Employee e1 = new Employee("雷禅 海皇", 26);
            Employee e2 = new Employee("院照 心愛", 27);
            e1.print();
            e2.print();
        }
    
    }
    
  4. 保存して実行します。表示は前と同じです。

    コンソール
    雷禅 海皇(26歳)
    院照 心愛(27歳)
    

コンストラクタの形

コンストラクタは、クラス名と同じ名前 で、戻り値の型を書かない メソッドのようなものです。new Employee("雷禅 海皇", 26) と書くと、オブジェクトが作られた直後にコンストラクタが呼ばれ、引数の値がフィールドに入ります。

書き方
クラス名(引数) {
    フィールドに値を入れる処理
}

this

コンストラクタの引数の名前(name)と、フィールドの名前(name)が同じなので、コンストラクタの中で name と書くと引数のほうを指します。フィールドのほうを指すには、this.name と書きます。this は、「このオブジェクト自身」という意味です。this.name = name; は、「このオブジェクトのフィールド name に、引数の name を入れる」と読みます。

引数の無いコンストラクタ

コンストラクタを1つも書いていないクラスには、引数の無いコンストラクタ(Employee())が自動で用意されます。8.2 で new Employee() と書けたのはこのためです。コンストラクタを1つでも書くと、自動の用意はされなくなるので、new Employee() はエラーになりました。

【知識メモ】Spring入門のクラスにはコンストラクタを書かない

Spring入門で作る社員のクラス(Entity)は、コンストラクタを書きません。自動で用意される引数の無いコンストラクタで new Employee() と作り、値は1つずつメソッドで入れます(第9章の setter)。Spring のような仕組みの多くは、引数の無いコンストラクタでオブジェクトを作る決まりになっているためです。この教材では、第14章でも Spring入門と同じ作りにします。

8.6 参照

Employee e1 = new Employee(…); を実行すると、変数 e1 にはオブジェクトそのものではなく、そのオブジェクトを指す 参照 が入ります。一部の書籍や記事で説明している、参照がメモリ上の番地(アドレス)であるとは、Java の仕様では決められていません(Java 仮想マシン仕様 2.7「Representation of Objects」、英語)。参照の中身をプログラムから見たり、数として計算したりすることもできません。

変数に入っているのがオブジェクトではなく参照であることは、変数を別の変数に代入したときの動きを見るとよく分かります。

  1. Main.java の main メソッドに、緑の行を書き足します。

    ch08/Main.java
    package ch08;
    
    public class Main {
    
        public static void main(String[] args) {
            Employee e1 = new Employee("雷禅 海皇", 26);
            Employee e2 = new Employee("院照 心愛", 27);
            e1.print();
            e2.print();
    
            Employee e3 = e1;
            e3.age = 27;
            e1.print();
            System.out.println("e1 と e3 は同じオブジェクトか:" + (e1 == e3));
            System.out.println("e1 と e2 は同じオブジェクトか:" + (e1 == e2));
        }
    
    }
    
  2. 保存して実行します。

    コンソール
    雷禅 海皇(26歳)
    院照 心愛(27歳)
    雷禅 海皇(27歳)
    e1 と e3 は同じオブジェクトか:true
    e1 と e2 は同じオブジェクトか:false
    

e3.age = 27; と書いただけなのに、e1.print() の表示が 27 歳に変わりました。Employee e3 = e1; は、オブジェクトを複製したのではなく、同じオブジェクトの参照を e3 にも入れた からです。e1 と e3 は同じ1つのオブジェクトを指しているので、e1 == e3 は true です。

変数 e1 と e3 は同じオブジェクト(雷禅 海皇、27)を指している。変数 e2 は別のオブジェクト(院照 心愛、27)を指している
図8-2 e1 と e3 は同じオブジェクトを指す

一方、e1 と e2 は、new を別々に行って作った別のオブジェクトです。たとえ名前と年齢が同じ値だったとしても、e1 == e2 は false です。== は「同じオブジェクトを指しているか」を比べるもので、「中身が同じか」は比べません。第5章で、文字列の比較に == を使ってはいけないと説明したのは、このためです。String もクラスなので、== は中身ではなく参照を比べてしまいます。

【知識メモ】ハッシュコードで同じオブジェクトかを見てみる

参照の中身はプログラムから見られません。ただ、オブジェクトの ハッシュコード という整数を表示すると、2つの変数が同じオブジェクトを指しているかの目安になります。

ハッシュ(ハッシュ値)とは、データから決まった計算で求めた、そのデータの目印になる数のことです。たくさんのデータの中から目的のものを速く探したり、2つのデータが同じかを手早く比べたりするのに使われます。Java では、すべてのオブジェクトが hashCode() というメソッドを持っていて、これを呼ぶとそのオブジェクトのハッシュコードが返ります。Employee のように hashCode() を書き直していないクラスでは、オブジェクトごとに Java が決めた数が返ります。

Main.java の main メソッドの最後に、次の3行を書き足して実行してみましょう。

ch08/Main.java(main メソッドの最後に書き足す)
System.out.println("e1 のハッシュコード:" + e1.hashCode());
System.out.println("e2 のハッシュコード:" + e2.hashCode());
System.out.println("e3 のハッシュコード:" + e3.hashCode());
コンソール(数字は実行するたびに変わります)
e1 のハッシュコード:925858445
e2 のハッシュコード:1927950199
e3 のハッシュコード:925858445

Employee e3 = e1; で参照を代入したので、e1 と e3 は同じオブジェクトを指していて、ハッシュコードも同じです。e2 は別のオブジェクトなので、違う値になります。

ただし、ハッシュコードは参照そのものでも、メモリ上の番地でもありません。別のオブジェクトでも、まれに同じ値になることがあります。

このハッシュコードは、第10章 10.3 でもう一度出てきます。println でオブジェクトを表示したときの「クラス名@…」の @ の後ろが、ハッシュコードを16進数で表したものです。

【知識メモ】基本型の変数は値そのものを持つ

int a = 26; int b = a; b = 27; と書いても、a は 26 のままです。基本型(int など)の変数は値そのものを持ち、代入すると値が複製されるからです。参照が入るのは、クラスの型(String、Employee)と配列の変数だけです。

8.7 null と NullPointerException

クラスの型の変数には、「どのオブジェクトも指していない」ことを表す null を入れられます(第5章 5.8)。null の変数に対してフィールドやメソッドを使うと、実行したときに NullPointerException が起きて、プログラムはそこで止まります。実際に起こしてみましょう。

  1. Main.java の main メソッドの最後に、緑の行を書き足します。

    ch08/Main.java(main メソッドの最後)
            System.out.println("e1 と e2 は同じオブジェクトか:" + (e1 == e2));
    
            Employee e4 = null;
            e4.print();
        }
    
    }
    
  2. 保存して実行します。これまでの表示の後に、赤い文字で次のように表示されます。

    コンソール(最後の部分)
    Exception in thread "main" java.lang.NullPointerException: Cannot invoke "ch08.Employee.print()" because "e4" is null
    	at ch08.Main.main(Main.java:18)
    
  3. 確かめたら、書き足した2行を消して保存します。

この赤い表示は スタックトレース といい、「何のエラーが」「どこで」起きたかを表しています。

部分 意味
java.lang.NullPointerException 起きたエラーの種類。null に対してメソッドやフィールドを使った
Cannot invoke "ch08.Employee.print()" because "e4" is null エラーの説明。「e4 が null なので、Employee の print() を呼べない」
at ch08.Main.main(Main.java:18) 起きた場所。Main.java の 18 行目(Main クラスの main メソッドの中)。Eclipse ではこの部分がリンクになっていて、クリックするとその行に飛べる

NullPointerException は、Java で最もよく出会うエラーです。出たときは、スタックトレースの「どの変数が null か」を読み、その変数に値を入れている場所を確かめます。エラーの扱いは、第12章で詳しく学びます。

【知識メモ】Spring入門で出会う NullPointerException

Spring入門では、フィールドに値を入れる処理を Spring に任せる仕組み(DI)を使います。そのための印(@Autowired)を書き忘れると、フィールドが null のままになり、この NullPointerException が起きます。スタックトレースの読み方を知っていれば、原因の場所がすぐに分かります。

8.8 うまくいかないときは

症状 考えられる原因と対処
「コンストラクター Employee() は未定義です」 引数付きのコンストラクタを書いたので、引数の無い new Employee() が使えなくなっています。new Employee("雷禅 海皇", 26) のように引数を渡してください。
「コンストラクター Employee(String, int) は未定義です」 コンストラクタをまだ書いていないか、引数の型や数が違います。Employee.java のコンストラクタと見比べてください。
「非 static フィールド name を static 参照できません」「型 Employee の非 static メソッド print() を static 参照することはできません」 main メソッドの中で、オブジェクトを指定せずにフィールドやメソッドを使っています。new で作ったオブジェクトの変数を付けて、e1.name・e1.print() のように書いてください。
「Employee を型に解決できません」 Employee クラスがまだ無いか、別のパッケージに作っています。Main と同じ ch08 パッケージにあるか確かめてください。
コンストラクタに「メソッドの戻りの型がありません」 コンストラクタの名前がクラス名と違います(employee のように小文字になっているなど)。クラス名と同じ Employee にしてください。
NullPointerException が出る null の変数のメソッドやフィールドを使っています。スタックトレースの because "〇〇" is null の変数に、値を入れているかを確かめてください。詳しくは 付録A「よくある実行時のエラー」 を見てください。

ほかのエラーは、付録A「よくあるコンパイルエラー」・付録A「よくある実行時のエラー」 も参考にしてください。

8.9 まとめと確認問題

まとめ

  • クラス は、どんなデータ(フィールド)と処理(メソッド)を持つかを定義したもの。new クラス名(…) で オブジェクト を作る。1つのクラスから、いくつでもオブジェクトを作れる
  • フィールドとメソッドは 変数.名前 で使う。static の付かないメソッドは、オブジェクトに対して呼び出し、そのオブジェクトのフィールドを使う
  • コンストラクタ は、クラス名と同じ名前で戻り値の型を書かない。new のときに呼ばれ、フィールドに値を入れる。this.name は「このオブジェクトのフィールド name」
  • コンストラクタを1つも書かなければ、引数の無いコンストラクタが自動で用意される。1つでも書くと、用意されなくなる
  • クラスの型の変数に入っているのは 参照。代入すると同じオブジェクトを指す。== は同じオブジェクトかどうかを比べる
  • null の変数に対してメソッドやフィールドを使うと NullPointerException。スタックトレースで、何が・どこで起きたかを読む

この章で使った書き方は、付録B「文法早見表」の「メソッドとクラス」 にまとめています。

確認問題

問1 部署を表すクラス Department を、部署名のフィールド String deptName だけを持つクラスとして定義してください。

解答を見る

public class Department { String deptName; }

問2 コンストラクタが、ふつうのメソッドと違う点を2つ答えてください。

解答を見る

名前がクラス名と同じであることと、戻り値の型を書かないことです。new でオブジェクトを作るときに呼ばれます。

問3 this.name = name; の this.name と name は、それぞれ何を指していますか。

解答を見る

this.name はこのオブジェクトのフィールド name、name はコンストラクタ(メソッド)の引数の name です。

問4 次のコードを実行した後、a.age はいくつですか。
Employee a = new Employee("林檎 星飛", 24);
Employee b = a;
b.age = 25;

解答を見る

25 です。a と b は同じオブジェクトを指しているので、b.age を変えると a.age も変わります。

問5 Employee e = null; e.print(); を実行するとどうなりますか。

解答を見る

NullPointerException が起きて、プログラムが止まります。e がどのオブジェクトも指していないのに、メソッドを呼んだためです。


前へ

第7章 メソッド

次へ

第9章 カプセル化とパッケージ

目次へ

【Java入門】目次

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?