BeanShell は Java に基づいた スクリプト言語 で、Java に非常に似ています。Java よりも初心者にとってはるかに親しみやすいです。BeanShell を学べば、Java を学ぶのがはるかに簡単になります。
bsh-xx.jar をダウンロードして、作業ディレクトリに置きます。
~/beanshell $ ls -F
bsh-2.0b4.jar bsh_console.sh*
~/beanshell $ cat bsh_console.sh
#!/bin/bash
export CLASSPATH=bsh-2.0b4.jar
java bsh.Console &
~/beanshell $
私の bsh_console.sh
を作業ディレクトリにコピーします。jar
ファイルにはコンパイルされた Java コードが含まれています。CLASSPATH
は java
コマンドにコンパイルされた Java コードの場所を教えます。
これで BeanShell を実行できます:
~/beanshell $ ./bsh_console.sh
~/beanshell $
新しいウィンドウが表示され、BeanShell と対話できるようになります。これ以降、そのウィンドウでの対話を主に参照します。
ウィンドウから:
bsh % pwd();
/Users/fschmidt/beanshell
bsh % print("Hello world!");
Hello world!
bsh % print(1+1);
2
bsh %
BeanShell の pwd
コマンドは Bash の pwd
コマンドに似ており、BeanShell の print
コマンドは Bash の echo
コマンドにやや似ています。しかし、構文は異なります。BeanShell と Java はほとんどのプログラミング言語と同様の構文を持っています。Bash が command arg1 arg2 arg3
を行うのに対し、ほとんどのプログラミング言語は command(arg1,arg2,arg3)
を行います。さらに、Java ではステートメント(コマンドライン)の末尾に ;
が必要です。
pwd
と print
は BeanShell のみのコマンドです。Java にはありません。
また、Java には標準の算術演算子があります。
bsh % String message = "Hello world!";
bsh % print(message);
Hello world!
bsh % int i = 2;
bsh % print(i);
2
bsh % print(i+1);
3
bsh % i = i + 5;
bsh % print(i);
7
bsh %
変数は値を保持します。Java(BeanShell ではなく)では、変数は型で宣言する必要があります。型 String
はテキスト用で、int
は整数用です。
=
コマンドは変数に値を割り当てます。
bsh % print( message.toUpperCase() );
HELLO WORLD!
bsh % print( message.length() );
12
bsh % print( message.getClass() );
class java.lang.String
bsh %
Java はオブジェクト指向言語であり、主にオブジェクトを扱います。実世界の例で説明します。犬やトースターを表示するには、show(dog)
や show(toaster)
のようにします。表示はこれらのオブジェクトに対して行うもので、オブジェクトに組み込まれているわけではありません。対照的に、犬を走らせるには dog.run()
、トースターでパンを焼くには toaster.toast(bread)
のようにします。走ることは犬に組み込まれた機能であり、パンを焼くことはトースターに組み込まれた機能です。オブジェクトに組み込まれた関数は「メンバー関数」と呼ばれます。
しかし、実際にはこれにはもっと深い意味があります。犬は犬科の一種であり、すべての犬科は走ることができます。したがって、犬が走る能力は実際には犬科であることから来ています。Java では、犬、犬科、トースターを「クラス」と呼び、犬は犬科のサブクラスであり、犬科は犬のスーパークラスであると言います。
プログラミングに戻ります。message
(文字列)のクラスは java.lang.String です。そのリンクをクリックして、文字列ができることをすべて見てください。たとえば、toUpperCase や length があります。これらの関数は値を返します。文字列はまた getClass もできますが、この機能はスーパークラス java.lang.Object から来ています。オブジェクトはすべての基本クラスです。java.lang.String のトップをもう一度見て、クラス階層を見て、String が Object のサブクラスであることを確認してください。
bsh % List list = new ArrayList();
bsh % print( list );
[]
bsh % print( list.size() );
0
bsh % list.add("a");
bsh % print( list );
[a]
bsh % print( list.size() );
1
bsh % list.add("b");
bsh % list.add("c");
bsh % print( list );
[a, b, c]
bsh % print( list.size() );
3
bsh % print( list.get(0) );
a
bsh % print( list.get(1) );
b
bsh % print( list.getClass() );
class java.util.ArrayList
bsh %
java.util.ArrayList はクラスです。クラスの新しいオブジェクトを作成するには、new
演算子を使用します。ArrayList ページのトップを見ると、「すべての実装されたインターフェース:」が表示され、「List」が含まれており、それをクリックすると java.util.List に移動します。リストはインターフェースであり、純粋に抽象的なクラスと考えることができます。インターフェースはオブジェクトが何をするかを指定するだけで、どのようにするかは指定しません。ArrayList のような具体的なクラスは、オブジェクトが何をするかを実際に行うための実装を指定します。インターフェースは、異なる方法でインターフェースを実装する複数のクラスによって実装/サブクラス化されることができます。java.util.List の「すべての既知の実装クラス:」でこれを見ることができます。
リストの最初のインデックスは 0 であり、1 ではありません。したがって、リストの最後のインデックスは list.size() - 1
です。
Java はクラスをパッケージに整理します。List と ArrayList のパッケージは java.util です。便利なクラスがたくさんあります。Java には膨大な数の標準クラスがあり、Java のコア概念を伝えるために必要なクラス以上は説明しません。必要なクラスは自分で学ぶことができます。
bsh % print( 3 > 4 );
false
bsh % print( 3 >= 4 );
false
bsh % print( 3 < 4 );
true
bsh % print( 3 <= 4 );
true
bsh % print( 3 == 4 );
false
bsh % print( 3 != 4 );
true
bsh % print( 3 < 4 && 3 > 4 );
false
bsh % print( 3 < 4 || 3 > 4 );
true
bsh % boolean b = 3 < 4;
bsh % print(b);
true
bsh % print( b == true );
true
bsh %
==
は等価性をチェックし、!=
は不等価性をチェックし、&&
は「and」、||
は「or」です。これらはブール演算子であり、ブール値を返します。+
のような算術演算子とは異なります。boolean
は true
または false
の値を持つことができる型です。
bsh % String s1 = new String("hi");
bsh % String s2 = new String("hi");
bsh % print( s1 == s2 );
false
bsh % print( s1.equals(s2) );
true
bsh % String s3 = s1;
bsh % print( s1 == s3 );
true
bsh %
物理世界で同一の 2 つのオブジェクトがある場合、それらは同じオブジェクトではありませんが、同等のオブジェクトです。Java では、object1 == object2
は object1 と object2 が同じオブジェクトを参照しているかどうかをチェックします。オブジェクト変数はオブジェクトを参照し、その値を含んでいません。object1.equals(object2)
はオブジェクトの等価性をチェックします。
型 int
と boolean
はプリミティブ型です。それらはオブジェクトではありません。プリミティブ型変数はプリミティブ値を含んでいるため、何も参照しません。この場合、==
は等しい値をチェックします。
今、Bash コマンドラインに戻ります。
~/beanshell $ ls -F
bsh-2.0b4.jar bsh.sh* bsh_console.sh* code.bsh
~/beanshell $ cat bsh.sh
#!/bin/bash
export CLASSPATH=bsh-2.0b4.jar
java bsh.Interpreter $*
~/beanshell $ cat code.bsh
/* これはコメントです */
// これもコメントです
print("Hi");
print("Bye");
~/beanshell $ ./bsh.sh code.bsh
Hi
Bye
~/beanshell $
bsh.sh
はコマンドラインから BeanShell ファイルを実行します。code.bsh
を変更し続けて、私の例を示します。
Java では、コメントは /*
と */
の間、または //
と行の終わりの間にあります。コメントは無視されます。
~/beanshell $ cat code.bsh
int x = 5;
print("最初の if");
if( x == 5 ) {
print("x == 5");
}
print("2 番目の if");
if( x > 5 ) {
print("x > 5");
} else {
print("x <= 5");
}
print("3 番目の if");
if( x > 5 ) {
print("x > 5");
} else if( x < 5 ) {
print("x < 5");
} else {
print("x == 5");
}
~/beanshell $ ./bsh.sh code.bsh
最初の if
x == 5
2 番目の if
x <= 5
3 番目の if
x == 5
~/beanshell $
if
文はブール引数を取ります。
~/beanshell $ cat code.bsh
~/beanshell $ cat code.bsh
print("最初のループ");
int i = 1;
while( i <= 3 ) {
print(i);
i = i + 1;
}
print("2 番目のループ");
for( int i = 1; i <= 3; i = i + 1 ) {
print(i);
}
List list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
print("3 番目のループ");
for( int i = 0; i < list.size(); i = i + 1 ) {
String s = list.get(i);
print(s);
}
print("4 番目のループ");
Iterator iter = list.iterator();
while( iter.hasNext() ) {
String s = iter.next();
print(s);
}
print("5 番目のループ");
for( String s : list ) {
print(s);
}
~/beanshell $ ./bsh.sh code.bsh
最初のループ
1
2
3
2 番目のループ
1
2
3
3 番目のループ
a
b
c
4 番目のループ
a
b
c
5 番目のループ
a
b
c
~/beanshell $
最初の形式の for
ループには 3 つの要素があります: 初期化ステートメント、ループ条件、およびループの各反復後に実行されるステートメントです。2 番目の形式の for
ループは、シーケンスで値を返す反復可能なものを通過します。4 番目のループについては、List.iterator() を参照してください。
~/beanshell $ cat code.bsh
{
String s = "ok";
print( "最初 " + s );
}
print( "2 番目 " + s );
~/beanshell $ ./bsh.sh code.bsh
最初 ok
2 番目 void
~/beanshell $
中括弧 {
と }
の間のコードはブロックです。中括弧が for
文のようなステートメントの一部である場合、ブロックはステートメント全体を含むように拡張されます。ブロック内で宣言された変数は、そのブロック内でのみ存在します。
BeanShell では未定義の変数は void
ですが、Java ではコンパイルエラーが発生します。
算術演算子であることに加えて、+
は文字列を連結します。
~/beanshell $ cat code.bsh
String[] array = { "a", "b", "c", "d", "e" };
print( "array = " + Arrays.asList(array) );
print( "length = " + array.length );
print( "array[1] = " + array[1] );
array[1] = "bb";
print( "modified array = " + Arrays.asList(array) );
print("ループ");
for( String s : array ) {
print(s);
}
array = new String[3];
print( "new array = " + Arrays.asList(array) );
array[2] = "two";
print( "modified new array = " + Arrays.asList(array) );
~/beanshell $ ./bsh.sh code.bsh
array = [a, b, c, d, e]
length = 5
array[1] = b
modified array = [a, bb, c, d, e]
ループ
a
bb
c
d
e
new array = [null, null, null]
modified new array = [null, null, two]
~/beanshell $
配列は異常であり、プリミティブ型でもオブジェクトでもありません。配列はリストができることを何もできません。Java に配列がある理由は、配列が基本的な低レベルのプログラミング概念であり、Java が低レベルの言語であるためです。
配列は保持する型で宣言され、その型のみを保持できます。配列はサイズを変更できません。
配列は文字列になる方法を知らないため、Arrays.asList() を使用して配列をリストに変換し、適切に表示できるようにしました。これは static
関数であり、オブジェクトの一部ではなく、クラスに関連付けられた一般的な関数であることに注意してください。
コードの第 2 部では、array
を長さ 3 の新しい配列に割り当て、値を持たないようにします。Java は特別な値 null
を使用して値がないことを意味します。
~/beanshell $ cat code.bsh
int add(int x,int y) {
return x + y;
}
void addAndShow(int x,int y) {
int sum = x + y;
print( x + " + " + y + " = " + sum );
}
void sayBye() {
print("Bye");
}
print( "add(2,3) = " + add(2,3) );
addAndShow(2,3);
sayBye();
~/beanshell $ ./bsh.sh code.bsh
add(2,3) = 5
2 + 3 = 5
Bye
~/beanshell $
関数は再利用可能なコードを可能にし、プログラミングのコア概念です。Java では、関数定義は戻り値の型、次に関数名、次に型付きの関数パラメータ、次に関数を実装するブロックで始まります。void
の戻り値の型は何も返されないことを意味します。
~/beanshell $ cat code.bsh
Iterator iter = new Iterator() {
int i = 0;
boolean hasNext() {
return i < 10;
}
int next() {
i = i + 1;
return i;
}
};
while( iter.hasNext() ) {
print( iter.next() );
}
~/beanshell $ ./bsh.sh code.bsh
1
2
3
4
5
6
7
8
9
10
~/beanshell $
BeanShell は新しいクラスを実装することを許可していませんが、Java ではそれが必要です。しかし、BeanShell はインターフェースを実装することを許可しており、新しいクラスを実装することに似ています。この場合、Iterator を実装し、実装する必要がある 2 つのメンバー関数を定義します。通常、実装にはメンバー関数とメンバーデータ/変数の両方が含まれます。メンバーデータはオブジェクトの状態を記述し、メンバー関数はその状態を変更することがよくあります。このイテレータは 1 から 10 までカウントし、メンバー変数 i
は現在のカウントを追跡します。
この例はオブジェクト指向プログラミングの味を与えるためのものです。Java を学ぶときに、これについてもっと学ぶことができます。
このチュートリアルの目的は、Java の学習を容易にする基本的な Java の概念を紹介することです。詳細や複雑な例は避けました。
Java を学ぶとき、BeanShell は実験のための便利なツールであると私は今でも思っています。Java でテストするのに時間がかかることを BeanShell で素早くテストできます。