Report 5
課題
講義資料オブジェクト指向プログラムJavaI&IIの中のサンプルプログラムについて考察せよ。
講義資料サンプルプログラム考察については、ローカル変数以降 interface までとする。
ローカル変数とクラス変数
ローカル変数:メソッド内部で宣言した変数。宣言したメソッド以外では使えない。
ローカル変数が値を格納していられるのはメソッドが終了するまで。
ローカル変数はメソッドが呼び出されるたびに初期化される。
クラス変数 :メソッド外部で宣言した値。クラス全体で使う値を格納しておくことができる。
classs Display {
int n // クラス変数
void Disp() {
int i; // ローカル変数
for (i = 1; i <= n; i++) //変数iに1を代入、iがn以下の間、iに+1する
System.out.print(i + " "); //変数iの値とスペースを出力
}
class VarSample {
public static void main(String args[]) {
Display obj = new Display(); // クラスDisplayのオブジェクトobj生成
obj.n = 10; // オブジェクトobjの変数nに10を代入
obj.Disp(); // オブジェクトobjのDisp()実行
}
}
実行結果
1 2 3 4 5 6 7 8 9 10
static変数
static変数:変数を宣言するときにstaticという修飾子つけることでクラス全体で値を共有する。
静的変数ともいう。
class Sum {
int total;
Sum() { // コンストラクタ(クラス名と同名)
total = 0; // 0 クリア
}
void add(int x) {
total += x;
}
}
class SumSample {
public static void main(String args[]) {
Sum obj1 = new Sum(); // クラスSumのオブジェクトobj1生成
Sum obj2 = new Sum(); // クラスSumのオブジェクトobj2生成
obj1.add(10); //obj1のメソッドaddの引数xに10を代入
obj1.add(20); //obj1のメソッドaddの引数xに20を代入
obj2.add(30); //obj2のメソッドaddの引数xに30を代入
obj2.add(40); //obj2のメソッドaddの引数xに30を代入
System.out.println("obj1.total = " + obj1.total); //obj1.totalを出力
System.out.println("obj2.total = " + obj2.total); //obj2.totalを出力
}
}
実行結果
obj1.total = 30
obj2.total = 70
class Sum {
static int total; // 値を共有させる
Sum() { // コンストラクタ(クラス名と同名)
total = 0; // 0 クリア
}
void add(int x) {
total += x;
}
}
class SumSample {
public static void main(String args[]) {
Sum obj1 = new Sum(); // クラスSumのオブジェクトobj1生成
Sum obj2 = new Sum(); // クラスSumのオブジェクトobj2生成
obj1.add(10); //obj1のメソッドaddの引数xに10を代入
obj1.add(20); //obj1のメソッドaddの引数xに20を代入
obj2.add(30); //obj2のメソッドaddの引数xに30を代入
obj2.add(40); //obj2のメソッドaddの引数xに40を代入
System.out.println("obj1.total = " + obj1.total); //totalは共有されてるため、引数xに代入した値は
System.out.println("obj2.total = " + obj2.total); //オブジェクト毎に区別されずに計算される。
}
}
実行結果
obj1.total = 100
obj2.total = 100
コンストラクタ
コンストラクタ:クラス名と同じ名前のメソッドのこと。しかしメソッドと違って、返り値を指定
することはできない。
そのクラスのオブジェクトが生成されたときにコンストラクタの処理が行われる。
class Sum {
int total;
Sum() { // コンストラクタ 引数無し
total = 0;
}
Sum(int x) { // コンストラクタ 引数 x
total = x;
}
void add(int x) {
total += x;
}
}
class ConstrcSample {
public static void main(String args[]) {
Sum obj1 = new Sum(); // クラスSumのオブジェクトobj1生成
obj1.add(10);
obj1.add(20);
System.out.println("sum1 = " + obj1.total);
Sum obj2 = new Sum(100); // クラスSumのオブジェクトobj2生成
// コンストラクタSumの引数xに100を代入
obj2.add(10);
obj2.add(20);
System.out.println("sum2 = " + obj2.total);
}
}
実行結果
sum1 = 30
sum2 = 130
staticイニシャライズ
staticイニシャライズ:staticイニシャライズは、クラスが呼ばれたときに自動的に実行される。
コンストラクタよりも早く処理したい場合や、一度だけ処理を行いたい
場合などに用いる。
class Disp {
static { // static イニシャライズ
System.out.println("initialize");
}
Disp() { // コンストラクタ
System.out.println("construct");
}
}
class StaticSample {
public static void main(String args[]) {
Disp obj1 = new Disp(); // オブジェクト生成時にコンストラクタを処理
Disp obj2 = new Disp(); // オブジェクト生成時にコンストラクタを処理
}
}
実行結果
initialize
construct
construct
メソッドのオーバーロード
メソッドのオーバーロード:同じクラスの中に同じ名前のメソッドを2つ以上定義すること。
ただし、引数の型、個数は異ならなくてはならない。
class Display {
void Disp() { // メソッド Disp 引数なし
System.out.println("Nothing");
}
void Disp(int x) { // メソッド Disp 引数 x
System.out.println(x);
}
void Disp(int x, int y) { // メソッド Disp 引数 x, y
System.out.println(x + y);
}
}
class OvldSample {
public static void main(String args[]) {
Display obj = new Display(); // クラスDisplayのオブジェクトobj生成
obj.Disp(); // オブジェクトobjのDisp()を実行
obj.Disp(1); // オブジェクトobjのDisp(1)を実行
obj.Disp(1, 2); // オブジェクトobjのDisp(1,2)を実行
}
}
実行結果
Noting
1
3
アクセス制御
変数を宣言するときの修飾子で、アクセス制御するもの。
private :同じクラス内でのみアクセスできる
無指定 :同じパッケージからのみアクセスできる
protected :同じクラスのパッケージと別パッケージのサブクラスからのみアクセスできる
public :すべてのクラスからアクセスできる
privateを用いて、変数の参照を不可にするプログラム例
class keisan {
atatic int tanka; // static変数
private float rate; // private変数rateの宣言
keisan() { // コンストラクタ
tanka = 1000;
rate = 0.05f;
}
init keisan(int kazu) {
int kingaku;
kingaku = (int)(tanka * kazu * (1.0 + rate));
return kingaku; //kingakuの値を返す
}
}
class PrvSample {
public static void main(String args[]) {
keisan obj1 = new keisan(); //クラスkeisanのオブジェクトobj1を生成
int kazu = 3;
int kingaku = obj1.keisan(kazu);
System.out.println("tanka = " + obj1.tanka);
System.out.println("kazu = " + kazu);
System.out.println("kingaku = " + kingaku);
// System.out.println("rate = " + obj1.rate); //private変数のため参照不可
}
}
実行結果
tanka = 1000
kazu = 3
kingaku = 3150
継承
継承:既存のクラス(スーパークラス)の内容を新しいクラス(サブクラス)が受け継ぐこと。
(サブクラスにはスーパークラスの内容が元から加えられている。)
サブクラスを作成することを拡張するといい、
class サブクラス名 extends スーパークラス名{
… … …
}
で表す。
class Display { // スーパークラス Display
void Disp() { // メソッド
System.out.println("Hello!");
}
}
class Succeed extends Display { // スーパークラス Displayを継承したサブクラス Succeed
public static void main(String args[]) { // メソッド
Succeed obj = new Succeed(); // オブジェクト生成
obj.Disp(); // スーパークラスから継承したメソッドを利用
}
}
実行結果
Hello!
オーバライド:サブクラス内にスーパークラスと同じメソッド名、引数、型を持つメソッドを
定義すること。このメソッドを呼び出す時、サブクラスで定義したメソッドが
呼び出される。
class Display { // スーパークラス Display
void Disp() { // メソッド
System.out.println("Hello!");
}
}
class Override extends Display { // サブクラス Override
void Disp() { // メソッドのオーバーライド
System.out.println("Hello! Java!!");
}
public static void main(String args[]) { // メソッド
Override obj = new Override(); // オブジェクト生成
obj.Disp(); // サブクラスのメソッド Disp が実行される
}
}
実行結果
Hello! Java!!
super
super:サブクラス内で super. という指定をつけることでメソッドがオーバーライドされていても
スーパークラスのメソッドを実行する。メソッドに限らず変数でも使える。
class Display { // スーパークラス Display
void Disp() { // メソッド
System.out.println("Hello!");
}
}
class SuperSample extends Display { // サブクラス SuperSample
void Disp() { // メソッドのオーバーライド
super.Disp(); // スーパークラスの Disp 実行
System.out.println("Hello! Java!!");
}
public static void main(String args[]) { // メソッド
SuperSample obj = new SuperSample(); // オブジェクト生成
obj.Disp(); // サブクラスの Disp 実行
}
}
実行結果
Hello!
Hello! Java!!
this
this. :クラス変数とローカル変数の名前が重複する時、 this.変数名 とすることで
クラス変数を呼び出す。
this() :そのクラスの別のコンストラクタを呼び出す。どのコンストラクタかは
()の中の引数に対応している。コンストラクタの先頭文でなくてはならない。
class Keisan { // スーパークラス Keisan
int x = 100;
void add(int x, int y) { // メソッド
int w1 = x + y; //引数xと引数yを足す
int w2 = this.x + y; //クラス変数xと引数yを足す
System.out.println("w1 = " + w1 + " w2 = " + w2);
}
}
class ThisSample1 extends Keisan { // サブクラス ThisSample1
public static void main(String args[]) { // メソッド
ThisSample1 obj = new ThisSample1(); // オブジェクト生成
obj.add(10, 20); // add 実行
}
}
実行結果
w1 = 30 w2 = 120
class Keisan {
Keisan(int x, int y) { // 引数が二つのコンストラクタ
System.out.println("Keisan = " + (x * y));
}
Keisan(int x) { // 引数が一つのコンストラクタ
this(x, 1); // Keisan(x, 1)を呼び出す
}
}
class ThisSample2 {
public static void main(String args[]) { // メソッド
Keisan obj1 = new Keisan(200, 5); // 引数が二つのコンストラクタ実行
Keisan obj2 = new Keisan(200); // 引数が一つのコンストラクタ実行
}
}
実行結果
Keisan = 1000
Keisan = 200
abstract
abstract:メソッドを宣言する時にこの修飾子を使うと、抽象メソッドとなる。抽象メソッドのある
クラスは abstract をつけて抽象クラスにする必要がある。
抽象メソッドで定義するのは引数で、処理内容を定義しない。そのため
抽象クラスのオブジェクトを生成することはできない。
抽象クラスを利用するためには、抽象クラスを継承させ、サブクラスでオーバーライドする。
public abstract class PreDefine { // 抽象クラス PreDefine
public abstract int add(int x, int y); // 抽象メソッド add
public int sub(int x, int y) { // メソッド sub
return x - y;
}
}
class AbstractSample extends PreDefine { // 抽象クラス PreDefine の継承
public int add(int x, int y) { // 抽象メソッドの内容を定義
return x + y;
}
public static void main(String args[]) {
AbstractSample obj = new AbstractSample(); //AbstractSampleのオブジェクト obj を生成
System.out.println("add = " + obj.add(100, 80));
System.out.println("sub = " + obj.sub(100, 80));
}
}
実行結果
add = 180
sub = 20
interface
interface:interface の宣言は class のかわりに interface を使う。
インターフェースの変数は定数で、メソッドは抽象メソッドである。
クラスの継承のように implement を使ってインターフェースを実装する。
public interface PreDefine { // インタフェース PreDefine
int add(int x, int y); // 抽象メソッド add
int sub(int x, int y); // 抽象メソッド sub
}
class InterfaceSample implement PreDefine { // PreDefine のインプリメント
public int add(int x, int y) { // 抽象メソッド add の内容を定義
return x + y;
}
public int sub(int x, int y) { // 抽象メソッド sub の内容を定義
return x + y;
}
public static void main(String args[]) {
InterfaceSample obj = new InterfaceSample();
System.out.println("add = " + obj.add(100, 80));
System.out.println("sub = " + obj.sub(100, 80));
}
}
実行結果
add = 180
sub = 20
感想
今回の課題は今までで一番時間がかかりました。だから今までで一番頭に入ってるはず!たぶん・・・
参考文献
やさしいJava 第2版
JAVAクイックリファレンス