円を表すクラス Circle を定義せよ。

【問題 1】基本確認と例外の問題 ( 部分点有 10 点 )
様々な処理において,不正な値を使用してしまったときに投げる例外を考えておくと便利である。この例外を表すクラス
BadValueException を,Exception クラスのサブクラスとして定義せよ。
【問題 2 正解例】
class BadValueException extends Exception { }
【問題 2】基本確認と例外の問題 ( 部分点有 60 点 )
円を表すクラス Circle を定義せよ。クラス Circle は以下のメンバを持つ。
①中心点の X 座標,Y 座標,直径を表す private な double 型フィールド x, y, r
②フィールド x, y, r を初期化する public なコンストラクタ Circle( double x, double y, double r )
③ x の public なゲッタ double getX( ),x の public なセッタ void setX ( double x )
④ y の public なゲッタ double getY( ),y の public なセッタ void setY ( double y )
⑤ r の public なゲッタ double getR( ),r の public なセッタ void setR ( double r )
※ただし,セッタ setR( ) が実引数として負の値を受け取ったときには,フィールド r に値を設定せずに BadValueException 型
例外オブジェクトを投げるようにせよ。したがって,メソッド setR( ) の定義にはそれに合わせた例外指定を行う必要がある事に
注意せよ。なお,BadValueException クラスは 問題 1 で定義済みとして扱って良い。
⑥円の面積を計算して返すメソッド double calcArea( )
※なお,円の面積は,半径 × 半径 × 円周率 で求まる。円周率は java.lang.Math.PI を使うこと。
⑦次の様な処理 (1)〜(3) を順次を行う public static void main( String[ ] args ) メソッド。
(1) Circle 型変数 c を宣言し,中心の 2 次元座標が ( 0.0, 0.0 ) で,半径 1.0 の円を表す Cricle 型オブジェクトを生成して
その参照値で c を初期化する。
(2) try ブロックの中で,c が表す円の半径の値を c.setR( ) セッタを使って 2.0 に変更し,c.calcArea( ) メソッドを呼び出し
て,c の表す円の面積を System.out.println( ) メソッドで表示する。
(3) つづく catch ブロックは,BadValueException 型例外を受け取る様に定義し,そのブロック内で "a bad radius value!" と
表示する。
まずクラスの外枠から書こう (4 点 )
【問題
2 正解例】
class Circle {
private double x, y, r;
public Circle( double x, double y, double r ) {
this.x = x; this.y = y; this.r = r;
}
public double getX( ) { return x; }
public void setX( double x ) { this.x = x; }
public double getY( ) { return y; }
public void setY( double y ) { this.y = y; }
public double getR( ) { return r; }
public void setR( double r ) throws BadValueException {
if( r < 0.0 ) throw new BadValueException( );
this.r = r;
}
public double calcArea( ) {
return r * r * java.lang.Math.PI;
}
public static void main( String args[ ] ) {
Circle c = new Circle( 0.0, 0.0, 1.0 );
try {
c.setR( 2.0 );
System.out.println( c.calcArea( ) );
}
catch( BadValueException e ) {
System.out.println( "a bad radius value!" );
}
}
}
…① (2 点 ×3=6 点 )
…② (5 点 )
…③ (5 点 )
…④ (5 点 )
…⑤ (10 点 )
…⑥ (5 点 )
…⑦ (main メソッドの外枠 5 点 )
…(1) (5 点 )
…(2) (5 点 )
…(3) (5 点 )
【問題 3】スレッドの問題 ( 部分点有 30 点 )
皿にのった沢山のハンバーグを二人のフードファイターが取り合って食べる,という
早食い競争のシミュレーションをスレッドを使って行う。皿上のすべてのハンバーグが
食べられた時点で,より多くのハンバーグを食べた方が勝ちとする。
ハンバーグをのせる皿を表すクラス Dish の定義は右のようになっている。Dish の
メンバーは次の通り。
① この皿にのっているハンバーグの残数を表す private な int 型のフィールド n
② n を初期化する public なコンストラクタ
③ n の public なゲッタ int getN( ),n の public なセッタ void setN( int n )
class Dish {
private int n;
public Dish( int n ) { this.n = n; }
public int getN( ) { return n; }
public void setN( int n ) { this.n = n; }
}
フードファイターを表すスレッドクラス FoodFighter を定義せよ。クラス FoodFighter は以下のメンバを持つ。
① private な Dish 型フィールド d (d は,ハンバーグを載せた皿を表している )
② d を初期化する public なコンストラクタ public FoodFighter( Dish d )
③ オーバライドされた run( ) メソッド。次の様な処理で,皿 d 上のハンバーグの在庫から 1 個ハンバーグを食べることができる。
if( d.getN( ) > 0 ) {
d.setN( d.getN( ) - 1 ); System.out.println( "1 個食べた。" );
}
そこで,この処理を繰り返し処理の中で行い,皿の上のハンバーグが残っているかぎり食べ続ける様に run() メソッドをオーバラ
イドせよ。
※ハンバーグの在庫より多いハンバーグが食べられてしまうような矛盾が起こらないように,クリティカルセクションをしっかり
設定すること。また,各フードファイターが 1 個ハンバーグを食べるたびに,他のフードファイターにもハンバーグを食べられ
るチャンスを残しておくこと ( 言い方を変えると,一方のフードファイターが皿を独占するようなことがないようにすること )。
なお,実際にフードファイトの試合を行う main( ) メソッドを含むクラス Game の定義を,解答欄の最後に掲載するので参考にせよ。
【問題 3 正解例】
class FoodFighter extends Thread {
まずクラスの外枠から書こう (5 点 )
private Dish d;
…① (2 点 )
public FoodFighter( Dish d ) { this.d = d; }
…② (3 点 )
public void run( ) {
while( d.getN( ) > 0 ) {
synchronized( d ) {
if( d.getN( ) > 0 ) {
d.setN( d.getN( ) - 1 );
System.out.println( "1 個食べた。" );
}
}
}
}
…③ (run メソッドをオーバライド:5 点 )
…③ ( 繰り返してケーキの在庫が
あるかぎり食べ続ける様に定義されて
いる:5 点 )
…③ ( クリティカルセクションの指定が正しい:5 点 )
…③ ( ロック用オブジェクトの指定が正しい:5 点 )
}
参考:この部分は,右の様にしてはいけない。
なぜなら,最初に d からロックを得た
FoodFighter 型オブジェクトが,ロック
を保持している間にすべてのハンバーグ
を独占して食べてしまうからである。
正解例のように,繰り返しの内側にクリ
ティカルセクションを設定する必要が
ある。
synchronized( d ) {
while( d.getN( ) > 0 ) {
if( d.getN( ) > 0 ) {
d.setN( d.getN( ) - 1 );
System.out.println( "1 個食べた。" );
}
}
}
class Game {
public static void main( String[] args ) {
Dish d = new Dish( 20 ); // ハンバーグが 20 個のった皿を用意する
FoodFighter akira = new FoodFighter( d );
FoodFighter ichiro = new FoodFighter( d );
akira.start();
ichiro.start();
}
}