JShellで始めるJava入門 - Javaの世界を覗いてみる
JShellでJavaを始めてみましょう。
目的
プログラム未経験者が、Javaプログラミングで出てくるいろいろな概念をなんとなく把握する。
環境設定
まずは環境設定からです。
こちらからJDKをダウンロードします。
http://jdk.java.net/11/
Windowsの人は、Oracle JDKのほうのexeをダウンロードしたほうがいいでしょうね。Macの人でもコマンドラインに不慣れな人はdmgをインストールしたほうがいいです。Oracle JDKを使う場合はAccept License Agreement
をチェックする必要があります。
MacやLinuxの人は、tar.gzをダウンロードして
$ tar xf openjdk-11-ea+11_osx-x64_bin.tar.gz
としてもいいと思います。Windowsでtarをインストールしてる人やBashが使える人もこちらで。
2018/9/25にはJDK11が正式リリースされるので、Macではbrew install java
でインストールできるようになると思います。
JShellを起動する
ではJShellを起動してみます。
Windowsの人は「コマンドプロンプト」、MacやLinuxの人は「ターミナル」を開いてください。
$ jshell
で起動したらラッキー
ちなみに、$ jshell
というのは、こういったコマンドラインでjshell
と入力して[enter]キーを押してくださいね、という記法です。
起動しなかったら、Windowsの場合は"\Program files\Java\jdk-11\bin\jshell"
を起動します。\Prog
くらいを入力して[tab]を押すと補完してくれると思います。
Macの場合は/Library/Java/jdk-11/Contents/Home/bin/jshell
あたりに。
試しに12+23
を入力して[enter]キーを押してください。
35
という結果が現れましたね。
JShellに何かを入力して[enter]キーを押すと、その入力をJShellがJavaのコードだと解釈して実行してくれます。今回入力したのは単なる計算ですが、これもJavaのプログラムの一部になります。
ということで、初めてのJavaプログラムは12+23
ということになりました。やったね!
以降、jshellへの入力とその結果を次のように表します。
jshell> 12 + 23
$1 ==> 35
これはJShellに12+23
を入力して[enter]キーを押してくださいね、そうすると35
が表示されますよ、ということです。$1 ==>
の部分はとりあえず無視しましょう。
値を扱う
演算
先ほどは足し算を行いました。では引き算はどうでしょう?4-3
を試してみます。
jshell> 4 - 3
$2 ==> 1
掛け算は*
, 割り算は/
を使います。また、%
で割り算の余りを計算できます。
jshell> 8 * 2
$3 ==> 16
jshell> 8 / 2
$4 ==> 4
jshell> 7 % 5
$5 ==> 2
3+4*2
はどうでしょう?
jshell> 3 + 4 * 2
$6 ==> 11
掛け算が先に計算されていますね。3+4
をカッコでくくれば、足し算を先に計算します。
jshell> (3 + 4) * 2
$7 ==> 14
いろいろな型
ところで、22/7
はどうなるでしょうか?
jshell> 22 / 7
$8 ==> 3
整数として計算されていますね。小数点以下の結果が欲しいとき、つまり実数として計算したい場合には22.0/7
とします。
jshell> 22.0 / 7
$9 ==> 3.142857142857143
小数点を付けると、実数として扱われます。また演算のどちらかの項が実数であれば、実数として計算を行います。このように、Javaでは整数と実数を区別して計算します。
文字列とメソッド
ここまで数値を扱ってきました。プログラムでは単語や文章など一連の文字を扱うことも多くあります。こういった一連の文字のことをプログラムの世界では文字列と呼びます。Javaでは"
(ダブルクォート)で囲って文字列を表します。
jshell> "aaa"
$10 ==> "aaa"
文字列の連結は+
演算子を使います。
jshell> "te" + "st"
$11 ==> "test"
引き算はどうなるでしょうか?"test"-"st"
で"te"
が得れれば便利ですね。
jshell> "test" - "st"
| エラー:
| 二項演算子'-'のオペランド型が不正です
| 最初の型: java.lang.String
| 2番目の型: java.lang.String
| "test" - "st"
| ^-----------^
エラーが出ました。ここでオペランドというのは、演算子の項のことです。-
演算子には文字列は使えないということを言っています。こういうエラーメッセージもちゃんと読めるようになったほうがいいですが、今の時点では-
演算子に文字列は使えないんだなーくらいの認識で大丈夫です。
文字列に対しては演算子として+
演算子だけが使えます。
メソッド
文字列に対しては、いろいろな操作がしたくなります。例えば文字数を数えてみましょう。"test".length()
と入力してみます。len
まで入力して[Tab]キーを入力すると、続きを入力してくれると思います。こういった機能を「補完」といいます。
jshell> "test".length()
$12 ==> 4
4がとれましたね。
このlength()
をメソッドといいます。文字列には、このようなメソッドがたくさん用意されていて、文字列に対する操作を行います。
"test".
で[Tab]キーを押すと、文字列に対して呼び出せるメソッドの一覧が表示されます。
では、他のメソッドも使ってみましょう。"test".repeat(3)
を実行してみましょう。
jshell> "test".repeat(3)
$13 ==> "testtesttest"
test
が3回繰り返した文字列が表示されましたね。repeat
メソッドは、文字列を指定した回数繰り返すメソッドです。このように、メソッドには何か指定することが必要なときがあります。このような、メソッドに対して指定する値を「引数(ひきすう)」といいます。
もうひとつ、replace
メソッドを使ってみましょう。"test".replace("st","")
を実行してみます。
jshell> "test".replace("st","")
$14 ==> "te"
replace
メソッドは文字列を置き換えるメソッドで、置き換え前の文字列と置き換え後の文字列を引数に取ります。このように2つ以上の引数をとる場合は,
で引数を区切ります。""
は空文字列といいます。"st"
を""
に置き換えることで、文字列から"st"
を省いたわけですね。
メソッド呼び出しを連結させることもできます。
jshell> "test".repeat(3).replace("st","")
$15 ==> "tetete"
"test"
が3回繰り返されて"testtesttest"
になり、"st"
が省かれて"tetete"
になっています。
JShellの操作
基本的な操作として、上キーを押すと前に入力したものが出てきます。前に入力したものをもう一度実行したい場合に使えます。
JShellでは、[Enter]キーが押されたときにキリのいいところまで入力されていると判断できれば、その式を実行します。しかし、途中で改行してしまった場合やカッコが足りなかった場合など、中途半端に行が終わった場合は、次のように続きの入力を求められます。
jshell> "test".repeat(
...>
長い行を入力するときに自分で改行したときはいいのですが、ちゃんと1行入力したつもりなのにどこかでカッコが足りなくて行が終わっていないときには、間違い探しが面倒で、改めて入力したほうが早いときもあります。そういうときは[Ctrl]+[c]でキャンセルできます。
JShellを終了させるには/exit
コマンドを使います。
jshell> /exit
| 終了します
$
変数
ところでこの値、円周率に近いので円周率の代わりにいろいろ使いたいとします。けれどもいちいち22.0/7
と入力するのは面倒ですね。
そこで変数ですよ。
変数はvar 変数名=値
とすることで定義できます。
jshell> var pi = 22.0 / 7
pi ==> 3.142857142857143
これでpi
という変数が定義されて3.142857142857143
という値が割り当てられました。pi
とだけ入力してみると、割り当てられた値が表示されます。
jshell> pi
pi ==> 3.142857142857143
これを使って、半径5の円の円周の長さを求めてみます。円周の長さは直径x円周率でしたね。変数は、値として演算に使うことができます。
jshell> 5*2*pi
$16 ==> 31.428571428571427
面積は半径x半径x円周率でしたね。
jshell> 5*5*pi
$17 ==> 78.57142857142857
このように、変数を使って値を使いまわすことができました。
ところで、$17
の位置には変数piを定義したときにはpi
と表示されていましたね。つまり、これは$17
という変数に78.57142857142857
を割り当てましたよ、ということを表しています。
jshell> $17
$17 ==> 78.57142857142857
ところで、実際にはJavaではMath.PI
で精度の高い円周率が保持されています。
jshell> Math.PI
$82 ==> 3.141592653589793
Math
クラスのPI
フィールド、ということになりますが、詳しくはまた別に勉強しましょう。
円周率としてこの値を使うと、半径5の円の面積は次のようになります。
jshell> 5*5*Math.PI
$81 ==> 78.53981633974483
変数pi
に、このMath.PI
を割り当てておきましょう。
jshell> pi=Math.PI
pi ==> 3.141592653589793
このように、変数には値を割り当てなおすこともできます。
改めて5*5*pi
を計算してみると、次のようにMath.PI
を使った場合と同じ結果がでました。
jshell> 5*5*pi
$84 ==> 78.53981633974483
メソッドの定義
変数を使って値を使いまわすことができましたが、半径x半径x円周率のような式を使いまわすことができると便利です。
Javaではメソッドを定義することで式を使いまわすことができます。
ちょっと長いですが、double menseki(double r){return r*r*pi;}
を実行してみてください。
jshell> double menseki(double r){return r*r*pi;}
| 次を作成しました: メソッド menseki(double)
これでmenseki
メソッドが定義されました。次のようにして使えます。
jshell> menseki(5)
$34 ==> 78.53981633974483
jshell> menseki(3)
$33 ==> 28.274333882308138
これで式を使いまわすことができますね。
それではメソッドの定義を少し詳しく見ておきましょう。メソッドの定義を適当に改行すると次のようになります。
double menseki(double r) {
return r*r*pi;
}
この定義は次のようになっています。
結果の型 メソッド名(引数の型 引数を扱う変数) {
return 式;
}
型というのは値の種類のことで、ここまで出てきたものでは整数がint
、実数がlong
、文字列がString
になっています。今回は、実数を受け取って実数を返すmenseki
という名前のメソッドを定義したことになります。受け取った引数をr
で受け取るようにしています。radius(半径)のrです。
値を返すときにはreturn
文を使います。ここで、受け取った半径を2回掛けて円周率を掛けたものを返しています。
次のように、JShellの中で改行をして定義することもできます。
jshell> double menseki(double r) {
...> return r*r*pi;
...> }
| 次を変更しました: メソッド menseki(double)
練習:引数の名前はr
である必要はありません。menseki2として、引数をaで受け取るように同じ機能のメソッドを定義してみてください。
練習:半径を受け取って円周の長さを返すメソッドを定義してみてください。
Swing
なんか文字ばっかりでつまらん、ってなりませんでしたか?ということで文字ばっかりじゃないものを実行してみましょう。
ウィンドウを表示します。Javaでは、標準でSwingというGUIツールキットが用意されています。GUIツールキットというのは、ウィンドウを表示したりボタンを配置したりする部品群のことです。
ウィンドウを表示
まずはウィンドウを用意します。
jshell> var f = new javax.swing.JFrame("test")
f ==> javax.swing.JFrame[fram ... bled=true]
ちょっとよくわかりませんが、変数fになんらかが割り当てられました。
これに対してshow()
メソッドを呼び出してみます。
jshell> f.show()
左上に何か表示されました。
小さいので、サイズを大きくしてみます。サイズを決めるにはsetSize
メソッドを使います。ここで横サイズと縦サイズと指定します。
jshell> f.setSize(400,300)
クラスとオブジェクト
ウィンドウを用意するとき
var f = new javax.swing.JFrame("test")
を実行しました。
Javaでは、ウィンドウやボタンなどプログラムで扱う対象を「オブジェクト」として用意します。ここでは変数f
にはウィンドウのオブジェクトが割り当てられています。Swingではウィンドウはjavax.swing.JFrame
という型で表します。オブジェクトはなんらかの型を基にしてして生成されます。オブジェクトの基になるような型を「クラス」と呼びます。javax.swing.JFrame
はクラスということになります。
クラスからオブジェクトを生成するときにはnew
演算子を使ってnew クラス(引数)
のようにして生成します。引数はクラスによって決まっています。
見方によっては、オブジェクトを生成するときはnew
演算子と共に特別なメソッドを呼び出しているようにも見えます。このように見たとき、このメソッドのことを「コンストラクタ」と呼びます。コンストラクタは、クラスと同じ名前で呼び出しにnew
演算子が必要なメソッドだと言えます。
JavaDoc
このjavax.swing.JFrame
のドキュメントはここにあります。
https://download.java.net/java/early_access/jdk11/docs/api/java.desktop/javax/swing/JFrame.html
英語ですね。日本語がいいという場合は、バージョンは古いですが、こちらを。
https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/JFrame.html
このドキュメントの形式を「JavaDoc」といいます。JavaのAPIのドキュメントは、だいたいこの形式になっています。
「javadoc JFrame」など、javadoc+クラス名でぐぐると、だいたいJavaDocが出てきます。
パッケージとimport
ウィンドウが表示できたので、テキストエリアを配置してみましょう。テキストエリアは複数行の文字列が入力できる部品です。Swingではテキストエリアはjavax.swing.JTextArea
クラスで扱います。またこのようにウィンドウに配置する部品を「コンポーネント」と呼びます。
テキストエリアを配置するために、まずはテキストエリアのオブジェクトを生成する必要があります。オブジェクトを生成するには、クラス名と同じ名前のメソッド、つまりコンストラクタにnew
演算子を付けて呼び出すんでしたね。しかしjavax.swing.JTextArea
というのは長くていちいち入力するのは面倒です。
実際にはjavax.swing.JTextArea
は二つの部分に別れていて、最後の区切りだけがクラス名、その前はパッケージ名となっています。つまりjavax.swing
というパッケージのJTextArea
クラスを表しています。
そこで、import
文を使うと、パッケージ名を省略できるようになります。import javax.swing.*
とすると、javax.swing
パッケージのクラスはパッケージ名を省略してクラス名だけで表すことができるようになります。
jshell> import javax.swing.*
それでは、テキストエリアを表すJTextArea
クラスのオブジェクトを生成してみましょう。
jshell> var textarea = new JTextArea()
textarea ==> javax.swing.JTextArea[,0,0,0x0,i ... rap=false]
これをウィンドウに配置する必要があります。ウィンドウを表すJFrame
オブジェクトに対してadd
メソッドを呼び出すことでウィンドウに追加できます。
jshell> f.add(textarea)
$14 ==> javax.swing.JTextArea[,0,0,0x0,inval ... se,wrap=false]
ただ、このままではウィンドウに表示されないので、ウィンドウを再編成してもらう必要があります。ウィンドウのサイズを変えると再編成が行われるので、ウィンドウの端をドラッグしてサイズを変えるか、setSize
メソッドを呼び出すかしてみます。
jshell> f.setSize(400,300)
テキストエリアが表示されて、文字が入力できるようになりました。
テキストエリアに対して、appendメソッドで文字列を追加することができます。
jshell> textarea.append("te")
jshell> textarea.append("st")
ただし、そのままだと開業されずに続けて追加されてしまいます。
改行は\n
で表します。
jshell> textarea.append("\ntester\n")
ボタンの追加
さて、それでは、ボタンを追加してみましょう。SwingではボタンはJButton
クラスで扱います。コンストラクタの引数にボタンのラベル文字列を指定することができます。
jshell> var button = new JButton("Hello")
button ==> javax.swing.JButton[,0,0,0x0,inval...pable=true]
これをウィンドウに追加したいのですが、すでにテキストエリアを配置しているので、重ならない位置に追加する必要があります。
JFrameでは、東西南北と真ん中という指定でコンポーネントを配置します。
add
メソッドの第一引数に配置する場所、第二引数に配置するコンポーネントを指定します。
jshell> f.add("North", button)
$27 ==> javax.swing.JButton[,0,0,0x0,inval...ltCapable=true]
North
をスペルミスなどすると、このようなエラーが出ます。大文字小文字も区別するので気をつけてください。
jshell> f.add("Nort", button)
| Exception java.lang.IllegalArgumentException: cannot add to layout: unknown constraint: Nort
| at BorderLayout.addLayoutComponent (BorderLayout.java:468)
| at BorderLayout.addLayoutComponent (BorderLayout.java:429)
| at JRootPane$1.addLayoutComponent (JRootPane.java:507)
| at Container.addImpl (Container.java:1151)
| at Container.add (Container.java:1028)
| at JFrame.addImpl (JFrame.java:553)
| at Container.add (Container.java:459)
| at (#31:1)
setSize
メソッドでウィンドウを再構成させると、ボタンが表示されています。
jshell> f.setSize(400,300)
けれども、このボタンを押しても何も起きませんね。なにか処理を書く必要があります。次のように入力してみてください。addActionListener
はちょっと長いですが、addAc
まで入力して[tab]キーを押すと続きは補完されるはずです。
jshell> button.addActionListener(ae -> textarea.append("Hello!\n"))
これで、ボタンが押されたときに「Hello」と表示されるようになりました。
ボタンが押されたときの処理を追加するにはaddActionListener
メソッドを使います。
ここで引数にae->textarea.append("Hello!\n")
を指定しています。addActionListener
メソッドには「ボタンが押されたときにこの処理を呼び出してくださいね」という感じでなんらかの処理を渡す必要がありました。ここでの処理はtextarea.append("Hello!\n")
ですが、処理を値として渡すには「ラムダ式」などを使う必要があります。
ラムダ式は次のように書きます。
引数 -> 処理
ボタンを押したときの処理の場合は、引数としてActionEvent
オブジェクトを受け取るのでここではae
としていますが、わかりやすければなんでも構いません。受け取った引数は、今回は使っていません。
テキストフィールドで入力を受け取る
もうちょっとがんばりましょうね。
ボタンを押すとテキストフィールドに入力された文字列が表示される、というのをやってみます。
テキストフィールドとボタンを追加したいのですが、JFrameのレイアウト方式ではそのままでは追加できません。そこで、JPanel
コンポーネントを使います。
jshell> var panel = new JPanel()
jshell> f.add("South", panel)
JPanel
コンポーネントは左から順にコンポーネントを並べるレイアウトになっていて、ここにいろいろ載せてからJFrame
ウィンドウに追加すると、いい感じになります。ここではSouth
の位置に追加することにしました。
ウィンドウサイズを変えてみると、少し何か表示されてますね。
テキストフィールドを追加します。テキストフィールドは1行だけの入力するコンポーネントでJTextField
コンポーネントを使います。
jshell> var textfield = new JTextField()
jshell> textfield.setColumns(15)
jshell> panel.add(textfield)
最後にボタンを追加してみましょう。
jshell> var printButton = new JButton("Print")
jshell> printButton.addActionListener(ae -> textarea.append(textfield.getText() + "\n"))
jshell> panel.add(printButton)
ボタンを押すとテキストフィールドに入力した文字列がテキストエリアに追加されました。
練習:Yeah!
とテキストエリアに表示するボタンを追加してみましょう。
練習:テキストフィールドに入力された文字列のアルファベットを大文字にしてテキストエリアに出力するボタンを追加してみましょう。文字列のアルファベットを大文字にするには、toUpperCase
メソッドを使います。先にtoUpperCase
メソッドの使い方を試しておきましょう。
JShellを離れてJavaのプログラムを作る
最後に、これまでJShellで試したことを、独立したJavaのプログラムとして書いてみましょう。
メモ帳やテキストエディットなどで次のソースコードを入力して、デスクトップにFirstWindow.java
という名前で保存してください。
import javax.swing.*;
public class FirstWindow {
public static void main(String... args) {
var frame = new JFrame("test");
var textarea = new JTextArea();
frame.add(textarea);
var textfield = new JTextField();
textfield.setColumns(15);
var button = new JButton("Print");
button.addActionListener(ae -> textarea.append(textfield.getText() + "\n"));
var panel = new JPanel();
panel.add(textfield);
panel.add(button);
frame.add("North", panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.show();
}
}
いろいろJShellでは出なかったものが追加されていますね。また、JShellで入力したコマンドには;
(セミコロン)がついています。けれども、このチュートリアルを始める前に比べたら「読める、読めるぞ!」という感じじゃないでしょうか。
では、このソースコードを動かしてみます。
コマンドプロンプトを開いてください。今回はJShellは使いません。
cd
コマンドを使ってデスクトップに移動します。
$ cd Desktop
それから、javac
コマンドで先ほど入力したソースコードをコンパイルします。
$ javac FirstWindow.java
エラーが出たら修正して保存してからまたコンパイルを行なってください。
エラーが出なくなったら作成されたファイルを確認してみましょう。
Windowsではdir
コマンド、MacやLinuxではls
コマンドを使います。
$ dir FirstWindow.*
FirstWindow.class
ファイルができていますね。これがJavaの実行コードです。これを実行するにはjava
コマンドを使います。
$ java FirstWindow
ここからJavaの本格的な勉強を始めてください。