再評価のための復習: メソッド

メソッドの概念

Method concept

  • メソッドを呼ぶと定義された処理が実行される
  • メソッドを呼ぶ時に引数を渡す場合がある。
  • メソッドを呼ぶと戻り値が返ってくる場合がある。

メソッドの定義

例: int型の数値を2つ足した合計を返すメソッドの定義

メソッド

引数

  • メソッド名の後ろのカッコの中に、型と引数名を書く。
  • 複数の場合はカンマで区切る
  • 引数がない場合は書かない(カッコは必要)

戻り値(返り値)

  • 戻り値の肩をメソッド名の前に書く。
  • 戻り値はreturn文で指定する。
  • 戻り値がない場合は、戻り値の型として「void」を指定する。return文はなくても良い(あっても良いがreturnの後ろに何も書かない)。

アクセス修飾子

  • フィールドと同様にアクセス修飾子をつけることで、そのメソッドを呼び出すことのできる呼び出し元を制限することができる。
  • アクセス修飾子は戻り値の型の前に書く。

処理で使える変数

  • 引数
  • フィールド
  • その場で定義した変数

教科書

  • P.66: メソッドの定義
  • P.68: メソッドの呼び出し(1)
  • P.70: メソッドの呼び出し(2)

Spring Bootによるウェブアプリ開発: Formの基礎

前回の要点

  • http://start.spring.ioでプロジェクトを作成する。
  • 処理の流れ
  • テンプレートとコントローラを作る。
  • テンプレート
    • HTMLで記述する。ただし単独で現れるタグは後ろに「/」をつける。
    • コントローラから送られてきた値を表示するところで、th:text属性を使う。
  • コントローラ
    • クラスに@Controllerアノテーションをつける。
    • クラスとメソッドにつける@RequestMappingアノテーションで担当するURLを指定する。
    • メソッドの返り値で利用するテンプレートを指定する。
    • テンプレートに値を送り込みたい場合は、メソッドにModelMap型の引数を加え、そのaddAttributeメソッドで名前と値を指定する。
  • その他
    • ポート番号を変える: resourcesにあるapplication.propertiesに「server.port = 18080」などと記述する。

ドキュメント

Formの作成と表示

おみくじアプリを作ってみよう。

処理のシーケンスは次のようになる。

おみくじのシーケンス

名前を入力する(フォームの利用)

  • formタグ: どこからどこまでがフォームかを表す。action属性でどこに送るか指定する。method属性でどのような形で送るかを指定する。
  • inputタグ: name属性で区別のための名前をつける。この例ではその名前にnameとつけて紛らわしいので注意すること。
  • buttonタグ: type属性をsubmitとすることで、formの送信ボタンにすることができる。

コントローラ

  • 18〜21行目:「/lecture04/omikuji_input」にアクセスがあると、「lecture04/omikuji_input」がブラウザに送られる。
  • 26〜34行目:「/lecture04/omikuji_output」にアクセスがあると、「lecture04/omikuji_output」がブラウザに送られる。
    • 27行目:「フォームから送られてくるパラメータを受け取るための引数」を指定する為に@RequestParamアノテーションをつける。
    • 28〜31行目: String型の変数を乱数によって「吉」か「大吉」にする。
    • 32行目: 「result」という名前で変数resultをテンプレートに送る。
    • 32行目: 「name」という名前で変数nameをテンプレートに送る。

結果の表示

  • コントローラからは「name」と「result」という名前で値が送られてきている。それぞれ、th:text属性で表示する。

例1: 掲示板

テンプレート

  • 最初の表示(get)とコメントを書き込む時(post)の両方でこのテンプレートを使う。
  • formのaction属性は省略すると、同じURLにアクセスすることになる。
  • リストから一つづつ取り出すのは、th:each属性を使う。コロンの左側でつけた名前でアクセスできる(スコープは、属性をつけた要素の内側)。注意しなければならないのは、繰り返し出力されるのは、th:each属性がついた要素(タグ)だということ。例えば、commentListに3つの文字列が入っていたとしたら、li要素が3つ出力される。
  • タグ無しで値を出力するのはth:blockタグを使う。

コントローラ

  • @RequestMappingはgetとpostの両方で実行されるが、@GetMappingと@PostMappingを使うことで、同じURLでgetとpostの処理を別のメソッドに分けて書くことができる。
  • コントローラ全体

例2: じゃんけん

テンプレート

  • 最初の表示(get)とじゃんけんをした時(post)の両方でこのテンプレートを使う。
  • th:ifで条件が真(true)の時だけ要素を表示させることができる。ここでは、コントローラからresultが送られてきた時(つまりresultがnullでない)にそれを表示している。
  • input要素のtype属性は「radio」。checked=”checked”をつけた要素がデフォルトで選択される。
  • name属性は全て同じにする(nameを同じにすると同一グループとなり排他的選択ができる)。
  • 選択されたボタンのvalue属性がコントローラに送られる。

コントローラ

  • getとpostで同じメソッド名となっているが、これをオーバーロードという(教科書P.132)。
  • StringBuilderは文字列を繋げる時に使える(教科書P.82)。
  • 律儀にコンピュータの手を決定して結果を出力してもいいが、ここでは選択した手に関わらずランダムで結果を出力している。
  • コントローラ全体

例3: アンケート

テンプレート

  • チェックボックスはname属性で区別する。

コントローラ

  • チェックボックスは、チェックをしたときにしかパラメータが送信されない。そのため、デフォルトの@RequestParamではエラーになる。
  • パラメータが送信されなくてもエラーにならないようにするには、「required = false」とする。
  • チェックされているときはtrue、チェックされてない時(パラメータが無い時)は、falseになる。
  • コントローラ全体

教科書

再評価のための復習: フィールド

最もシンプルなフィールドの定義

型名 フィールド名;

これにアクセス修飾子や初期化がつく。

フィールド定義の例

外部からのアクセス(アクセス修飾子の違い)

教科書

Spring Bootによるウェブアプリ開発: プロジェクトの作成からページの表示まで

プロジェクトの雛形を作成

  1. ブラウザで「http://start.spring.io」にアクセスする。
  2. 「Cradle Project」を選択する。
  3. グループIDとして、パッケージ名を入力する。ここでは「ユーザ名.webapp」とする。
  4. アーティファクトIDとしてプロジェクト名を入力する。ここでは「webapp」とする。
  5. 利用する依存ライブラリを入力する。名前の一部を入力すると選択肢が現れるのでクリックして選択する。ここでは「Web」と「Thymeleaf」を選択する。
  6. 選択されたものが表示されているので「Web」と「Thymeleaf」が選択されていることを確認する。
  7. クリックするとプロジェクトのファイル(ZIPファイル)のダウンロードが始まる。

start.spring.ioでプロジェクト作成

NetBeansでインポート

メニューから[ファイル]→[プロジェクトをインポート]→[ZIPから]を選択し、ダウンロードしたファイル(webapp.zip)を指定してインポートする。

インポート直後の構成

Spring Bootアプリケーションの実行

アプリケーションを実行するためのタスクが定義されているため、それを使う。

プロジェクトを右クリックして、[Task]→[boot]→[bootRun]を選択する。

アプリケーションが立ち上がると、出力ウィンドウの最後に「Started WebappApplication」と表示される。

その1行前に「Tomcat started on port(s): 8080 (http)」と出力されているということは、8080番ポートにアクセスすれば何らかの反応があるはずである。http://localhost:8080/にアクセスしてみよう。

サーバが出力したエラーページ

エラーメッセージが表示されたが、これは、まだコンテンツを返すプログラムを作っていないために表示されるもので、正常な動作である。アプリケーションを終了するには、出力ウィンドウの左側にあるStopボタンをクリックする。

Spring Web MVC frameworkの基礎中の基礎

処理の流れ

これから作るウェブアプリケーションはSpringのWeb MVCフレームワークを利用している。このフレームワークにおける処理の流れを次の図に示す(http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-servletより引用)。

Mvc

フロントコントローラがリクエストを適切なコントローラに渡し、コントローラが出力するデータをビュー(テンプレート)が表示するという仕組み。このうち、自分で作るのは、「コントローラ」と「ビューテンプレート」である。

まずは、単純に「こんにちは」と表示するようにコントローラとテンプレートを作ってみよう。

テンプレートを作る

テンプレートとは雛形のことであり、そこに流し込まれるデータとともに使うことが一般的な使い方であるが、まずはデータの流し込みを想定しないテンプレートを作成してみよう。

まず、テンプレートを格納するディレクトリを作成しよう。Resourcesのtemplatesにlecture03というディレクトリ(パッケージ)を作る。NetBeansのパッケージの表示の仕方によっては、作業が難しい。プロジェクトウィンドウの背景部分を右クリックし、「Javaパッケージの表示方法」を「ツリー」にすると階層構造がわかりやすい。

パッケージをツリーで表示

lecture03を右クリックして新規から「HTMLファイル」を選択する。ファイル名を「hello」と入力する。拡張子は自動でつくので入力しない。作成したら、次のように書き換えよう。

今の所、次の2点が注意する点で、これ以外は普通のHTMLファイルである。

  • 2行目: xmlns属性はXML名前空間の宣言である。テンプレートエンジンであるThymeleafはHTMLへの埋め込みをXMLによって行うことが大きな特徴である。名前宣言によってThymeleafによる操作をthというプレフィックスで行うことができる。
  • 4行目: 単独で使われるタグ(brやhr等)は後ろに/をつける(XMLのルール)。

コントローラを作る

コントローラは、リクエストに対してどのテンプレートを使うか(そしてテンプレートにどのような値を埋め込むか)ということを決定するためのものである。

具体的には@Controllerアノテーションをつけたクラスで、リクエストに対応してメソッドを定義する。メソッドの返り値としてテンプレートを指定する。

  • 12行目: コントローラを表すアノテーション
  • 13行目: このコントローラが、「/lecture03」のURLを担当することを表す。
  • 16〜19行目: /hello(つまりhttp://localhost:8080/lecture03/hello)に対応するメソッド
    • 16行目: /helloに対応すること表す
    • 17行目: 戻り値の型はStringにする。メソッド名はなんでも良い。
    • 18行目: テンプレートのルート(resources/templates)から利用するテンプレートの相対パス(拡張子は除く)

20行目以降は次節以降で解説する。

動作を確認

http://localhost:8080/lecture03/helloにブラウザでアクセスしよう。

テンプレートに値を渡す

  • メソッドにModelMap型の引数を加える。
  • そのaddAttributeメソッドで名前と値を登録する。
  • テンプレートでth:text属性を使う。

例1: サイコロ

アクセスするたびに表示される数が変化する。乱数については教科書P.108を参照。

例2: 挨拶

現在時刻によって表示されれる挨拶が変化する。時刻の扱いについては、教科書P.257を参照。

再評価のための復習: インスタンス

インスタンス化

  • クラスは「型の設計図」のこと。
  • クラス(設計図)からインスタンス(実体)を作ることができる。
  • インスタンス化: インスタンスを作ること。
  • インスタンス化はnew演算子を使う。
  • コンストラクタはインスタンス化の時に使われるメソッド(今後解説する)で、その時に使われる引数を記述する。下の例は引数なし。

インスタンス化

1行でまとめて書くこともできる。

エラーになる例

person3がインスタンス化されていない(注: 厳密には「初期化されていない」)ためコンパイルエラー(コンパイル時にエラーになってコンパイルできない)になる。

コンパイルできる(person4はnullで初期化されている)が、実行時にエラーになる(ランタイムエラー)。person4がインスタンス化されてない(実態がない)のに使おうとしたため。

基本型(プリミティブ型)は?

  • インスタンス化が必要なのは参照型(クラス型)
  • newは使わない。
  • 初期化は必要

次はOK。

1行で書くのもOK。

初期化がないのはNG(コンパイルエラー)。

基本型でnullは扱えないのでNG(コンパイルエラー)。

Gradleの利用

ビルドとは

ソフトウェアのビルド(英: build)は、ソースコードファイルを独立したソフトウェア生成物に変換するコンピュータ上で実行されるプロセス、またはその結果を指す。ビルドにおいて最も重要なのはコンパイルプロセスであり、ソースコードファイルを実行ファイルに変換する。

ビルド (ソフトウェア) – Wikipedia

要するに「コードを書いた後に実行できるようするまでにする作業」のこと。これまでは、NetBeansで行ってきた(「ファイルの実行」をクリックすることで、コンパイルが行われ実行された)。

Javaを用いた開発に使われるビルドツール

  • Ant
  • Maven
  • Gradle
  • etc…

Android用の開発環境であるAndroid StudioではGradleが採用されている。

NetBeansでGradleを使う

プラグイン

Gradle Supportプラグインをインストールすることで、Gradleベースのプロジェクトを作成・管理することができる。

プラグインを確認

インストール済みにあることを確認する。

プロジェクトの作成

Single Gradle Projectを選択。

プロジェクトを選択

プロジェクト名とメインクラス(メインメソッドを作るクラス)を指定する。メインクラスは完全修飾クラス名(パッケージ名を頭につける)で指定する。

プロジェクト名とメインクラス

プロジェクトには、メインクラス(Main.java)とビルドスクリプト(build.gradleとsettings.gradle)が作成される。

プロジェクトの構造

実行する

Main.javaに書き加える。

プロジェクトを右クリックして、Runをクリック。

runタスクの実行

出力ウィンドウに出力される。

出力ウィンドウ

外部のライブラリを使う

これまで、JDKに含まれるライブラリ(クラス)を使ってきたが、世の中には様々なライブラリが公開されている。ライブラリをプロジェクトに取り込んで使ってみよう。

GradleはMavenのリポジトリ(ライブラリが保管されているサーバ)からライブラリをダウンロードする機能があるので、Mavenのリポジトリから利用するライブラリを探すのが簡単だ。

今回は、HTMLパーサ(HTMLを解釈してあれこれするためのソフト)のJsoupを使ってみよう。MavenのリポジトリのJsoup 1.10.2のページにある、Gradle用の記述をコピーし、build.gradleのdependenciesにペーストする。

Mavenレポジトリからコピー

プロジェクトを右クリックして、Reload Projectをクリックすると、依存ライブラリがダウンロードされ、プロジェクトに追加される。

Dependenciesに追加される

Jsoupの利用例

ニュースのサイトからニュースのタイトル一覧を取得しよう。

注意: ブラウザで人間が操作するのではなく、機械的にページを取得する行為は一般に「ウェブスクレイピング(Web scraping)」というが、スクレイピングが想定されていない場合が多い(あるいは明示的に禁止されている)。ウェブから情報を取得するときには、まず専用のAPIがあるかどうか確認しよう。またスクレイピングによって情報を取得する場合も、その頻度を調整するなど、迷惑をかけないようにしよう(提供する側の立場としては、そもそもスクレイピングして欲しくない場合が多い)。

例外処理

教科書[P.65]を参照。

ポイント:

  • 例外(exception、エラーのこと)が発生したらcatch節に飛ぶ。
  • 例外の種類
    • チェック例外: 必ずtryでチェックしなければならない。
    • 非チェック例外: チェックしなくて良い。例えば、0で除算など。

再評価のための復習: クラスの概要

クラスとは

  • クラスとは型の設計図のこと。注: ここではわかりやすさのため設計図に例えるが、設計図の比喩が適切でない場合もあるので注意すること。「適切でない場合」については今後解説する。
  • クラスから作られるものをインスタンス(実体)という。
  • 基本的に、1クラス1ファイルで定義する。ファイル名は「クラス名.java」とする。
  • クラスにはメンバーによって構成される(クラスの中にかけるのはメンバーだけ)。
  • メンバーの種類にはフィールドとメソッドがある(フィールドとメソッド以外のものはない)。
  • [慣例] クラス名は大文字ではじめる。
  • [慣例] フィールド名とメソッド名は小文字ではじめる。

クラスの構造

カウンターアプリを作る

JavaFXでWindowを表示する

  • JavaFXのアプリケーションはjavafx.application.Applicationを継承して作る。
  • ちなみにjavafx.application.Applicationは抽象クラス(アブストラクトクラス)。
  • startメソッドをオーバーライドして、そこで各種設定(部品配置等)を行う。startメソッドはJavaFXにおけるコンストラクタのような役割。
  • アプリケーションの起動は「Application.launch(アプリケーションのクラス名.class);」で行う。

ボタンなどを配置する

イベントハンドラー(オブザーバー)

  • ボタンクラスはイベント(ボタンがクリックされた等)が発生した時に、何か処理をすること(させること)ができる。
  • 「イベントが発生した時の処理」を担当するクラスを「イベントハンドラー(event handler)」という。
  • もっと詳しく知りたい人へ: Observerパターン
  • (JavaFxの場合)ButtonのイベントハンドラーはEventHandlerインターフェースを実装する。
  • ボタンに関するイベントが発生すると、ボタンに登録したイベントハンドラーのhandleメソッドが実行される。

ExampleHandlerをきちんと動作させる(カウントボタンでラベルに表示されるカウンターを増やし、リセットボタンで0にする)には次の2つができるようにすればいいが、煩雑なコードになる。

  • labelのsetTextメソッドを呼べるようにする
  • countButtonとresetButtonのどちらからイベントが発生したか区別できるようにする

カウンターの機能をうまく実現するには、CounterAppがイベントを処理するようにするのが簡潔になる。

JavaFXについて知る

インターフェース(復習)

  • クラスと同様で、型を定義できる。
  • クラスと違って、単体では使えない(インスタンスを作ることができない)。クラスに実装(implements)する。
  • インターフェースで記述できるメソッドは抽象メソッド(本体がない)。したがってクラスでそのメソッドをオーバーライドして実装しなければ(本体を書かなければ)ならない。

例えると:

  • クラス: 設計図(どのような機能があるのか、その機能をどのような処理で実現するのかが書いてある)。
  • インスタンス: 製品・生産物・実体(設計図に基づいて作られるもの)。
  • インターフェース: 規格(設計の時点で持つべき機能が定義されている。どのように実現するのかは書いていない)。

設計図が違っても、同じ規格に準拠していれば、それらの設計図から作られた実体は同じように扱うことができる(その規格の範囲内では)。

例えばスマホ内蔵のバッテリーは特に標準規格がないので、あるスマホバッテリーを他のスマホで使うことはできない。
乾電池は形・サイズ・電圧の規格(単一、単二等)が合っていれば(インターフェースが合っていれば)、メーカや電池系(マンガン、アルカリ等)が違っても(処理の実装が違っても)入れ替えて使うことができる(注: 厳密には、電池系についても規格があるのでマンガンとアルカリで入れ替えてはダメな場合等もある)。

インターフェース

キャッシュレジスターをプログラムする。

レジで会計する(税込の合計金額を計算してレシートを印刷する)ときに必要なのは、商品の値段と商品名だ。だから、Bookクラスに「値段を取得するメソッド」と「商品名を取得するメソッド」があればOK。

では、Bookで表現できないものをレジで会計するには、どのようにすればいいのか?

  • Book以外も受け付けるようにレジを改良する(クラスごとに保存、計算するプログラムが必要になる)。
  • Bookより上位のクラス(例えば商品クラス)を定義し、それを継承するように書き直す(Java言語は単一継承のためうまく実現できない場合も)。
  • getPriceメソッドをなんとかして呼ぶ(リフレクションを使う)。ちなみに、ダック・タイピングをサポートする言語ならば簡単だが、Java言語はそうでは無い。
  • 商品を表すインターフェースを定義し、レジで扱いたいクラスはそれを実装(implements)する。
  • etc…

インターフェースとは

クラスに特定のメンバー(メソッドとフィールド、主にメソッド)が存在することを保証する仕組み。クラスと同様に型として扱うことができる。

  • インターフェースには「クラスが持っていてほしいメンバー」を定義する。ただしメソッドの本体(実際に実行される部分)は無い(抽象メソッドという)。
  • インターフェースをimplementsしたクラスは、そのインターフェースに定義されているメンバー全体を実装する(メソッドの本体も書く)。

まずはBookだけを計算できるレジ

商品を表すProduct

  • クラスと同様にメンバー(フィールド、メソッド)を持つ。
  • ただし、メソッドは本体がない(抽象メソッド)。

Productを実装(implements)

Product対応レジ