JShellで始めるJava - Javaの世界を覗いてみる

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あたりに。

image.png

試しに12+23を入力して[enter]キーを押してください。
35という結果が現れましたね。
image.png

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]キーを押すと、文字列に対して呼び出せるメソッドの一覧が表示されます。
image.png

では、他のメソッドも使ってみましょう。"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()

左上に何か表示されました。
image.png
小さいので、サイズを大きくしてみます。サイズを決めるにはsetSizeメソッドを使います。ここで横サイズと縦サイズと指定します。

jshell> f.setSize(400,300)

大きくなった!
image.png

クラスとオブジェクト

ウィンドウを用意するとき
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)

テキストエリアが表示されて、文字が入力できるようになりました。

image.png

テキストエリアに対して、appendメソッドで文字列を追加することができます。

jshell> textarea.append("te")

jshell> textarea.append("st")

ただし、そのままだと開業されずに続けて追加されてしまいます。
image.png

改行は\nで表します。

jshell> textarea.append("\ntester\n")

ちゃんと改行されましたね。
image.png

ボタンの追加

さて、それでは、ボタンを追加してみましょう。SwingではボタンはJButtonクラスで扱います。コンストラクタの引数にボタンのラベル文字列を指定することができます。

jshell> var button = new JButton("Hello")
button ==> javax.swing.JButton[,0,0,0x0,inval...pable=true]

これをウィンドウに追加したいのですが、すでにテキストエリアを配置しているので、重ならない位置に追加する必要があります。
JFrameでは、東西南北と真ん中という指定でコンポーネントを配置します。
image.png

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)

image.png

けれども、このボタンを押しても何も起きませんね。なにか処理を書く必要があります。次のように入力してみてください。addActionListenerはちょっと長いですが、addAcまで入力して[tab]キーを押すと続きは補完されるはずです。

jshell> button.addActionListener(ae -> textarea.append("Hello!\n"))

これで、ボタンが押されたときに「Hello」と表示されるようになりました。
image.png

ボタンが押されたときの処理を追加するには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の位置に追加することにしました。
ウィンドウサイズを変えてみると、少し何か表示されてますね。
image.png

テキストフィールドを追加します。テキストフィールドは1行だけの入力するコンポーネントでJTextFieldコンポーネントを使います。

jshell> var textfield = new JTextField()

jshell> textfield.setColumns(15)

jshell> panel.add(textfield)

setColumnsメソッドで幅を決めています。
image.png

最後にボタンを追加してみましょう。

jshell> var printButton = new JButton("Print")

jshell> printButton.addActionListener(ae -> textarea.append(textfield.getText() + "\n"))

jshell> panel.add(printButton)

ボタンを押すとテキストフィールドに入力した文字列がテキストエリアに追加されました。
image.png

練習:Yeah!とテキストエリアに表示するボタンを追加してみましょう。
練習:テキストフィールドに入力された文字列のアルファベットを大文字にしてテキストエリアに出力するボタンを追加してみましょう。文字列のアルファベットを大文字にするには、toUpperCaseメソッドを使います。先にtoUpperCaseメソッドの使い方を試しておきましょう。

JShellを離れてJavaのプログラムを作る

最後に、これまでJShellで試したことを、独立したJavaのプログラムとして書いてみましょう。
メモ帳やテキストエディットなどで次のソースコードを入力して、デスクトップにFirstWindow.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

ウィンドウが表示されたでしょうか?表示されれば成功です。
image.png

ここからJavaの本格的な勉強を始めてください。