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 に移動します。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("first if");
if( x == 5 ) {
print("x == 5");
}
print("second if");
if( x > 5 ) {
print("x > 5");
} else {
print("x <= 5");
}
print("third if");
if( x > 5 ) {
print("x > 5");
} else if( x < 5 ) {
print("x < 5");
} else {
print("x == 5");
}
~/beanshell $ ./bsh.sh code.bsh
first if
x == 5
second if
x <= 5
third if
x == 5
~/beanshell $
if 文はブール引数を取ります。
~/beanshell $ cat code.bsh
~/beanshell $ cat code.bsh
print("first loop");
int i = 1;
while( i <= 3 ) {
print(i);
i = i + 1;
}
print("second loop");
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("third loop");
for( int i = 0; i < list.size(); i = i + 1 ) {
String s = list.get(i);
print(s);
}
print("fourth loop");
Iterator iter = list.iterator();
while( iter.hasNext() ) {
String s = iter.next();
print(s);
}
print("fifth loop");
for( String s : list ) {
print(s);
}
~/beanshell $ ./bsh.sh code.bsh
first loop
1
2
3
second loop
1
2
3
third loop
a
b
c
fourth loop
a
b
c
fifth loop
a
b
c
~/beanshell $
最初の形式の for ループには、初期化ステートメント、ループ条件、およびループの各反復後に実行されるステートメントの3つの要素があります。2番目の形式の for ループは、シーケンスで値を返す反復可能なものを通過します。4番目のループについては、List.iterator() を参照してください。
~/beanshell $ cat code.bsh
{
String s = "ok";
print( "first " + s );
}
print( "second " + s );
~/beanshell $ ./bsh.sh code.bsh
first ok
second 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("loop");
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]
loop
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 で素早くテストできます。