Java超入門

目次

  1. 最初のプログラムを作る
    1. eclipseを使ってJavaプログラムを書く
    2. 基本的な計算プログラムを書く
      1. キーボードからデータを入力する
      2. コンソールウィンドウに結果を表示する
    3. プログラミング上の注意
  2. グラフィックスを扱う
    1. アプレットを使う
    2. アプリケーションでウィンドウを作る
  3. GUIを使う
    1. マウス割り込み処理
    2. ボタンの割り込み処理
  4. アニメーション
    1. スレッドの扱い
    2. オフスクリーン


最初のプログラムを作る

eclipseを使ってJavaプログラムを書く

  1. 「ファイル」→「新規」→「プロジェクト...」メニューを選び、
  2. 「Javaプロジェクト」をクリックしてプロジェクト名を入力する
  3. 「新規Javaパッケージ」アイコンをクリックして(あるいは、「ファイル」→「新規」→「パッケージ」メニューを選ぶ)パッケージ名を英小文字で入力する
  4. 「新規Javaクラス」アイコンをクリックして(あるいは、「ファイル」→「新規」→「クラス」メニューを選ぶ)クラス名を英小文字(半角)で入力する(先頭の文字を大文字にするのが慣例)
  5. その入力画面の下の方にある「どのメソッドスタブを作成しますか?」というところにリストされている「public static void main(String[] args)」にチェックマークを入れる
  6. 表示されるプログラムの「public static ... {」の最後をクリックして、「Enter」キーを押し、「System.out.println("Hello Java world.");」と入力する(""の中を除いて、一字一句この通りに入力しなければいけない)
  7. ファンクションキーのF11を押す、あるいは、「実行...」ボタン(緑の○の中に白抜きで右向き三角形がある)をクリックする(あるいは「実行」→「実行」メニューを選ぶ)
  8. これで、下のコンソールウィンドウに「Hello Java world.」という文字列が表示される(ハズ)

完成したプログラムの例

// プログラム例1
package stepByStep;

public class MyApplication1 {
        public static void main(String[] args) {
                System.out.println("Hello Java world.");
        }
}

プログラムの解説

以下のプログラム例ではパッケージ名は省略する。

基本的な計算プログラムを書く

キーボードから入力して、計算して、表示する、という一連の作業をプログラムに書く。基本的なプログラミング作法はC言語と同じなので、詳しくは成書を参考にされたい(たとえば、「誰でも勉強すれば分かるC言語プログラミング入門」)。

// プログラム例2
// *1
import java.util.*;

public class MyApplication {
        public static void main(String[] args) {
// *2
                Scanner keyboardInput = new Scanner(System.in);
                double dollar; 
                int yen, price;
                while(true) {
                        System.out.print("1ドルは何円ですか? ");
// *3
                        dollar = keyboardInput.nextDouble();
// *4
                        System.out.print("ドルの買い物金額(端数は切り捨て)を入力して下さい ");
// *5
                        price = keyboardInput.nextInt();
                        yen = (int)(dollar * price);
// *6
                        System.out.println("それは円に換算すると "+yen+" 円です");
                }
        }
}

プログラムの解説

mainメソッドが大きくなっただけ。最初の1行はシステムの用意したプログラムを利用するための手続き。次の行はこの後で説明する。次の2行は変数を宣言している。 double,int はCと同じように、実数型、整数型の変数を指定する。while(true) は無限ループを表す。ループの中の命令群は、この後で説明する。

キーボードからデータを入力する

  1. キーボードから(System.in)データを入力するためのクラス(Scanner)のインスタンス(という)を作成する*2)
  2. Scannerクラスを使うために「java.util.*」というパッケージを読み込む(import)(プログラム例の *1)
  3. キーボードから入力されたデータをプログラムに取り込む。Double型として読み込む場合は「nextDouble()」を使い、int 型として読み 込む場合は「nextInt()」を使う(nextDouble(), nextInt() Scannerクラス内で定義されているメソッドの名称)(プログラム例 *3, *5)

豆知識 このように、クラス毎に定義されたメソッドを呼び出し て計算を実行する、というのが基本的なJavaの計算手順である。メソッドがどのクラスで定義されているのかを指定するために、メソッドの前に「クラス名 +「.」、あるいは「クラスのインスタンス」+「.」と書く。プログラム例1でも出てきた「System.」もその形式で書かれている。この場合はSystemというクラスがあって、その中のout.printlnというメソッドを実行する、と解釈できる。

「クラス名」+「.」+「メンバー名」
「クラスのインスタンス名」+「.」+「メンバー名」

豆知識 インスタンスを訳すと「実例」だが、この場合は、「実際に動くもの」というような意味で使われている。プログラムはクラス単位で構成される、と説明したが、クラスの定義プログラムはいわば見本のようなもの で、実際に使う場合のその「実例」を作って、それを動かす、と考えるとよい。見本は必要なときにいつでも使えるようにしておきたいので、実際に使う場合は そのコピーを取って使う、と考えても良い。コピーは見本と待った同じ機能を持っているので、例えば、上のプログラム*3のように 「keyboardInput.nextDouble」と書いたものは「Scanner.nextDouble」と書いたものと同じ機能を有する。

コンソールウィンドウに結果を表示する

最初に作ったプログラムのように、文字列を表示するために「System.out.print("...");」あるいは「System.out.println("...");」という命令を使う。「println」の場合は、文字列を表示した後に改行する。計算結果を表示する場合も、プログラム例2の(*6)のように、「+」を使って変数の内容を文字列に変換して表示させる。実数の場合、すべての桁が文字列に変換されるので、あまり見た目が良くない。

Cで使われる書式付きの表示命令であるprintfを使うことができる。たとえば、プログラム例2の(*6)は次のように書いても良い。

System.out.printf("それは円に換算すると %d 円です", yen);

プログラミング上の注意

変数の宣言は使う前であればどこにおいても構わない。二つの変数の入れ替えの際に使われる変数のように、その場限りの変数は使うときに宣言する、ということがよく行われている。ただし、変数の有効範囲に注意すること。良く間違いやすいのは、for文の中で宣言した変数をfor文の外で参照するということである。たとえば、for文の制御変数はそのときに宣言するというスタイルがよく使われる(for(int i=0; i<n; i++) {...})。ある条件を満たしたらbreakして、そのときのiの値を使って後処理する、というようなアルゴリズムを使う場合も多いが、この場合、「int i」はfor文の中だけで有効なので、ループの外ではiは未定義状態になる。

Cで普通に使われるポインタ記号「*p」は使えない。しかし、アドレス渡しは普通に行われている。

もどる


グラフィックスを扱う

計算結果を数値(文字列)で表示させるだけならば、コンソールウィンドウを使う今までの方法で十分。しかし、グラフを表示させたい場合、テキスト表 示用のコンソールウィンドウを使うわけにはいかないので、グラフィックス用のウィンドウを作って、そこに描画する、という仕掛けを作る必要がある。

アプレットを使う

ウィンドウを自前で作るのもそれほどむつかしくはないが、ブラウザをウィンドウとして利用する方法が簡便である。プラウザを利用するプログラムはアプレットと呼ばれる(アプレットとは簡単なアプリケーションという意味である)。

// プログラム例3
// *1
import java.applet.*;
import java.awt.Graphics;

// *2
public class MyApplet1 extends Applet {
// *3
	private static final long serialVersionUID = 1L;
// *4
	public void paint(Graphics g) {
// *5
		g.drawString("Hello JAVA", 40, 30);
		g.drawRect(50,30,100,50);
		g.drawOval(100, 50, 100, 80);
	}
}

プログラムの説明

ブラウザを使うために必要なメソッドはJavaのシステムプログラムに用意されているAppletクラスで定義されているのでそれをベースにすればよい。その仕掛けがクラスの「継承」という考え方である。それを*2のように書く。

 継承はオブジェクト指向プログラムの決まった用語であるが、英単語のextendsをそのまま素直に訳して「拡張」の方が分かりやすいのではないかと思うので、以下では「拡張する」と言うことにする。

拡張するためには元のプログラムを参照しなければいけないので「java.applet.*」 というパッケージを読み込むために*1のimport文が必要である。また、「extends Applet {」と入力して改行したとたんに「public clase ...」の行に警告マークが表示される。そのマークを消すために*3が必要となる。どう使われるか分からないが、書かないと警告マークを見続けるのはスト レスなので、こう書く習慣にする。

Appletを拡張した場合、その中に*4のようなpaintメソッドを定義した場合は、必ず最初に実行するという約束になっているので、それを利用する。実際の描画は*4にあるGraphicsクラスを使う。そのために「java.awt.Graphics」というパッケージを読み込む必要がある(*1)。

Graphicsクラスのインスタンスgを使って、「g.draw...」と書くと、Graphicsクラスで定義されているメソッドが呼び出されて実行される。「drawString」は文字を書く、「drawRect」は長方形を描く、「drawOval」は(楕)円を描くメソッドである。どのようなメソッドがあるか、引数をどのように指定するかということは、コンテンツアシスト機能で、ある程度知ることができる。

アプリケーションでウィンドウを作る

ウィンドウズで普通に見られるウィンドウはJaveの用意しているAWT(Abstract Window Toolkit)を利用することで簡単につくることができる。

アプレットがAppletクラスを拡張したように、AWTの持っているFrameクラスを拡張するとウィンドウを表示させることができる。次のプロ グラムを実行すると、普段良く見慣れたウィンドウが出現する。タイトルバーには「私のフレーム」という文字列もあり、右上にはちゃんと「極小化」「最大 化」「クローズ」ボタンの三つのアイコンが並んでいる。「最大化」ボタンをクリックすると、ウィンドウが画面一杯に拡がる。たったこれだけのプログラムで 「あの」ウィンドウが生成できるとは、感激! 

// プログラム例4
// *1
import java.awt.*;

// *2
public class MyFrame1 extends Frame {
	private static final long serialVersionUID = 1L;
// *3
	MyFrame1(String title) {
		this.setSize(600,400);
		this.setTitle(title);
		this.setVisible(true);
	}
// *4
	public static void main(String[] a) {
		new MyFrame1("私のフレーム");
	}
}

Appletクラスを拡張した場合と同じように、クラス名の後に「extends Frame」を付け加えると、定義したクラスにシステムに用意されたFrameクラスのメソッドが使えるようになる(*2)。「private static ...」はアプレットの場合と同じ、警告メッセージを出させないための命令文である。通常のアプリケーションと同様、*4のmainメソッドが最初に実行 される。newは新規に何かを作成する場合に使われる。この場合はMyFrame1というクラスのインスタンス(コピーのようなもの)を新規に作る、とい う意味である。

*3はコンストラクタと言い、このクラスのインスタンスを作っ たときに最初に一回だけ実行される特別なメソッド(初期化ルーチン)である。この場合は大きさを決めて(setSize)、タイトルバーに文字列をセット し(setTitle)、見えるようにする(setVisible(true))という命令が書かれている。

この後、最後のカッコの前に、プログラム例3の*4に書かれているpaintメソッドをそのままそっくりコピーペーストすると、プログラム例3と同じようなグラフィックスが見られる。

ウィンドウは表示されたものの、終了しようとしてクローズボタンを押しても反応しない。 終了させる場合はコンソールウィンドウの上部にある赤い■をクリックする必要がある。それでは煩わしいので、クローズボタンをクリックしてウィンドウが閉 じるようしたい。しかし、それをするには、クリックしたことを察知して、そのときウィンドウを閉じる別のプログラムを起動させる、という仕掛けが必要があ る。その仕組みを理解するのは「割り込み処理」の知識が必要だが、勉強するのを待っていられないので、とりあえず、クローズボタンに反応するプログラムの作り方だけを書いておく。Frameクラスを拡張する場合は、常に、この命令群を書く、という習慣にする。

// プログラム例4a
import java.awt.*;
// *1 
import java.awt.event.*;

public class MyFrame1 extends Frame {
	private static final long serialVersionUID = 1L;

	MyFrame1(String title) {
		this.setSize(600,400);
		this.setTitle(title);
// *2
		this.addWindowListener(new MyWindowAdapter());
		this.setVisible(true);
	}
	public static void main(String[] a) {
		new MyFrame1("私のフレーム");
	}
// *3
	class MyWindowAdapter extends WindowAdapter { // ウィンドウを閉じる
		public void windowClosing(WindowEvent we) {
			System.exit(0);
		}
	}
}

追加したのは3箇所、*1は「割り込み処理」を行うメソッドの定義されているパッケージを組み込む命令、*2はこのプログラムに割り込まれたときに 動かすプログラムを指定する命令、*3の「MyWindowAdapter」クラスがウィンドウを閉じるという仕事をするプログラムである。これはメソッ ドではなく、内部クラスと呼ばれるプログラムの単位である。システムの用意しているWindowAdapterクラスを拡張している。System.exit()はコンソールウィンドウへの出力同様Systemクラスで定義されているメソッドで、ウィンドウを閉じる作業を記述している。

もどる


GUIを使う

一回限りのグラフではなく、実行段階でデータを取り替えながらその時々のグラフを描かせるというプログラムを作りたい。たとえば、マウスをクリック するとその位置情報を使って何かを描く、というように。その場合はウィンドウのクローズボタンに反応するプログラムを組み込んだ場合と同様に、マウスがク リックされた時に割り込んで優先的に処理するプログラムを追加する必要がある。

マウス割り込み処理

次のプログラムは、マウスをクリックすると、クリックされた点を中心にした円が描かれる、というものである。

// プログラム例5
import java.applet.*;
import java.awt.*;
// *1
import java.awt.event.*;

public class MyMouse0 extends Applet {
	private static final long serialVersionUID = 1L;
	int x=100, y=100;
// *2
	public void init() {
		this.setSize(400,300);
		this.addMouseListener(new MyMouseAdapter());
	}
	
	public void paint(Graphics gr) {
		gr.drawOval(x-15, y-15, 30, 30);
	}
// *3
	class MyMouseAdapter extends MouseAdapter {
		public void mouseClicked(MouseEvent me) {
			x = me.getX();
			y = me.getY();
			repaint();
		}
	}
} 

プログラムの説明

*3が割り込み処理のプログラム、*2はアプレットを動かしたときに最初に実行されるプログラム(initメソッド)で、その2行目に書かれている のが、マウスがクリックされた時に動かすプログラムを指定したもの、*1で、それらのプログラム内容が詳しく書かれたシステムで定義されたevent処理 プログラムを組み込む命令である。

*2の2行目は全部覚えていなくても、「this.」と入力するとコンテンツアシスト機能で候補メソッドが表示される(プルダウンメニュー)のでそこの中から選べばよい。「MyMouseAdapter()」はMouseAdapterクラスを拡張した内部クラスの名前なので、別の好きな名前で構わない。

*3の「getX(), getY()」はクリックされた点の座標を取り込むメソッドである。ウィンドウの左上隅を(0,0)として、横方向がX、縦方向がYである。 repaint()は新しいx、yの値を使って再描画するメソッドである。これによって、直前まで表示されていたグラフィックスは消去されて、新しい円が 表示される。

別のプログラム例(落書き帳)

マウスをドラッグしたり動かしたりしたことを検知して割り込み処理を行うこともできる。そのときはMouseMotionAdapterクラスを拡張した内部クラスを作って処理内容を定義する。処理内容はMouseAdapterの場合と同じように考えればよい。

// プログラム例6
import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class MyMouse2 extends Applet { 
	private static final long serialVersionUID = 1L;
	int x=0, y=0;
	
	public void init() {
		this.setSize(600, 480);
		addMouseListener(new MyMouseAdapter());
		addMouseMotionListener(new MyMouseMotionAdapter());
	}
	class MyMouseAdapter extends MouseAdapter {
		public void mouseClicked(MouseEvent me) {
			Graphics g = getGraphics();
			int x = me.getX();
			int y = me.getY();
			g.setColor(Color.white);
			g.fillRect(x-50, y-50, 100, 100);
			g.setColor(Color.black);
			g.dispose();
		}
	}
	class MyMouseMotionAdapter extends MouseMotionAdapter {
		public void mouseDragged(MouseEvent me) {
			Graphics g = getGraphics();
			int xx = me.getX();
			int yy = me.getY();
			if(Math.abs(x-xx) + Math.abs(y-yy) < 20) {
				g.drawLine(x, y, xx, yy);
			}
			x = xx; y = yy;
			g.dispose();
		}
	}
}

マウスをドラッグしたり、クリックしたりしてみて下さい。ドラッグが鉛筆、クリックが消しゴムのつもりです。

ボタンの割り込み処理

ボタンを作っておいて、マウスでクリックしたときにそのボタンに組み込まれたプログラムを実行する、というようなプログラムを作る場合も割り込み処理が必要である。次のプログラムはそのような割り込み処理を組み込んだもので、ボタンをクリックすると画面表示が変化する。

// プログラム例7
import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class MyButton extends Applet {
	private static final long serialVersionUID = 1L;
	int wPosition = 100;

	public void init() {
		this.setSize(400, 300);
// *1
		Button left = new Button("左へ");
		left.addActionListener(new MyListener());
		this.add(left);
		Button right = new Button("右へ");
		right.addActionListener(new MyListener());
		this.add(right);
	}
	public void paint(Graphics g) {
		g.fillOval(wPosition, 100, 60, 40);
	}
// *2
	class MyListener implements ActionListener {
		public void actionPerformed(ActionEvent ae) {
			if (ae.getActionCommand() == "右へ") wPosition += 10;
			else wPosition -= 10;
			repaint();
		}
	}
}

マウスの割り込み処理と違うのは、ボタンを作成して表示させる部分である。*1の最初の3行ではButtonクラスのインスタンスを作り、それに 「左へ」というラベルと付け、それがクリックされた時に動かすプログラムを指定し、アプレットに貼り付ける(this.add)という一連の動作を指定し ている。この三つ組みが基本である。

*2の割り込み処理では二つのボタンのどちらがクリックされたのかを識別して別々の動きをするように書かれている。クリックされたボタンの違いはボ タンのラベルで識別する。getActionCommand()はクリックされたボタンのラベル(文字列)を返すメソッド(関数)である。「右へ」ボタン がクリックされたらボールの位置を右へ、「左へ」ボタンがクリックされたらボールの位置を左へずらすという処理をしてからrepaintメソッドで再描画 している。

別のプログラム例(スロットマシンもどき)

// プログラム例8
import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class Slot extends Applet {
	private static final long serialVersionUID = 1L;
	boolean a, b, c;

	public void init() {
		this.setSize(400, 300);
		Button left = new Button("play");
		left.addActionListener(new MyListener());
		this.add(left);
	}
	public void paint(Graphics g) {
		if(a) g.fillOval(50, 100, 70, 70);
		else g.drawOval(50, 100, 70, 70);
		if(b) g.fillOval(150, 100, 70, 70);
		else g.drawOval(150, 100, 70, 70);
		if(c) g.fillOval(250, 100, 70, 70);
		else g.drawOval(250, 100, 70, 70);
		if(a && b && c) g.drawString("あたり!", this.getWidth()/2-10, 80);
	}
	class MyListener implements ActionListener {
		// 複数のボタンイベントは ActionEvent.getActionCommand() で識別する
		public void actionPerformed(ActionEvent ae) {
			if(Math.random() < 0.2) a = true; else a = false;
			if(Math.random() < 0.5) b = true; else b = false;
			if(Math.random() < 0.7) c = true; else c = false;
			repaint();
		}
	}
}

何回かボタンをクリックしてみて下さい。「あたり」の表示される確率はいくつくらいでしょうか。

もどる


アニメーション

テレビや映画は1秒間に数十コマの静止画を表示することによって人間の目には像が連続的に動いているように錯覚させる表示法である。パソコンでアニ メーションを表示させる場合も同じ手法を用いる。すなわち、絵の一部分を少しずつ変えたスライドを多数枚用意し、それを次から次へ表示させる。あまり高速 に表示させても識別できないので、強制的に少しずつ時間をおいて表示させる必要がある。この仕組みを実現するのがスレッドという技術である。

スレッドの扱い

スレッドというのはプログラムの実行単位で、今までも使われていたが、それを陽に意識する必要はなかった。しかし、強制的に作業を中断するにはス レッドを一時停止させる必要がある。そこで、Threadクラスのstartメソッドsleepメソッドを使ってスレッドの進行を制御する仕組みが導入さ れた。

次のプログラムは、ディジタルクロックを表示するものである。システムタイマー「Date」から現在時刻を1秒おきに取り込み、paintで表示させている。結果的に1秒ごとに表示が更新されるので、ディジタルクロックのように見える。

// プログラム例:ディジタルクロック

import java.applet.*;
import java.awt.*;
import java.util.*;
// *1
public class DigitalClock extends Applet implements Runnable {
	private static final long serialVersionUID = 1L;
// *2	
	public void init() {
		Thread th = new Thread(this);
		th.start();
	}
// *3
	public void run() {
		while(true) {
			repaint();
			try {
				Thread.sleep(999);
			}
			catch(Exception e) {
			}
		}
	}
// *4
	public void paint(Graphics g) {
		Date now = new Date();	
		g.setFont(new Font("Serif",Font.BOLD,24));
		g.drawString(now.toString().substring(0, 10), 10,70);		
		g.drawString(now.toString().substring(11, 19), 10,100);
	}
}

*1 の「implemens Runnable」、*2 の「Thread.start」、*3 の「run()」が必ず組で出てくる。

次のプログラムはボールを投げ上げたときの動きを連続的に表現したものである。

// プログラム例9
import java.applet.*;
import java.awt.*;
// *1
public class MyThread0 extends Applet implements Runnable {
	private static final long serialVersionUID = 1L;
	int x = 0;

	public void init() {
		this.setSize(300,300);
// *2
		new Thread(this).start();
	}
// *3
	public void run() {
		while(true) {
			try{
				x = x+2;
				if(x > 300) x = 0;
				repaint();
// *4
				Thread.sleep(10);
			}
			catch(Exception ex) {
			}
		}
	}
	public void paint(Graphics g) {
		int y = 200 - (int)(x*(1-x/300.0));
		g.fillOval(x, y, 20, 20);
	}
}

プログラムの説明

中核部分は*3のrunメソッドである。すぐにwhile (true)とあるので、常に無限ループで繰り返し実行される。try...catchを除いて読んでみると、最初の2行はボールの横座標を右へずらす命 令、次が再描画(repaint)、そして4行目にあるのが、スレッドの一時休止(sleep)命令である。sleep(10)の10は10ミリ秒休止す る、という意味である。これで、10ミリ秒ごとにボールを2ピクセルずつ右に移動させて現在地を表示させる、という作業を永遠に繰り返す、という命令群に なっている。10を100に変えれば更新スピードが遅くなるので、玉の動きが緩やかになる。

try...catchは割り込みが発生する可能性のある処理を実行させるときに使われる構文で、catchの後に割り込みが発生した場合の処理を(もしあれば)書いておく。

スレッドを開始する命令は*2のように書く。Thread(this)のthisは自分自身、という意味である。自分自身をスレッドと見なしてそれをスタートさせている。

スレッドはThreadクラスで定義されているので、それを拡 張したクラスを作ればよいようなものであるが、このクラスは、すでにAppletクラスを拡張して作られている。extendsの後には一つのクラス名し か書けないという制約があるので、そのような場合は、Threadクラスと同じような機能が定義されたRunnableimplementsすることで代用している。このようなやり方はインターフェースを実装する、と言われる。

結局

1.Runnableインターフェースを実装(implements)する
2.Thread(this).start() をnewする
3.run()メソッドでsleepさせながら画面を更新させる(repaint)

という手順でアニメーションを作ることができる

  1. Runnableインターフェースを実装(implements)する
  2. Thread(this).start() をnewする
  3. run()メソッドでsleepさせながら画面を更新させる(repaint)

オフスクリーン

プログラム例9を実行させると分かるが、動きは十分になめらかなのだがちらつきが激しい。これはpaintで画面を更新するときの仕方によるらし い。paintメソッドで直接描画する代わりに、仮想画面(オフスクリーン)を作り、そこに描画をして、完成した図を一枚の絵のように表示する、という仕 方をすることによって、ちらつきを緩和することができる。いわば、キャンバスの上で一々描かずに、どこかで描いた絵をキャンバスに貼る、というようなイ メージである。

// プログラム例10
public class MyThread05 extends Applet implements Runnable {
	private static final long serialVersionUID = 1L;
	int x = 0;
// *1
	Image img;
	Graphics gs;
	
	public void init() {
		this.setSize(300,300);
// *2
		img = this.createImage(300, 300);
		gs = img.getGraphics();
		new Thread(this).start();
	}
	public void run() {
		while(true) {
			try{
// *3
				int y = 200 - (int)(x*(1-x/300.0));
				gs.setColor(Color.white);
				gs.fillOval(x, y, 20, 20);
				x = x+2;
				if(x >300) x = 0;
				y = 200 - (int)(x*(1-x/300.0));
				gs.setColor(Color.black);
				gs.fillOval(x, y, 20, 20);
				repaint();
				Thread.sleep(10);
			}
			catch(Exception ex) {
			}
		}
	}
	public void paint(Graphics g) {
// *4
		g.drawImage(img, 0, 0, this);
	}
}

プログラムの説明

*1でImageクラスGraphicsクラスのインスタンスを作り、*2で仮想スクリーンの大きさを定義し、Graphicsのメソッドを適用する画面を定義する。これにより、gsを使ってGraphicsのメソッドを実行すると、imgで定義した仮想スクリーンに描画されることになる。

*4で実際に画面に表示する場合は、drawImageメソッドを使って、仮想スクリーンをそっくりそのまま描画するだけである。

仮想スクリーンを更新する場合は、消さない限りは前に描いたものも残っているので、積極的に前画面を消去する必要がある。ここでは、直前に描いたものが分かっているので、同じものを地の色、すなわち白色で描く(setColor(Color.white))ことで表示を消している。


Javaの文法、抜粋

変数宣言

変数は宣言してから使う。変数はint型、double型、boolean型、String型などがある。宣言の仕方は次の例の通り。配列を宣言する場合は、たとえば、int[] 型という型があると思えばよい。

int a = 0;
double x = 3.1;
boolean judge = false;
String s = "text";
int[] b = new int[100];
double[] z = new double[10000];
int[][] a = new int[100][100];

for(int i=0; i<n; i++) {...}

自分で変数の型(クラス)を定義することができる。

変数は使う前であれば、どこで宣言しても構わない。for 文の中の「int i」のように、プログラムの途中で宣言しても構わない。ただし、宣言した場所によって、その変数の有効範囲が決まる。for 文の中で宣言された変数は、for 文を抜けたときに未定義になる(for の途中で break させ、そのときの制御変数の値を利用する、という使い方はできない)。メソッド内で定義された変数はそのメソッドの内部だけでしか使えない。

条件文

計算結果、入力結果に応じて計算方法を変えたい場合に「if ...」「if ... else ...」などの構文を使う。

if(a > 0) b = 1; else b = 0;

b = a > 0 ? 1 : 0; // 上のif文と同じ

条件を記述する式を条件式という。条件式は比較演算子、論理演算子を使って、2項比較を組み合わせて作る。

比較演算子 意味
論理演算子 意味
>, >= より大きい、以上 && かつ
<, <= より小さい、以下 || または
==, != 等しい、等しくない ! ではない

特殊な条件文をテンプレートにしたものにswitch構文がある。int型の変数の値によって実行命令を変えたい場合に使う。

if(m == 0) { ... }
else if(m == 1) { ... }
else if(m == 2) { ... }
...
			// このような単調な繰り返しの場合は、次のように書ける
switch(m)
case(0) : { ... ; break; }
case(1) : { ... ; break; }
case(2) : { ... ; break; }
(以下これの繰り返し)
default : { ... }	// case(.)指定が無かった場合

while繰り返し構文

フィードバック構造を作るための基本はwhile構文である。ループを抜けるためにbreak文を使い、ループの途中をスキップするためにcontinue文を使う。

while(true) { n /= 2; m++; if(n == 0) break; }

do { ... } while();

while(x < 2) { x *= 1+r; }

for繰り返し構文

典型的な繰り返し構造をテンプレートにしたのがfor構文である。

「初期条件設定」→「判定」→「条件下での命令実行」→「制御変数の更新」→「判定」→「実行」→...

for(int i=0; i<n; i++) { x *= 1+1.0/i; }

サブルーチン(メソッド、関数)定義

ひとまとまりの作業手順はなるべくモジュール化(カプセル化)して、プログラム構造をはっきり見えるようにすると同時に作業負担を減らす、というこ とが、どんなプログラミング言語を使う場合にも重要である。javaの場合は、メソッドと呼ばれるサブルーチンを定義することができる。

int sign(double x) {
	if(x < 0) return -1;
	if(x > 0) return 1;
	return 0;
}