- 投稿日:2019-02-11T23:17:25+09:00
ThymeleafでPUTする時 hidden型を使っている
ThymeleafでPUTする時は、単純にformメソッドのactionにPUTを指定しているわけではない。
調べた経緯
PUTできるように実装したのに、chromeのdeveloperコンソールでRequest Methodを見ていたところ
POST
になっててあれ?ってなったため。。Thmeleafのソースがどのように展開されているかをみる
formタグのactionには
post
を指定した上で、hidden型を使って、putを実現していることがソースを見るとわかる。
・hidden型とは
https://developer.mozilla.org/ja/docs/Web/HTML/Element/Input/hidden
もともとフォームに表示させずに値を送信したいときなどに使うもの。
- Thymeleafのコード
sample.html<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta http-equiv='Content-type' content='text/html; charset=utf-8' /> <title>test</title> </head> <body> <!-- ここに注目 --> <form th:action="@{/user}" th:method="put"> <input class="btn btn-default btn-xs" type="submit" value="更新" /> </form> <!-- ここに注目 --> </body> </html>
- 画面に表示されたソースのコード(thymeleaf展開後)
sample.html<!DOCTYPE html> <html> <head> <meta http-equiv='Content-type' content='text/html; charset=utf-8' /> <title>test</title> </head> <body> <!-- ここに注目 --> <form action="/user" method="post"> <input type="hidden" name="_method" value="put"/> <input class="btn btn-default btn-xs" type="submit" value="更新" /> </form> <!-- ここに注目 --> </body> </html>理由
formタグは、
get
とpost
メソッドしかサポートしていない。
そのため、formタグ上はmethod="post"
を指定し、hidden型でvalue="put"
を指定する方法を取っていると思われる。
結果としてRequest MethodはPOST
だが_method
で指定したメソッドで送信されるためPUT
で送信される。調べてみると他のRailsなどのフレームワークでもこのような方法でputを実現しているみたい。
- 投稿日:2019-02-11T18:08:35+09:00
04. SpringBoot + Thymeleafでフロントエンドを作ってみた
概要
今回はAPIではなくフロントエンド(Thymeleaf)を作ってみようと思います。
「前回まではAPIだったのに突然フロントエンドなんてできるのか?」とお思いの方もいらっしゃるかもしれませんが、
筆者の感覚としてはAPIもフロントエンドも実装はそこまで変わりません。ある程度のルール(ファイルの配置箇所など)を守ればSpringBootがよしなにやってくれるので、
主に変わるのはController層くらいで、それにView層が追加されるくらいなものです。
つまりModel(Service、Mapper)層はAPIと同じような構成、実装で構わないということです。では実際にソースを見ていきましょう!
本題
前回までは同じプロジェクトを使用していましたが、
今回はフロントエンドになるので新しいプロジェクトを切っていきます。(手順は割愛します)
作り物としてはシンプルに、前回と同じく郵便番号検索APIにリクエストし、その結果をhtmlにして返してくれるものとしましょう。
今回のメインはThymeleafによるViewの実装なので、そちらの解説をメインにしていきます。1. 依存を追加する
お馴染みSpringInitializrを使っていきます。
今回は「Web」「MySQL」「MyBatis」「Lombok」「Thymeleaf」を指定して作っていきます。
上記を選択したらGenerateProjectをクリックし、ダウンロードできたzipの中にあるbuild.gradleをプロジェクトに反映させます。
Refleshを忘れずに。2. Modelを作る
前回作成したGetAddressApiClientとResponseHeaderInterceptorをコピーしてそのまま持ってきます。
あ、データクラスも忘れずに持ってきましょう。3. ControllerとViewを作る
3-1. トップ画面を出すControllerとView
とりあえずトップ画面です。
SpringBootではリダイレクトとフォワードが利用可能です。今回はリダイレクトを使用しています。TopController.java@Controller public class TopController { @GetMapping("/top") public String top() { return "/top"; } @GetMapping("/") public String index() { return "redirect:/top"; // この記述で/topにリダイレクト可能になります } }つづいてhtmlですが、載せるほどのものではないのでここでは割愛します。
単純なアンカーで検索画面に飛ばすだけです。3-2. 検索と結果を表示するControllerとViewを作る
まとめてバリデーションも実装しちゃいましょう。
まずはControllerから。AddressSearchController.java@Controller @RequiredArgsConstructor public class AddressSearchController { private final GetAddressApiClient client; @GetMapping("/address/search") public String search(@ModelAttribute SearchForm form) { // (1) return "/address/search"; } @PostMapping("/address/confirm") public String confirm(@ModelAttribute @Valid SearchForm form, BindingResult bindingResult, Model model) { if (bindingResult.hasErrors()) { // (2) return "/address/search"; } GetAddressApiResponse response = client.request(form.getPostalCode()); model.addAttribute("addressList", response.getResults()); // (3) return "/address/confirm"; } }では要点を簡単に説明していきます。
(1).@ModelAttribute
を引数に付与してModelからformを取り出しています。初期表示のタイミングではModelにインスタンスが存在しないため、Springがnew
し、そのオブジェクトを渡してくれます。メソッド内で明示的にnew
してmodel.addAttribute()
しても同じことですが、この記述をしておけばforward
で値を引き継げるので便利です!
(2). お馴染みbindingResult.hasErrors()
で入力された郵便番号に不正があった場合には検索画面に戻します。因みにアノテーションは前回作ったZipCode
をそのまま流用しています。
(3). 入力された郵便番号に不正がなければ前回作成したClient
を介して住所情報を取得し、addressList
という名前でViewに値を渡します。続いて検索画面のhtmlです。
search.html<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <!-- (1) --> <head> <meta charset="UTF-8"> <title>Sample Search</title> </head> <body> <h2>検索画面</h2> <form th:action="@{/address/confirm}" th:method="post" th:object="${searchForm}"> <label th:for="*{postalCode}">郵便番号</label><input th:field="*{postalCode}"> <span th:if="${#fields.hasErrors('postalCode')}" th:errors="*{postalCode}">error message</span><br/> <!-- (2) --> <button type="submit">検索する</button> </form> </body> </html>まず初めにこのhtmlで登場している各
th
タグや記述方法について説明していきましょう。
- 変数式
${}
…Controllerから渡されたインスタンスの値を使用する場合に使用する記述方法。単純に「値を表示したいな」と思ったら使用すると考えていただければよいかと思います!- リンク式
@{}
…リンクを記述する場合に使用できる記述方法。コンテキストパスを補完してくれます。ここでは紹介しませんが、getパラメタを変数で埋め込んだりもできます。- 選択変数式
*{}
…ネストされた変数の値を表示する場合に使用する記述方式。このhtmlではth:object="${searchForm}"
で展開されたインスタンスにネストされているpostalCode
にアクセスしている、と考えてください。th:action
…アクション属性を指定します。th:for
…labelのfor
属性を指定します。th:field
…よく使用するであろうタグです。この記述をすると、id
とname
属性に変数名が入り、value
が空の状態でhtmlが作成されます。formとhtmlのフィールド同士をマッピングするときによく使用します。th:if
…よく使用するであろうタグです。値を評価した結果がtrue
であればそのタグが描画されます。(1). thymeleafのタグ
th
を使用するための記述です。これを記載しないとthymeleafを使用できないので忘れないようにしましょう。
(2).${#fields.hasErrors('postalCode')}
によって、postalCode
の値でバリデーション違反が発生した場合にtrue
を返してくれます。th:errors
でフィールド名を指定することにより、そのフィールドに対するエラーメッセージを表示できます。つまりこの一文でバリデーション違反があった場合のエラーメッセージ出力ができます。最後に確認画面のhtmlです。
confirm.html<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Sample Confirm</title> </head> <body> <h2>検索結果画面</h2> <table border="1"> <tr> <th>郵便番号</th> <th>都道府県コード</th> <th>住所1</th> <th>住所2</th> <th>住所3</th> <th>住所カナ1</th> <th>住所カナ2</th> <th>住所カナ3</th> </tr> <tr th:each="result : ${addressList}"> <td th:text="${result.zipcode}"></td> <td th:text="${result.prefcode}"></td> <td th:text="${result.address1}"></td> <td th:text="${result.address2}"></td> <td th:text="${result.address3}"></td> <td th:text="${result.kana1}"></td> <td th:text="${result.kana2}"></td> <td th:text="${result.kana3}"></td> </tr> </table> <a th:href="@{/address/search}">検索画面に戻る</a> </body> </html>今回は結果がリストで帰ってくるので、テーブルで出力させる形にしました。
この画面で使用しているタグについては以下の通りです。
th:each
…よく使用するであろうタグです。javaの拡張for文をイメージしていただければわかりやすいかと思います。${addressList}
から値を順番に取り出し、その値をresult
という名前で使用できるようにしています。th:text
…よく使用するであろうタグです。その名の通り、画面表示させたい場合に使用し、レンダリング後は<td></td>
に値が展開されます。尚XSSに対応しており、メタ文字をエスケープしてくれますので安心して使用できます。こんなところでしょうか。
では最後にブラウザから叩いてみましょう!!4. 実際に叩いてみる
4-1. トップ画面
bootRunして http://localhost:8080/ にアクセスします。
郵便番号で検索するをクリックして、検索画面へ遷移してみます。4-2. 検索画面
レンダリング後のHTMLソースはこんな感じです。
th:field
が展開されてid
とname
が変数名になり、value
が空になっていますね。
では正常な値を入れて検索するをクリックしましょう。4-3. 結果画面
続いて結果が複数の場合。
th:each
がちゃんと機能して、複数の場合でも全件表示できていますね。では最後にバリデーションエラーの場合を見てみましょう。
4-4. バリデーションエラー
無事エラーメッセージが表示できましたね。
因みにこのメッセージはZipCode.message
のデフォルトにべた書きしている文字列です。最後に
めちゃくちゃ簡単な内容ではありましたが、フロントエンドの実装でした。
thymeleafは奥が深く、私が触れているタグや記述方式は氷山の一角です。
もっともっといろいろなことができますので、いろいろ調べてみてください!あとはcssやjavascriptなどが必要になるかと思いますが、最近
semantic ui
に触れる機会がありました。
CDNで利用可能で、class名を指定することで勝手に装飾してくれますので、
興味のある方はぜひ触れてみてください!最後までご覧いただきありがとうございましたー!!
- 投稿日:2019-02-11T16:30:00+09:00
各言語で定義できる関数のパラメータの最大個数
ちょっと気になって、関数で定義できるパラメータの最大個数について実験してみました。
255を閾値として、それ以上のパラメータを持つ関数を定義・実行できるのか、各言語のREPLを使って調べました。 (JavaScript はブラウザのコンソールです。)
JavaScript は256以上できたので "(unlimited)" としています、実際はもっと少ないかも。
C, C++, C# はある方からいただいたコメントを元にしています。
C, C++, NodeJS, PHP, Ruby について @Nabetani 様 よりいただいた情報を反映しています。
Language Version the maximum number note C 127以上 コンパイラによって変わる。 オーバフローが発生するまで制限なく扱える場合もある。 SOLOLEARN, @Nabetani C++ 256以上 コンパイラによって変わる。 オーバフローが発生するまで制限なく扱える場合もある。 SOLOLEARN, @Nabetani C# 16383 オーバフローするまで成功すると思われる。 Stackoverflow Python 3.6.5 255 256個以上のパラメータを持つ関数は定義不可。 PHP 7.2.9 262145 オーバフローするまで成功すると思われる。 @Nabetani Ruby 2.5.1 130767 オーバフローするまで成功すると思われる。 @Nabetani Kotlin 1.3.0 255 256個以上のパラメータを持つ関数は定義可能だが実行時に java.lang.NullPointerException
が発生する。Java 11.0.2 255 256個以上のパラメータを持つ関数は定義不可。 JavaScript Chrome 72.0.3626.96 (unlimited) オーバフローするまで成功すると思われる。 NodeJS 11.9.0 65535 ルール上は65535。 現実にはオーバフローするまで。 @Nabetani 特に Kotlin は 1.3 で 255個のパラメータを持つ関数を定義できるようになりました。 Java も、 ルールとして 255までパラメータ持てることになっています。 たぶん Scala も?
Python
シンタックスエラーが関数定義の時に255までしか受け付けませんとメッセージを返します。
>>> def f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61, a62, a63, a64, a65, a66, a67, a68, a69, a70, a71, a72, a73, a74, a75, a76, a77, a78, a79, a80, a81, a82, a83, a84, a85, a86, a87, a88, a89, a90, a91, a92, a93, a94, a95, a96, a97, a98, a99, a100, a101, a102, a103, a104, a105, a106, a107, a108, a109, a110, a111, a112, a113, a114, a115, a116, a117, a118, a119, a120, a121, a122, a123, a124, a125, a126, a127, a128, a129, a130, a131, a132, a133, a134, a135, a136, a137, a138, a139, a140, a141, a142, a143, a144, a145, a146, a147, a148, a149, a150, a151, a152, a153, a154, a155, a156, a157, a158, a159, a160, a161, a162, a163, a164, a165, a166, a167, a168, a169, a170, a171, a172, a173, a174, a175, a176, a177, a178, a179, a180, a181, a182, a183, a184, a185, a186, a187, a188, a189, a190, a191, a192, a193, a194, a195, a196, a197, a198, a199, a200, a201, a202, a203, a204, a205, a206, a207, a208, a209, a210, a211, a212, a213, a214, a215, a216, a217, a218, a219, a220, a221, a222, a223, a224, a225, a226, a227, a228, a229, a230, a231, a232, a233, a234, a235, a236, a237, a238, a239, a240, a241, a242, a243, a244, a245, a246, a247, a248, a249, a250, a251, a252, a253, a254, a255, a256, a257): ... print(1) ... File "<stdin>", line 1 SyntaxError: more than 255 argumentsPHP
256以上のパラメータでも定義・実行できます。
php > function f($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9, $a10, $a11, $a12, $a13, $a14, $a15, $a16, $a17, $a18, $a19, $a20, $a21, $a22, $a23, $a24, $a25, $a26, $a27, $a28, $a29, $a30, $a31, $a32, $a33, $a34, $a35, $a36, $a37, $a38, $a39, $a40, $a41, $a42, $a43, $a44, $a45, $a46, $a47, $a48, $a49, $a50, $a51, $a52, $a53, $a54, $a55, $a56, $a57, $a58, $a59, $a60, $a61, $a62, $a63, $a64, $a65, $a66, $a67, $a68, $a69, $a70, $a71, $a72, $a73, $a74, $a75, $a76, $a77, $a78, $a79, $a80, $a81, $a82, $a83, $a84, $a85, $a86, $a87, $a88, $a89, $a90, $a91, $a92, $a93, $a94, $a95, $a96, $a97, $a98, $a99, $a100, $a101, $a102, $a103, $a104, $a105, $a106, $a107, $a108, $a109, $a110, $a111, $a112, $a113, $a114, $a115, $a116, $a117, $a118, $a119, $a120, $a121, $a122, $a123, $a124, $a125, $a126, $a127, $a128, $a129, $a130, $a131, $a132, $a133, $a134, $a135, $a136, $a137, $a138, $a139, $a140, $a141, $a142, $a143, $a144, $a145, $a146, $a147, $a148, $a149, $a150, $a151, $a152, $a153, $a154, $a155, $a156, $a157, $a158, $a159, $a160, $a161, $a162, $a163, $a164, $a165, $a166, $a167, $a168, $a169, $a170, $a171, $a172, $a173, $a174, $a175, $a176, $a177, $a178, $a179, $a180, $a181, $a182, $a183, $a184, $a185, $a186, $a187, $a188, $a189, $a190, $a191, $a192, $a193, $a194, $a195, $a196, $a197, $a198, $a199, $a200, $a201, $a202, $a203, $a204, $a205, $a206, $a207, $a208, $a209, $a210, $a211, $a212, $a213, $a214, $a215, $a216, $a217, $a218, $a219, $a220, $a221, $a222, $a223, $a224, $a225, $a226, $a227, $a228, $a229, $a230, $a231, $a232, $a233, $a234, $a235, $a236, $a237, $a238, $a239, $a240, $a241, $a242, $a243, $a244, $a245, $a246, $a247, $a248, $a249, $a250, $a251, $a252, $a253, $a254, $a255, $a256, $a257) { echo 1; } php > php > function f($a0 = 1, $a1 = 1, $a2 = 1, $a3 = 1, $a4 = 1, $a5 = 1, $a6 = 1, $a7 = 1, $a8 = 1, $a9 = 1, $a10 = 1, $a11 = 1, $a12 = 1, $a13 = 1, $a14 = 1, $a15 = 1, $a16 = 1, $a17 = 1, $a18 = 1, $a19 = 1, $a20 = 1, $a21 = 1, $a22 = 1, $a23 = 1, $a24 = 1, $a25 = 1, $a26 = 1, $a27 = 1, $a28 = 1, $a29 = 1, $a30 = 1, $a31 = 1, $a32 = 1, $a33 = 1, $a34 = 1, $a35 = 1, $a36 = 1, $a37 = 1, $a38 = 1, $a39 = 1, $a40 = 1, $a41 = 1, $a42 = 1, $a43 = 1, $a44 = 1, $a45 = 1, $a46 = 1, $a47 = 1, $a48 = 1, $a49 = 1, $a50 = 1, $a51 = 1, $a52 = 1, $a53 = 1, $a54 = 1, $a55 = 1, $a56 = 1, $a57 = 1, $a58 = 1, $a59 = 1, $a60 = 1, $a61 = 1, $a62 = 1, $a63 = 1, $a64 = 1, $a65 = 1, $a66 = 1, $a67 = 1, $a68 = 1, $a69 = 1, $a70 = 1, $a71 = 1, $a72 = 1, $a73 = 1, $a74 = 1, $a75 = 1, $a76 = 1, $a77 = 1, $a78 = 1, $a79 = 1, $a80 = 1, $a81 = 1, $a82 = 1, $a83 = 1, $a84 = 1, $a85 = 1, $a86 = 1, $a87 = 1, $a88 = 1, $a89 = 1, $a90 = 1, $a91 = 1, $a92 = 1, $a93 = 1, $a94 = 1, $a95 = 1, $a96 = 1, $a97 = 1, $a98 = 1, $a99 = 1, $a100 = 1, $a101 = 1, $a102 = 1, $a103 = 1, $a104 = 1, $a105 = 1, $a106 = 1, $a107 = 1, $a108 = 1, $a109 = 1, $a110 = 1, $a111 = 1, $a112 = 1, $a113 = 1, $a114 = 1, $a115 = 1, $a116 = 1, $a117 = 1, $a118 = 1, $a119 = 1, $a120 = 1, $a121 = 1, $a122 = 1, $a123 = 1, $a124 = 1, $a125 = 1, $a126 = 1, $a127 = 1, $a128 = 1, $a129 = 1, $a130 = 1, $a131 = 1, $a132 = 1, $a133 = 1, $a134 = 1, $a135 = 1, $a136 = 1, $a137 = 1, $a138 = 1, $a139 = 1, $a140 = 1, $a141 = 1, $a142 = 1, $a143 = 1, $a144 = 1, $a145 = 1, $a146 = 1, $a147 = 1, $a148 = 1, $a149 = 1, $a150 = 1, $a151 = 1, $a152 = 1, $a153 = 1, $a154 = 1, $a155 = 1, $a156 = 1, $a157 = 1, $a158 = 1, $a159 = 1, $a160 = 1, $a161 = 1, $a162 = 1, $a163 = 1, $a164 = 1, $a165 = 1, $a166 = 1, $a167 = 1, $a168 = 1, $a169 = 1, $a170 = 1, $a171 = 1, $a172 = 1, $a173 = 1, $a174 = 1, $a175 = 1, $a176 = 1, $a177 = 1, $a178 = 1, $a179 = 1, $a180 = 1, $a181 = 1, $a182 = 1, $a183 = 1, $a184 = 1, $a185 = 1, $a186 = 1, $a187 = 1, $a188 = 1, $a189 = 1, $a190 = 1, $a191 = 1, $a192 = 1, $a193 = 1, $a194 = 1, $a195 = 1, $a196 = 1, $a197 = 1, $a198 = 1, $a199 = 1, $a200 = 1, $a201 = 1, $a202 = 1, $a203 = 1, $a204 = 1, $a205 = 1, $a206 = 1, $a207 = 1, $a208 = 1, $a209 = 1, $a210 = 1, $a211 = 1, $a212 = 1, $a213 = 1, $a214 = 1, $a215 = 1, $a216 = 1, $a217 = 1, $a218 = 1, $a219 = 1, $a220 = 1, $a221 = 1, $a222 = 1, $a223 = 1, $a224 = 1, $a225 = 1, $a226 = 1, $a227 = 1, $a228 = 1, $a229 = 1, $a230 = 1, $a231 = 1, $a232 = 1, $a233 = 1, $a234 = 1, $a235 = 1, $a236 = 1, $a237 = 1, $a238 = 1, $a239 = 1, $a240 = 1, $a241 = 1, $a242 = 1, $a243 = 1, $a244 = 1, $a245 = 1, $a246 = 1, $a247 = 1, $a248 = 1, $a249 = 1, $a250 = 1, $a251 = 1, $a252 = 1, $a253 = 1, $a254 = 1, $a255 = 1, $a256 = 1) { echo 1; } php > f() php > ; 1Ruby
256以上のパラメータでも実行できます。
2.5.1 :004 > def f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61, a62, a63, a64, a65, a66, a67, a68, a69, a70, a71, a72, a73, a74, a75, a76, a77, a78, a79, a80, a81, a82, a83, a84, a85, a86, a87, a88, a89, a90, a91, a92, a93, a94, a95, a96, a97, a98, a99, a100, a101, a102, a103, a104, a105, a106, a107, a108, a109, a110, a111, a112, a113, a114, a115, a116, a117, a118, a119, a120, a121, a122, a123, a124, a125, a126, a127, a128, a129, a130, a131, a132, a133, a134, a135, a136, a137, a138, a139, a140, a141, a142, a143, a144, a145, a146, a147, a148, a149, a150, a151, a152, a153, a154, a155, a156, a157, a158, a159, a160, a161, a162, a163, a164, a165, a166, a167, a168, a169, a170, a171, a172, a173, a174, a175, a176, a177, a178, a179, a180, a181, a182, a183, a184, a185, a186, a187, a188, a189, a190, a191, a192, a193, a194, a195, a196, a197, a198, a199, a200, a201, a202, a203, a204, a205, a206, a207, a208, a209, a210, a211, a212, a213, a214, a215, a216, a217, a218, a219, a220, a221, a222, a223, a224, a225, a226, a227, a228, a229, a230, a231, a232, a233, a234, a235, a236, a237, a238, a239, a240, a241, a242, a243, a244, a245, a246, a247, a248, a249, a250, a251, a252, a253, a254, a255, a256, a257) 2.5.1 :005?> puts 1 2.5.1 :006?> end => :f 2.5.1 :001 > def f(a0 = 1, a1 = 1, a2 = 1, a3 = 1, a4 = 1, a5 = 1, a6 = 1, a7 = 1, a8 = 1, a9 = 1, a10 = 1, a11 = 1, a12 = 1, a13 = 1, a14 = 1, a15 = 1, a16 = 1, a17 = 1, a18 = 1, a19 = 1, a20 = 1, a21 = 1, a22 = 1, a23 = 1, a24 = 1, a25 = 1, a26 = 1, a27 = 1, a28 = 1, a29 = 1, a30 = 1, a31 = 1, a32 = 1, a33 = 1, a34 = 1, a35 = 1, a36 = 1, a37 = 1, a38 = 1, a39 = 1, a40 = 1, a41 = 1, a42 = 1, a43 = 1, a44 = 1, a45 = 1, a46 = 1, a47 = 1, a48 = 1, a49 = 1, a50 = 1, a51 = 1, a52 = 1, a53 = 1, a54 = 1, a55 = 1, a56 = 1, a57 = 1, a58 = 1, a59 = 1, a60 = 1, a61 = 1, a62 = 1, a63 = 1, a64 = 1, a65 = 1, a66 = 1, a67 = 1, a68 = 1, a69 = 1, a70 = 1, a71 = 1, a72 = 1, a73 = 1, a74 = 1, a75 = 1, a76 = 1, a77 = 1, a78 = 1, a79 = 1, a80 = 1, a81 = 1, a82 = 1, a83 = 1, a84 = 1, a85 = 1, a86 = 1, a87 = 1, a88 = 1, a89 = 1, a90 = 1, a91 = 1, a92 = 1, a93 = 1, a94 = 1, a95 = 1, a96 = 1, a97 = 1, a98 = 1, a99 = 1, a100 = 1, a101 = 1, a102 = 1, a103 = 1, a104 = 1, a105 = 1, a106 = 1, a107 = 1, a108 = 1, a109 = 1, a110 = 1, a111 = 1, a112 = 1, a113 = 1, a114 = 1, a115 = 1, a116 = 1, a117 = 1, a118 = 1, a119 = 1, a120 = 1, a121 = 1, a122 = 1, a123 = 1, a124 = 1, a125 = 1, a126 = 1, a127 = 1, a128 = 1, a129 = 1, a130 = 1, a131 = 1, a132 = 1, a133 = 1, a134 = 1, a135 = 1, a136 = 1, a137 = 1, a138 = 1, a139 = 1, a140 = 1, a141 = 1, a142 = 1, a143 = 1, a144 = 1, a145 = 1, a146 = 1, a147 = 1, a148 = 1, a149 = 1, a150 = 1, a151 = 1, a152 = 1, a153 = 1, a154 = 1, a155 = 1, a156 = 1, a157 = 1, a158 = 1, a159 = 1, a160 = 1, a161 = 1, a162 = 1, a163 = 1, a164 = 1, a165 = 1, a166 = 1, a167 = 1, a168 = 1, a169 = 1, a170 = 1, a171 = 1, a172 = 1, a173 = 1, a174 = 1, a175 = 1, a176 = 1, a177 = 1, a178 = 1, a179 = 1, a180 = 1, a181 = 1, a182 = 1, a183 = 1, a184 = 1, a185 = 1, a186 = 1, a187 = 1, a188 = 1, a189 = 1, a190 = 1, a191 = 1, a192 = 1, a193 = 1, a194 = 1, a195 = 1, a196 = 1, a197 = 1, a198 = 1, a199 = 1, a200 = 1, a201 = 1, a202 = 1, a203 = 1, a204 = 1, a205 = 1, a206 = 1, a207 = 1, a208 = 1, a209 = 1, a210 = 1, a211 = 1, a212 = 1, a213 = 1, a214 = 1, a215 = 1, a216 = 1, a217 = 1, a218 = 1, a219 = 1, a220 = 1, a221 = 1, a222 = 1, a223 = 1, a224 = 1, a225 = 1, a226 = 1, a227 = 1, a228 = 1, a229 = 1, a230 = 1, a231 = 1, a232 = 1, a233 = 1, a234 = 1, a235 = 1, a236 = 1, a237 = 1, a238 = 1, a239 = 1, a240 = 1, a241 = 1, a242 = 1, a243 = 1, a244 = 1, a245 = 1, a246 = 1, a247 = 1, a248 = 1, a249 = 1, a250 = 1, a251 = 1, a252 = 1, a253 = 1, a254 = 1, a255 = 1, a256 = 1) 2.5.1 :002?> puts 1 2.5.1 :003?> end => :f 2.5.1 :004 > f() 1 => nilKotlin
定義はできているように見えます。しかし実行時にエラーが出ました。
>>> fun f(a0: Int, a1: Int, a2: Int, a3: Int, a4: Int, a5: Int, a6: Int, a7: Int, a8: Int, a9: Int, a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17: Int, a18: Int, a19: Int, a20: Int, a21: Int, a22: Int, a23: Int, a24: Int, a25: Int, a26: Int, a27: Int, a28: Int, a29: Int, a30: Int, a31: Int, a32: Int, a33: Int, a34: Int, a35: Int, a36: Int, a37: Int, a38: Int, a39: Int, a40: Int, a41: Int, a42: Int, a43: Int, a44: Int, a45: Int, a46: Int, a47: Int, a48: Int, a49: Int, a50: Int, a51: Int, a52: Int, a53: Int, a54: Int, a55: Int, a56: Int, a57: Int, a58: Int, a59: Int, a60: Int, a61: Int, a62: Int, a63: Int, a64: Int, a65: Int, a66: Int, a67: Int, a68: Int, a69: Int, a70: Int, a71: Int, a72: Int, a73: Int, a74: Int, a75: Int, a76: Int, a77: Int, a78: Int, a79: Int, a80: Int, a81: Int, a82: Int, a83: Int, a84: Int, a85: Int, a86: Int, a87: Int, a88: Int, a89: Int, a90: Int, a91: Int, a92: Int, a93: Int, a94: Int, a95: Int, a96: Int, a97: Int, a98: Int, a99: Int, a100: Int, a101: Int, a102: Int, a103: Int, a104: Int, a105: Int, a106: Int, a107: Int, a108: Int, a109: Int, a110: Int, a111: Int, a112: Int, a113: Int, a114: Int, a115: Int, a116: Int, a117: Int, a118: Int, a119: Int, a120: Int, a121: Int, a122: Int, a123: Int, a124: Int, a125: Int, a126: Int, a127: Int, a128: Int, a129: Int, a130: Int, a131: Int, a132: Int, a133: Int, a134: Int, a135: Int, a136: Int, a137: Int, a138: Int, a139: Int, a140: Int, a141: Int, a142: Int, a143: Int, a144: Int, a145: Int, a146: Int, a147: Int, a148: Int, a149: Int, a150: Int, a151: Int, a152: Int, a153: Int, a154: Int, a155: Int, a156: Int, a157: Int, a158: Int, a159: Int, a160: Int, a161: Int, a162: Int, a163: Int, a164: Int, a165: Int, a166: Int, a167: Int, a168: Int, a169: Int, a170: Int, a171: Int, a172: Int, a173: Int, a174: Int, a175: Int, a176: Int, a177: Int, a178: Int, a179: Int, a180: Int, a181: Int, a182: Int, a183: Int, a184: Int, a185: Int, a186: Int, a187: Int, a188: Int, a189: Int, a190: Int, a191: Int, a192: Int, a193: Int, a194: Int, a195: Int, a196: Int, a197: Int, a198: Int, a199: Int, a200: Int, a201: Int, a202: Int, a203: Int, a204: Int, a205: Int, a206: Int, a207: Int, a208: Int, a209: Int, a210: Int, a211: Int, a212: Int, a213: Int, a214: Int, a215: Int, a216: Int, a217: Int, a218: Int, a219: Int, a220: Int, a221: Int, a222: Int, a223: Int, a224: Int, a225: Int, a226: Int, a227: Int, a228: Int, a229: Int, a230: Int, a231: Int, a232: Int, a233: Int, a234: Int, a235: Int, a236: Int, a237: Int, a238: Int, a239: Int, a240: Int, a241: Int, a242: Int, a243: Int, a244: Int, a245: Int, a246: Int, a247: Int, a248: Int, a249: Int, a250: Int, a251: Int, a252: Int, a253: Int, a254: Int, a255: Int, a256: Int, a257: Int) { println(1) } >>> fun f(a0: Int = 1, a1: Int = 1, a2: Int = 1, a3: Int = 1, a4: Int = 1, a5: Int = 1, a6: Int = 1, a7: Int = 1, a8: Int = 1, a9: Int = 1, a10: Int = 1, a11: Int = 1, a12: Int = 1, a13: Int = 1, a14: Int = 1, a15: Int = 1, a16: Int = 1, a17: Int = 1, a18: Int = 1, a19: Int = 1, a20: Int = 1, a21: Int = 1, a22: Int = 1, a23: Int = 1, a24: Int = 1, a25: Int = 1, a26: Int = 1, a27: Int = 1, a28: Int = 1, a29: Int = 1, a30: Int = 1, a31: Int = 1, a32: Int = 1, a33: Int = 1, a34: Int = 1, a35: Int = 1, a36: Int = 1, a37: Int = 1, a38: Int = 1, a39: Int = 1, a40: Int = 1, a41: Int = 1, a42: Int = 1, a43: Int = 1, a44: Int = 1, a45: Int = 1, a46: Int = 1, a47: Int = 1, a48: Int = 1, a49: Int = 1, a50: Int = 1, a51: Int = 1, a52: Int = 1, a53: Int = 1, a54: Int = 1, a55: Int = 1, a56: Int = 1, a57: Int = 1, a58: Int = 1, a59: Int = 1, a60: Int = 1, a61: Int = 1, a62: Int = 1, a63: Int = 1, a64: Int = 1, a65: Int = 1, a66: Int = 1, a67: Int = 1, a68: Int = 1, a69: Int = 1, a70: Int = 1, a71: Int = 1, a72: Int = 1, a73: Int = 1, a74: Int = 1, a75: Int = 1, a76: Int = 1, a77: Int = 1, a78: Int = 1, a79: Int = 1, a80: Int = 1, a81: Int = 1, a82: Int = 1, a83: Int = 1, a84: Int = 1, a85: Int = 1, a86: Int = 1, a87: Int = 1, a88: Int = 1, a89: Int = 1, a90: Int = 1, a91: Int = 1, a92: Int = 1, a93: Int = 1, a94: Int = 1, a95: Int = 1, a96: Int = 1, a97: Int = 1, a98: Int = 1, a99: Int = 1, a100: Int = 1, a101: Int = 1, a102: Int = 1, a103: Int = 1, a104: Int = 1, a105: Int = 1, a106: Int = 1, a107: Int = 1, a108: Int = 1, a109: Int = 1, a110: Int = 1, a111: Int = 1, a112: Int = 1, a113: Int = 1, a114: Int = 1, a115: Int = 1, a116: Int = 1, a117: Int = 1, a118: Int = 1, a119: Int = 1, a120: Int = 1, a121: Int = 1, a122: Int = 1, a123: Int = 1, a124: Int = 1, a125: Int = 1, a126: Int = 1, a127: Int = 1, a128: Int = 1, a129: Int = 1, a130: Int = 1, a131: Int = 1, a132: Int = 1, a133: Int = 1, a134: Int = 1, a135: Int = 1, a136: Int = 1, a137: Int = 1, a138: Int = 1, a139: Int = 1, a140: Int = 1, a141: Int = 1, a142: Int = 1, a143: Int = 1, a144: Int = 1, a145: Int = 1, a146: Int = 1, a147: Int = 1, a148: Int = 1, a149: Int = 1, a150: Int = 1, a151: Int = 1, a152: Int = 1, a153: Int = 1, a154: Int = 1, a155: Int = 1, a156: Int = 1, a157: Int = 1, a158: Int = 1, a159: Int = 1, a160: Int = 1, a161: Int = 1, a162: Int = 1, a163: Int = 1, a164: Int = 1, a165: Int = 1, a166: Int = 1, a167: Int = 1, a168: Int = 1, a169: Int = 1, a170: Int = 1, a171: Int = 1, a172: Int = 1, a173: Int = 1, a174: Int = 1, a175: Int = 1, a176: Int = 1, a177: Int = 1, a178: Int = 1, a179: Int = 1, a180: Int = 1, a181: Int = 1, a182: Int = 1, a183: Int = 1, a184: Int = 1, a185: Int = 1, a186: Int = 1, a187: Int = 1, a188: Int = 1, a189: Int = 1, a190: Int = 1, a191: Int = 1, a192: Int = 1, a193: Int = 1, a194: Int = 1, a195: Int = 1, a196: Int = 1, a197: Int = 1, a198: Int = 1, a199: Int = 1, a200: Int = 1, a201: Int = 1, a202: Int = 1, a203: Int = 1, a204: Int = 1, a205: Int = 1, a206: Int = 1, a207: Int = 1, a208: Int = 1, a209: Int = 1, a210: Int = 1, a211: Int = 1, a212: Int = 1, a213: Int = 1, a214: Int = 1, a215: Int = 1, a216: Int = 1, a217: Int = 1, a218: Int = 1, a219: Int = 1, a220: Int = 1, a221: Int = 1, a222: Int = 1, a223: Int = 1, a224: Int = 1, a225: Int = 1, a226: Int = 1, a227: Int = 1, a228: Int = 1, a229: Int = 1, a230: Int = 1, a231: Int = 1, a232: Int = 1, a233: Int = 1, a234: Int = 1, a235: Int = 1, a236: Int = 1, a237: Int = 1, a238: Int = 1, a239: Int = 1, a240: Int = 1, a241: Int = 1, a242: Int = 1, a243: Int = 1, a244: Int = 1, a245: Int = 1, a246: Int = 1, a247: Int = 1, a248: Int = 1, a249: Int = 1, a250: Int = 1, a251: Int = 1, a252: Int = 1, a253: Int = 1, a254: Int = 1, a255: Int = 1) { println(1) } >>> f() java.lang.NullPointerException at Line_1.f$default(Line_1.kts:1) >>> f(1) java.lang.NullPointerException at Line_1.f$default(Line_1.kts:1) >>> fun f(a0: Int = 1, a1: Int = 1, a2: Int = 1, a3: Int = 1, a4: Int = 1, a5: Int = 1, a6: Int = 1, a7: Int = 1, a8: Int = 1, a9: Int = 1, a10: Int = 1, a11: Int = 1, a12: Int = 1, a13: Int = 1, a14: Int = 1, a15: Int = 1, a16: Int = 1, a17: Int = 1, a18: Int = 1, a19: Int = 1, a20: Int = 1, a21: Int = 1, a22: Int = 1, a23: Int = 1, a24: Int = 1, a25: Int = 1, a26: Int = 1, a27: Int = 1, a28: Int = 1, a29: Int = 1, a30: Int = 1, a31: Int = 1, a32: Int = 1, a33: Int = 1, a34: Int = 1, a35: Int = 1, a36: Int = 1, a37: Int = 1, a38: Int = 1, a39: Int = 1, a40: Int = 1, a41: Int = 1, a42: Int = 1, a43: Int = 1, a44: Int = 1, a45: Int = 1, a46: Int = 1, a47: Int = 1, a48: Int = 1, a49: Int = 1, a50: Int = 1, a51: Int = 1, a52: Int = 1, a53: Int = 1, a54: Int = 1, a55: Int = 1, a56: Int = 1, a57: Int = 1, a58: Int = 1, a59: Int = 1, a60: Int = 1, a61: Int = 1, a62: Int = 1, a63: Int = 1, a64: Int = 1, a65: Int = 1, a66: Int = 1, a67: Int = 1, a68: Int = 1, a69: Int = 1, a70: Int = 1, a71: Int = 1, a72: Int = 1, a73: Int = 1, a74: Int = 1, a75: Int = 1, a76: Int = 1, a77: Int = 1, a78: Int = 1, a79: Int = 1, a80: Int = 1, a81: Int = 1, a82: Int = 1, a83: Int = 1, a84: Int = 1, a85: Int = 1, a86: Int = 1, a87: Int = 1, a88: Int = 1, a89: Int = 1, a90: Int = 1, a91: Int = 1, a92: Int = 1, a93: Int = 1, a94: Int = 1, a95: Int = 1, a96: Int = 1, a97: Int = 1, a98: Int = 1, a99: Int = 1, a100: Int = 1, a101: Int = 1, a102: Int = 1, a103: Int = 1, a104: Int = 1, a105: Int = 1, a106: Int = 1, a107: Int = 1, a108: Int = 1, a109: Int = 1, a110: Int = 1, a111: Int = 1, a112: Int = 1, a113: Int = 1, a114: Int = 1, a115: Int = 1, a116: Int = 1, a117: Int = 1, a118: Int = 1, a119: Int = 1, a120: Int = 1, a121: Int = 1, a122: Int = 1, a123: Int = 1, a124: Int = 1, a125: Int = 1, a126: Int = 1, a127: Int = 1, a128: Int = 1, a129: Int = 1, a130: Int = 1, a131: Int = 1, a132: Int = 1, a133: Int = 1, a134: Int = 1, a135: Int = 1, a136: Int = 1, a137: Int = 1, a138: Int = 1, a139: Int = 1, a140: Int = 1, a141: Int = 1, a142: Int = 1, a143: Int = 1, a144: Int = 1, a145: Int = 1, a146: Int = 1, a147: Int = 1, a148: Int = 1, a149: Int = 1, a150: Int = 1, a151: Int = 1, a152: Int = 1, a153: Int = 1, a154: Int = 1, a155: Int = 1, a156: Int = 1, a157: Int = 1, a158: Int = 1, a159: Int = 1, a160: Int = 1, a161: Int = 1, a162: Int = 1, a163: Int = 1, a164: Int = 1, a165: Int = 1, a166: Int = 1, a167: Int = 1, a168: Int = 1, a169: Int = 1, a170: Int = 1, a171: Int = 1, a172: Int = 1, a173: Int = 1, a174: Int = 1, a175: Int = 1, a176: Int = 1, a177: Int = 1, a178: Int = 1, a179: Int = 1, a180: Int = 1, a181: Int = 1, a182: Int = 1, a183: Int = 1, a184: Int = 1, a185: Int = 1, a186: Int = 1, a187: Int = 1, a188: Int = 1, a189: Int = 1, a190: Int = 1, a191: Int = 1, a192: Int = 1, a193: Int = 1, a194: Int = 1, a195: Int = 1, a196: Int = 1, a197: Int = 1, a198: Int = 1, a199: Int = 1, a200: Int = 1, a201: Int = 1, a202: Int = 1, a203: Int = 1, a204: Int = 1, a205: Int = 1, a206: Int = 1, a207: Int = 1, a208: Int = 1, a209: Int = 1, a210: Int = 1, a211: Int = 1, a212: Int = 1, a213: Int = 1, a214: Int = 1, a215: Int = 1, a216: Int = 1, a217: Int = 1, a218: Int = 1, a219: Int = 1, a220: Int = 1, a221: Int = 1, a222: Int = 1, a223: Int = 1, a224: Int = 1, a225: Int = 1, a226: Int = 1, a227: Int = 1, a228: Int = 1, a229: Int = 1, a230: Int = 1, a231: Int = 1, a232: Int = 1, a233: Int = 1, a234: Int = 1, a235: Int = 1, a236: Int = 1, a237: Int = 1, a238: Int = 1, a239: Int = 1, a240: Int = 1, a241: Int = 1, a242: Int = 1, a243: Int = 1, a244: Int = 1, a245: Int = 1, a246: Int = 1, a247: Int = 1, a248: Int = 1, a249: Int = 1, a250: Int = 1, a251: Int = 1, a252: Int = 1, a253: Int = 1, a254: Int = 1) { println(1) } >>> f() 1 >>>Java
256個以上のパラメータがあると、定義することもできません。
jshell> void f(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20, int a21, int a22, int a23, int a24, int a25, int a26, int a27, int a28, int a29, int a30, int a31, int a32, int a33, int a34, int a35, int a36, int a37, int a38, int a39, int a40, int a41, int a42, int a43, int a44, int a45, int a46, int a47, int a48, int a49, int a50, int a51, int a52, int a53, int a54, int a55, int a56, int a57, int a58, int a59, int a60, int a61, int a62, int a63, int a64, int a65, int a66, int a67, int a68, int a69, int a70, int a71, int a72, int a73, int a74, int a75, int a76, int a77, int a78, int a79, int a80, int a81, int a82, int a83, int a84, int a85, int a86, int a87, int a88, int a89, int a90, int a91, int a92, int a93, int a94, int a95, int a96, int a97, int a98, int a99, int a100, int a101, int a102, int a103, int a104, int a105, int a106, int a107, int a108, int a109, int a110, int a111, int a112, int a113, int a114, int a115, int a116, int a117, int a118, int a119, int a120, int a121, int a122, int a123, int a124, int a125, int a126, int a127, int a128, int a129, int a130, int a131, int a132, int a133, int a134, int a135, int a136, int a137, int a138, int a139, int a140, int a141, int a142, int a143, int a144, int a145, int a146, int a147, int a148, int a149, int a150, int a151, int a152, int a153, int a154, int a155, int a156, int a157, int a158, int a159, int a160, int a161, int a162, int a163, int a164, int a165, int a166, int a167, int a168, int a169, int a170, int a171, int a172, int a173, int a174, int a175, int a176, int a177, int a178, int a179, int a180, int a181, int a182, int a183, int a184, int a185, int a186, int a187, int a188, int a189, int a190, int a191, int a192, int a193, int a194, int a195, int a196, int a197, int a198, int a199, int a200, int a201, int a202, int a203, int a204, int a205, int a206, int a207, int a208, int a209, int a210, int a211, int a212, int a213, int a214, int a215, int a216, int a217, int a218, int a219, int a220, int a221, int a222, int a223, int a224, int a225, int a226, int a227, int a228, int a229, int a230, int a231, int a232, int a233, int a234, int a235, int a236, int a237, int a238, int a239, int a240, int a241, int a242, int a243, int a244, int a245, int a246, int a247, int a248, int a249, int a250, int a251, int a252, int a253, int a254, int a255) { System.out.println(1); } | Error: | too many parameters | void f(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20, int a21, int a22, int a23, int a24, int a25, int a26, int a27, int a28, int a29, int a30, int a31, int a32, int a33, int a34, int a35, int a36, int a37, int a38, int a39, int a40, int a41, int a42, int a43, int a44, int a45, int a46, int a47, int a48, int a49, int a50, int a51, int a52, int a53, int a54, int a55, int a56, int a57, int a58, int a59, int a60, int a61, int a62, int a63, int a64, int a65, int a66, int a67, int a68, int a69, int a70, int a71, int a72, int a73, int a74, int a75, int a76, int a77, int a78, int a79, int a80, int a81, int a82, int a83, int a84, int a85, int a86, int a87, int a88, int a89, int a90, int a91, int a92, int a93, int a94, int a95, int a96, int a97, int a98, int a99, int a100, int a101, int a102, int a103, int a104, int a105, int a106, int a107, int a108, int a109, int a110, int a111, int a112, int a113, int a114, int a115, int a116, int a117, int a118, int a119, int a120, int a121, int a122, int a123, int a124, int a125, int a126, int a127, int a128, int a129, int a130, int a131, int a132, int a133, int a134, int a135, int a136, int a137, int a138, int a139, int a140, int a141, int a142, int a143, int a144, int a145, int a146, int a147, int a148, int a149, int a150, int a151, int a152, int a153, int a154, int a155, int a156, int a157, int a158, int a159, int a160, int a161, int a162, int a163, int a164, int a165, int a166, int a167, int a168, int a169, int a170, int a171, int a172, int a173, int a174, int a175, int a176, int a177, int a178, int a179, int a180, int a181, int a182, int a183, int a184, int a185, int a186, int a187, int a188, int a189, int a190, int a191, int a192, int a193, int a194, int a195, int a196, int a197, int a198, int a199, int a200, int a201, int a202, int a203, int a204, int a205, int a206, int a207, int a208, int a209, int a210, int a211, int a212, int a213, int a214, int a215, int a216, int a217, int a218, int a219, int a220, int a221, int a222, int a223, int a224, int a225, int a226, int a227, int a228, int a229, int a230, int a231, int a232, int a233, int a234, int a235, int a236, int a237, int a238, int a239, int a240, int a241, int a242, int a243, int a244, int a245, int a246, int a247, int a248, int a249, int a250, int a251, int a252, int a253, int a254, int a255) { System.out.println(1); } | ^----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------^ | modified method f(int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int), however, it cannot be referenced until this error is corrected: | too many parameters | void f(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20, int a21, int a22, int a23, int a24, int a25, int a26, int a27, int a28, int a29, int a30, int a31, int a32, int a33, int a34, int a35, int a36, int a37, int a38, int a39, int a40, int a41, int a42, int a43, int a44, int a45, int a46, int a47, int a48, int a49, int a50, int a51, int a52, int a53, int a54, int a55, int a56, int a57, int a58, int a59, int a60, int a61, int a62, int a63, int a64, int a65, int a66, int a67, int a68, int a69, int a70, int a71, int a72, int a73, int a74, int a75, int a76, int a77, int a78, int a79, int a80, int a81, int a82, int a83, int a84, int a85, int a86, int a87, int a88, int a89, int a90, int a91, int a92, int a93, int a94, int a95, int a96, int a97, int a98, int a99, int a100, int a101, int a102, int a103, int a104, int a105, int a106, int a107, int a108, int a109, int a110, int a111, int a112, int a113, int a114, int a115, int a116, int a117, int a118, int a119, int a120, int a121, int a122, int a123, int a124, int a125, int a126, int a127, int a128, int a129, int a130, int a131, int a132, int a133, int a134, int a135, int a136, int a137, int a138, int a139, int a140, int a141, int a142, int a143, int a144, int a145, int a146, int a147, int a148, int a149, int a150, int a151, int a152, int a153, int a154, int a155, int a156, int a157, int a158, int a159, int a160, int a161, int a162, int a163, int a164, int a165, int a166, int a167, int a168, int a169, int a170, int a171, int a172, int a173, int a174, int a175, int a176, int a177, int a178, int a179, int a180, int a181, int a182, int a183, int a184, int a185, int a186, int a187, int a188, int a189, int a190, int a191, int a192, int a193, int a194, int a195, int a196, int a197, int a198, int a199, int a200, int a201, int a202, int a203, int a204, int a205, int a206, int a207, int a208, int a209, int a210, int a211, int a212, int a213, int a214, int a215, int a216, int a217, int a218, int a219, int a220, int a221, int a222, int a223, int a224, int a225, int a226, int a227, int a228, int a229, int a230, int a231, int a232, int a233, int a234, int a235, int a236, int a237, int a238, int a239, int a240, int a241, int a242, int a243, int a244, int a245, int a246, int a247, int a248, int a249, int a250, int a251, int a252, int a253, int a254, int a255) { System.out.println(1); } | ^----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------^ jshell> void f(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20, int a21, int a22, int a23, int a24, int a25, int a26, int a27, int a28, int a29, int a30, int a31, int a32, int a33, int a34, int a35, int a36, int a37, int a38, int a39, int a40, int a41, int a42, int a43, int a44, int a45, int a46, int a47, int a48, int a49, int a50, int a51, int a52, int a53, int a54, int a55, int a56, int a57, int a58, int a59, int a60, int a61, int a62, int a63, int a64, int a65, int a66, int a67, int a68, int a69, int a70, int a71, int a72, int a73, int a74, int a75, int a76, int a77, int a78, int a79, int a80, int a81, int a82, int a83, int a84, int a85, int a86, int a87, int a88, int a89, int a90, int a91, int a92, int a93, int a94, int a95, int a96, int a97, int a98, int a99, int a100, int a101, int a102, int a103, int a104, int a105, int a106, int a107, int a108, int a109, int a110, int a111, int a112, int a113, int a114, int a115, int a116, int a117, int a118, int a119, int a120, int a121, int a122, int a123, int a124, int a125, int a126, int a127, int a128, int a129, int a130, int a131, int a132, int a133, int a134, int a135, int a136, int a137, int a138, int a139, int a140, int a141, int a142, int a143, int a144, int a145, int a146, int a147, int a148, int a149, int a150, int a151, int a152, int a153, int a154, int a155, int a156, int a157, int a158, int a159, int a160, int a161, int a162, int a163, int a164, int a165, int a166, int a167, int a168, int a169, int a170, int a171, int a172, int a173, int a174, int a175, int a176, int a177, int a178, int a179, int a180, int a181, int a182, int a183, int a184, int a185, int a186, int a187, int a188, int a189, int a190, int a191, int a192, int a193, int a194, int a195, int a196, int a197, int a198, int a199, int a200, int a201, int a202, int a203, int a204, int a205, int a206, int a207, int a208, int a209, int a210, int a211, int a212, int a213, int a214, int a215, int a216, int a217, int a218, int a219, int a220, int a221, int a222, int a223, int a224, int a225, int a226, int a227, int a228, int a229, int a230, int a231, int a232, int a233, int a234, int a235, int a236, int a237, int a238, int a239, int a240, int a241, int a242, int a243, int a244, int a245, int a246, int a247, int a248, int a249, int a250, int a251, int a252, int a253, int a254) { System.out.println(1); } | created method f(int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int) jshell> f(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); 1 jshell>JavaScript
パラメータが256個以上でも関数定義できます・
function f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61, a62, a63, a64, a65, a66, a67, a68, a69, a70, a71, a72, a73, a74, a75, a76, a77, a78, a79, a80, a81, a82, a83, a84, a85, a86, a87, a88, a89, a90, a91, a92, a93, a94, a95, a96, a97, a98, a99, a100, a101, a102, a103, a104, a105, a106, a107, a108, a109, a110, a111, a112, a113, a114, a115, a116, a117, a118, a119, a120, a121, a122, a123, a124, a125, a126, a127, a128, a129, a130, a131, a132, a133, a134, a135, a136, a137, a138, a139, a140, a141, a142, a143, a144, a145, a146, a147, a148, a149, a150, a151, a152, a153, a154, a155, a156, a157, a158, a159, a160, a161, a162, a163, a164, a165, a166, a167, a168, a169, a170, a171, a172, a173, a174, a175, a176, a177, a178, a179, a180, a181, a182, a183, a184, a185, a186, a187, a188, a189, a190, a191, a192, a193, a194, a195, a196, a197, a198, a199, a200, a201, a202, a203, a204, a205, a206, a207, a208, a209, a210, a211, a212, a213, a214, a215, a216, a217, a218, a219, a220, a221, a222, a223, a224, a225, a226, a227, a228, a229, a230, a231, a232, a233, a234, a235, a236, a237, a238, a239, a240, a241, a242, a243, a244, a245, a246, a247, a248, a249, a250, a251, a252, a253, a254, a255) { console.log(1); } f(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); 1
- 投稿日:2019-02-11T12:12:06+09:00
【Java】リダイレクトされた最終URLを取得する方法
概要
あるURLをリクエストするとリダイレクトされる場合があります。リダイレクトされた最終のURLを取得する方法のメモです。
コード
ライブラリにはokhttp3をつかう
リダイレクトされた最終URLを取得するクラス
RedirectFinalUrlResolver.javapackage example; import java.io.IOException; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class FinalUrlResolver { private OkHttpClient mClient = new OkHttpClient.Builder() .addNetworkInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { return chain.proceed(chain.request()); } }) .build(); public String get(String url) throws IOException { final Response r = mClient.newCall(new Request.Builder().url(url).build()).execute(); return r.request().url().toString(); } }実行する側のクラス
Example.javapackage example; import java.io.IOException; public class Example { public static void main(String[] args) throws IOException { FinalUrlResolver o=new FinalUrlResolver(); String url="https://qiita.com/settings/account"; String finalUrl=o.get(url); System.out.println("original url="+url); System.out.println("final url="+finalUrl); } }依存関係(maven)
以下をpom.xmlに追加する
<dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>3.13.1</version> </dependency>実行結果
Example.javaを実行すると、リダイレクトされた最終のURLが取得できた。
original url=https://qiita.com/settings/account final url=https://qiita.com/login?redirect_to=https%3A%2F%2Fqiita.com%2Fsettings%2Faccount
- 投稿日:2019-02-11T11:40:28+09:00
【Java初心者向け】例外処理について
例外とは
プログラム実行中に発生する何らかのトラブルを指す。
- プログラマーの不注意で作りこむバグ
- 要件や仕様の間違い
- 実行マシンの不都合や- ほかのソフトウェアとの連携不都合
など、その種類は多岐に渡るが、ユーザーが利用するソフトウェアは、トラブルが発生したからといって停止してしまったり、動作しなくなったり、動作しても正常に処理をしなかったりしなくてはいけない。
そのためプログラマーは、さまざまな事態に対応する「万一の場合に備えたプログラミングが要求される。
それに対応する役割を担うのがこの例外処理と言える。try、catch、finally
例外が発生する可能性がある処理をtryブロックで括り、例外が発生したときの処理をtryブロックに続くcatchブロックに記述する。
try
tryブロック内には、複数の文を記述することができる。
もし、例外が発生したらtryブロック内の以降の処理はスキップされ、すぐに対応するcatchブロックに制御が移る。
一度catchブロックに制御が移ると、それ以降のtryブロックの処理は必要性に関わらず実行されることがなくなるcatch
catchブロックは例外が発生したときの処理を記述するためのブロックである。
catchブロックの目的はプログラムを正常な状態に復帰させることで、このブロックの処理が終了すると「トラブルは収束したとして、正常な動作に戻る。
なお、catchブロックは、発生した例外の種類ごとに複数記述できるため、例外の種類ごとに対処処理を変えることができる。また、catchブロックを省略することも可能。catchブロックを省略するのは、そのメソッド内では、例外の処理方法を決められないケースである。
複数のcatchブロックを用意した際に、どのパターンの例外が発生しても到達できないコードを記述した場合、コンパイラはコンパイルエラーを発生させる。
【到達不可能なケースの例】
SampleExceptionpublic class SampleException extends Exception{}SubSampleExceptionpublic class SubSampleException extends SampleException{}Mainpublic class Main { public static void main(String[] args) { try { sample(); sub(); } catch (SampleException e) { System.out.println("A"); } catch (SubSampleException e) { System.out.println("B"); } } private static void sample() throws SampleException { throw new SampleException(); } private static void sub() throws SubSampleException{ }mainメソッドtryブロックの1行目で、sample()メソッドを呼び出し
→catch(SampleException e){}ブロックが受け取り、ブロック内に記述された処理内容を行う。mainメソッド2行目で、sub()メソッドを呼び出し
→catch(SampleException e){}ブロックが受け取り、ブロック内に記述された処理内容を行う。
SubSampleExceptionに到達するよりも前に、スーパークラスのSampleExceptionでcatchされる。よって、
【出力結果】
A
Aこのような結果になる。
tryブロック二行目でsub()メソッドを呼び出すことによってSubSampleExceptionをスローしているが、SampleExceptionクラスはSubSampleExceptionクラスのスーパークラスであるため、SampleExceptionブロックでもこの例外を受け取ること(catch)ができる。
そのため、SubSampleExceptionで例外を受け取るブロックよりも前に、先に書かれているSampleExceptionクラスで受け取るブロックで処理が行われる。このような場合、SubSampleExceptionでのcatchブロックは、到達不可能なコードと判断され、コンパイラはコンパイルエラーを発生させる。
finally
- つないだままのネットワーク切断
- 開いたままになっているファイルのクローズ
- 保持したままのデータベースの接続状態の開放
など、例外発生の有無にかかわらず、実行したい処理はプログラムの形態を問わずに存在する。
こういった例外発生の有無にかかわらず実行したい処理を記述するためのものがfinallyブロックである。finallyブロックを記述した場合、例外が発生しなければtryブロック実行後にfinallyブロックに記述した処理が実行される。例外が発生した場合は、tryブロックからcatchブロックに制御が移り、その後finallyブロックが実行される。
finallyブロックは、例外発生の有無にかかわらず、実行したい処理を記述するためのものであり、これはcatchブロック内でreturnされていても同じで、 returnによって呼び出し元のメソッドに制御が戻る前に、finallyブロックは必ず実行される。
finallyブロックは、例外の種類によって分ける必要がない。
finallyブロックが実行されないのは、tryブロックやcatchブロック内でSystem.exitメソッドを呼び出して、アプリケーションを強制終了したときか、JVMやOSがクラッシュしたときだけである。
try-catch-finally構文の記述におけるルールについて
- try-catch-finally文の構文は、その出現順を変更することはできない。
→したがって、catch-try-finallyやtry-finally-catchのように順番を変更することはできない。
- ネストしたtry-cacth-finally文を記述することができる。
samplepublic class Main { public static void main(String[] args) { try { try { String[] array = { "A", "B", "C" }; System.out.println(array[3]); //① } catch (ArrayIndexOutOfBoundsException e) { System.out.println("D"); //② } finally { System.out.println("E"); //③ } } catch (ArrayIndexOutOfBoundsException e) { System.out.println("F"); } finally { System.out.println("G"); //④ } } }このように複数のtry-catchがネストしている場合、スローされた例外を受け取るのは、その例外に対応したもっとも近いcatchブロックである。
そのため、上記のコードでは、
① tryブロックで3つの値しか存在しない配列arrayに対して、4つ目の値を出力しようとしたため、cacthブロックに制御が移り、
② ①で発生した例外に対応するもっとも近いcatchブロックで処理を行った後
③ 内側のfinallyブロックで処理を行い、
④ 最後に外側のfinallyブロックが処理を行う。といった流れになる。
このとき、finallyブロックは必ず実行されるため、内側、外側の両方のfinallyの処理が実行される。throwとthrows
Javaの例外処理には「throw」と「throws」という処理がある。
どちらも処理を「投げる」という意味だが、その内容は大きく異なる。throw
例外を意図的に起こして、例外処理を行わせる。
メソッド内で記述を行う。examplevoid sample (int num) { if(num < 0) { throw new IllegalArgumentException(“負の値は使用できません。”); } }throws
メソッド内で発生した例外を、自身のメソッド内では処理をせず、メソッドの呼び出し元で例外処理を行う。
throwsが書かれたメソッド内には例外処理の記述をせず、throwsが書かれたメソッドを呼び出した側のメソッドで例外処理を行う。examplepublic static void sample() throws IOException{ FileWriter fw = new FileWriter("data.txt"); }FileWriterは文字ファイルを書き込むための簡易クラスで、try-catch文でキャッチしないとコンパイルエラーになる検査例外に該当するため、処理を行う際は必ずtry-catch文を記述する必要があるが、throwsの記述を行うことで、メソッドの呼び出し元で対応させている。
検査例外、非検査例外について
Javaにおけるプログラムの実行中に発生するトラブルには、大きく分けて、2つの種類がある。
- 実行環境のトラブルなど、プログラムからは対処しようのない自体を表すエラー
- プログラムが対処できる例外
の2つである。
例外はさらに、検査例外と非検査例外に分かれる。
- 検査例外 例外処理を記述したかどうかをコンパイラが検査する例外(try-catchが必須)
- 非検査例外 例外処理を記述したかどうかをコンパイラが検査しない例外(try-cacthは任意)
Javaは例外処理をプログラマーが記述し忘れることを防ぐために、検査例外を基本としている。
ソフトウェアが巨大化、複雑化していく歴史の中で、例外処理をプログラマーが記述し忘れる失敗が増え、バグの原因となった反省から、コンパイラによる自動チェック機能が盛り込まれたということが背景にある。Javaの例外クラスは大きく分けて、
- Error
- Exception
- RuntimeException(Exceptionのサブクラス)
に分かれ、それぞれエラー、検査例外、非検査例外を表している。
Exceptionクラスのサブクラスは、RuntimeExceptionとそのサブクラスを除いて、すべて検査例外である。
そのため、Exceptionクラスを継承している例外クラスは、try-catchしているか、もしくはthrows句で宣言しているかのどちらかを強制される。一方、ExceptionのサブクラスであってもRuntimeExceptionとそのサブクラスは非検査例外として扱われる。(RuntimeExceptionはExceptionのサブクラス)そのため、RuntimeExceptionとそのサブクラスはtry-catchを強制されない。もちろん強制されないだけで、try-catchを記述することはできる。また、非検査例外はthrows句で宣言していなくても、どちらでも問題ない。エラーはErrorクラスが表すが、実際に使われるのは、そのサブクラスである。
たとえば、Errorを継承したサブクラスには、OutOfMemoryErrorやNoClassDefFoundError、StackOverflowErrorなどがある。なお、エラーに分類されるためには、Errorを継承している必要がある。
これらのトラブルが発生した場合、対応するErrorのサブクラスのインスタンスをJVMが作成し、プログラムに通知する。これは例外と同じメカニズムだが、エラーの場合は例外と違って「プログラムで対処する」ことを求められていない。そのため、try-catchしたり、throwsで宣言したりする必要はない。(「求められていない」だけであって、必要であればcatchして処理させることも可能。)
- 各クラスがどのような種類の例外に対応しているか
- 検査例外、非検査例外のどちらに該当するか
などについては
Java SE 8 API仕様
https://docs.oracle.com/javase/jp/8/docs/api/
から詳細について確認ができる。
- 投稿日:2019-02-11T10:44:35+09:00
Java開発者に送るKotlinのスコープ関数
スコープ関数とは
Kotlinの標準ライブラリに定義されているジェネリック関数。
ジェネリック関数なので、どんな型にも適用できる関数です。
スコープ関数を使うことで、よりKotlinらしいコードが書けます。letとrun
Streamのmap関数のようなイメージです。
val str: String = "5963" // 変数strをIntに変換する // letを使った場合 val i: Int = str.let { it.toInt() } // 変数strをIntに変換する // runを使った場合 val i2: Int = str.run { this.toInt() }
let
に続くラムダ式は引数が1つです。この引数はstr
への参照です。
run
に続くラムダ式は引数がありません。代わりに、このラムダ式内のthis参照はstr
です。
ラムダ式の結果がlet
、run
の戻り値となります。また、今回の例の変数
str
のような、関数の呼び出されるオブジェクトをレイシーバーオブジェクトといいます。使いどころ
fun getName(): String? = "" fun makeGreeting(name: String) = "Hello, $name" fun greet(): String? { val name = getName() if (name == null) { return null } return makeGreeting(name) }
greet()
関数では
getName()
の結果を、makeGreeting()
関数に渡し、
その結果がgreet()
関数の戻り値となります。ただし、
getName()
の戻り値はnull許容型なので、一度nullチェックが必要です。
これを、let
を使って書き換えてみます。fun greet(): String? { return getName()?.let { makeGreeting(it) } }
getName()
の結果を安全呼び出しを使い、letを呼び出します。
こうすると、かなりスッキリ書けます。
安全呼び出しや、安全キャストの結果を関数の引数に渡す場合に便利です。
(もちろん、それ以外の場合にもよく使われます。)applyとalso
letとrunに似ていますが、戻り値は常にレシーバーオブジェクトです。
val str: String = "5963" // 変数strを標準出力 // alsoを使った場合 val str2: String = str.also { print(it) } // 変数strを標準出力 // applyを使った場合 val str3: String = str.apply { print(this) }使いどころ
class Person { var firstName: String? = null var middleName: String? = null var lastName: String? = null } fun registerNewPerson() : Person { val person = Person() person.firstName = "久美子" person.middleName = "スーザン" person.lastName = "山本" return person }
registerNewPerson
関数では、Person
のインスタンスを新たに作って返します。
Person
を初期化するだけですが、一旦変数に置かなければなりません。
also
を使ってみましょう。fun registerNewPerson() : Person { return Person().also { it.firstName = "久美子" it.middleName = "スーザン" it.lastName = "山本" } }
Person
の一時変数を作らずに実装できます。
Builderパターンでは無いオブジェクトを扱う場合などに、
そのオブジェクトの初期化処理がスコープ関数の中にまとまるので、可読性向上につながります。with
withはちょっと変わりダネです。
レシーバーオブジェクトを引数で渡すrun
っといったところです。val str = "5963" val i: Int = with(str) { this.toInt() }使いどころ
class Greeter { fun greet(): String = "Hello, world" } fun greet(greeter: Greeter) = with(greeter) { greet() }withを使って単一式関数にします。
this参照が変わり違った文脈で記述できるようになります。
- 投稿日:2019-02-11T10:43:54+09:00
Java開発者に送るKotlinとの相互運用Tips
KotlinコードをJavaから呼び出すとき
デフォルト引数
Kotlinのデフォルト引数付き関数をJavaから扱いたい場合、全ての引数を指定しなければなりません。
ですが、関数に@JvmOverload
アノテーションを付加すると自動的にオーバーロードメソッドが生成されます。// Kotlin class OverloadSample { @JvmOverloads // アノテーションをつけると、Javaから呼び出し可能なオーバーロードメソッドが生成される fun test(arg1: Boolean = true, arg2: Int = 1, arg3: String = "true") : Boolean { return arg1 && arg2 == 1 && arg3 == "true" } }Javaからの呼び出しコードを実装してみます。
// Java OverloadSample os = new OverloadSample(); os.test(true, 1, "true"); os.test(true, 1); os.test(true);トップレベル関数、プロパティ
クラスに属さないトップレベルのKotlin関数をJavaから呼び出す方法です。
Kotlinのトップレベル関数は
ソースファイル名+Kt
という名前のクラスが生成され、
そのクラスのstatic関数へコンパイルされます。// Utility.kt fun doSomething() { // Do something }// Java UtilityKt.doSomething();上記の
ソースファイル名+Kt
というクラス名を変更したい場合は@JvmName
アノテーションを使います。このアノテーションはパッケージに記述しまし。// Utility.kt @file: JvmName("Util") package com.sample fun doSomething() { // Do something }// Java Util.doSomething();拡張関数
拡張関数はトップレベル関数と同じく、
ソースファイル名+Kt
という名前のクラスのstatic関数としてコンパイルされます。Javaから呼び出す場合は、thisとなるオブジェクトが第一引数となります。// StringUtility.kt fun String.join(otherString: String) : String { return this + otherString }// Java StringUtilityKt.join("Hello, ", "World!");objectクラス
objectクラスをJavaからみると、
INSTANCE
というstaticフィールドを持ったクラスとなります。objectクラスのプロパティか関数にアクセスするには、このINSTANCE
を経由します。// Kotlin object LogUtil { fun debug(log: String) { // } }// Java LogUtil.INSTANCE.debug("completed!");JavaコードをKotlinから呼び出すとき
プラットフォーム型
Java関数の戻り値をKotlinコードで受ける場合など、
その戻り値がnull許容型か否かは@NonNull
と@Nullable
の
アノテーションで判断されます。// Java public class Sample { @NonNull String getString1() { return // } @Nullable String getString2() { return // } }Kotlinで呼び出すと以下のようになります。
// Kotlin val sample = Sample() val str1 = sample.string1 // 非null許容型 val str2 = sample.string2 // null許容型ただし、
@NonNull
や@Nullable
のアノテーションは
コンパイル時に強制力を持つものではないので注意が必要です。では、アノテーションをつけない場合は...
// Java public class Sample { // アノテーション無し String getString3() { return // } }Kotlinから呼び出してみます。
// Kotlin val sample = Sample() val str3 = sample.string3 // String!
String!
という型になります。
この!
のついた型をプラットフォーム型といいます。null許容型でも非null許容型でも扱える、どっちも型です。
Nullであるか否かを開発者に委ねる考え方です。// Kotlin val sample = Sample() val str = sample.string3 val length = str.length // 非null許容型として扱う val char = str?.get(0) // null許容型として扱うstatic関数、staticフィールド
何らかの理由でstatic関数やフィールドが必要な状況があり得ます。
例えば...Kotlinでstaticっぽく使える
companion object
。
ここでアノテーションを使うと、Javaのstaticとしてコンパイルされます。// Kotlin class Sample { companion object { @JvmField // staticフィールドへのコンパイルを指定するアノテーション var TAG: String = "Sample" @JvmStatic // static関数へのコンパイルを指定するアノテーション fun tag(): String { return "Sample" } } }// Java String tag = Sample.TAG; tag = Sample.tag();SAM変換
特定の条件下において、
Javaのインターフェースを実装したクラスをラムダ式で作ることができます。val executor: ThreadPoolExecutor // executeメソッドの引数にはRunnableを実装したオブジェクトを渡す executor.execute(object: Runnable{ override fun run() { // } }) // SAM変換により、ラムダ式で表現可能! executor.execute { // }KotlinでSAM変換が有効となる条件は以下です。
- Javaで宣言されたインターフェースであること
- 抽象メソッドが1つだけのインターフェースであること
Kotlinには適切な関数型が存在するのでKotlinで宣言したインターフェースではSAM変換は有効になりません