例外の種類について

Posted コメントするカテゴリー: JAVA

JAVAの例外クラスは、Throwableというクラスがあります。

throw文で投げることができ、catch節で受け止めることができるクラスはすべてThrowableクラスが元になっています。

Throwableは、大きく分けてErrorとExceptionの2つに分類でできます。

  • Error

もはや動作を継続するのは期待できないときに投げられるエラー

  • Exception

正しく例外処理を行って、動作が継続することを期待するときのエラー
————————————————————————
さらに「Exception」は2種類に分けられます

  • Exception → RuntimeException

実行中に起こり、コンパイラによって前もってチェックされない例外(unchecked例外とも言う)

  • Exception → RuntimeException以外のエラー

コンパイラによって前もってチェックされる例外(checked例外とも言う)

————————————————————————
checked例外とunchecked例外の2種類に分かれます。

それぞれ取り扱う例外の種類が違うので、以下にまとめます。

  • unchecked例外

実行中のプログラムが原因で発生する例外(任意記述)
メモリ不足やプログラムの例外処理では復旧できない例外

  • checked例外

必ず任意の例外処理を記述しなければならないです。(必須記述)
記述しない場合はコンパイルエラーになります。
DBが原因だったり、java実行環境以外の環境が原因の例外

checked例外の場合、次の2種類の方法で必ず例外処理を書かなければなりません

  • ①メソッド内のcatch節でその例外をキャッチします
void Test() {
	try {
		throw new IOException();
	} catch (IOException e) {
		
	}
}
  • ②メソッド内のthrows節でその例外を投げることを宣言します
void Test() throws IOException {
	throw new IOException();
}

コールスタックについて

Posted コメントするカテゴリー: JAVA

例外時のエラー処理を行った場合、通常のメソッドのreturn時の挙動とは異なります。

通常のreturn時には、メソッドのひとつ前に戻る。動作を行いますが、例外時のエラーはcatchに飛びます。catchに飛ぶ場所は、コーディングの仕方によってケースバイケースなので、ひとつ前のcatchに飛ぶこともあり、メソッドが何重にも深いところから呼ばれている場合には、おおもとのcatchまで飛んでいくケースもあるので注意が必要です。

この何重にもcatchが書かれている場合のことをコールスタックと呼びます。

例外について

Posted コメントするカテゴリー: JAVA

javaの例外は、プログラムの誤りを通知し、適切なエラー処理を行う為の機能になります。

例外をうまく使うことで、エラーが起こった時にうまく処理する仕組みにすることができます。

例外の例

ArrayIndexOutOfBoundsException 配列の長さを超えている
FileNotFoundException ファイルが見つからなかった
IllegalArgumentException 引数が異常な値だった
OutOfMemoryError メモリが足りなくなった

等のエラーを拾うことができ、エラー内容に応じた処理にするとキレイなコードになります。

実際にテストコードを書いて、例外をおこしてみます。
下記のコードを書いてコンパイルすると、コンパイルエラーがおきます。

public class TestException {

    public static void main(String[] args) {
        
        int[] TestArray = new int[3];
        
        TestArray[50] = 0;
        
    }

}

上のコードのエラーを、例外をキャッチしてエラー処理を行うようにしてみます。

public class TestException {

    public static void main(String[] args) {
        
        int[] TestArray = new int[3];
        
        try {
            TestArray[50] = 0;
        } catch(Exception e) {
            System.out.println("例外 -> " + e);
        }
        
    }

}

これを実行すると、次のような結果が出力されます。

例外 -> java.lang.ArrayIndexOutOfBoundsException: 50

さらに、public static void mainの中でメソッドを呼び、そのメソッドの中で例外を発生させる。

package TestPackage;

public class ExecptionTest1 {

	public static void main(String[] args) {

		int[] TestArray = new int[3];

		System.out.println("Void Main start !");

		try {
			System.out.println("Try start !");
			TestFunc(TestArray, 100, 0);
			System.out.println("Try end !");
			//TestArray[50] = 0;
		} catch (Exception e) {
			System.out.println("例外 -> " + e);
		}

		System.out.println("Void Main end !");
	}

	static void TestFunc(int[] arr, int index, int value) {
		System.out.println("TestFunc start !");
		arr[index] = value;
		System.out.println("TestFunc end !");
	}

}

上記のコードを実行すると、次のような出力になる。

Void Main start !
Try start !
TestFunc start !
例外 -> java.lang.ArrayIndexOutOfBoundsException: 100
Void Main end !

Tryの中でTestFuncメソッドが呼ばれ、そのメソッド内で例外が発生したら、
もともとのTryにあるcatchが働き、例外処理がされる。

抽象クラスとは

Posted コメントするカテゴリー: JAVA

抽象クラスについて勉強します。

クラスの前にまずは、抽象メソッドについてです。
抽象メソッドとは、メソッドの名前と引数の型だけが定まっているものを言います。
別名でabstractメソッドとも言います。

abstract class TestClass{
    public abstract void TEST();
}

TESTというメソッドを宣言していても、中身はありません。(抽象メソッド)

このように、中身がないメソッドを含むクラスのことを抽象クラスといいます。

抽象クラスに書いた抽象メソッドは、中身がないので、具体的な挙動はサブクラスのほうで書く必要がある。
サブクラスで動作を書くことを前提として抽象クラスを設計するケースが多く、プログラムをする時にはその意図を汲み取ってコーディングをする。

finalクラスの拡張について

Posted コメントするカテゴリー: JAVA

修飾子のfinalをクラスにつけて宣言すると、そのクラスは拡張が禁止されます。

拡張が禁止されたクラスのことをfinalクラスと言います。

finalクラスの例

final class FClass {

}

例えば、FClassを継承したクラスを作ろうとすると

class FSUBClass extends FClass {

}

とするとコンパイルエラーになります。

クラスライブラリとパッケージ

Posted コメントするカテゴリー: JAVA

クラスを数多くあつめたものをクラスライブラリと呼びます。

また、関連のあるクラスを1つのグループにまとめたものをパッケージと呼びます。
利用する場合には「import」宣言をして呼び出します。
パッケージを作る場合は「package」宣言を行って作ります。

この辺りは実際に作ってみないとまだまだ実感がわかない概念です。
今後の為に言葉だけは覚えておこうと思います。

アクセスメソッドについて

Posted コメントするカテゴリー: JAVA

クラス内のフィールドの修飾子についてのメモ。

一般的にはクラスを設計する際には、クラス内のフィールドについては、privateに設定しておくのが良いとされています。

フィールド自体はprivateで、その値を参照したり、代入したりするのは、その専用のメソッドを書くのが設計上よいです。

そこで、フィールドの内容を取得するメソッドのことをアクセスメソッドまたはアクセサと呼びます。

フィールドの値をprivateにしておくことによって、他のクラスからの直接的な参照を防ぐ考えを、情報隠蔽という。
クラスの設計をする際には、この考え方をベースにしたほうがよさそうです。

スーパークラスの継承とアクセス制御

Posted コメントするカテゴリー: JAVA

少し時間が空いてしまいました。

久しぶりのブログになりますが、今日はスーパークラスとサブクラスの関係について、もうすこし詳しく勉強します。

クラスの、スーパークラスのフィールドとメソッドを継承するという動作について、ひとつ掘り進んで考えてみます。

一口に継承といっても、スーパークラス側でprivateの修飾子で宣言されたメソッドについては継承することができません。

finalメソッドについて

Posted コメントするカテゴリー: JAVA

スーパークラスをもとにしたサブクラスでは、スーパークラス側にfinalをつけられたメソッドを呼び出すことはできますが、オーバーライドすることはできません。

finalをつけるメソッドは、スーパークラスにて、システムの根幹に関わるメソッドに対してつけます。
書き換えてしまってシステムが誤動作させたくないメソッドについて使用します。

多様性について

Posted コメントするカテゴリー: JAVA

多様性について勉強します。
正直、なにがなんだかよくわかりませんが、オブジェクト指向ではよく登場するようです。

言葉の意味では、以下のような要約になります。

オブジェクト指向での多様性とは、サブクラスのインスタンスを、スーパークラスのインスタンスのように使うことといいます。

例えばこれまで書いてきた以下のようなテストコードがあるとすると、サブクラスのインスタンスを作った後に、そのインスタンスをもとに、スーパークラスの型の変数に代入することができます。

TestClassChild tcc = new TestClassChild();
TestClassParent tcp = tcc;

上記のtcpから、スーパークラスのフィールドやメソッドが呼び出すことができます。(tccも通常どおり使うことができる)
このような使い方を多様性(ポリモルフィズム)と呼ぶようです。

このあたりは実践で使ってみないとピンとこないかもしれません。

public class SuperClassTest3{

    public static void main(String[] args) {
        
        //オブジェクトのインスンタンスを生成する
        TestClassChild tcc = new TestClassChild();
       	
       	System.out.println(tcc.TestA);
       	System.out.println(tcc.TestB);
       	
       	
       	//tcc.PrintTextC();
       	//tcc.PrintTextP();

    }
}

class TestClassChild extends TestClassParent
{
    TestClassChild() {
    	//引数なしコンストラクタ用
    	
    	//スーパークラスの引数なしコンストラクタを呼ぶ
    	super();
    	
    }

    TestClassChild(int TestAA, int TestBB) {
    	
    	//スーパークラスの引数つきコンストラクタを呼ぶ
    	super(TestAA, TestBB);

    }

    void PrintTextC() {
    	System.out.print("PrintTextC !! \n");
    }
    
    void PrintTextP() {
    	System.out.print("PrintTextP オーバーライドテスト !! \n");
    }

}

class TestClassParent
{
	int TestA = 10;
	int TestB = 20;
	
    TestClassParent(int a, int b) {
        //やっていることは「setTest」メソッドを同じ
        TestA = a;
        TestB = b;
        
        System.out.print("引数つきコンストラクタ !! \n");
        
    }
	
    TestClassParent() {
    	//引数なしコンストラクタ用

        System.out.print("コンストラクタ !! \n");
    	
    }
    
    void PrintTextP() {
    	System.out.print("PrintTextP !! \n");
    }
    
    void PrintParentTest() {
    	System.out.print("PrintParentTest !! \n");
    }
    
    

}













@Overrideという記述について

Posted コメントするカテゴリー: JAVA

JKD1.5以降では、オーバーライドされているメソッドかどうかという区別をする為に

@Override

という記述をメソッドの上に書く様式が出てきました。
コンパイル時にこのメソッドは親クラスのメソッドをオーバーライドしているものかどうか、をチェックする動作になり、オーバーライド漏れを防ぐ場面で有効な手段となります。

(2015.05.09追記)
この書き方はアノテーションといい、Override以外にも使用方法は多岐にわたる

シグニチャについて

Posted コメントするカテゴリー: JAVA

親クラス内のメソッドをオーバーライドする条件として、以下の点を考えます。

・メソッド名が同じか
・引数列の型が同じか

上記の条件がそろった時にはじめて、子クラス内のメソッドでオーバーライドが成立します。
この条件(メソッド名、引数列の型)のことをメソッドのシグニチャとよび、signatureと書きます。

HAS-A関係

Posted コメントするカテゴリー: JAVA

HAS-A関係について勉強します。

オブジェクト指向では、おもに包含と呼ぶこともあるようです。
正直よくわかりませんので、調べてみました。

HAS-A関係を簡単に表すと

犬は頭、胴体、を含んでいる。

胴体は首、シッポ、ヘソ、足を含んでいる

足は、指、肉球(?)を含んでいる

という関係になり、犬というものを分割して捕らえていく考え方になります。

オブジェクト指向に、このHAS-A関係、の考え方がどのように関係してくるのか、じっくりと勉強したいと思います。

道は長い

IS-A関係

Posted コメントするカテゴリー: JAVA

オブジェクト指向では、「AはBの一種である」ということがいえる関係のことをIS-A関係という。

例えば、サブクラスはスーパークラスの一種である。というように、次のような形で表します。

人間は哺乳類の一種である。

哺乳類は動物の一種である。

鳥は鳥類の一種である。

鳥類は動物の一種である。

というような例をIS-A関係と考えます。

スーパークラスの引数なしコンストラクタの呼び出しについて

Posted コメントするカテゴリー: JAVA

前回の例では、継承したスーパークラスを何気に使っていましたが、スーパークラス側で初期化(コンストラクタ)が必要な設計になっている場合、どのように実装したらいいのかが気になります。

javaの言語仕様としては、コンストラクタの呼び出しは自動的に呼ばれる仕様になっているようです。

このときに呼ばれるのは「引数なし」コンストラクタとなるようです。

この自動的に呼び込まれるコンストラクタを自分の明示により呼び出す仕組みが「super()」という呼び出し方です。

以下に例を書きます。

public class SuperClassTest3{

    public static void main(String[] args) {
        
        //オブジェクトのインスンタンスを生成する
        TestClassChild tcc = new TestClassChild();
       	
       	System.out.println(tcc.TestA);
       	System.out.println(tcc.TestB);
       	
       	
       	//tcc.PrintTextC();
       	//tcc.PrintTextP();

    }
}

class TestClassChild extends TestClassParent
{
    TestClassChild() {
    	//引数なしコンストラクタ用
    	
    	//スーパークラスの引数なしコンストラクタを呼ぶ
    	super();
    	
    }

    TestClassChild(int TestAA, int TestBB) {
    	
    	//スーパークラスの引数つきコンストラクタを呼ぶ
    	super(TestAA, TestBB);

    }

    void PrintTextC() {
    	System.out.print("PrintTextC !! \n");
    }
    
    void PrintTextP() {
    	System.out.print("PrintTextP オーバーライドテスト !! \n");
    }

}

class TestClassParent
{
	int TestA = 10;
	int TestB = 20;
	
    TestClassParent(int a, int b) {
        //やっていることは「setTest」メソッドを同じ
        TestA = a;
        TestB = b;
        
        System.out.print("引数つきコンストラクタ !! \n");
        
    }
	
    TestClassParent() {
    	//引数なしコンストラクタ用

        System.out.print("コンストラクタ !! \n");
    	
    }
    
    void PrintTextP() {
    	System.out.print("PrintTextP !! \n");
    }
}

実行した結果は以下のようになります。

コンストラクタ !!
10
20

結果として「コンストラクタ !! 」と表示されているのは

TestClassChild tcc = new TestClassChild();

でTestClassChildのインスタンスが生成された際に、子クラス(TestClassChild)の引数なしコンストラクタ「TestClassChild()」が反応し

「super();」が呼ばれた結果

親クラスの引数なしコンストラクタ(TestClassParent())が呼ばれて

「System.out.print(“コンストラクタ !! \n”);」が実行されたから

になります。

少しややこしいけど、書きなれて体得していくしかないかと思います。

フィールドの継承

Posted コメントするカテゴリー: JAVA

先ほど書いた実験コードに、フィールドが継承されるかどうかの検証をしてみます。

以下のようなコードを書いてみました。

public class SuperClassTest3{

    public static void main(String[] args) {
        
        //オブジェクトのインスンタンスを生成する
        TestClassChild tcc = new TestClassChild();
       	
       	System.out.println(tcc.TestA);
       	System.out.println(tcc.TestB);
       	
       	
       	//tcc.PrintTextC();
       	//tcc.PrintTextP();

    }
}

class TestClassChild extends TestClassParent
{
    TestClassChild() {
    	//引数なしコンストラクタ用
    	
    }

    void PrintTextC() {
    	System.out.print("PrintTextC !! \n");
    }
    
    void PrintTextP() {
    	System.out.print("PrintTextP オーバーライドテスト !! \n");
    }

}

class TestClassParent
{
	int TestA = 10;
	int TestB = 20;
	
    TestClassParent() {
    	//引数なしコンストラクタ用
    	
    }
    
    void PrintTextP() {
    	System.out.print("PrintTextP !! \n");
    }
    
    

}

結果は下記のようになり、親クラスのTestA、TestBというフィールドの値を参照することができています。

10
20

■注意■
フィールドとメソッドは継承元(親クラス)のものが参照できますが、コンストラクタは継承されず、使うことができません。

extendsした親クラスのメソッドを子クラスのメソッドでオーバーライドする

Posted コメントするカテゴリー: JAVA

先ほど作成したテストコードを改造して、親クラスをextendsした子クラス内で親クラスと同名のメソッドを記述してオーバーライドしてみます。

書いたコードは以下のとおり

public class SuperClassTest2{

    public static void main(String[] args) {
        
        //オブジェクトのインスンタンスを生成する
        TestClassChild tcc = new TestClassChild();
       	
       	
       	tcc.PrintTextC();
       	tcc.PrintTextP();
        

    }
}

class TestClassChild extends TestClassParent
{
    TestClassChild() {
    	//引数なしコンストラクタ用
    	
    }

    void PrintTextC() {
    	System.out.print("PrintTextC !! \n");
    }
    
    void PrintTextP() {
    	System.out.print("PrintTextP オーバーライドテスト !! \n");
    }

}

class TestClassParent
{
    TestClassParent() {
    	//引数なしコンストラクタ用
    	
    }
    
    void PrintTextP() {
    	System.out.print("PrintTextP !! \n");
    }
    
    

}

子クラス(TestClassChild)内に「PrintTextP」というメソッドを書いて、親クラスのメソッドをオーバーライドしています。
これを実行すると以下のような結果になります。

PrintTextC !!
PrintTextP オーバーライドテスト !!

もともと親クラスにあったメソッドが子クラス内に書いたメソッドに置き換えられて実行されている。

extendsを使ってみる

Posted コメントするカテゴリー: JAVA

スーパークラスから拡張したクラスを作ってみます。

下記のようなテストコードを書いて実行してみます。

public class SuperClassTest{

    public static void main(String[] args) {
        
        //オブジェクトのインスンタンスを生成する
        TestClassChild tcc = new TestClassChild();
       	
       	
       	tcc.PrintTextC();
       	tcc.PrintTextP();
        

    }
}

class TestClassChild extends TestClassParent
{
    TestClassChild() {
    	//引数なしコンストラクタ用
    	
    }

    void PrintTextC() {
    	System.out.print("PrintTextC !! \n");
    }
    
    void PrintTextP() {
    	System.out.print("PrintTextP !! \n");
    }

}

class TestClassParent
{
    TestClassParent() {
    	//引数なしコンストラクタ用
    	
    }
    
    void PrintTextP() {
    	System.out.print("PrintTextP !! \n");
    }
}

メインの処理の「SuperClassTest」のクラスの中から「TestClassChild」のクラスのインスタンスを生成して、そのTestClassChild内のメソッドを呼びました。

結果は

PrintTextC !!

という表示がされ、TestClassChild内のメソッドを呼べていることがわかります。

次にに、TestClassChildクラスが継承している「TestClassParent」クラスのメソッドも、同じTestClassChildインスタンス(ここではtccという名前)から呼んでみました。

すると結果は

PrintTextP !!

と表示され、継承元の「PrintTextP」メソッドが正しく動作していることがわかります。

今回の例はシンプルな継承の例ですが、一つの親クラスから、多数の子クラスを派生させることも可能なので、後ほどつめて実験してみようと思います。

スーパークラスについて

Posted コメントするカテゴリー: JAVA

スーパークラスについて勉強します。

続きは後日、、

2014.10.09追記
スーパークラスという前に、まずは継承という概念について。
javaやc++等のオブジェクト指向言語で、作成したクラスをもとに、その機能を引き継ぎつつ、違うクラスを作成することができます。

この概念を継承といいます。

元のクラスを継承してできた新しいクラスのことを、サブクラスと呼び、元のクラスのことをスーパークラスといいます。

スーパークラスは原則として1つのみです。
スーパークラスは1個のみですが、サブクラスは1個のみという制約はなく、いくつでも作り出すことができます。

サブクラスは多段に拡張していくことができます。

javaはクラスが階層的に積み重なるように作ることができ、この構造をクラス階層という。

public、protected、private修飾子について

Posted コメントするカテゴリー: JAVA

public、protected、privateは、変数やクラスを、どの範囲から参照可能かを決める修飾子です。(他にも色々ありますが、もっとも良く使う修飾子です)

public     自ファイルおよび他ファイル、全てのクラスから参照可能
protected  他ファイルの他クラス以外、全てのクラスから参照可能
private    自ファイルの自クラスのみ参照可能
指定なし    自ファイル内の自クラス、サブクラス、他クラスから参照可能

ちょっとわかりづらいですが、上記のような関係性があり、それらの動きをよく考えつつプログラムを組みます。

修飾子について

Posted コメントするカテゴリー: JAVA

クラス内のフィールドやメソッドに対して、修飾子をつけて区別します。

■final
変更不可能な値やクラスを指し示します
主に、「定数」のような使い方をします。
また、finalで指定した変数には、プログラムの途中で値を代入することはできません。

■abstract
抽象クラスや抽象メソッドであることを示します
メソッド本体がないメソッドのことを言います。
メソッドにはつけられるけど、フィールドにはつけられない。

■static
クラスフィールドやクラスメソッドであることを示します

■synchronized
synchronizedメソッド

■native
JAVA言語以外で書かれたメソッドであることを示します

、、、と列挙してみましたが、まだよくわかっていないです。

クラスメソッドについて

Posted コメントするカテゴリー: JAVA

クラス内にあるメソッドについても、フィールドと同じようにクラスメソッドと呼ぶような宣言の仕方があります。

クラスフィールドと同じように「static」という修飾子をつけて表します。
例として、下記の「countUpTestD」というメソッドをクラスフィールドにしています。

class TestClassSub
{
    //フィールドの初期化
    int TestA = 10;
    int TestB = 30;
    static int TestC = 20;
    int TestD = 40;
     
    TestClassSub(int a, int b) {
        //やっていることは「setTest」メソッドを同じ
        TestA = a;
        TestB = b;
    }
     
    TestClassSub() {
    	//引数なしコンストラクタ用
    	
    }
     
    void setTest(int a, int b){
        TestA = a;
        TestB = b;
    }

    int sumAB(){
        return TestA + TestB;
    }

    int countUpTestC(){
        return TestC++;
    }

    void countUpTestC2(){
        TestC++;
    }

    static int countUpTestD(){
        return TestD++;
    }


}

クラスメソッドは、別名「staticメソッド」という場合もある。

staticをつけずに宣言したメソッドは「インスタンスメソッド」や「staticではない(通常の)メソッド」などと呼び、クラスメソッドと区別をします。

クラスメソッドは特定のインスタンスに関連していな為、インスタンスが生成されていない状態でも呼び出すことができます。
他のクラスから呼び出すときには次のように書きます。

クラス名.メソッド名(引数)

クラスフィールドについて

Posted コメントするカテゴリー: JAVA

例えば、以下のクラスをnewしてインスタンスを生成する際、インスタンスをnewした回数を取り扱いたい場合は、クラスの中にクラスフィールドという、全インスタンスに共通の情報保存場所が必要になります。
この保存場所をクラスフィールド(またはクラス変数、スタティックフィールド)と呼び、クラス内に宣言することができます。

これまでに作ってきたクラス

class TestClassSub
{
    //フィールドの初期化
    int TestA = 10;
    int TestB = 30;
     
    TestClassSub(int a, int b) {
        //やっていることは「setTest」メソッドを同じ
        TestA = a;
        TestB = b;
    }
     
    TestClassSub() {
    	//引数なしコンストラクタ用
    	
    }
     
    void setTest(int a, int b){
        TestA = a;
        TestB = b;
    }

    int sumAB(){
        return TestA + TestB;
    }
}

上記のクラスに対し、クラスフィールドを加えたクラス

class TestClassSub
{
    //フィールドの初期化
    int TestA = 10;
    int TestB = 30;
    
    static int TestC = 20;
     
    TestClassSub(int a, int b) {
        //やっていることは「setTest」メソッドを同じ
        TestA = a;
        TestB = b;
    }
     
    TestClassSub() {
    	//引数なしコンストラクタ用
    	
    }
     
    void setTest(int a, int b){
        TestA = a;
        TestB = b;
    }

    int sumAB(){
        return TestA + TestB;
    }
}

上記のTestClassSubクラスを使う場合、一度、クラスのインスタンスを生成し、クラスフィールドを加算するメソッドを何度か呼んでみます。

public class TestClass5 {

    public static void main(String[] args) {
        
        int retA;
        
        System.out.print("hello\n");
        
        //引数なしコンストラクタ
        TestClassSub tc = new TestClassSub();
       
        retA = tc.countUpTestC();
        System.out.print("retA -> " + retA + "\n");
        retA = tc.countUpTestC();
        System.out.print("retA -> " + retA + "\n");
        retA = tc.countUpTestC();
        System.out.print("retA -> " + retA + "\n");
        retA = tc.countUpTestC();
        System.out.print("retA -> " + retA + "\n");
        retA = tc.countUpTestC();
        System.out.print("retA -> " + retA + "\n");
        
    }
}

class TestClassSub
{
    //フィールドの初期化
    int TestA = 10;
    int TestB = 30;
    
    static int TestC = 20;
     
    TestClassSub(int a, int b) {
        //やっていることは「setTest」メソッドを同じ
        TestA = a;
        TestB = b;
    }
     
    TestClassSub() {
    	//引数なしコンストラクタ用
    	
    }
     
    void setTest(int a, int b){
        TestA = a;
        TestB = b;
    }

    int sumAB(){
        return TestA + TestB;
    }

    int countUpTestC(){
        return TestC++;
    }

}


すると、実行した結果は次のようになります。

hello
retA -> 20
retA -> 21
retA -> 22
retA -> 23
retA -> 24

スタックとヒープ

Posted コメントするカテゴリー: JAVA

前例のプログラムで、次のように、クラスからインスタンスを生成しました。

        //引数なしコンストラクタ
        TestClassSub tc = new TestClassSub();

この時、tcが確保されている領域をスタック(stack)と呼びます。
また、TestClassSubのインスタンスが確保されている領域をヒープ(heap)と呼びます。

フィールドの初期化

Posted コメントするカテゴリー: JAVA

フィールドの初期化を行うには、コンストラクタの内部でもよく、コンストラクタの外でもOK。

前回に投稿したTestClassSubクラスのフィールドを初期化するには、次のように書いてもOK。

class TestClassSub {
    int TestA = 10;
    int TestB = 30;
     
    TestClassSub(int a, int b) {
        //やっていることは「setTest」メソッドを同じ
        TestA = a;
        TestB = b;
    }
     
    TestClassSub() {
    	//引数なしコンストラクタ用
    	
    	
    	
    }
     
    void setTest(int a, int b){
        TestA = a;
        TestB = b;
    }
    int getAB(){
        return TestA + TestB;
    }
}

初期化されていないフィールドの値は、その型に応じて初期化される。
変数の値については、未定義になる。

具体的には、値は次のようになる。

Boolean型 false;
整数型 0
浮動小数点型 0.0
参照型 null

引数なしコンストラクタ

Posted コメントするカテゴリー: JAVA

前回に書いたクラスで、コンストラクタを呼び出した時は以下のように書きました。

TestClass tc = new TestClass(100, 200);

これはコンストラクタを呼ぶと同時に引数、100、200をつけています。
このコンストラクタの呼び方を変更して、引数をつけないで呼び出す方法もやってみます。
具体的には下記のように記述します。

TestClass tc = new TestClass();

また、ひとつのクラスの中にはコンストラクタが複数あってもエラーにはならないです。
全体として下記のように記述してみました。
詳しい動作検証は、また後ほどやります。

public class TestClass2 {

    public static void main(String[] args) {
        
        int retA;
        
        System.out.print("hello\n");
        
        //これだとエラーになる
        //TestClassSub tc = new TestClassSub();
        
        //引数をつけるとエラーにならない(コンストラクタで使う為?)
        TestClassSub tc = new TestClassSub(100, 200);
        
        retA = tc.getAB();
        System.out.print("retA -> " + retA);
        
    }
}


class TestClassSub {
    int TestA;
    int TestB;
     
    TestClassSub(int a, int b) {
        //やっていることは「setTest」メソッドを同じ
        TestA = a;
        TestB = b;
    }
     
    TestClassSub() {
    	//引数なしコンストラクタ用
    	
    }
     
    void setTest(int a, int b){
        TestA = a;
        TestB = b;
    }
    int getAB(){
        return TestA + TestB;
    }
}

実行した結果は次のようになります

hello
retA -> 0

実際に動かしてみる

Posted コメントするカテゴリー: JAVA

次のようなプログラムを作り、コンパイル後、実行しました。

public class TestClass {

    public static void main(String[] args) {
        
        int retA;
        
        System.out.print("hello\n");
        
        //これだとエラーになる
        //TestClassSub tc = new TestClassSub();
        
        //引数をつけるとエラーにならない(コンストラクタで使う為?)
        TestClassSub tc = new TestClassSub(100, 200);
        
        retA = tc.getAB();
        System.out.print("retA -> " + retA);
        
    }
}


class TestClassSub {
    int TestA;
    int TestB;
     
    TestClassSub(int a, int b) {
        //やっていることは「setTest」メソッドを同じ
        TestA = a;
        TestB = b;
    }
     
    void setTest(int a, int b){
        TestA = a;
        TestB = b;
    }
    int getAB(){
        return TestA + TestB;
    }
}

一番最初に、TestClassSubのインスタンスを作ろうとした時に、下記のようなエラーが表示されました。

d:\data\java>javac TestClass.java
TestClass.java:7: シンボルを見つけられません。
シンボル: コンストラクタ TestClassSub()
場所    : TestClassSub の クラス
        TestClassSub tc = new TestClassSub();
                          ^
エラー 1 個

少し悩んでいたところ、TestClassSubのコンストラクタは引数を書いていたので、インスタンスを作る際にも引数がないとエラーになることに気づき、引数をつけると無事にコンパイルがとおりました。
インスタンスを作り、「getAB」というメソッドを試したまでですが、無事に下記のように表示されました。

d:\data\java>java TestClass
hello
retA -> 300

まずはエラーにならずにサクっと動作させるようにして進みたいと思います。
エラーでつまずくと、少し後ろ向きになってしまいますが、そうゆう場合には、一旦できているところまでを見直しつつ、なるべく前向きに勉強していきます。
道は長い

コンストラクタを使う

Posted コメントするカテゴリー: JAVA

先ほど作成した下記のクラス

class TestClass {
    int TestA;
    int TestB;
     
    void setTest(int a, int b){
        TestA = a;
        TestB = b;
    }
    int getAB(){
        return TestA + TestB;
    }
}

に対して、コンストラクタを追加します。

class TestClass {
    int TestA;
    int TestB;
    
    TestClass(int a, int b) {
        //やっていることは「setTest」メソッドを同じ
        TestA = a;
        TestB = b;
    }
    
    void setTest(int a, int b){
        TestA = a;
        TestB = b;
    }
    int getAB(){
        return TestA + TestB;
    }
}

コンストラクタを呼び出すのは、以下のように書きます。

TestClass tc = new TestClass(100, 200);