1
プログラミング言語
3
第
06
回(
2007
年
10
月
29
日)
2/33今日の配布物
片面の用紙
1
枚
今日の課題が書かれています。
本日の出欠を兼ねています
3/33
今日やること
http://www.tnlab.ice.uec.ac.jp/~s-okubo/class/java06/
にアクセスすると、教材があります。
2007
年
10
月
29
日分
と書いてある部分が、本日の教材です。
本日の内容
前回の課題の解答
アブストラクトクラスとアブストラクトメソッド
定数
キャスト
4/33前回の課題の解答
5/33
前回の課題
その1:
次のプログラムを考える。
このとき、次の事を行った場合、どのような結果に
なるかを答え、その理由を考察しなさい。
6/33 class Test01{private int private_data01=10; protected int protected_data01=20; int data01=30;
public void test_func01a(){
System.out.println(private_data01); }
public void test_func01b(){ System.out.println(data01); }
public void test_func01c(){
System.out.println(private_data01); } } クラスTest01 private_data01;
共通事項
その
1
の
1
•
test_func01a();
•
test_func01b();
•
test_func01c();
protected_data01; data01;•
それぞれの変数
は、修飾子が異
なっている。
•
3
つのメソッドが
ある。
7/33
class Test01{
private int private_data01=10; protected int protected_data01=20; int data01=30;
public void test_func01a(){
System.out.println(private_data01); }
public void test_func01b(){ System.out.println(data01); }
public void test_func01c(){
System.out.println(private_data01); } } クラスTest01 private_data01;
共通事項
その
1
の
2
•
test_func01a();
•
test_func01b();
•
test_func01c();
protected_data01; data01;両方とも、
private_data01
を
画面に出力する
メソッド
data01
を
画面に出力する
メソッド
8/33class Test02 extends Test01{ int data02a=40;
public void test_func02a(){ System.out.println(50); }
public void test_func01a(){ //[ここに書かれる その1] }
public void test_func01b(int data02b){ System.out.println(data02b); } }
共通事項
その
2
の
1
クラスTest02 private_data01; • test_func01a(); • test_func01b(); • test_func02a(); protected_data01; data01; data02a; • test_func01a(); • test_func01b (int data02b) • test_func01c();9/33
class Test02 extends Test01{ int data02a=40;
public void test_func02a(){ System.out.println(50); }
public void test_func01a(){ //[ここに書かれる その1] }
public void test_func01b(int data02b){ System.out.println(data02b); } }
共通事項
その
2
の
2
クラスTest02 private_data01; • test_func01a(); • test_func01b(); • test_func02a(); protected_data01; • test_func01a() data01; data02a; • test_func01b (intintintint data02bdata02bdata02bdata02b)• test_func01c();
同じ名前・同じ引数なので、
こちらが優先される。
オーバーライド
オーバーライド
オーバーライド
オーバーライド
同じ名前・異なる引数なので、
両立し、どちらが使われるかは引数に
よって判断される。
オーバーロード
オーバーロード
オーバーロード
オーバーロード
10/33class Test02 extends Test01{ int data02a=40;
public void test_func02a(){ System.out.println(50); }
public void test_func01a(){ //[ここに書かれる その1] }
public void test_func01b(int data02b){ System.out.println(data02b); } }
共通事項
その
2
の
3
クラスTest02 private_data01; • test_func01a(); • test_func01b(); • test_func02a(); protected_data01; • test_func01a() data01; data02a; • test_func01b (int data02b) • test_func01c();data02
を
画面に出力する
メソッド
50
という値を
画面に出力する
メソッド
問題
問題
問題
問題によって
によって
によって
によって
異
異
異
異なる
なる
なる
なる
11/33
public class Sample05a{
public static void main(String[] args){ Test02 dt02 = new Test02();
//[ここに書かれる その2] } }
共通事項
その
3
クラスSample05a• main(String[]String[]String[]String[] argsargsargsargs);
static
なメソッド
main
12/33
public class Sample05a{
public static void main(String[] args){
Test02 Test02 Test02
Test02 dtdtdt02 = new Test02();dt02 = new Test02();02 = new Test02();02 = new Test02();
//[ここに書かれる その2] }
}
共通事項
その
4 dt02
生成後
• main(String[] args); クラスオブジェクト private_data01; • test_func01a(); • test_func01b(); • test_func02a(); protected_data01; data01; data02a; • test_func01a(); • test_func01b (int data02b); • test_func01c(); dt02 インスタンス
13/33
public class Sample05a{
public static void main(String[] args){ Test02 dt02 = new Test02();
//[ここに書かれる その2] dt02.test_func02a(); } }
その
1
private_data01; • test_func01a(); • test_func01b(); • test_func02a(); protected_data01; data01; data02a; • test_func01a(); • test_func01b (int data02b); • test_func01c(); dt0250
という値を
画面に出力する
メソッド
コンソールに
と表示される。
50
• main(String[] args);
14/33
public class Sample05a{
public static void main(String[] args){ Test02 dt02 = new Test02();
//[ここに書かれる その2] dt02.test_func01a(); } }
その
2
private_data01; • test_func01a(); • test_func01b(); • test_func02a(); protected_data01; data01; data02a; • test_func01a(); • test_func01b (int data02b); • test_func01c(); dt02コンパイルするときに、
エラーがでて失敗する。
class Test02 extends Test01{ 略
public void test_func01a(){ //[ここに書かれる その1]
System.out.println(private_data01);
} 略
• main(String[] args);
クラス
Test01
部分の
private
な変数アクセスしようとする
(が、
private
なので
15/33
public class Sample05a{
public static void main(String[] args){ Test02 dt02 = new Test02();
//[ここに書かれる その2] dt02.test_func01c(); } }
その
3
private_data01; • test_func01a(); • test_func01b(); • test_func02a(); protected_data01; data01; data02a; • test_func01a(); • test_func01b (int data02b); • test_func01c(); dt02private_data01の値10が
画面に出力される。
• main(String[] args);
クラス
Test01
部分の
private
な変数アクセスしようとする
(同じクラス内にいるので
アクセスできる!)
16/33
public class Sample05a{
public static void main(String[] args){ Test02 dt02 = new Test02();
//[ここに書かれる その2] dt02.test_func01a(); } }
その
4
private_data01; • test_func01a(); • test_func01b(); • test_func02a(); protected_data01; data01; data02a; • test_func01a(); • test_func01b (int data02b); • test_func01c(); dt02class Test02 extends Test01{ 略
public void test_func01a(){ //[ここに書かれる その1]
System.out.println(protected_data01);
} 略
• main(String[] args);
クラス
Test01
部分の
protected
な変数にアクセスしようとする
(継承しているクラスからは、
public
のように見えるので、
アクセスできる!)
private_data01の値20が
画面に出力される。
17/33
public class Sample05a{
public static void main(String[] args){ Test02 dt02 = new Test02();
//[ここに書かれる その2] dt02.test_func01b(); dt02.test_func01b(10000); } }
その
5
private_data01; • test_func01a(); • test_func01b(); • test_func02a(); protected_data01; data01; data02a; • test_func01a(); • test_func01b (int data02b); • test_func01c(); dt02• main(String[] args);
引数が無い場合は
こちらが実行される。
最初にdata01の値30が、
次に引数として与えられ
たdata02bの値10000が
出力される
引数がある場合は
こちらが実行される。
18/33前回の課題
その2:
次の3つのプログラムを実行し出力結果を述べな
さい。また、何故そのような結果になったのか、考
察しなさい。
19/33 class Test01{ int value01a; Test01(){ value01a=10; } Test01(int a){ value01a=a*100; } }
class Test02 extends Test01{ class Test02 extends Test01{ class Test02 extends Test01{ class Test02 extends Test01{
int value02a; Test02(){ value02a=20; } Test02(int a, int b){ super(a); value02a=b*1000; } } public class Sample05a{
public static void main(String[] args){ Test02 dt01 = new Test02();
System.out.println(dt01.value01a); System.out.println(dt01.value02a); } }
共通事項
変数が
2
つ
value01a
value02a
コンストラクタ
4
つ
クラス
Test02
は、
クラス
Test01
を継承
value02a; value01a; Test01(); Test01(int a); Test02(); Test02(int a, int b); dt01 20/33 class Test01{ int value01a; Test01(){ Test01(){ Test01(){ Test01(){ value01a=10; value01a=10; value01a=10; value01a=10; }}}} Test01(int a){ value01a=a*100; } }class Test02 extends Test01{ int value02a; Test02(){ Test02(){Test02(){ Test02(){ value02a=20; value02a=20;value02a=20; value02a=20; }}}} Test02(int a, int b){ super(a); value02a=b*1000; } } public class Sample05a{
public static void main(String[] args){ Test02 dt01 = new Test02();Test02();Test02();Test02();
System.out.println(dt01.value01a); System.out.println(dt01.value02a); } }
コンソールに
と表示される。
10
20
value02a
を
初期化。
20に。引数無しで
インスタンス生成
その
1
:
value02a; value01a; Test01(); Test01(int a); Test02(); Test02(int a, int b); dt01初期化されてない
value01a
は、これで初期化。
10に。21/33 class Test01{ int value01a; Test01(){ value01a=10; } Test01( Test01( Test01(
Test01(intintintint a){a){a){a){ value01a=a*100; value01a=a*100; value01a=a*100; value01a=a*100; }}}} }
class Test02 extends Test01{ int value02a; Test02(){ value02a=20; } Test02( Test02(Test02(
Test02(intintint a, int a, a, a, intintint b){int b){b){b){ super(a); super(a);super(a); super(a); value02a=b*1000; value02a=b*1000;value02a=b*1000; value02a=b*1000; }}}} } public class Sample05b{
public static void main(String[] args){ Test02 dt01 = new Test02(5,10);Test02(5,10);Test02(5,10);Test02(5,10);
System.out.println(dt01.value01a); System.out.println(dt01.value02a); } }
コンソールに
と表示される。
500
10000
引数
5
と
10
で
インスタンス生成
処理が終わったら
続きを実行。
value02a
を
初期化。
10*1000に。その
2
:
value02a; value01a; Test01(); Test01(int a); Test02(); Test02(int a, int b); dt01super(a)
により、
Test01(a)
が
実行される。
value01aが5*100に 22/33その
3
:
class Test01{ int value01a; Test01(){ Test01(){ Test01(){ Test01(){ value01a=10; value01a=10; value01a=10; value01a=10; }}}} Test01(int a){ value01a=a*100; } }class Test02 extends Test01{ int value02a; Test02(){ value02a=20; } Test02( Test02(Test02(
Test02(intintint a, int a, a, a, intintint b){int b){b){b){ value02a=b*1000; value02a=b*1000;value02a=b*1000; value02a=b*1000; }}}}
} public class Sample05c{
public static void main(String[] args){ Test02 dt01 = new Test02(5,10);Test02(5,10);Test02(5,10);Test02(5,10);
System.out.println(dt01.value01a); System.out.println(dt01.value02a); } }
コンソールに
と表示される。
10
10000
引数
5
と
10
で
インスタンス生成
value02a
を
初期化。
10*1000に。 value02a; value01a; Test01(); Test01(int a); Test02(); Test02(int a, int b); dt01初期化されてない
value01a
は、これで初期化。
10に。23/33
アブストラクトクラス
と
アブストラクトメソッド
24/33アブストラクトとは
クラスを書く際に、拡張されることを前提に、クラスを書
くことができる。
アブストラクトクラス
アブストラクトクラスは、拡張されることが前提なので、
それ自身をクラスにするインスタンスは作れない。
アブストラクトクラスの中では、拡張時にオーバーライド
されることを前提に、メソッドを書くことができる。
アブストラクトメソッド
アブストラクトメソッドは、サブクラス内でオーバーライ
ドしないと、コンパイル時にエラーが出る。
25/33
アブストラクトクラス
拡張されることを前提としたクラス
書式:通常のクラスの書き方に
abstract
とつける。
abstract abstract abstract abstract 修飾子 class クラス名{ クラスと同じように、 変数の宣言 コンストラクタ メソッド 等を書く } abstract abstract abstract abstract 修飾子 class クラス名{ クラスと同じように、 変数の宣言 コンストラクタ メソッド 等を書く } 26/33アブストラクトクラスの例
abstract abstract abstractabstract class Test01{ void test01(){
System.out.println("Test 01"); }
}
class Test02 extends Test01{ void test02(){
System.out.println("Test 02"); }
}
public class Sample06a{
public static void main(String[] args){ Test02 dt01 = new Test02();
} }
アブストラクトクラス
アブストラクトクラス
アブストラクトクラス
アブストラクトクラス
Test01 dt01 = new Test01();はできない。
Test01
をスーパークラス
とするサブクラス
Test02
27/33
アブストラクトメソッド
サブクラスで、オーバーライドされる前提のメソッド。
サブクラス内でオーバーライドされないと、コンパイル時
にエラーが出る。
書式:メソッドに
abstract
とつける。
abstract abstract abstract abstract 修飾子 class クラス名{ 略 abstract abstract abstract abstract 修飾子 返値の型 メソッド名(引数); } abstract abstract abstract abstract 修飾子 class クラス名{ 略 abstract abstract abstract abstract 修飾子 返値の型 メソッド名(引数); }必
必
必
必ず
ず
ずオーバーライド
ず
オーバーライド
オーバーライド
オーバーライドされるため
されるため
されるため
されるため、
、
、
、
実際
実際
実際
実際に
に
に行
に
行
行う
行
う
う
う内容
内容
内容は
内容
は、
は
は
、
、
、ここには
ここには
ここには
ここには書
書
書
書かない
かない
かない
かない
28/33アブストラクトメソッドの例
abstract abstract abstractabstract class Test01{ void test01(){ System.out.println("Test 01"); } abstract abstract abstract
abstract void test02(); }
class Test02 extends Test01{ void test02(){
System.out.println("Test 02"); }
}
public class Sample06b{
public static void main(String[] args){ Test02 dt01 = new Test02();
} }
アブストラクト
アブストラクト
アブストラクト
アブストラクト
クラス
クラス
クラス
クラス
Test01
を
スーパークラス
とする
サブクラス
Test02
アブストラクト
アブストラクト
アブストラクト
アブストラクト
メソッド
メソッド
メソッド
メソッド
必
必
必
必ず
ず
ず
ずオーバーライド
オーバーライド
オーバーライド
オーバーライド
29/33
クラスの継承について(追記)
30/33クラスの拡張について
クラスを拡張するとき、スーパークラスとして利用できる
のは、ただ
1
つだけ。
2
つのクラスをスーパークラスとして持つことはできない。
class Test02 extends Test01,Test03Test01,Test03Test01,Test03Test01,Test03{ クラスと同じように、 変数の宣言 コンストラクタ メソッド 等を書く }
class Test02 extends Test01,Test03Test01,Test03Test01,Test03Test01,Test03{ クラスと同じように、 変数の宣言 コンストラクタ メソッド 等を書く }
こういうことはできない
こういうことはできない
こういうことはできない
こういうことはできない
31/33
定数
定数
今まで使ってきた
i=100;
の
100
とか、
System.out.println("test data")
の"test data"を
定数
定数
定数
定数
と言う。
文字通り、値を変更できない。
定数にも色々あります。
100
とか
200
のような、数値定数
"Test Data"
のように、文字列を
""
で囲った文字列定数
'A'
や
'z'
のように、
1
文字を
''
で囲った文字定数
さまざまな定数
100L
末尾にLをつける
明示的にlong型を指定した
10進数数値定数
100
そのまま値を書く
10進数数値定数
0.5e2
値1e値2
数値定数の指数表現(double型)
値1×10
値20x100
先頭に0xをつける
16進数数値定数
0100
先頭に0をつける
8進数数値定数
例
書き方
true
ture もしくは
false
論理定数
例:
public class Sample06c {
public static void main(String[] args) { int data01=100100100;100
int data02=010001000100;0100 int data03=0x0x0x1000x100100;100 double data04=0.50.50.50.5; double data05=0.5e20.5e20.5e20.5e2; char data06='a''a''a''a'; char data07=''''¥¥¥¥n'n'n'n';
System.out.println("Test"Test"Test"Test¥¥¥¥t1"t1"t1"t1" + data07 + "Test 2""Test 2""Test 2""Test 2"); }
}
public class Sample06c {
public static void main(String[] args) { int data01=100100100100;
int data02=0100010001000100; int data03=0x0x0x0x100100100100; double data04=0.50.50.50.5; double data05=0.5e20.5e20.5e20.5e2; char data06='a''a''a''a'; char data07=''''¥¥¥¥n'n'n'n';
System.out.println("Test"Test"Test"Test¥¥¥¥t1"t1"t1"t1" + data07 + "Test 2""Test 2""Test 2""Test 2"); } } 先頭に0がついている と8進数表記の意味に 先頭に0xがついている と16進数表記の意味に 指数表現。値1e値2だと、 値1×10値2に
赤色の太文字のは、
全部定数
¥n や ¥t は、エスケープ文字 と言われる、特殊な文字。 ¥nは改行、 ¥tはタブ。System.out.println
は、値を出力するときは、
10
進表記で出力します
特殊な意味をもつ文字
代表的なモノは、以下の通り
エスケープ文字
¥¥
¥
¥r
行頭への復帰
¥'
'
¥"
"
¥t
タブ
¥n
改行
¥b
バックスペース
書き方
記号定数
記号定数を宣言することができる。
値を変更することができない変数のように使うことができる。
可読性とかを向上するために使用したりする。
使うためには、あらかじめ宣言する必要がある。
宣言の仕方は、
定数名は、慣習として、全部 大文字 で書く。
たとえば、
MAX_VALUE
という記号定数を、整数値
65535
とし
て宣言するなら、
のようにする。
final
int MAX_VALUE=100;
final
型 定数名
=
値
;
記号定数の例
public class Sample06d {
public static void main(String[] args) { final int MAX_VALUE=100;
int temp01=50; System.out.println(temp01<MAX_VALUE); temp01=150; System.out.println(temp01<MAX_VALUE); } }
public class Sample06d {
public static void main(String[] args) { final int MAX_VALUE=100;
int temp01=50; System.out.println(temp01<MAX_VALUE); temp01=150; System.out.println(temp01<MAX_VALUE); } } 文字定数 MAX_VALUEを100 として宣言。 整数型の変数temp01を、初期値 50として宣言。 temp01と MAX_VALUEを 比較して、 結果を出力。 temp01と MAX_VALUEを 比較して、 結果を出力。 変数temp01の値に150を代入。 MAX_VALUEは定数なので、 後から値を代入するようなことはできない 38/33
型変換とキャスト
39/33
自動型変換(オートキャスト)の例
public class Sample06e {
public static void main(String[] args){ int idt=100;
double ddt=50.2; ddt
ddtddt ddt====idtidtidt;;;;idt
System.out.println(ddt); }
}
public class Sample06e {
public static void main(String[] args){ int idt=100;
double ddt=50.2;
ddt ddt ddt ddt====idtidtidtidt;;;;
System.out.println(ddt); } }
次のようなプログラムの場合
……
。
自動的に型変換を行い、
情報を失うことなく
代入してくれる。
この例だと、
double
型の変数
ddt
には
100
という値が代入されます。
double
型の変数に
整数型の変数の値を
代入している!
40/33自動型変換
Javaでは、自動的に型変換が行われる。
型の違う変数へ代入のときなど
例:
double の変数に
int を代入
情報を失うことがないように変換する。
int
から
double や、float から
double は、情報を
失うことなく、きちんと変換する。
情報を失う場合は、コンパイルでエラーがでる。
例1:
int型の変数に50.5を代入
例2:
int型の変数にdouble型の変数の値を代入
41/33
コンパイルでエラーが出る例
public class Sample06f {
public static void main(String[] args){ int idt=100; double ddt=50.2; idt idtidt idt====ddtddtddt;;;;ddt System.out.println(idt); } }
public class Sample06f {
public static void main(String[] args){ int idt=100; double ddt=50.2; idt idt idt idt====ddtddtddtddt;;;; System.out.println(idt); } }
次のようなプログラムの場合
……
。
Java
では、情報が落ちる場合は、
コンパイル時にエラーが出る。
整数型の変数に
double
型の変数の値を
代入している!
42/33強制的な型変換(キャスト)
強制的に型変換を行うこともできる。
書式
(
(
(
(型
型
型)
型
)
)変数名
)
変数名
変数名
変数名
(
(
(
(型
型
型
型)
)
)
)変数名
変数名
変数名
変数名
(
(
(
(型
型
型)
型
)
)定数
)
定数
定数
定数
(
(
(
(型
型
型
型)
)
)
)定数
定数
定数
定数
例えば、double 型の定数
50.5 を、整数型に変換した
い場合、
のようにする。
(
(
(
(int
int
int
int)
)
)50.5
)
50.5
50.5
50.5
(
(
(
(int
int
int)
int
)
)
)50.5
50.5
50.5
50.5
上のものを
int型の定数
idtに代入したいなら、
のようにする。
idt
idt
idt
idt=(
=(
=(int
=(
int
int
int)
)
)
)50.5;
50.5;
50.5;
50.5;
idt
idt
idt
idt=(
=(
=(
=(int
int
int)
int
)
)
)50.5;
50.5;
50.5;
50.5;
43/33
明示的な型変換の例
public class Sample06g {
public static void main(String[] args){ int idt=100;
double ddt=50.2; idt
idtidt
idt=(=(=(=(intintintint))))ddtddtddt;;;;ddt
System.out.println(idt); }
}
public class Sample06g {
public static void main(String[] args){ int idt=100;
double ddt=50.2;
idt idt idt
idt=(=(=(int=(intintint))))ddtddtddtddt;;;;
System.out.println(idt); } }