(windows XP版)
Java言語は1990年初頭にジェームス・ゴスリン(James Gosling)博士によって開発された言語として有名です。Java言語の仕様としては、C言語やC++言語から受け継がれていると見られる文法規則もたくさんあるようですので、C言語やC++言語になじみの深いユーザーにとっては、理解しやすいところも多いのではないかと考えられます。
かつてC言語は構造化言語、関数・手続き型と呼ばれていましたが、C++言語ではこれをベースにクラスという概念を取り入れました。また、さらに多くの機能を持つクラスライブラリーというものを充実させた結果、C++では言語はかなり複雑、難解な部分も散見されます。これに対してJava言語ではC++言語のクラス、構造体、共用体を一元化した「クラス」として統一的に使用できるように設計してありますので、コードを眺めてみると非常にすっきりとした感じを受けます。
さらに、Java言語では文字や画像をはじめ、音声などのマルチメディアを簡単に操作できるようなクラスライブラリーが提供されています。筆者も日ごろJava言語をよく利用しているというわけではありませんが、今回の「プログラム言語で日本語多めに」というテーマで、近年愛好者が急増しているJava言語を取り上げてみたいと思います。
詳しいJava言語の文法などについては、各自で専門書などを参考にされたらよいかと思います。今回試行した環境はサン・マイクロシステムズ社から提供されているJDK1.6.26
J2SDKバージョン1.4.0(少々古めです)をダウンロードしたものを使っております。これもインストール方法については、同社のインストール手順書などを参考にしてください。パソコンはいつものようにWindowsXPを使用しました。またJava言語が実行できる環境で、FLEXやC言語の処理系が動くような環境設定(パスが通るようにすることなど)が必要です。
また、C++言語編と同じように、日本語で書かれたJava言語ファイルの名前を仮にファイル1.jjavaとすると
>jjava ファイル1
というバッチコマンドによりファイル1.javaを生成し、さらに翻訳(javacによるコンパイル)を行い、Javaバイトコード(中間コード)であるファイル1.classを生成します。jjavaというFLEXで作成された日本語カスタマイザー実行プログラムは、C++言語の場合とほとんど同じ仕様です。この中間コードを実行するためには以下のように入力すれば、Javaインタープリターによりプログラムが実行されます。
>java ファイル1
やはりここで注意しなければならないことは、ほかの言語と同様に変数名、クラス名などをjp_str_***(***は数字)のような自動的に割り当てる適当な英数文字が、Javaで定義されたクラス名などの英数文字と衝突をしないようにすることです。(今回試行したバージョンでは、全クラス名を検索したところ、今回メーカーが提供しているクラス名の中には、幸い衝突するような文字列はありませんでした)
ここで、日本語定義の領域がかなり大きくなってきましたので、Java言語編ではC++言語編と同様、自分でよく使う予約語や演算子などの日本語定義部分をプログラムとは別に、外部である程度まとめて宣言できるようにしておきます。そして処理するときにバッチコマンドの機能を利用して、宣言ファイルと日本語Javaファイルを結合して、日本語定義部分を通常のJava言語に置き換えをするということにしました。
以下は、別に定義した日本語Java宣言ファイルの内容です。
#日本語定義 整数型 "int"
#日本語定義 文字型 "char"
#日本語定義 実数型 "float"
#日本語定義 論理型 "boolean"
#日本語定義 型なし "void"
#日本語定義 全域で使用可 "public"
#日本語定義 仲間内で使用可 "private"
#日本語定義 派生の仲間まで使用可 "protected"
#日本語定義 一つの実体だけ "static"
#日本語定義 引き継ぎ "extends"
#日本語定義 実装 "implements"
#日本語定義 もし "if"
#日本語定義 それ以外 "else"
#日本語定義 戻る "return"
#日本語定義 繰り返し "while"
#日本語定義 反復 "for"
#日本語定義 後判定反復 "do"
#日本語定義 対象作成 "new"
#日本語定義 振り分け "switch"
#日本語定義 場合分け "case"
#日本語定義 振り分け終了 "break"
#日本語定義 真 "true"
#日本語定義 偽 "false"
#日本語定義 かつ "&&"
#日本語定義 または "||"
// クラス関係
#日本語定義 はじまり "main"
#日本語定義 仲間の集まり "class"
#日本語定義 文字列の仲間 "String"
#日本語定義 窓枠の仲間 "Frame"
#日本語定義 字体の仲間 "Font"
#日本語定義 図画の仲間 "Graphics"
#日本語定義 文書領域の仲間 "TextArea"
#日本語定義 メニュー欄の仲間 "MenuBar"
#日本語定義 メニュー中項目の仲間 "Menu"
#日本語定義 メニュー小項目の仲間 "MenuItem"
#日本語定義 二次元図形描画の仲間 "Graphics2D"
#日本語定義 窓枠を適応させる仲間 "WindowAdapter"
#日本語定義 動作に対するご用聞き "ActionListener"
#日本語定義 動作に伴うでき事の仲間 "ActionEvent"
#日本語定義 整数の仲間 "Integer"
#日本語定義 整数値 "intValue()"
#日本語定義 文字列を整数に変換 "Integer.valueOf"
#日本語定義 表示する "System.out.println"
#日本語定義 終了する "System.exit(0)"
#日本語定義 窓枠ご用聞きの追加 "addWindowListener"
#日本語定義 動作ご用聞きの追加 "addActionListener"
#日本語定義 項目ご用聞きの追加 "addItemListener"
#日本語定義 動作が実行されたとき "actionPerformed"
#日本語定義 窓枠を閉じる "windowClosing( WindowEvent win_evnt )"
これ以降の例題では、プログラム内に上記の日本語定義の部分はありません。
はじめに、例3-1として西暦年を入力し、その年がうるう年かどうかを判定するプログラムを示します。これはC++言語編での例題から日本語プログラムを参考にして作ってみました。
//
西暦を入力し、その年がうるう年かどうかを判定する
#日本語定義 例題3─1 "ex1"
#日本語定義 引数
#日本語定義 その年
#日本語定義 年のデータ
#日本語定義 結果表示
#日本語定義 うるう年の判定
#日本語定義 うるう年である "1"
#日本語定義 うるう年ではない "0"
#日本語定義 がうるう年である "== 1"
#日本語定義 剰余計算 "%"
#日本語定義 が割り切れる "== 0"
#日本語定義 ならば ""
仲間の集まり 例題3─1{
全域で使用可 一つの実体だけ 型なし はじまり( 文字列の仲間 引数[]
)
{
整数の仲間 年のデータ = 対象作成 整数の仲間( 引数[0] ) ;
文字列の仲間 結果表示[] = {"うるう年ではない","うるう年である"};
表示する( "西暦" + 年のデータ.整数値 + "年は" + 結果表示[うるう年の判定( 年のデータ.整数値 )] );
}
一つの実体だけ 整数型 うるう年の判定(整数型 その年)
{
もし ( ( その年 剰余計算 400)が割り切れる
) ならば { 戻る うるう年である;}
それ以外 もし ( ( その年 剰余計算 100)が割り切れる ) ならば { 戻る うるう年ではない;}
それ以外 もし ( ( その年 剰余計算 4)が割り切れる ) ならば { 戻る うるう年である;}
戻る うるう年ではない;
}
}
例3─1
詳しいJava言語の文法についての解説はしませんが、例題3─1は日本語定義により、実はex1というクラス名となっています。Java言語ではファイル名も同じex1.javaとしておく必要があります。ほとんどのコードについてはC++言語編から流用しており、それをJava言語の文法に合うようにアレンジしました。
Java言語では豊富なクラスライブラリーが提供されておりますので、それをどういうふうに使いこなしていくのかが、使う人の力量ということになるのではないでしょうか。これは次のようなJava言語のコードに展開されます。
//
西暦を入力し、その年がうるう年かどうかを判定する
class ex1{
public static void main( String
jp_str_0[] )
{
Integer jp_str_2 = new Integer( jp_str_0[0] ) ;
String jp_str_3[] = {"うるう年ではない","うるう年である"};
System.out.println( "西暦" + jp_str_2.intValue() + "年は" + jp_str_3[jp_str_4(
jp_str_2.intValue() )] );
}
static int jp_str_4(int jp_str_1)
{
if ( ( jp_str_1 % 400)== 0 ) { return 1;}
else if ( ( jp_str_1 % 100)== 0 ) { return 0;}
else if ( ( jp_str_1 % 4)== 0 ) { return 1;}
return 0;
}
}
例3─1を展開したもの
次は例3-1のプログラムを実行させ、西暦を2000年、2010年としたときの結果です。
次の例は、平成1年(西暦1989年)の1月1日が日曜日であったことを利用して、指定した日の曜日を求めるプログラムです。西暦と年月日を入力すると、曜日と元号を表示するプログラムです。 ただし、1989年は平成元年ではありますが昭和の最後の週の年でもありますので、元号は「昭和64年/平成元年」としています。また、2019年の元号は「平成31年/令和元年」としています。 なお、1989年より小さい西暦年や2099年より大きい西暦年を入力するとプログラムは終了するようにもしています。
西暦から直接曜日を求める公式は世の中にあるようですが、今回はそれとは違ったアルゴリズムを用いております。まず1年365日は7で割った余りを求めると1になります。つまり、うるう年がなければ1年たつと曜日が1日ずれることになります。さらに、各月についても、うるう年がなければ毎月それぞれ規則的にずれます。このうるう年のずれについては、また別に計算して最後にすべての補正値を合計します。そして、この補正値の合計を7で割った余りを求めれば、指定した年月日の曜日が求められます。
年の補正値は、毎年1を足すだけで求められますが、月の補正値は表を用いております。しかし、うるう年の計算だけは、平成12年が西暦2000年という特殊な年ですので、毎年うるう年かどうかの判定を行い補正値を加算させました。
今回は、仲間の集まり(クラス)をいくつか分けて作成することにしました。また、宣言されているクラス内からだけアクセスすることができる仲間内で使用可(private)というアクセス修飾子を使ってデータのカプセル化を行っております。
また、パッケージ宣言というものを使用して、いくつかの独立したクラスファイルを同じディレクトリ内にまとめるようにします。パッケージ名は、「ex2」としました。まず「ex2」というディレクトリを作成して、その中に以下の日本語Javaプログラムである「ex2.jjava」を書き込みます。コンパイルは以下のように
>jjava ex2\ex2
と入力するとコンパイルできます。
//1989年(平成元年)1月1日が日曜日であったことを利用して、指定した日の曜日を求める
#日本語定義 例題3─2 "ex2"
#日本語定義 引数
#日本語定義 その年
#日本語定義 その月
#日本語定義 その日
#日本語定義 年のデータ "y_val"
#日本語定義 月のデータ "m_val"
#日本語定義 日のデータ "d_val"
#日本語定義 結果表示
#日本語定義 ならば " "
#日本語定義 の個数が正常 ".length == 3"
#日本語定義 年月日が正常範囲である
#日本語定義 曜日の表示データ
#日本語定義 うるうの介
#日本語定義 日数太郎
#日本語定義 曜日の丸
#日本語定義 例題3─2のファイルをまとめる "package ex2"
例題3─2のファイルをまとめる;
仲間の集まり 例題3─2{
全域で使用可 一つの実体だけ 型なし はじまり( 文字列の仲間[] 引数 ) {
もし ( 引数の個数が正常 )
ならば {
整数の仲間 年のデータ = 文字列を整数に変換( 引数[0] ) ;
整数の仲間 月のデータ = 文字列を整数に変換( 引数[1] ) ;
整数の仲間 日のデータ = 文字列を整数に変換( 引数[2] ) ;
うるう年計算の仲間 うるうの介 = 対象作成 うるう年計算の仲間();
もし ( うるうの介.年月日が正常範囲である( 年のデータ.整数値, 月のデータ.整数値, 日のデータ.整数値 ) )
ならば {
表示する( "西暦" +年のデータ.整数値 + "年" + 月のデータ.整数値 + "月" + 日のデータ.整数値 + "日は" );
日数計算の仲間 日数太郎 = 対象作成 日数計算の仲間();
整数型 合計補正日数 =
日数太郎.補正日数を求める( 年のデータ.整数値, 月のデータ.整数値,日のデータ.整数値 );
曜日の仲間 曜日の丸= 対象作成 曜日の仲間();
表示する( 曜日の丸.曜日の表示データ(合計補正日数 剰余計算 7 ) + "曜日です" );
もし ( 平成元年である ) ならば {
表示する( "また" + 年のデータ.整数値 + "年は" + "昭和64年/平成元年です");
}
それ以外 もし ( 平成である ) ならば {
表示する( "また" + 年のデータ.整数値 + "年は" + "平成" + (年のデータ-= 1988) + "年です");
}
それ以外 もし ( 令和元年である ) ならば {
表示する( "また" + 年のデータ.整数値 + "年は" + "平成31年/令和元年です");
}
それ以外 ならば {
表示する( "また" + 年のデータ.整数値 + "年は" + "令和" + (年のデータ-= 2018) + "年です");
}
}
}
}
}
#日本語定義 うるう年計算の仲間 "ex2$urutoshi"
#日本語定義 うるう年の判定
#日本語定義 うるう年の補正
#日本語定義 補正日数
#日本語定義 うるう年である "true"
#日本語定義 うるう年ではない "false"
#日本語定義 がうるう年である "== true"
#日本語定義 剰余計算 "%%"
#日本語定義 が割り切れる "== 0"
#日本語定義 が割り切れない "!= 0"
#日本語定義 年が正常範囲 "((1989 <= y_val)&&(y_val <= 2099))"
#日本語定義 月が正常範囲 "((1 <= m_val)&&(m_val <= 12))"
#日本語定義 年月の正常範囲 "(1989 <= y_val)&&((1 <= m_val)&&(m_val <= 12))"
#日本語定義 平成元年である "(y_val == 1989)"
#日本語定義 平成である "((1989 < y_val)&&(y_val < 2019))"
#日本語定義 令和元年である "(y_val == 2019)"
#日本語定義 月の最大日数
仲間の集まり うるう年計算の仲間 {
仲間内で使用可
整数型 補正日数 = 0;
整数型 月の最大日数[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
全域で使用可
論理型 うるう年の判定(整数型 その年) {
もし ( ( (その年 剰余計算 4)が割り切れる ) かつ
( (その年 剰余計算 100)が割り切れない) または
( (その年 剰余計算 400)が割り切れる ) )
ならば { 戻る うるう年である; }
それ以外 ならば 戻る うるう年ではない;
}
整数型 うるう年の補正( 整数型 年のデータ, 整数型 月のデータ ) {
整数型 補正日数= 0;
もし ( ( うるう年の判定( 年のデータ ) がうるう年である ) かつ ( 月のデータ <= 2 ) )
ならば 補正日数 = -1;
反復 ( 整数型 その年 = 1989; その年 <= ( 年のデータ ); ++その年 ) {
もし ( うるう年の判定( その年 ) がうるう年である ) ならば ++補正日数;
}
戻る(補正日数);
}
論理型 年月日が正常範囲である( 整数型 年のデータ, 整数型 月のデータ, 整数型 日のデータ ) {
もし ( 年が正常範囲 かつ 月が正常範囲 かつ ( 1 <= 日のデータ ) )
ならば {
もし ( ( 日のデータ <= 29 ) かつ ( 月のデータ == 2 ) かつ うるう年の判定( 年のデータ ) )
ならば { 戻る 真; }
それ以外 もし ( 日のデータ <= 月の最大日数[月のデータ-1] )
ならば { 戻る 真; }
}
戻る 偽;
}
}
#日本語定義 曜日の仲間 "ex2$youbi"
#日本語定義 七つの曜日
仲間の集まり 曜日の仲間 {
仲間内で使用可
文字列の仲間 七つの曜日[] = {"日","月","火","水","木","金","土",};
全域で使用可
文字列の仲間 曜日の表示データ(整数型 その日) {
戻る 七つの曜日[その日];
}
}
#日本語定義 日数計算の仲間 "ex2$7_youbi"
#日本語定義 月の補正日数
#日本語定義 補正日数を求める
#日本語定義 合計補正日数
仲間の集まり 日数計算の仲間 {
仲間内で使用可
整数型 月の補正日数[] = { 0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5 };
整数型 合計補正日数;
全域で使用可
整数型 補正日数を求める( 整数型 その年, 整数型 その月, 整数型 その日 ) {
うるう年計算の仲間 うるうの介 = 対象作成 うるう年計算の仲間();
合計補正日数 = (その年 - 1989) + 月の補正日数[その月-1]
+ その日 - 1 + うるうの介.うるう年の補正(その年,その月);
戻る 合計補正日数;
}
}
例3─2
例3─2では、少し入力のチェックにもこだわってみました。引数の数が違ったり、年、月、日が範囲外のものを入力しても計算は行われません。しかし、数字以外のものを入力すると、システムからエラーメッセージが返されますが、これは「try」、「catch」、「throw」という例外処理によりプログラム側で解決もできますが、今回は割愛させていただきます。これは次のようなJava言語のコードに展開されます。
//1989年(平成元年)1月1日が日曜日であったことを利用して、指定した日の曜日を求める
package ex2;
class ex2{
public static void main( String[] jp_str_0 ) {
if ( jp_str_0.length == 3 )
{
Integer y_val = Integer.valueOf( jp_str_0[0] ) ;
Integer m_val = Integer.valueOf( jp_str_0[1] ) ;
Integer d_val = Integer.valueOf( jp_str_0[2] ) ;
ex2$urutoshi jp_str_7 = new ex2$urutoshi();
if ( jp_str_7.jp_str_5( y_val.intValue(), m_val.intValue(), d_val.intValue() ) )
{
System.out.println( "西暦" +y_val.intValue() + "年" + m_val.intValue() + "月" +
d_val.intValue() + "日は" );
ex2$7_youbi jp_str_8 = new ex2$7_youbi();
int jp_str_17 =
jp_str_8.jp_str_16( y_val.intValue(), m_val.intValue(),d_val.intValue() );
ex2$youbi jp_str_9= new ex2$youbi();
System.out.println( jp_str_9.jp_str_6(jp_str_17 % 7 ) + "曜日です" );
if ( (y_val == 1989) ) {
System.out.println( "また" + y_val.intValue() + "年は" + "昭和64年/平成元年です");
}
else if ( ((1989 < y_val)&&(y_val < 2019)) ) {
System.out.println( "また" + y_val.intValue() + "年は" + "平成" + (y_val-= 1988) +
"年です");
}
else if ( (y_val == 2019) ) {
System.out.println( "また" + y_val.intValue() + "年は" + "平成31年/令和元年です");
}
else {
System.out.println( "また" + y_val.intValue() + "年は" + "令和" + (y_val-= 2018) +
"年です");
}
}
}
}
}
class ex2$urutoshi {
private
int jp_str_12 = 0;
int jp_str_13[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
public
boolean jp_str_10(int jp_str_1) {
if ( ( (jp_str_1 % 4)== 0 ) &&
( (jp_str_1 % 100)!= 0) ||
( (jp_str_1 % 400)== 0 ) )
{ return true; }
else return false;
}
int jp_str_11( int y_val, int m_val ) {
int jp_str_12= 0;
if ( ( jp_str_10( y_val ) == true ) && ( m_val <= 2 ) )
jp_str_12 = -1;
for ( int jp_str_1 = 1989; jp_str_1 <= ( y_val ); ++jp_str_1 ) {
if ( jp_str_10( jp_str_1 ) == true ) ++jp_str_12;
}
return(jp_str_12);
}
boolean jp_str_5( int y_val, int m_val, int d_val ) {
if ( ((1989 <= y_val)&&(y_val <= 2099)) && ((1 <= m_val)&&(m_val <= 12)) && ( 1
<= d_val ) )
{
if ( ( d_val <= 29 ) && ( m_val == 2 ) && jp_str_10( y_val ) )
{ return true; }
else if ( d_val <= jp_str_13[m_val-1] )
{ return true; }
}
return false;
}
}
class ex2$youbi {
private
String jp_str_14[] = {"日","月","火","水","木","金","土",};
public
String jp_str_6(int jp_str_3) {
return jp_str_14[jp_str_3];
}
}
class ex2$7_youbi {
private
int jp_str_15[] = { 0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5 };
int jp_str_17;
public
int jp_str_16( int jp_str_1, int jp_str_2, int jp_str_3 ) {
ex2$urutoshi jp_str_7 = new ex2$urutoshi();
jp_str_17 = (jp_str_1 - 1989) + jp_str_15[jp_str_2-1]
+ jp_str_3 - 1 + jp_str_7.jp_str_11(jp_str_1,jp_str_2);
return jp_str_17;
}
}
例3─2を展開したもの
例3─2のプログラムで平成1年1月8日、平成12年(西暦2000年)2月29日、平成18年(西暦2006年)2月3日、さらに天皇陛下の御退位により、 平成最後の日となる平成31年(西暦2019年)4月30日、令和2年(西暦2020年)6月15日としたときの実行結果です。
パッケージ内にまとめられたプログラムの実行は、以下のように「パッケージ名.プログラム名」で実行できます。
次に例3-3として、現在の時間を読み出して、それを江戸時代の時間の読み方である「刻」として表示するプログラムを示します。これはC言語編での例題から日本語プログラムを参考にして作ってみました。
また、このプログラムの実行結果をフレームといういわゆるGUI(グラフィック・ユーザー・インターフェース)の部品を利用して表示をしてみました。
// 現在の刻を表示する
import java.awt.*;
import java.awt.event.*;
import java.util.*;
#日本語定義 例題3─3 "ex3"
#日本語定義 引数
#日本語定義 題名を設定する "setTitle"
#日本語定義 大きさを設定する "setSize"
#日本語定義 可視かどうかを設定 "setVisible"
#日本語定義 窓際族
#日本語定義 派遣くん
全域で使用可 仲間の集まり 例題3─3 引き継ぎ 窓枠の仲間 {
全域で使用可 一つの実体だけ 型なし はじまり( 文字列の仲間 引数[] ) {
窓枠の仲間 窓際族 = 対象作成 例題3─3();
窓際族.題名を設定する("今の刻を表示する");
窓際族.大きさを設定する(600,200);
窓際族.可視かどうかを設定( 真 );
}
例題3─3(){ 窓枠ご用聞きの追加( 対象作成 派遣くん()); }
仲間の集まり 派遣くん 引き継ぎ 窓枠を適応させる仲間 {
全域で使用可 型なし 窓枠を閉じる { 終了する; }
}
#日本語定義 絵なりくん
#日本語定義 文字蔵さん
#日本語定義 領域に描画する "paint"
#日本語定義 傾斜太文字 "Font.ITALIC|Font.BOLD"
#日本語定義 青色 "Color.blue"
#日本語定義 文字を描く "drawString"
#日本語定義 字体を設定する "setFont"
#日本語定義 色を設定する "setColor"
全域で使用可 型なし 領域に描画する( 図画の仲間 絵なりくん ) {
文字列の仲間 文字列零 = "今の刻は";
文字列の仲間 文字列一 = "子刻(ねのこく)です。";
文字列の仲間 文字列二 = "丑刻(うしのこく)です。";
文字列の仲間 文字列三 = "寅刻(とらのこく)です。";
文字列の仲間 文字列四 = "卯刻(うのこく)です。";
文字列の仲間 文字列五 = "辰刻(たつのこく)です。";
文字列の仲間 文字列六 = "巳刻(みのこく)です。";
文字列の仲間 文字列七 = "午刻(うまのこく)です。";
文字列の仲間 文字列八 = "未刻(ひつじのこく)です。";
文字列の仲間 文字列九 = "申刻(さるのこく)です。";
文字列の仲間 文字列十 = "酉刻(とりのこく)です。";
文字列の仲間 文字列十一 = "戌刻(いぬのこく)です。";
文字列の仲間 文字列十二 = "亥刻(いのこく)です。\n";
字体の仲間 文字蔵さん = 対象作成 字体の仲間( "Serif", 傾斜太文字, 30 );
絵なりくん.字体を設定する( 文字蔵さん );
絵なりくん.色を設定する( 青色 );
絵なりくん.文字を描く( 文字列零, 220, 100 );
現在の時刻を取り出す;
振り分け( 現在時刻 / 2 ) {
場合分け 子刻: { 絵なりくん.文字を描く(文字列一, 120,150); }; 振り分け終了;
場合分け 丑刻: { 絵なりくん.文字を描く(文字列二, 120,150); }; 振り分け終了;
場合分け 寅刻: { 絵なりくん.文字を描く(文字列三, 120,150); }; 振り分け終了;
場合分け 卯刻: { 絵なりくん.文字を描く(文字列四, 120,150); }; 振り分け終了;
場合分け 辰刻: { 絵なりくん.文字を描く(文字列五, 120,150); }; 振り分け終了;
場合分け 巳刻: { 絵なりくん.文字を描く(文字列六, 120,150); }; 振り分け終了;
場合分け 午刻: { 絵なりくん.文字を描く(文字列七, 120,150); }; 振り分け終了;
場合分け 未刻: { 絵なりくん.文字を描く(文字列八, 120,150); }; 振り分け終了;
場合分け 申刻: { 絵なりくん.文字を描く(文字列九, 120,150); }; 振り分け終了;
場合分け 酉刻: { 絵なりくん.文字を描く(文字列十, 120,150); }; 振り分け終了;
場合分け 戌刻: { 絵なりくん.文字を描く(文字列十一,120,150); }; 振り分け終了;
場合分け 亥刻: { 絵なりくん.文字を描く(文字列十二,120,150); }; 振り分け終了;
}
}
}
#日本語定義 現在の時刻を取り出す "Calendar rightNow = Calendar.getInstance()"
#日本語定義 現在時刻 "rightNow.get(rightNow.HOUR_OF_DAY)"
#日本語定義 子刻 "0"
#日本語定義 丑刻 "1"
#日本語定義 寅刻 "2"
#日本語定義 卯刻 "3"
#日本語定義 辰刻 "4"
#日本語定義 巳刻 "5"
#日本語定義 午刻 "6"
#日本語定義 未刻 "7"
#日本語定義 申刻 "8"
#日本語定義 酉刻 "9"
#日本語定義 戌刻 "10"
#日本語定義 亥刻 "11"
#日本語定義 文字列零
#日本語定義 文字列一
#日本語定義 文字列二
#日本語定義 文字列三
#日本語定義 文字列四
#日本語定義 文字列五
#日本語定義 文字列六
#日本語定義 文字列七
#日本語定義 文字列八
#日本語定義 文字列九
#日本語定義 文字列十
#日本語定義 文字列十一
#日本語定義 文字列十二
例3─3
細かい文法的なところはJava言語関係の資料を見ていただければ分かると思いますが、Javaではおびただしい量のクラスライブラリーがメーカーから供給されています。これがすべて英語表記であり、それぞれのクラスで使用されている単語を見ても、とてもよく似た語句を使ってあるものがいくつも見受けられます。ここでうまく日本語定義を用いることで、混乱しやすい部分をプログラマーが後で見てもすぐに思い出すことができるようにする効果もあるのではないかと考えております。これは次のようなJava言語のコードに展開されます。
// 現在の刻を表示する
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class ex3 extends Frame {
public static void main( String jp_str_0[] ) {
Frame jp_str_1 = new ex3();
jp_str_1.setTitle("今の刻を表示する");
jp_str_1.setSize(600,200);
jp_str_1.setVisible( true );
}
ex3(){ addWindowListener( new jp_str_2()); }
class jp_str_2 extends WindowAdapter {
public void windowClosing( WindowEvent win_evnt ) { System.exit(0); }
}
public void paint( Graphics jp_str_3 ) {
String jp_str_5 = "今の刻は";
String jp_str_6 = "子刻(ねのこく)です。";
String jp_str_7 = "丑刻(うしのこく)です。";
String jp_str_8 = "寅刻(とらのこく)です。";
String jp_str_9 = "卯刻(うのこく)です。";
String jp_str_10 = "辰刻(たつのこく)です。";
String jp_str_11 = "巳刻(みのこく)です。";
String jp_str_12 = "午刻(うまのこく)です。";
String jp_str_13 = "未刻(ひつじのこく)です。";
String jp_str_14 = "申刻(さるのこく)です。";
String jp_str_15 = "酉刻(とりのこく)です。";
String jp_str_16 = "戌刻(いぬのこく)です。";
String jp_str_15二 = "亥刻(いのこく)です。\n";
Font jp_str_4 = new Font( "Serif", Font.ITALIC|Font.BOLD, 30 );
jp_str_3.setFont( jp_str_4 );
jp_str_3.setColor( Color.blue );
jp_str_3.drawString( jp_str_5, 220, 100 );
Calendar rightNow = Calendar.getInstance();
switch( rightNow.get(rightNow.HOUR_OF_DAY) / 2 ) {
case 0: { jp_str_3.drawString(jp_str_6, 120,150); }; break;
case 1: { jp_str_3.drawString(jp_str_7, 120,150); }; break;
case 2: { jp_str_3.drawString(jp_str_8, 120,150); }; break;
case 3: { jp_str_3.drawString(jp_str_9, 120,150); }; break;
case 4: { jp_str_3.drawString(jp_str_10, 120,150); }; break;
case 5: { jp_str_3.drawString(jp_str_11, 120,150); }; break;
case 6: { jp_str_3.drawString(jp_str_12, 120,150); }; break;
case 7: { jp_str_3.drawString(jp_str_13, 120,150); }; break;
case 8: { jp_str_3.drawString(jp_str_14, 120,150); }; break;
case 9: { jp_str_3.drawString(jp_str_15, 120,150); }; break;
case 10: { jp_str_3.drawString(jp_str_16,120,150); }; break;
case 11: { jp_str_3.drawString(jp_str_15二,120,150); }; break;
}
}
}
例3─3を展開したもの
例3─3のプログラムを実行させたときの結果です。(これは15時00分ごろに実行しました)
次の例題は、簡単なメモ紙を作ってみました。これはファイルを読み込むことも、保存することもできません。ただデスクトップに表示しておくだけのものですが、WindowsXP上ではマウスの右クリックの機能を使い、ほかのワープロやインターネットブラウザーなどから文書をコピーしてこのメモ紙に貼り付けることもできます。
//
簡単なテキスト編集ができるメモ紙を作る
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
#日本語定義 例題3─4 "ex4"
#日本語定義 窓際族
#日本語定義 派遣くん
#日本語定義 文書小僧
#日本語定義 ふぉん徒
#日本語定義 引数
#日本語定義 項目の文字列
#日本語定義 欄丸
#日本語定義 中太
#日本語定義 小太
#日本語定義 起こった蔵
全域で使用可 仲間の集まり 例題3─4 引き継ぎ 窓枠の仲間
実装 動作に対するご用聞き
{
文書領域の仲間 文書小僧 = 対象作成 文書領域の仲間();
全域で使用可 一つの実体だけ 型なし はじまり( 文字列の仲間 引数[] )
{
窓枠の仲間 窓際族 = 対象作成 例題3─4();
窓際族.題名を設定する( "簡単なメモ紙" );
窓際族.大きさを設定する( 600, 400 );
窓際族.窓枠を表示する();
}
例題3─4(){
字体を設定する( 対象作成 字体の仲間( 字体名, 字体の種類,
字体の大きさ1 ));
メニュー欄の仲間 欄丸 = 対象作成 メニュー欄の仲間();
メニュー中項目の仲間 中太 = 対象作成 メニュー中項目の仲間("ファイル");
メニュー小項目の仲間 小太 = 対象作成 メニュー小項目の仲間( "終了" );
小太.動作ご用聞きの追加( ここ );
中太.項目を追加する( 小太 );
欄丸.項目を追加する(中太);
メニュー蘭を作成する( 欄丸 );
文書小僧.字体を設定する( 対象作成 字体の仲間( 字体名, 字体の種類,
字体の大きさ2 ) );
窓枠に追加する( 文書小僧 );
窓枠ご用聞きの追加( 対象作成 派遣くん() );
}
仲間の集まり 派遣くん 引き継ぎ 窓枠を適応させる仲間 {
全域で使用可 型なし 窓枠を閉じる { 終了する; }
}
全域で使用可 型なし 動作が実行されたとき( 動作に伴うでき事の仲間 起こった蔵 ){
もし ( 起こった蔵.実行された命令を取り出す() == "終了" ) 終了する;
}
}
#日本語定義 題名を設定する "setTitle"
#日本語定義 大きさを設定する "setSize"
#日本語定義 窓枠を表示する "setVisible(true)"
#日本語定義 窓枠に追加する "add"
#日本語定義 字体を設定する "setFont"
#日本語定義 項目を追加する "add"
#日本語定義 ここ "this"
#日本語定義 メニュー蘭を作成する "setMenuBar"
#日本語定義 実行された命令を取り出す "getActionCommand"
#日本語定義 字体名 "\"SansSerif\""
#日本語定義 字体の大きさ1 "12"
#日本語定義 字体の大きさ2 "14"
#日本語定義 字体の種類 "Font.PLAIN"
例3─4
これも文法的な細かいところは関係資料を見ていただければ分かると思いますが、コードの量としては、非常に少なく書くことができました。しかし、字数によって自動的にスクロールもできるようになりますので、かなり本格的な機能は持っているようです。デスクトップ上にちょっとしたメモ紙として置いておくこともできると思います。これは次のようなJava言語のコードに展開されます。
//
簡単なテキスト編集ができるメモ紙を作る
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
public class ex4 extends Frame
implements ActionListener
{
TextArea jp_str_2 = new TextArea();
public static void main( String jp_str_4[] )
{
Frame jp_str_0 = new ex4();
jp_str_0.setTitle( "簡単なメモ紙" );
jp_str_0.setSize( 600, 400 );
jp_str_0.setVisible(true);
}
ex4(){
setFont( new Font( "SansSerif",
Font.PLAIN, 12 ));
MenuBar jp_str_6 = new MenuBar();
Menu jp_str_7 = new Menu("ファイル");
MenuItem jp_str_8 = new MenuItem( "終了" );
jp_str_8.addActionListener( this );
jp_str_7.add( jp_str_8 );
jp_str_6.add(jp_str_7);
setMenuBar( jp_str_6 );
jp_str_2.setFont( new Font( "SansSerif",
Font.PLAIN, 14 ) );
add( jp_str_2 );
addWindowListener( new jp_str_1() );
}
class jp_str_1 extends WindowAdapter {
public void windowClosing( WindowEvent win_evnt ) { System.exit(0); }
}
public void actionPerformed( ActionEvent jp_str_9 ){
if ( jp_str_9.getActionCommand() == "終了" ) System.exit(0);
}
}
例3─4を展開したもの
例3─4のプログラムを実行させたときの結果です。
ウィンドウの右上隅にある終了ボタンをクリックしても終了できますが、メニューバーの「ファイル」をマウスでクリックすると「終了」という項目が表示されますので、これを選択して終了することもできます。
次の例題は二次元の図形を描画するプログラムです。今回は縁起をかついで三段飾りもちを描いてみます。
// 三段飾り餅を描く
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
#日本語定義 例題3─5 "ex5"
#日本語定義 窓際族
#日本語定義 派遣くん
#日本語定義 引数
#日本語定義 題名を設定する "setTitle"
#日本語定義 大きさを設定する "setSize"
#日本語定義 背景色を設定する "setBackground"
#日本語定義 窓枠を表示する "setVisible(true)"
#日本語定義 領域に描画する "paint"
#日本語定義 楕円形を描画する "Ellipse2D.Float"
#日本語定義 矩形を描画する "Rectangle2D.Float"
#日本語定義 属性を設定する "setPaint"
#日本語定義 塗りつぶす "fill"
全域で使用可 仲間の集まり 例題3─5 引き継ぎ 窓枠の仲間{
全域で使用可 一つの実体だけ 型なし はじまり( 文字列の仲間 引数[]
) {
窓枠の仲間 窓際族 = 対象作成 例題3─5();
窓際族.題名を設定する("三段飾りもち");
窓際族.大きさを設定する(500,400);
窓際族.背景色を設定する(肌色);
窓際族.窓枠を表示する();
}
例題3─5(){ 窓枠ご用聞きの追加( 対象作成 派遣くん()); }
仲間の集まり 派遣くん 引き継ぎ 窓枠を適応させる仲間 {
全域で使用可 型なし 窓枠を閉じる { 終了する; }
}
#日本語定義 絵なりくん
#日本語定義 絵美ちゃん
全域で使用可 型なし 領域に描画する( 図画の仲間 絵なりくん ) {
二次元図形描画の仲間 絵美ちゃん = ( 二次元図形描画の仲間 )
絵なりくん;
絵美ちゃん.属性を設定する(紅色);
絵美ちゃん.塗りつぶす(対象作成 楕円形を描画する(150,160,200,50));
絵美ちゃん.属性を設定する(灰白色);
絵美ちゃん.塗りつぶす(対象作成 楕円形を描画する(175,110,150,50));
絵美ちゃん.属性を設定する(草色);
絵美ちゃん.塗りつぶす(対象作成 楕円形を描画する(200,60,100,50));
絵美ちゃん.属性を設定する(茶色);
絵美ちゃん.塗りつぶす(対象作成 矩形を描画する(150,200,200,20));
絵美ちゃん.塗りつぶす(対象作成 矩形を描画する(200,220,100,100));
絵美ちゃん.属性を設定する(肌色);
絵美ちゃん.塗りつぶす(対象作成 楕円形を描画する(225,225,50,50));
}
}
#日本語定義 肌色 "new Color(210,202,68)"
#日本語定義 茶色 "new Color(186,125,50)"
#日本語定義 紅色 "new Color(55,94,55)"
#日本語定義 灰白色 "new Color(184,213,184)"
#日本語定義 草色 "new Color(237,85,160)"
例3─5
複雑な色はRGB3色を0~255までの数値で指定します。これは次のようなJava言語のコードに展開されます。
// 三段飾り餅を描く
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class ex5 extends Frame{
public static void main( String jp_str_2[] ) {
Frame jp_str_0 = new ex5();
jp_str_0.setTitle("三段飾り餅");
jp_str_0.setSize(500,400);
jp_str_0.setBackground(new Color(210,202,68));
jp_str_0.setVisible(true);
}
ex5(){ addWindowListener( new jp_str_1()); }
class jp_str_1 extends WindowAdapter {
public void windowClosing( WindowEvent win_evnt ) { System.exit(0); }
}
public void paint( Graphics jp_str_3 ) {
Graphics2D jp_str_4 = ( Graphics2D ) jp_str_3;
jp_str_4.setPaint(new Color(55,94,55));
jp_str_4.fill(new Ellipse2D.Float(150,160,200,50));
jp_str_4.setPaint(new Color(184,213,184));
jp_str_4.fill(new Ellipse2D.Float(175,110,150,50));
jp_str_4.setPaint(new Color(237,85,160));
jp_str_4.fill(new Ellipse2D.Float(200,60,100,50));
jp_str_4.setPaint(new Color(186,125,50));
jp_str_4.fill(new Rectangle2D.Float(150,200,200,20));
jp_str_4.fill(new Rectangle2D.Float(200,220,100,100));
jp_str_4.setPaint(new Color(210,202,68));
jp_str_4.fill(new Ellipse2D.Float(225,225,50,50));
}
}
例3─5を展開したもの
例3─5のプログラムを実行させたときの結果です。
次の例題はC言語編、C++言語編でもやりましたが、任意の桁数、円周率πを求めるプログラムをJava版として移植してみました。これも日本語ベースでコードの移植を行いましたので、かなり 短時間でスムーズにできたのではないかと感じました。
プログラムはC言語編やC++言語編と同様に二つに分かれており、メインの部分はこの例題3─6です。また、もう一つのクラスファイルは 実際に長いπを求めるための詳細な計算部分です。それぞれ別々のクラスファイルとして翻訳(コンパイル)しておきます。
今回も詳細な長いπを計算をするクラスファイルについては掲載は差し控えておりますが、興味のある方はC言語編の参考資料として掲げております書籍を見ていただければ分かると思います。また、結果の表示については例題3─4の簡単なメモ紙に表示するようにし ました。
// マチンの公式を使用して、任意の桁数πの値を計算するプログラム
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
#日本語定義 例題3─6 "ex6"
#日本語定義 窓際族
#日本語定義 派遣くん
#日本語定義 文書小僧
#日本語定義 ふぉん徒
#日本語定義 引数
#日本語定義 項目の文字列
#日本語定義 欄丸
#日本語定義 中太
#日本語定義 小太
#日本語定義 起こった蔵
全域で使用可 仲間の集まり 例題3─6 引き継ぎ 窓枠の仲間
実装 動作に対するご用聞き
{
文書領域の仲間 文書小僧 = 対象作成 文書領域の仲間();
全域で使用可 一つの実体だけ 型なし はじまり( 文字列の仲間 引数[] )
{
窓枠の仲間 窓際族 = 対象作成 例題3─6();
窓際族.題名を設定する( "πを2万桁求める" );
窓際族.大きさを設定する( 600, 400 );
窓際族.窓枠を表示する();
}
例題3─6(){
メニュー欄の仲間 欄丸 = 対象作成 メニュー欄の仲間();
メニュー中項目の仲間 中太 = 対象作成 メニュー中項目の仲間("ファイル");
メニュー小項目の仲間 小太 = 対象作成 メニュー小項目の仲間( "終了" );
小太.動作ご用聞きの追加( ここ );
中太.項目を追加する( 小太 );
欄丸.項目を追加する(中太);
メニュー蘭を作成する( 欄丸 );
文書小僧.字体を設定する( 対象作成 字体の仲間( 字体名, 字体の種類, 字体の大きさ ) );
窓枠に追加する( 文書小僧 );
窓枠ご用聞きの追加( 対象作成 派遣くん() );
整数型[] 作業用配列一 = 対象作成 整数型[配列の最大値+1];
整数型[] 作業用配列二 = 対象作成 整数型[配列の最大値+1];
整数型[] πの結果 = 対象作成 整数型[配列の最大値+1];
長いπを求める仲間 長いπ = 対象作成 長いπを求める仲間();
長いπ.マチンの逆正接演算( 作業用配列一, 16, 5 );
長いπ.マチンの逆正接演算( 作業用配列二, 4, 239 );
長いπ.長い配列の減算( πの結果, 作業用配列一, 作業用配列二 );
文字列の仲間 表示用文字 = 対象作成 文字列の仲間();
文書小僧.文字を追加する( 表示用文字.値を変換する(πの結果[0]) );
文書小僧.文字を追加する(".\n");
反復 ( 整数型 反復数 = 1; 反復数 <= 求める桁数; 反復数++ ) {
文書小僧.文字を追加する( 表示用文字.値を変換する(πの結果[反復数]) );
もし ( 反復数 剰余計算 10 == 0 ) 文書小僧.文字を追加する(" ");
もし ( 反復数 剰余計算 50 == 0 ) 文書小僧.文字を追加する("\n");
}
}
仲間の集まり 派遣くん 引き継ぎ 窓枠を適応させる仲間 {
全域で使用可 型なし 窓枠を閉じる { 終了する; }
}
全域で使用可 型なし 動作が実行されたとき( 動作に伴うでき事の仲間 起こった蔵 ){
もし ( 起こった蔵.実行された命令を取り出す() == "終了" ) 終了する;
}
}
#日本語定義 長いπを求める仲間 "lng_pi"
#日本語定義 マチンの逆正接演算 "machins_arctan"
#日本語定義 長い配列の減算 "lng_dim_sub"
#日本語定義 反復数
#日本語定義 長いπ
#日本語定義 表示用文字
#日本語定義 配列の最大値 "20010"
#日本語定義 求める桁数 "20000"
#日本語定義 作業用配列一
#日本語定義 作業用配列二
#日本語定義 πの結果
#日本語定義 剰余計算 "%"
#日本語定義 題名を設定する "setTitle"
#日本語定義 大きさを設定する "setSize"
#日本語定義 窓枠を表示する "setVisible(true)"
#日本語定義 窓枠に追加する "add"
#日本語定義 字体を設定する "setFont"
#日本語定義 項目を追加する "add"
#日本語定義 文字を追加する "append"
#日本語定義 値を変換する "valueOf"
#日本語定義 ここ "this"
#日本語定義 が等しい ".equals"
#日本語定義 ならば ""
#日本語定義 メニュー蘭を作成する "setMenuBar"
#日本語定義 実行された命令を取り出す "getActionCommand"
#日本語定義 字体名 "\"SansSerif\""
#日本語定義 字体の大きさ "12"
#日本語定義 字体の種類 "Font.PLAIN"
例3─6
これを展開すると、次のようなJava言語のコードになります。
// マチンの公式を使用して、任意の桁数πの値を計算するプログラム
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
public class ex6 extends Frame
implements ActionListener
{
TextArea jp_str_2 = new TextArea();
public static void main( String jp_str_4[] )
{
Frame jp_str_0 = new ex6();
jp_str_0.setTitle( "πを2万桁求める" );
jp_str_0.setSize( 600, 400 );
jp_str_0.setVisible(true);
}
ex6(){
MenuBar jp_str_6 = new MenuBar();
Menu jp_str_7 = new Menu("ファイル");
MenuItem jp_str_8 = new MenuItem( "終了" );
jp_str_8.addActionListener( this );
jp_str_7.add( jp_str_8 );
jp_str_6.add(jp_str_7);
setMenuBar( jp_str_6 );
jp_str_2.setFont( new Font( "SansSerif", Font.PLAIN, 12 ) );
add( jp_str_2 );
addWindowListener( new jp_str_1() );
int[] jp_str_13 = new int[20010+1];
int[] jp_str_14 = new int[20010+1];
int[] jp_str_15 = new int[20010+1];
lng_pi jp_str_11 = new lng_pi();
jp_str_11.machins_arctan( jp_str_13, 16, 5 );
jp_str_11.machins_arctan( jp_str_14, 4, 239 );
jp_str_11.lng_dim_sub( jp_str_15, jp_str_13, jp_str_14 );
String jp_str_12 = new String();
jp_str_2.append( jp_str_12.valueOf(jp_str_15[0]) );
jp_str_2.append(".\n");
for ( int jp_str_10 = 1; jp_str_10 <= 20000; jp_str_10++ ) {
jp_str_2.append( jp_str_12.valueOf(jp_str_15[jp_str_10]) );
if ( jp_str_10 % 10 == 0 ) jp_str_2.append(" ");
if ( jp_str_10 % 50 == 0 ) jp_str_2.append("\n");
}
}
class jp_str_1 extends WindowAdapter {
public void windowClosing( WindowEvent win_evnt ) { System.exit(0); }
}
public void actionPerformed( ActionEvent jp_str_9 ){
if ( jp_str_9.getActionCommand() == "終了" ) System.exit(0);
}
}
例3─6を展開したもの
円周率を小数点以下2万桁として、例3─6のプログラムを実行させたときの最初の部分と最後の部分です。
C、C++言語編でも述べたように、日本語カスタマイザーを利用してJava言語を翻訳(コンパイル)するときに、プログラム中に文法的な問題があると警告メッセージやエラーメッセージが表示されます。このときにjp_str_*(*は数字)についてのエラー情報が出た場合、このjp_str_*とソースコード中の日本語文字列がどのように対応するのかが分からないとデバッグしにくいことが挙げられます。もっともエラーが出た行番号の情報は出力されますので、ソースコード上でどの行に問題があるのかは分かります。
このようなデバッグ状況に対処する方法としては、日本語カスタマイザーが出力するjjava_rule2.lexファイルが残っていますので、この中の規則記述部分を見ることによって、日本語文字列とそれに対応するjp_str_*がどれかということが分かります。多少手数はかかりますが、デバッグについて全く対処できないというわけではないと思います。
C、C++言語同様に、Java言語でも「mapjava」というFLEXを用いた簡単なデバッグ用のツールを作ってみました。中味はjjava_rule2.lexの規則記述部分だけを取り出して、表示するというものです。ここでは例題3-3において、変数であるjp_str_*がソースリスト中のどの日本語文字列に対応するか、という情報だけを取り出したい場合を考えます。
日本語カスタマイザーが出力したjava_rule2.lexをmapjavaで読み込ませた後、UNIXツールとして有名なawkのパターンマッチ機能を利用してjp_str_*だけを抽出した結果を以下に示します。(Windowsのコマンドプロンプトで動作するフリーウェアのawkは多数あると思いますが、ここでは日本語文字列の取り扱いができるgawkを使用しております)このような簡単なツールを作ることで、日本語と実際に使われている予約語や変数を対応させることができるのではないかと思います。
参考資料
James Gosling: on the Java Road ジェームズ・ゴースリン博士が公開しているブログページ
Java(TM) 2 SDK, Standard Edition Version 1.4.0 ドキュメント一式 サン・マイクロシステムズ社
Java2 中山茂著 技報堂出版 1999