- 投稿日:2020-07-26T22:39:53+09:00
Windows10からラズパイで実行するjavaFXプログラムをリモートデバッグする方法~環境構築からデバッグ実行まで①~
長いので分けて書く
Windows10でEclipseを使ったクロス開発環境を構築する
1.
以下のサイトから好きなバージョンをダウンロードし適当なフォルダに展開しておく。あまり深いフォルダに入れるのと日本語が入っているフォルダ名は何かとはまるので避ける
https://mergedoc.osdn.jp/
2.
ここではEclipse4.8Photonを使う。新しすぎるバージョンは古いプラグインとの相性が悪い
3.
Windows 64bit FullEdition javaを選択
4.
リンクをクリックしダウンロード
ダウンロード速度が呪い...
5.
適当なフォルダに展開し、起動
(展開したフォルダ)\pleiades-4.8\pleiades\eclipse\eclipse.exeで起動8.「ファイル」-「新規」-「その他」-「JavaFXプロジェクト」を選択
9.プロジェクト名にHelloRemoteを入力し、次へをクリック
10.そのまま「次へ」をクリック
11.言語を「FXML」へ変更
ルートタイプはAnchorPaneを選んで置く
「完了」をクリック
Scene BuilderをインストールしEclipseと連携させる
1.ダウンロード
https://gluonhq.com/products/scene-builder/
プラットフォームはWindowsインストーラーを選択
ダウンロードボタンを押ししばらく待つとダウンロードできる。
SceneBuilder-11.0.0.msi
インストール....2.EclipseとSceneBuilderを連携させる
「ウィンドウ」-「設定」-「javaFX」を開き
ScnenBuilder実行可能ファイルを選択し適用
3.EclipseのパッケージエクスプローラーからSample.fxmlを右クリックしSceneBuilderで開くを実行
5.Document-Hierarchy-AnchorPaneを選択し、MinWidth、MinHeightを640、480に変更
6.ControlsパネルからButtonをドラッグ&ドロップで配置
7.Buttonオブジェクトを選択、Codeのfx:idをtestBT、onActionにonTestBTを入力
8.同様にしてLabelを配置
fx:idはtestLBとしておく
10.View - ViewSampleControlSkeltonを選択
11.右下のFullにチェックを入れて、「コピー」
クリップボードにコピーされる
12.Eclipseに戻り、パッケージエクスプローラーのSampleController.javaをダブルクリック
13.全部消してから、クリップボードの内容を張り付け
14.パッケージエクスプローラーのMain.javaを右クリックしJavaアプリケーションで実行
15.優先ランチャーの選択
16.保存
17.実行されるが何も表示されない
18.いったん、プログラムを閉じプロジェクトクリーンを実行
これを実行しないとSceneBuilderで保存しただけでは、プロジェクト側に反映されない
19.再び実行
プログラムの変更
1.パッケージエクスプローラーのSampleController.javaを開き修正
@FXML
void onTestBT(ActionEvent event) {
Platform.runLater(() ->testLB.setText("HelloFX"));
}
2.実行 Buttonを押しラベルがHelloFXに変われば問題なし
次回
このプログラムをラズパイに配置して実行する方法を説明する
2020.0726 kamoshika
当記事と全く関係ないが....主のチャンネルのリンクを貼っておく
https://www.youtube.com/channel/UCbtzwsQhTuUzW3ERoBSYZDw/
- 投稿日:2020-07-26T22:39:53+09:00
Windows10からラズパイで実行するjavaFXプログラムをリモートデバッグする方法~環境構築編①~
長いので分けて書く
Windows10でEclipseを使ったクロス開発環境を構築する
1.
以下のサイトから好きなバージョンをダウンロードし適当なフォルダに展開しておく。あまり深いフォルダに入れるのと日本語が入っているフォルダ名は何かとはまるので避ける
https://mergedoc.osdn.jp/
2.
ここではEclipse4.8Photonを使う。新しすぎるバージョンは古いプラグインとの相性が悪い
3.
Windows 64bit FullEdition javaを選択
4.
リンクをクリックしダウンロード
ダウンロード速度が呪い...
5.
適当なフォルダに展開し、起動
(展開したフォルダ)\pleiades-4.8\pleiades\eclipse\eclipse.exeで起動8.「ファイル」-「新規」-「その他」-「JavaFXプロジェクト」を選択
9.プロジェクト名にHelloRemoteを入力し、次へをクリック
10.そのまま「次へ」をクリック
11.言語を「FXML」へ変更
ルートタイプはAnchorPaneを選んで置く
「完了」をクリック
Scene BuilderをインストールしEclipseと連携させる
1.ダウンロード
https://gluonhq.com/products/scene-builder/
プラットフォームはWindowsインストーラーを選択
ダウンロードボタンを押ししばらく待つとダウンロードできる。
SceneBuilder-11.0.0.msi
インストール....2.EclipseとSceneBuilderを連携させる
「ウィンドウ」-「設定」-「javaFX」を開き
ScnenBuilder実行可能ファイルを選択し適用
3.EclipseのパッケージエクスプローラーからSample.fxmlを右クリックしSceneBuilderで開くを実行
5.Document-Hierarchy-AnchorPaneを選択し、MinWidth、MinHeightを640、480に変更
6.ControlsパネルからButtonをドラッグ&ドロップで配置
7.Buttonオブジェクトを選択、Codeのfx:idをtestBT、onActionにonTestBTを入力
8.同様にしてLabelを配置
fx:idはtestLBとしておく
10.View - ViewSampleControlSkeltonを選択
11.右下のFullにチェックを入れて、「コピー」
クリップボードにコピーされる
12.Eclipseに戻り、パッケージエクスプローラーのSampleController.javaをダブルクリック
13.全部消してから、クリップボードの内容を張り付け
14.パッケージエクスプローラーのMain.javaを右クリックしJavaアプリケーションで実行
15.優先ランチャーの選択
16.保存
17.実行されるが何も表示されない
18.いったん、プログラムを閉じプロジェクトクリーンを実行
これを実行しないとSceneBuilderで保存しただけでは、プロジェクト側に反映されない
19.再び実行
プログラムの変更
1.パッケージエクスプローラーのSampleController.javaを開き修正
@FXML
void onTestBT(ActionEvent event) {
Platform.runLater(() ->testLB.setText("HelloFX"));
}
2.実行 Buttonを押しラベルがHelloFXに変われば問題なし
次回
このプログラムをラズパイに配置して実行する方法を説明する
2020.0726 kamoshika
当記事と全く関係ないが....主のチャンネルのリンクを貼っておく
https://www.youtube.com/channel/UCbtzwsQhTuUzW3ERoBSYZDw/
- 投稿日:2020-07-26T22:33:49+09:00
Apache + Tomcat + PebbleをMacのローカルで構築した
About
※この記事はセキュリティ度外視の課題専用の内容です。予めご了承ください。
大学の課題でApacheを設定、SSL化し、Apacheと連携させたTomcatからPebbleを起動させたので備忘録です。
Apacheの設定部分やローカルでのSSL化は省略します。
ちなみにSSL化については以下の記事に記載しました。
https://qiita.com/Raluer/items/02b848437844ba3cbb6chttpd.confの編集
以下のLoadModuleをコメントアウト
/usr/local/etc/httpd/httpd.confLoadModule proxy_module libexec/apache2/mod_proxy.so LoadModule proxy_ajp_module libexec/apache2/mod_proxy_ajp.so
ファイル末尾に以下の一文を追加
外部のコンフィグファイルに記載したAJP通信用の設定(これから作ります)を読み込み。/usr/local/etc/httpd.confInclude /usr/local/etc/httpd/extra/httpd-proxy.conf
httpd-proxy.confの編集
ターミナル上で
/usr/local/etc/httpd/extra/
にて/usr/local/etc/extra$ sudo vim httpd-proxy.confするとvimが起動して新規ファイルの作成になるので、以下のコードをコピペする。
/usr/local/etc/extra/httpd-proxy.conf<Location /pebble > ProxyPass ajp://localhost:8009/pebble Order allow,deny Allow from all </Location>これでApache側の設定はオールオッケー
ここからTomcatを入れていきます。Tomcatインストール
公式サイトから、好きなバージョンを選んで「Download」を押す。
飛んだページの「Core」の中から「tar.gz」をクリックしてダウンロード。
ルートディレクトリ(~/のところ)にダウンロードしておくと後々楽かも?ぶっちゃけどこでもいいです。ダウンロードしたtar.gzファイルをFinderから解凍して中を見ます。
「conf」というフォルダがあるので中に入り、server.xmlをお好きなテキストエディタで開きます。74行目あたりにある以下のコードを、
conf/server.xml<Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />今回HTTP通信は使わないので、コメントアウトします。
conf/server.xml<!-- <Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> -->
続いて117行目あたりにある、今回用いるAJP通信用の設定のアドレスを
127.0.0.1
に書き換え、secretRequiredを追加し、パラメータをfalseに設定します(ローカルのときのみ!)conf/server.xml<Connector protocol="AJP/1.3" address="127.0.0.1" port="8009" redirectPort="8443" secretRequired="false" />ちなみにsecretRequiredを設定しなかったせいで相当ハマりました。
Pebbleの導入
ここまで来たらラストスパート。
まずはPebbleをこのサイトからダウンロードします。
ダウンロード場所が少し分かりづらいですが、右上のPebble 2.6.4をクリックするとダウンロードできます。
ダウンロードしたファイルを解凍し、解凍したフォルダ内にある
pebble-2.6.4.war
を解凍せずにコピーし、先程のTomcatディレクトリに移動し、webapps
直下にペーストします。もともとのフォルダは不要です。中に入ってるwarファイルだけを使います。
warファイルにあとでアクセスするので、pebble.war
にリネームしておきましょう。TomcatとApacheサーバの起動
ここまで来たらほとんどゴールです。
ターミナルを開き、Tomcatのbin
の中に入ります。
Tomcatのサーバを起動するには、ターミナル上bin
の中でtomcat/bin$ ./startup.shのコマンドを打つだけです。ちなみに止めるときは
tomcat/bin$ ./shutdown.shを同じ場所で実行するだけです。
起動するのを確認したら、そのままterminal$ apachectl startを実行し、apacheサーバを起動します。
ゴール!
Tomcatサーバとapacheサーバがどちらも起動した状態になったので、ブラウザのURLに
localhost/pebble
と入力すると、少し読み込んだ後にPebbleのWelcomeページが表示されるはずです。あとがき
非常にハマってしまったので、是非とも参考にしてスムーズに駆け抜けてください…。
ハマった場合のチェックポイント
ポート8009は埋まってない?
埋まってたら適当に別のポート(8019とか)使うと出来ますよ。
server.xmlとhttpd-proxy.confどちらも変更するのを忘れずに!参考サイト
https://ameblo.jp/g-pinchan-new/entry-11573378743.html
https://qiita.com/brighton0725/items/0e116db637a8fea1d907
- 投稿日:2020-07-26T22:00:42+09:00
Java SE11 silver に受かった話
経歴
地方公務員(向いてないなあ)→SESに転職→1ヶ月の研修後、運用・保守の現場
研修ではjavaをやってました。その前に空白があったので、すっきりわかるJava入門とpaiza を1ヶ月ほどやってました。Bランクまではなんとか解けました。
研修最終日にsilver受けて、53%でした。。。
再受験で89%!合格!
トータル学習期間:3ヶ月くらい
気をつけたこと
1回目は勉強不足!が確実にあったので
2回目は黒本を解きまくって、終盤は満点しか出さないくらいのレベルでした。
Javaのことでいえば
・オーバーライドの仕様をよく確認する
・アクセス修飾子をよく確認する
・ローカル変数とフィールドの優先度とか
・コンストラクタの仕様
・例外処理、ラムダ式、モジュールシステムに関しては出題されるパターンが黒本と似ているので、それで覚える。(あんまりよくないですけど…)・あんまり参考にならんかもですけど、モジュールに関しては、役割とか、基本的なAPIがまとめられているのはbaseか、とかがよくでた印象でした。知識を問うような問題が多かった。
先人たちの記事
とても参考になりますので、ぜひ!
Java Silver 試験対策メモ
[java] Java SE 8 Silver メモさいごに
ほんとに認定教科書シリーズやりまくれば、受かります!
次は基本情報かLPIC受けたいし、なんか作りたいですね
あと、技術的な記事も書きたいですね
- 投稿日:2020-07-26T21:19:51+09:00
【Effective Javaを読む】 第2章 項目3 『privateのコンストラクタかenum型でシングルトン特性を強制する』
privateのコンストラクタかenum型でシングルトン特性を強制する
Java1.5より前ではシングルトンを実装する方法が2つあった(例1、例2)けど、1.5でできるようになった3つ目の方法(例4)が一番良いねってお話。
用語集
シングルトン
デザインパターンの一種。
「Singleton(シングルトン)パターン」と呼ばれることもある。
手短に言えば厳密に一度しかインスタンスが作成されないクラス。
「あるクラスのインスタンスが常にたった1つしか存在していない」という状態を実現したいときに利用される。シングルトンの作り方
・コンストラクタをprivateで宣言する。
(このクラスを利用する側からコンストラクタを呼び出せないようにするため)・インスタンスを取得するメソッドgetInstance( )をstaticで宣言する。
これにより、利用側はSingleton#getInstance( )という呼び出しでインスタンスを取得することができる。シングルトンサンプル/** * アプリケーション全体の設定情報 */ public class Config { /** * 外部からインスタンス化できないよう、コンストラクタをprivateで宣言する */ private Config() { // 実際はファイル・データベースなどから設定情報を // 読み込む処理をここに書く } /** * 唯一のインスタンスを返す * @return このクラスの唯一のインスタンス */ public static Config getInstance() { return ConfigInstanceHolder.INSTANCE; } /** * 指定されたキーに対応する設定値を返す * @param key 設定キー * @return 設定値 */ public String getValue(String key) { // 実際はコンストラクタで読み込んだ設定情報を // 返す処理をここに書く return ....; } /** * Configクラスの唯一のインスタンスを保持する内部クラス */ public static class ConfigInstanceHolder { /** 唯一のインスタンス */ private static final Config INSTANCE = new Config(); } }enum型
Enum(列挙型)とは、複数の定数をひとつにまとめておくことができる型のこと。
Enumで定義する定数のことを列挙子と呼ぶ。public class Main { public static void main(String[] args) { Fruit fruit_type = Fruit.Orange; System.out.println(fruit_type); } protected enum Fruit { Orange, Apple, Melon }; }実行結果OrangeElvis Presley
偉大なるロックンローラー
私は「A Little Less Conversation」が好きです
https://www.youtube.com/watch?v=Zx1_6F-nCawElvis has left the Building.
往年の人気歌手エルビス・プレスリーの有名なエピソードにまつわる表現です。
プレスリーのコンサートが終わっても、アンコールを期待してなかなか帰ろうとしない聴衆に向かって「エルビスはもうこの建物を出ました」とアナウンスを流して、聴衆が会場から去るよう促したことが始まりです。現在は、どのようなイベントについても、終了したことについて使われます。
サンプルコード
1.5より前でのシングルトンの作り方その1
コンストラクタをpriavteにして、クラスの利用者がそのクラスの唯一のインスタンスにアクセスできるようにpublic staticのメンバを提供している。
privateのコンストラクタは、public static finalのフィールドであるElvis.INSTANCEを初期化するために1度だけ呼ばれる。
これでElvisが世界に一人しかいないことが保証される。例1//public finalのフィールドによるシングルトン public class Elvis{ public static final Elvis INSTANCE = new Elvis(); private Elvis() { ... } public void leaveTheBuliding() { ... } }1.5より前でのシングルトンの作り方その2
その1のメンバをpublic staticにするのが2つ目の方法。
Elvis.getInstance()でオブジェクト参照を返す。
この良いところは宣言によりそのクラスがシングルトンになっていることが明白であること。例2//staticファクトリーメソッドによるシングルトン public class Elvis{ private static final Elvis INSTANCE = new Elvis(); private Elvis() { ... } public static Elvis getInstance() { return INSTANCE; } public void leaveTheBuilding() { ... } }でも、例1、例2の方法で作られたElvisには偽物が存在する可能性があって、それを防ぐには以下のようなメソッドを追加する必要がある。
例3//シングルトン特性を保持するためのreadResolveメソッド private Object readResolve() throws ObjectStreamException{ /* * 本物のElvisを返して、Elvisの偽物をガーベジコレクタに * 始末させる。 * */ return INSTANCE; }最新の一番良い方法
Java 1.5からできるようになった3つ目の方法。
単一要素をもつenum型を単純に作るだけ。
簡単な記述だし偽物を許さない鉄壁さもあるからシングルトンを作るならこのやり方にしましょう、だって。例4// enumシングルトン - 好ましい方法 public enum Elvis { INSTANCE; public void leaveTheBuilding() { ... } }
- 投稿日:2020-07-26T20:28:01+09:00
iOS: DeviceCheckの参照、保存をJavaで実装。(アカウントBan,リセマラ防止対応など)
iOSのdevice checkで出来ること。
- 端末から取得できるdevice tokenを元に、端末単位で2つのビット値をAppleのAPIに記録、参照できる。
- 端末を初期化、アプリのアンインストール&インストールしても保存されたビット値はリセットされない。
どんなことに利用できるか。
リセマラ防止。
- (初期インストール時、device checkのAPIに記録すると、再インストールされたことを判定できる。)
深刻な不正行為をするユーザーを端末単位で、アカウントbanする。
- device checkのAPIで、アカウントbanされた端末であることを記録。
- アプリの再インストール、端末の初期化後も、以前にアカウントbanされた端末である場合、利用できないようにする。
利用時の注意点
- 端末が中古市場等で別の人に渡った場合でも、保持される値なので慎重な運用が必要。
- 端末から取得したdevice tokenは時間的な有効期限があるみたい。(この部分の記憶は定かじゃないので、テストしてみてください。)アカウントbanで利用する場合は、banした後の次のアプリ起動時にdevice tokenをサーバーサイドに送って、そこですぐにdevice checkのAPIで更新するような工夫が必要。
事前準備、前提
- 認証キーのp8ファイルを取得。
- KEY_ID, TEAM_IDを取得
- DeviceTokenを端末で取得し、サーバーサイドに渡す。
参考記事
iOS11で追加されたDeviceCheckについて
apple 公式:
DeviceCheck APIのURL
baseのAPI
開発
https://api.development.devicecheck.apple.com/v1/
本番運用時
https://api.devicecheck.apple.com/v1/
APIの機能
参照:query_two_bits
https://api.devicecheck.apple.com/v1/query_two_bits
更新:update_two_bits
https://api.devicecheck.apple.com/v1/update_two_bits
device tokenのバリデーション:validate_device_token
https://api.devicecheck.apple.com/v1/validate_device_token
プログラム
iOSアプリでdevice tokenを取得。
※シミュレーターでは取得できません。
import DeviceCheck DCDevice.current.generateToken { (data, error) in guard let data = data else { return } let token = data.base64EncodedString() print(token) }サーバーサイド(Java)
取得、更新サンプル
// 取得 private void queryIOSDeviceCheckSample() { // この値で2つのbool値と最終更新日時を取得できる。 Response response = postRequest(DEVELOPMENT_BASE_API_URL + "query_two_bits", "端末から取得したdevicetoken", null, null); } // 更新 private void updateIOSDeviceCheckSample(Boolean bit0, Boolean bit1) { Response response = postRequest(DEVELOPMENT_BASE_API_URL + "update_two_bits", "端末から取得したdevicetoken", null, null); }API呼び出し処理
- "Authorization"ヘッダーにJWTのトークンを設定。
- request bodyにjson形式で各パラメーターを設定。
- device_token, transaction_id, timestamp, bit0, bit1
private static Response postRequest(String url, String deviceToken, Boolean bit0, Boolean bit1) throws IOException { MediaType JSON = MediaType.get("application/json; charset=utf-8"); JSONObject jsonObject = new JSONObject(); jsonObject.put("device_token", deviceToken); jsonObject.put("transaction_id", UUID.randomUUID().toString()); jsonObject.put("timestamp", new Date().getTime()); if (bit0 != null) { jsonObject.put("bit0", bit0); } if (bit1 != null) { jsonObject.put("bit1", bit1); } String json = jsonObject.toJSONString(); RequestBody body = RequestBody.create(JSON, json); String jwt = getJWTStr(); if (jwt == null) { return null; } Request request = new Request.Builder() .url(url) .header("Content-Type", "application/x-www-form-urlencoded") .header("Content-Length", String.valueOf(json.length())) .header("Authorization", "Bearer " + jwt) .post(body) .build(); OkHttpClient client = new OkHttpClient(); return client.newCall(request).execute(); }p8ファイルから、JWTトークンを取得。
プッシュ通知用ライブラリ「pushy」のソースを参考に実装:JWTトークンの取得処理
- pushyという、iOSのプッシュ通知用のライブラリがあり、 p8ファイルからJWTトークンを取得する処理がある。
- その部分を参考にして実装。 https://github.com/jchambers/pushy/blob/master/pushy/src/main/java/com/eatthepath/pushy/apns/auth/ApnsSigningKey.java#L124-L170
JTW(=JSON Web Token)
https://ja.wikipedia.org/wiki/JSON_Web_Token
private static String getJWTStr() { try { ECPrivateKey privateKey = getECPrivateKey(P8_SECRET_KEY_PATH); return Jwts.builder() .setHeaderParam("kid", KEY_ID) .setIssuer(TEAM_ID) .setIssuedAt(new Date()) .signWith(privateKey, SignatureAlgorithm.ES256) .compact(); } catch (Exception e) { return null; } } private static ECPrivateKey getECPrivateKey(String p8FilePath) throws Exception { final FileInputStream fileInputStream = new FileInputStream(new File(p8FilePath)); final ECPrivateKey signingKey; { final String base64EncodedPrivateKey; { final StringBuilder privateKeyBuilder = new StringBuilder(); final BufferedReader reader = new BufferedReader(new InputStreamReader(fileInputStream)); boolean haveReadHeader = false; boolean haveReadFooter = false; for (String line; (line = reader.readLine()) != null; ) { if (!haveReadHeader) { if (line.contains("BEGIN PRIVATE KEY")) { haveReadHeader = true; } } else { if (line.contains("END PRIVATE KEY")) { haveReadFooter = true; break; } else { privateKeyBuilder.append(line); } } } if (!(haveReadHeader && haveReadFooter)) { throw new IOException("Could not find private key header/footer"); } base64EncodedPrivateKey = privateKeyBuilder.toString(); } final byte[] keyBytes = Base64.getDecoder().decode(base64EncodedPrivateKey.getBytes(StandardCharsets.US_ASCII)); final PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); final KeyFactory keyFactory = KeyFactory.getInstance("EC"); try { signingKey = (ECPrivateKey) keyFactory.generatePrivate(keySpec); } catch (InvalidKeySpecException e) { throw new InvalidKeyException(e); } } return signingKey; }
- 投稿日:2020-07-26T20:24:31+09:00
JFR(Java Flight Recorder)を記録してダンプファイルを出力する方法
JFR(Java Flight Recorder)を記録してダンプファイルを出力する方法を紹介します。
ここでは、Eclipse GlassFish 5.1.0の状態を記録します。環境
- OS:CentOS Linux release 7.7.1908
- jdk1.8
- GlassFish 5.1.0
[glassfish@CENTOS7 ~]$ cat /etc/redhat-release CentOS Linux release 7.7.1908 (Core) [glassfish@CENTOS7 ~]$[glassfish@CENTOS7 ~]$ java -version java version "1.8.0_241" Java(TM) SE Runtime Environment (build 1.8.0_241-b07) Java HotSpot(TM) 64-Bit Server VM (build 25.241-b07, mixed mode) [glassfish@CENTOS7 ~]$[glassfish@CENTOS7 ~]$ /opt/glassfish5/glassfish/bin/asadmin version Version string could not be obtained from Server [localhost:4848]. (Turn debugging on e.g. by setting AS_DEBUG=true in your environment, to see the details.) Using locally retrieved version string from version class. Version = GlassFish Server Open Source Edition 5.1.0 (build default-private) Command version executed successfully. [glassfish@CENTOS7 ~]$GlassFish 5.1.0のインストールについては、以前投稿したCentOS7にEclipse GlassFish 5.1.0をインストールする方法を参照してください。
1. Glassfishの起動時のJVMオプションの設定
Glassfishの起動時のJVMオプションに以下を追加します。
-XX:+UnlockCommercialFeatures
-XX:+FlightRecorder
-XX:FlightRecorderOptions=<..>
具体的には「
/opt/glassfish5/glassfish/domains/domain1/config
」配下のdomain.xml
の「domain/configs/java-config」(domainタグ内のconfigsタグ内のjava-configタグ内)に以下の3行を追加します。/opt/glassfish5/glassfish/domains/domain1/config/domain.xmlに追加<jvm-options>-XX:+UnlockCommercialFeatures</jvm-options> <jvm-options>-XX:+FlightRecorder</jvm-options> <jvm-options>-XX:FlightRecorderOptions=defaultrecording=true,disk=true,repository=/var/log/jvm/diagnostics_images,maxsize=2048m,maxage=25h,dumponexit=true,dumponexitpath=/var/log/jvm/dump_test.jfr</jvm-options>※FlightRecorderOptionsの設定の詳細はJavaのページを参照してください。
2. Glassfishを起動
以下のコマンドでGlassfishを起動します。
/opt/glassfish5/glassfish/bin/asadmin start-domain domain1
実行結果[glassfish@CENTOS7 config]$ /opt/glassfish5/glassfish/bin/asadmin start-domain domain1 Waiting for domain1 to start ...... Successfully started the domain : domain1 domain Location: /opt/glassfish5/glassfish/domains/domain1 Log File: /opt/glassfish5/glassfish/domains/domain1/logs/server.log Admin Port: 4848 Command start-domain executed successfully. [glassfish@CENTOS7 config]$3. JFRダンプファイルの出力
まずは以下のコマンドでglassfishのプロセスIDを調べます。
ps -ef | grep glassfish | grep -v grep
実行結果[glassfish@CENTOS7 config]$ ps -ef | grep glassfish | grep -v grep glassfi+ 26302 1 5 19:54 pts/0 00:00:16 /usr/java/jdk1.8.0_241-amd64/bin/java -cp /opt/glassfish5/glassfish/modules/glassfish.jar -XX:+UnlockCommercialFeatures -XX:+UnlockDiagnosticVMOptions -XX:NewRatio=2 -XX:FlightRecorderOptions=defaultrecording=true,disk=true,repository=/var/log/jvm/diagnostics_images,maxsize=2048m,maxage=25h,dumponexit=true,dumponexitpath=/var/log/jvm/dump_test.jfr -XX:+FlightRecorder -XX:MaxPermSize=192m -Xmx512m -javaagent:/opt/glassfish5/glassfish/lib/monitor/flashlight-agent.jar -client -Djavax.xml.accessExternalSchema=all -Djavax.net.ssl.trustStore=/opt/glassfish5/glassfish/domains/domain1/config/cacerts.jks -Djdk.tls.rejectClientInitiatedRenegotiation=true -Djdk.corba.allowOutputStreamSubclass=true -Dfelix.fileinstall.dir=/opt/glassfish5/glassfish/modules/autostart/ -Dorg.glassfish.additionalOSGiBundlesToStart=org.apache.felix.shell,org.apache.felix.gogo.runtime,org.apache.felix.gogo.shell,org.apache.felix.gogo.command,org.apache.felix.shell.remote,org.apache.felix.fileinstall -Dcom.sun.aas.installRoot=/opt/glassfish5/glassfish -Dfelix.fileinstall.poll=5000 -Djava.endorsed.dirs=/opt/glassfish5/glassfish/modules/endorsed:/opt/glassfish5/glassfish/lib/endorsed -Djava.security.policy=/opt/glassfish5/glassfish/domains/domain1/config/server.policy -Dosgi.shell.telnet.maxconn=1 -Dfelix.fileinstall.bundles.startTransient=true -Dcom.sun.enterprise.config.config_environment_factory_class=com.sun.enterprise.config.serverbeans.AppserverConfigEnvironmentFactory -Dfelix.fileinstall.log.level=2 -Djavax.net.ssl.keyStore=/opt/glassfish5/glassfish/domains/domain1/config/keystore.jks -Djava.security.auth.login.config=/opt/glassfish5/glassfish/domains/domain1/config/login.conf -Dfelix.fileinstall.disableConfigSave=false -Dfelix.fileinstall.bundles.new.start=true -Dcom.sun.aas.instanceRoot=/opt/glassfish5/glassfish/domains/domain1 -Dosgi.shell.telnet.port=6666 -Dgosh.args=--nointeractive -Dcom.sun.enterprise.security.httpsOutboundKeyAlias=s1as -Dosgi.shell.telnet.ip=127.0.0.1 -DANTLR_USE_DIRECT_CLASS_LOADING=true -Djava.awt.headless=true -Dcom.ctc.wstx.returnNullForDefaultNamespace=true -Djava.ext.dirs=/usr/java/jdk1.8.0_241-amd64/lib/ext:/usr/java/jdk1.8.0_241-amd64/jre/lib/ext:/opt/glassfish5/glassfish/domains/domain1/lib/ext -Djdbc.drivers=org.apache.derby.jdbc.ClientDriver -Djava.library.path=/opt/glassfish5/glassfish/lib:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib com.sun.enterprise.glassfish.bootstrap.ASMain -upgrade false -domaindir /opt/glassfish5/glassfish/domains/domain1 -read-stdin true -asadmin-args --host,,,localhost,,,--port,,,4848,,,--secure=false,,,--terse=false,,,--echo=false,,,--interactive=true,,,start-domain,,,--verbose=false,,,--watchdog=false,,,--debug=false,,,--domaindir,,,/opt/glassfish5/glassfish/domains,,,domain1 -domainname domain1 -instancename server -type DAS -verbose false -asadmin-classpath /opt/glassfish5/glassfish/lib/client/appserver-cli.jar -debug false -asadmin-classname com.sun.enterprise.admin.cli.AdminMain [glassfish@CENTOS7 config]$プロセスIDが
26302
であることがわかります。以下のコマンドでJFR(Java Flight Recorder)の記録をダンプファイルに出力します。
jcmd <プロセスID> JFR.dump recording=0 filename=<出力ダンプファイルのパス>
実行結果[glassfish@CENTOS7 ~]$ jcmd 26302 JFR.dump recording=0 filename=/home/glassfish/perf/test_$(date "+%Y%m%d_%H%M%S").jfr 26302: Dumped recording 0, 2.5 MB written to: /home/glassfish/perf/test_20200726_200546.jfr [glassfish@CENTOS7 ~]$出力されたダンプファイルを確認します。
実行結果[glassfish@CENTOS7 ~]$ cd /home/glassfish/perf [glassfish@CENTOS7 perf]$ ls -l 合計 2600 -rw-rw-r--. 1 glassfish glassfish 2660207 7月 26 20:05 test_20200726_200546.jfr [glassfish@CENTOS7 perf]$3. 「jmc.exe」で出力されたダンプファイル(jfrファイル)を参照
出力したjfrダンプファイル(test_20200726_200546.jfr)をjdk1.8がインストールされているWindowsPCに転送します。
「
C:\Program Files\Java\jdk1.8.0_231\bin
」配下の「jmc.exe」(Java Mission Contorol)を起動します。メニューから「ファイル」-「ファイルを開く」で出力したjfrダンプファイル(test_20200726_200546.jfr)を開きます。
「jmc.exe」(Java Mission Contorol)で出力したjfrダンプファイルを参照することができます。
参考
- 投稿日:2020-07-26T18:53:52+09:00
eclipse使わずにJDBCでJavaアプリケーションとPostgreSQLの接続(コマンドプロンプトで実行)
はじめに
プログラミング教育の講師という立場でもある私は、初学者に対して統合開発環境をあえて使わずにプログラミング言語の基礎を理解するよう伝えています。
そのため、eclipseを使わずにJavaアプリケーションを動作させる環境を用意する必要がありました。この記事を読んでできること
コマンドプロンプトでPostgreSQLのAPIを使ったJavaアプリケーションを実行することができるようになります。
実行環境
実行環境は以下を使っています。
- OS
- Windows10
- Javaバージョン
- OpenJDK 14.0.2
- データベースバージョン
- PostgreSQL 12
PostgreSQL用JDBCのjarファイルを追加する
PostgreSQLをインストールする際の付属アプリケーションである「スタックビルダー」を起動してください。
インストールしたいアプリケーションから"pgJDBC vXX.X.XX"を選択してください。
これはインストーラーなので保存ディレクトリはどこでもOKです。(迷ったらダウンロードフォルダへ保存してください。)上記でダウンロードした"edb_pgjdbc.exe"を開いてjarファイルを追加します。
保存先はデフォルトのまま("C:\Program Files (x86)\PostgreSQL\pgJDBC")でインストールしてください。JDBCを使ってPostgreSQLとの接続を行う
私は最近、Javaプログラミングをする際は統合開発環境(eclipseなど)を使って開発する機会が増えて、滅多にサクラエディタなど簡単なエディタで実装することはなくなってきました。(大学などで学ぶ時はよく使っていました…。)
eclipseでのJDBC使用方法はよく見かけますがおさらいします。eclipseでJDBCを使う際には、Javaプロジェクトを新規作成後、
プロジェクトを右クリックし以下の操作でJDBCのjarファイルを追加します。(英語)
"Build Path"→"Add External Archives..."→"postgresql-XX.X.XX.jar"を選択
(日本語)
"ビルド・パス"→"外部アーカイブの追加"追加するとパッケージ・エクスプローラに表示されます。
実行したいソースコード
データベース(restaurantdb)にはすでにテーブル(menuitems)を生成しています。
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class P5_1 { public static void main(String[] args) { String url = "jdbc:postgresql://127.0.0.1:5432/restaurantdb"; String user = "postgres"; String password = "postgres"; String sql = "SELECT * FROM menuitems"; try (Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(sql)) { while(resultSet.next()) { String id = resultSet.getString(1); String name = resultSet.getString(2); int price = resultSet.getInt(3); String kindId = resultSet.getString(4); Boolean isDisabled = resultSet.getBoolean(5); System.out.println(id + " " + name + " " + price + " " + kindId + " " + isDisabled); } } catch (SQLException e) { e.printStackTrace(); } } }本題:eclipseを使わずにJavaのプログラムからデータベース接続しようとするとエラーが発生する問題を解決したい
C:\java-programming\JDBCSample>javac P5_1.java C:\java-programming\JDBCSample>java P5_1 java.sql.SQLException: No suitable driver found for jdbc:postgresql://127.0.0.1:5432/restaurantdb at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:702) at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:228) at P5_1.main(P5_1.java:15)上記エラーを抑える方法は2つあるようです。
・環境変数へ「CLASSPATH」を追加する
・実行時に実行オプション「-cp」を付与する環境変数へ「CLASSPATH」を追加する
1つ目に、環境変数へ「CLASSPATH」を追加するという選択肢があります。
"コントロール・パネル"→"システム"→"システムの詳細設定"→"環境変数"→"ユーザの環境変数"へ以下を追加してください。
変数名「CLASSPATH」
値「C:\Program Files (x86)\PostgreSQL\pgJDBC\postgresql-42.2.12.jar;.」
※値の最後にドット(.)が入っているので注意してください。ドットを入れ忘れるとデフォルトで設定されているカレントディレクトリへのクラスパスが無効となる場合があります。
※"postgresql-XX.X.XX.jar"は、格納場所やバージョンなどは適宜読み替えてください。
※すでに「CLASSPATH」が存在する場合、既存の値を消してしまうと他の環境が壊れる場合があるので、追記する形で編集してください。
例えば、「C:\XXX\YYY.jar;」を設定していた場合は、「C:\XXX\YYY.jar;C:\Program Files (x86)\PostgreSQL\pgJDBC\postgresql-42.2.12.jar;.」となるように追記します。(セミコロンは区切り文字です。)実行時に実行オプション「-cp」を付与する
何らかの理由で環境変数を変更できない場合、実行時にオプションをつけることができます。
例えば、「P5_1.java」をコンパイルし実行する場合、以下のコマンドを入力します。
> javac P5_1.java > java -cp "C:\Program Files (x86)\PostgreSQL\pgJDBC\postgresql-42.2.12.jar;." P5_1(実行結果が表示されます)
※値の最後にドット(.)が入っているので注意してください。ドットを入れ忘れるとデフォルトで設定されているカレントディレクトリへのクラスパスが無効となる場合があります。
※"postgresql-XX.X.XX.jar"は、格納場所やバージョンなどは適宜読み替えてください。まとめ
今回、eclipseを使わずにJavaプログラムからJDBCのAPIを呼び出しました。
あまりこれを使う機会は少ないかもしれませんが、仕組みを理解する上で試してみるのも良いかもしれません。ありがとうございました。
参考
- JDBCインタフェース|PostgreSQL
https://www.postgresql.jp/document/7.4/html/jdbc.html
- 投稿日:2020-07-26T15:41:58+09:00
Springで勤怠サイトを作ってみる。【概略】
概要
評価面談でSpringを勉強していると言ってしまったばっかりに、
次回面談までに勤怠サイトを作ることに・・・。
実業務でSpringベースの開発経験はあるけども、全体的に素人に毛が生えたレベル。PCの調子が悪くて(なんかカリカリ音がしている)成果物が消える恐れがあるので、
面談時のエビデンスのためにも作業履歴としてQiitaに残そうかな、と。構成(想定)
- Webアプリ
- フロント:Vue.js
- バックエンド:Spring
- DB:PostgreSQL
※追記事項があり次第記載します環境
- Eclipse - Version: Oxygen.3a Release (4.7.3a)
- Atom
※追記事項があり次第記載します。
- 投稿日:2020-07-26T13:00:07+09:00
(Intelij)Spring BootでHelloWorld
手順
- InteliJで「File」→「New」→「Project」
- 表示されたNew Projectで「Spring Initializer」を選択し、「Next」
- 適当に「Group」,「Artifact」を入力。サーバにデプロイしたいので、「Packaging」は「War」を選択し、「Next」
- Webアプリケーションを作りたいので、「Web」→「Spring Web」にチェックし、「Next」
- 適当に「Project name」,「Project location」を入力し、「Fisnish」
- 自動作成されたDemoApplicationに以下の通り追記し、実行。
私は
@RestController
がなくて、ハマりました・・・package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; + import org.springframework.web.bind.annotation.GetMapping; + import org.springframework.web.bind.annotation.RestController; @SpringBootApplication + @RestController public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } + @GetMapping("/hello") + public String sayHello() { + return "Hello World"; + } }
- 以下URLにアクセスすると「Hello World」が表示されるはず
- 投稿日:2020-07-26T09:47:35+09:00
Jacksonで良い感じに整形してシリアライズする
JavaでJSONにシリアライズしたいときはJSON-Bだと力不足なのでJacksonを使う事が多いのだけど、いつも書き方忘れるのでメモ。
整形せずにシリアライズする
データ交換用に整形せずにシリアライズするパターン。通常はこれ。
var item = Map.of("parent", Map.of("child", List.of("a", "b", "c"))); var json = new ObjectMapper().writeValueAsString(item);結果
{"parent":{"child":["a","b","c"]}}整形してフォーマットを綺麗にしたい場合 その1
画面出力や設定ファイル用にフォーマットを整えたい場合. INDENT_OUTPUTを使う
var item = Map.of("parent", Map.of("child", List.of("a", "b", "c"))); var mapper = new ObjectMapper(); mapper.enable(SerializationFeature.INDENT_OUTPUT); var json = mapper.writeValueAsString(item);結果
{ "parent" : { "child" : [ "a", "b", "c" ] } }整形してフォーマットを綺麗にしたい場合 その2
さらに要素の配列を改行付きで表示したい場合。要素が長い時とか用。PrettyPrinterとSYSTEM_LINEFEED_INSTANCEを使う。
var item = Map.of("parent", Map.of("child", List.of("a", "b", "c"))); var printer = new DefaultPrettyPrinter(); printer.indentArraysWith(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE); var json = new ObjectMapper().writer(printer).writeValueAsString(item);結果
{ "parent" : { "child" : [ "a", "b", "c" ] } }
- 投稿日:2020-07-26T00:31:02+09:00
JavaからVB.NETへ ―書き方対照メモ―
この記事について
作成の経緯
新人研修で3ヶ月間Javaをやってきたけれども、配属先部署で使う言語はVisual Basic .NETだったので新しく学ぶ必要が生じた。
しかし、「JavaからVB.NETへ移行」というケースはそんなにないのか(今ならC#あたりが普通…?)、文法の比較などを細かくしているサイトが見つからなかったため、自分で書いてみることにした。対象者・目的
- Javaの書き方やプログラミングの諸概念は一通り理解している
- これからVB.NETでもプログラムを書けるようになりたい
という人(まあ自分と数名の同期だけれど)にJavaとVB.NETの比較対象リファレンスを提供する。
環境
- Windows 10
- Visual Studio 2019
- .NET Framework 4.7.2
といっても、環境に依存するようなコードはほぼないはず。
記述上の注意
- Visual Basic .NET(VB.NET)のことは、以下単に「VB」と呼ぶ。
- 同じセクションにあるJavaとVBのコードは、基本的に同じ処理になるようにしている。
参考文献(総合)
- 羽山 博『基礎 Visual Basic 2019』(株式会社インプレス、2019年)
- VBを学習する上でお世話になっている教本。Javaなど他の言語を知っていれば、フルタイム×1週間くらいで読めてしまうと思われる。
- Java屋さんからVB.netプログラマになるために - Qiita
- Javaの視点からVBを見た数少ない記事。
- Visual Basic のドキュメント - はじめに、チュートリアル、リファレンス。 | Microsoft Docs
コードの基本構造
main
Main.javapublic class Main { public static void main(String[] args) { System.out.println("Hello Java!"); int a; String b; double c; } }
- ブロックは
{}
で区切られるpublic
などの修飾子は小文字;
で文を終える(改行それ自体は意味をもたない)Form1.vbPublic Class Form1 Private Sub ShowMessage(sender As Object, e As EventArgs) _ Handles Button1.Click Console.WriteLine("Hello VB!") Dim a As Integer : Dim b As String : Dim c As Double End Sub End Class
- ブロックは
(修飾子) Class
〜End Class
のように分けられる- 行の終わりは文(ステートメント)の終わり。
- 長い文中で意図的に改行させたいときは、行継続文字
_
を入れる- ただし、VB2010からは、特定の条件下で行継続文字がなくても改行できるようになった(暗黙の行継続)。
- 詳しいルールはVisual Basic 2010の新機能 - @ITを参照
- 1行の中に複数のステートメントを入れたいときは、
:
で区切る。コメント
Comment.java// 単数行コメント /* * 複数行コメント */Comment.vb' 単数行コメント
※VBに複数行コメントはない
ドキュメンテーションコメント
専用ツールでAPIドキュメントを生成したり、メソッド名上マウスオーバーで説明を表示したりできるやつ。
- Java: Javadoc形式で記述する。
/**
~*/
- Eclipseでは、対象メンバにカーソルを当ててから Alt+Shift+J で生成できる
JavaDoc.java/** * 引数で指定された2つの整数をかけ算し、その結果を返す。 * @param a かける数1 * @param a かける数2 * @return かけ算の結果 */ public static int doCalc(int a, int b) { return a * b; }
- VB: XMLで記述する。
'''
- Visual Studioでは、 対象メンバのすぐ上の行で
'''
と打つと生成できる。XmlDoc.vb''' <summary> ''' 引数で指定された2つの整数をかけ算し、その結果を返す。 ''' </summary> ''' <param name="a">かける数1</param> ''' <param name="b">かける数2</param> ''' <returns>かけ算の結果</returns> Public Shared Function DoCalc(a As Integer, b As Integer) As Integer Return a * b End Function参考
ファイル・フォルダ構成
※一部省略あり
Java (Eclipse)の例
- JavaProject
- bin
- package
Main.class
(ビルドされたJavaバイトコード)- src
- package
main.java
(ソースコード)- lib
- doc
.project
(Eclipseプロジェクトファイル).settings
.classpath
VB.NET Windows フォーム アプリケーション(Visual Studio)の例
- VisualStudioSolution
VisualStudioSolution.sln
(VSソリューションファイル)- FirstProject
FirstProject.vbproj
(VBプロジェクトファイル)- bin
- Debug
FirstProject.exe
(ビルドされたデバッグ用実行ファイル)- Release
- My Project
- obj
App.config
Form1.vb
(ソースコード[動作])Form1.Designer.vb
(ソースコード[デザイン])- SecondProject
- (FirstProjectと同様)
Visual Studioでは、複数のプロジェクトをソリューションとしてまとめることができる。(Eclipseでもワーキング・セットというものもあるが)
変数
データ型分類
- Java
- 基本型(
byte
,short
,int
,long
,float
,double
,char
,boolean
)- 参照型(
String
など)- VB
- 値型(
Byte
,Short
,Integer
,Long
,Single
(float相当),Double
,Decimal
(10進型),Char
,Boolean
,Date
など)- 参照型(
String
など)日付型は、Javaでは
java.util.Date
、java.util.Calender
、java.time
などの標準APIを使う必要がある(つまり必然的に参照型になる)。しかしVBでは、日付・時刻を管理できるDate
型を標準で用意している。宣言・アクセス修飾
DeclareVariable.javaint number; // package private String message; // package private public int publicNumber; private String privateMessage;DeclareVariable.vbDim Something ' Private Dim Number As Integer ' Private Dim Message As String ' Private Public PublicNumber As IntegerVB標準設定では、変数の宣言時に型の指定を省略することができる。その場合、初期値のデータ型に従って自動的に変数のデータ型も決められる(型の推定)。初期値がない場合はObject型とみなされる。
Option Strict On
にすると、型の推定は無効になる。変数名の規則
文字 Java VB 備考 半角英数字 ○ ○ 日本語文字 ○ ○ もちろんあまり推奨されない _
○ ○ アンダースコア &
○ × 先頭が数字 × × 初期化
InitiarizeVariable.javaint number = 100; String message = "Hello";InitiarizeVariable.vbDim Number As Integer = 100 Dim Message As String = "Hello" Dim Pi = 3.14 ' 自動的にDouble型として扱われる Dim BlankNumber As Integer ' 初期値は自動的に「0」になる Dim BlankMessage As String ' 初期値は自動的に「Nothing」になる定数宣言
Constant.javafinal int MAX_STOCK = 100; public static final String VERSION_ID = "v1.0.1-RELEASE";Constant.vbConst MAX_STOCK As Integer = 100 Const VERSION_ID As String = "v1.0.1-RELEASE" ' ConstステートメントではSharedは使えない参考
演算子
算術演算子
機能 Java VB.NET 備考 加算 a + b
a + b
減算 a - b
a - b
乗算 a * b
a * b
除算 a / b
a / b
整数除算(商) N/A a \ b
[VB] aとbはどちらも整数型でなければならない。 23 \ 5
の結果は4
になる剰余(余り) a % b
a Mod b
23 % 5
ないし23 Mod 5
の結果は3
になる累乗 (演算子としてはなし) a ^ b
VBの ^
は算術演算子の中で優先順位が最も高いことに注意インクリメント ++a
またはa++
N/A VBでは a += 1
などど書くしかないインクリメント --a
またはa--
N/A VBでは a -= 1
などど書くしかない整数同士の除算
Javaでは、割られる数
a
と割る数b
の両方が整数だと、結果の小数点以下が切り捨てられ、整数になる。これは代入先がdouble
型などの変数であっても変わらない。DivideInteger.javadouble x; x = 23 / 5; // xは4.0になる少なくとも片方が小数(倍精度浮動小数点数)だと、結果も小数になる。
java.DivideDouble.javadouble x; x = 23 / 5.0 // xは4.6になる一方、VBではできるだけ精度が落ちないように演算が行われる。
DivideInteger.vbDim x As Double x = 23 / 5 ' xは4ではなく4.6になるVBでもJavaのように整数同士の除算をしたい場合に、
\
演算子を使う。
vb:DivideWithBackSlashOperator.
Dim x As Double
x = 23 \ 5 ' xは4になる
Javaにおける累乗
Javaでは、
java.lang.Math.pow(a, b)
を使う。
第1引数a
が底、第2引数b
が指数(つまりVBでいうところのa ^ b
)。代入演算子
機能 Java VB.NET 備考 そのまま代入 a = b
a = b
加算結果を代入 a += b
a += b
減算結果を代入 a -= b
a -= b
乗算結果を代入 a *= b
a *= b
除算結果を代入 a /= b
a /= b
整数除算の結果を代入 N/A a \= b
剰余(余り)を代入 a % b
N/A [VB]Modに対応するものはない (ビット演算系は省略)
比較演算子
機能 Java VB.NET 備考 aはbよりも小さい a < b
a < b
aはb以下 a <= b
a <= b
aはbよりも大きい a > b
a > b
aはb以上 a >= b
a >= b
aはbに等しい a == b
a = b
VBでは =
は1個aはbに等しくない a != b
a <> b
論理演算子
以下の表では
A
やB
は条件式(True/Falseを返す式)を表す。
論理 機能 Java VB.NET 論理積(AND) AかつB N/A A And B
論理積(AND) AかつB(短絡評価) A && B
A AndAlso B
論理和(OR) AまたはB N/A A Or B
論理和(OR) AまたはB(短絡評価) A && B
A OrElse B
論理積(NOT) Aでない !A
Not A
排他的論理和(XOR) AまたはB、しかしAかつBではない ^A
A Xor B
短絡評価:
AがFalseなら条件式全体がFalseになることが確定するので、Bを評価せずに先へ進むこと。
このとき、Bに何らかのメソッドが書いてあっても実行されない。
これを利用して、AがTrueにならないとエラーになる式をBに書くことができる。
例:If Integer.TryParse(str, num) AndAlso num < 5 Then ...
連結演算子
Javaでは文字列の連結に
+
を使うが、VBでは&
を使う。VBでも
+
で文字列連結をすることは可能だが、片方が文字列型でない場合に意図しない結果となったり、エラーになる可能性があるため、Microsoftは&
の使用を推奨している。演算子の参考ページ
型変換
条件分岐
if文 / Ifステートメント
ConditionalBranch.javaif (age < 20) canBuyAlcohol = true; if (age < 13) { fareType = "child"; } else if (age < 18) { fareType = "student"; } else { fareType = "adult"; }ConditionalBranch.vbIf age < 20 Then canBuyAlcohol = True ' 1行ならばEnd Ifはいらない If age < 13 Then FareType = "child" ElseIf age < 18 Then FareType = "student" Else FareType = "adult" End IfVBでは、次のように「
:
」を使って複数のステートメントを1行に書くことも可能。ConditionalBranchInOneLine.vbIf 20 < age Then FareType = "adult" : CanBuyAlcohol = true Else CanBuyAlcohol = falseSwitch / Select Caseステートメント
1つの値と一致させる
ConditionalBranch2.javaswitch (num) { case 1: gender = "男性"; break; case 2: gender = "女性"; break; case 3: gender = "その他"; break; default: gender = "未回答"; break; }switch文の式(上記の
num
)は、基本型+String型(Java SE 7以降)のみ。ConditionalBranch2.vbSelect Case Num Case 1 Gender = "男性" Case 2 Gender = "女性" Case 3 Gender = "その他" Case Else Gender = "未回答" End Select複数の値に一致させる
ConditionalBranch3.javaswitch (phoneNumberPrefix) { case 090: case 080: case 070: isMobile = true; break; default: isMobile = false; break; }ConditionalBranch3.vbSelect Case PhoneNumberPrefix Case 090, 080, 070 IsMobile = true Case Else IsMobile = false End Select値の範囲を指定する
ConditionalBranch4.java// JavaのSwitch文ではできない(やるとしても別の変数を噛ませるしかない)
ConditionalBranch4.vbSelect Case MonthNumber Case 3 To 5 Season = "春" Case 6 To 8 Season = "夏" Case 9 To 11 Season = "秋" Case Else Season = "冬" End Select比較演算子を使う
ConditionalBranch5.java// JavaのSwitch文ではできない(素直にif文使った方が良い)
ConditionalBranch5.vbSelect Case Score Case Is < 60 Grade = "F" Case Is < 70 Grade = "C" Case Is < 80 Grade = "B" Case Is < 90 Grade = "A" Case Else Grade = "S" End Select繰り返し
for文 / Forステートメント
ForLoop.javafor (int i = 0; i <= 9; i++) { System.out.println(i + "回目の繰り返し処理です"); }ForLoop.vbFor i As Integer = 0 To 9 Step 1 ' 増分値1の場合、Stepは省略可能 Debug.WriteLine(i & "回目の繰り返し処理です") Nextどちらの言語でも、For文の初期化式内でループカウンタを宣言するのではなく、For文の外で宣言した変数を使うこともできる。その場合、For文を抜けてもその変数を使うことができる。
ForLoop2.javaint i; for (i = 0; i <= 9; i++) { System.out.println(i + "回目の繰り返し処理です"); } System.out.println(i + "回繰り返されました");ForLoop2.vbDim i As Integer For i = 0 To 9 Step 1 ' 増分値1の場合、Stepは省略可能 Debug.WriteLine(i & "回目の繰り返し処理です") Next Debug.WriteLine(i & "回繰り返されました")拡張for文 / For-Eachステートメント
ForEachLoop.javaint[] scoreArray = {70, 80, 90}; // 通常のfor文 for (int i = 0; i < scoreArray.length(); i++) { System.out.println(scoreArray[i]); } // 拡張for文 for (int score : scoreArray) { System.out.println(score); }ForEachLoop.vbDim ScoreArray() As Integer = {70, 80, 90} ' 通常のfor文 For i As Integer = 0 To UBound(ScoreArray) Debug.WriteLine(ScoreArray(i)) Next ' For Eachステートメント For Each score As Integer In ScoreArray Debug.WriteLine(score) Nextwhile文 / While-End Whileステートメント
条件がtrueである限り実行し続ける。
WhileLoop.javaint i = 0; while (i < 10) { System.out.println(i + "回目の繰り返し処理です"); i++; }WhileLoop.vbDim i As Integer = 0 While i < 10 Debug.WriteLine(i & "回目の繰り返し処理です") i += 1 End While※このサンプルではWhileよりもForのほうが適している
do-while文 / Do-Loopステートメント
後判断型(1回は実行される)
DoWhileLoop.javaRandom rd = new Random(); int num = 0; do { num = rd.nextInt(100) + 1; System.out.println(num); } while (num % 2 == 0);DoLoopWhile.vbDim rd As Random = new Random() Dim Num As Integer = 0 Do Num = rd.Next(1, 100) Debug.WriteLine(Num) Loop While Num Mod 2 = 0VBでは、
Loop While 条件
(条件がfalseになるまで繰り返す)のほか、Loop Until 条件
(条件がtrueになるまで繰り返す)というのも使える。DoLoopUntil.vbDim rd As Random = new Random() Dim Num As Integer = 0 Do Num = rd.Next(1, 100) Debug.WriteLine(Num) Loop Until Num Mod 2 <> 0
Until
以下の条件が逆転しているが、DoLoopWhile.vb
とDoLoopUntil.vb
はどちらも同じ処理になる。前判断型(1回も実行されない可能性がある)
DoLoopWhile2.vbDim i As Integer = 0 Do While i < 10 Debug.WriteLine(i & "回目の繰り返し処理です") i += 1 LoopDoLoopUntil2.vbDim i As Integer = 0 Do Until i >= 10 Debug.WriteLine(i & "回目の繰り返し処理です") i += 1 Loopループを抜ける
- Java:
break;
- VB:
Exit Do
、Exit For
、Exit While
途中で次の繰り返しに進む
- Java:
continue;
- VB:
Continue Do
、Continue For
、Continue While
配列
宣言
カッコの中で指定する数字の意味が違う点に注意。
ArrayDecralation.javaint[] numArray = new int[5];インデックス
0
,1
,2
,3
,4
の合計5個の要素を持った配列になる。
[n]
で指定するのは配列の要素数。ArrayDeclaration.vbDim NumArray(4) As Integerインデックス
0
,1
,2
,3
,4
の合計5個の要素を持った配列になる。
(n)
で指定するのはインデックスの最大値。初期化
ArrayInit.javaint[] numArray = { 10, 20, 30, 40, 50 };ArrayInit.vbDim NumArray() As Integer = { 10, 20, 30, 40, 50 }代入・利用
ArrayUse.javanumArray[3] = 31; int a = numArray[3];ArrayUse.vbNumArray(3) = 31 Dim a As Integer = NumArray(3)多次元配列
MultiDArray.vbint[][] numArray = new int[3][4]; double[][] doubleArray = { { 0.0, 0.1, 0.2 }, { 1.1, 2.2, 3.3, 4.4 } };MultiDArray.vbDim NumArray(2, 3) As Integer Dim DoubleArray(, ) As Double = { { 0.0, 0.1, 0.2 }, { 1.1, 2.2, 3.3, 4.4 } }
(, )
は一見するとインデックス最大値を入れ忘れているようにも見えるが、Javaでいう[][]
に相当するもの。配列サイズの変更
Javaでは一度作った配列のサイズを変更することはできず、新たに配列を作ってそこに値を移し替えるしかない。
しかし、VBでは
ReDim
ステートメントを使うことで配列のサイズを変更できる。ChangeArraySize.vbDim NumArray(9) As Integer ' ... ReDim Preserve NumArray(6)
Preserve
を付けると、元の要素の値が保持される(付けないと全ての要素が空になる)。
要素数を減らした場合、減らされた分の要素は削除される(上記例では、インデックス7
,8
,9
の3要素は削除される)。配列の長さ(要素数)
- Java
配列名.length
(要素数を返す) を使う。ArrayLength.javaint[] numArray = new int[5]; for (int i = 0; i < numArray.length; i++) { numArray[i] = i; } // 配列の中身は {0, 1, 2, 3, 4} になる
- VB:
配列名.Length
(要素数を返す)を使う。- 繰り返しで全要素を処理する場合は、
UBound(配列名)
(インデックスの最大値を返す)を使う。- For文の
To
は<
ではなく<=
の意味。- したがって、
0 To 配列名.Length
と書くと、最終回で配列の長さを突き抜けてしまいSystem.IndexOutOfRangeException
になる。- どうしても
UBound()
を覚えたくなければ、配列名.Length - 1
でもいけなくはないが…ArrayLength.javaDim NumArray(4) As Integer For i As Integer = 0 To UBound(NumArray) NumArray(i) = i Next ' 配列の中身は {0, 1, 2, 3, 4} になるメソッド / プロシージャ
概念の整理(整理し切れていない)
基本的に、「メソッド」=「プロシージャ」だと思っても実用上は困らない。
Javaでは「メソッド」しか出てこないのに対して、VBではどちらの単語も登場する。やっていることは同じ「一連の処理をまとめる」ということだが、「メソッド」は、プロシージャの中でもその所属元を意識している言葉、らしい。
「オブジェクト」が持つ「性質」(フィールド)と「機能」(メソッド)、という感じ。
ただ、英語で "what is the difference between a method and a procedure in visual basic" ってググると、"method vs procedure" じゃなくて "function vs procedure" って書いてあるページばかりがヒットする(method = function?)
このあたりはプログラム言語の歴史(関数 function とか サブルーチン subroutine)にかかわってきそう。参考
用語の比較
対象 Java VB 戻り値を返さない処理 メソッド( void
)Sub
プロシージャー戻り値を返す処理 メソッド( void
以外)Function
プロシージャークラスフィールドの読み書きをする処理 getter
/setterメソッド
Property
プロシージャー個々のインスタンスに属する処理 インスタンスメソッド (普通の Sub
/Function
プロシージャー)クラス全体に属する処理 static
メソッド共有( Shared
)メソッドイベントに応じた処理 N/A イベントハンドラー(Subプロシージャーの一形態) Subプロシージャー
戻り値を返さない 処理。(直接の戻り値がないだけなので、参照渡しを使って呼び出し元に存在する変数やオブジェクトを書き換え、データを返すようなことは可能)
- Java:
アクセス修飾子 [static] void 名前(型名 引数名, ...) {
~}
VoidMethod.javapublic void showMessage(int a, int b) { System.out.println(a + b); }
- VB:
アクセス修飾子 [Shared] Sub 名前(引数名 As 型名, ...)
~End Function
- イベントハンドラーもここに属する(後ろに
Handles
句が付くやつ)SubProc.vbPublic Sub ShowMessage(Str1 As String, Str2 As String) Debug.WriteLine(a + b) End SubFunctionプロシージャー
戻り値を返す処理。
- Java:
アクセス修飾子 [static] 戻り値の型 名前(型名 引数名, ...) {
~}
return
で戻り値を指定するReturnMethod.javapublic int doCalc(int a, int b) { return a * b; }
- VB:
アクセス修飾子 [Shared] Function 名前(引数名 As 型名, ...) As 戻り値の型
~End Function
Return
で戻り値を指定するFunctionProc.vbPublic Function DoCalc(a As Integer, b As Integer) As Integer Return a * b End FunctionPropertyプロシージャー
→ クラスの項目で解説
プロシージャーを途中で抜ける
ExitMethod.javapublic void showMessage() { if (errFlag) { return; // 実はvoidメソッドでもこれで抜けられる } else { System.out.println("処理成功") } } public int doCalc(int a, int b) { int result = a * b; if (result > 10) { return 0; // 値を返さずに抜けることは許されない } else { return result; } }ExitProcedure.vbPublic Sub ShowMessage() If ErrFlag Then Exit Sub ' VBではExit Sub Else Debug.WriteLine("処理成功") End Sub Public Function DoCalc(a As Integer, b As Integer) As Integer Dim result As Integer = a * b If (result > 10) Then Exit Function ' 戻り値がInteger型なので0を返す ElseIf (result > 50) Then DoCalc = result + 1 Exit Function ' 変数DoCalcに設定した値を返す Else Return result End If End FunctionJavaだと
return
せずにvoid以外のメソッドを抜けることは不可能だが、VBのFunctionプロシージャーではできてしまう。
ただし、戻り値の型によってはぬるぽ例外を発生させるなど、予期しない動作を招く原因になりかねないので、必ずReturn
すべきと思われる。可変長引数
- Java: 引数を
(データ型... 変数名)
とする
- 当該メソッド内では、配列変数のように扱うことができる
- 他の引数も指定する場合、可変長引数は引数リストの最後に置かなければならない
VariadicMethod.javapublic static int getSum(int... numbers) { int sum = 0; for (int i = 0; i < numbers.length; i++) { sum += numbers[i]; } return sum; }
- VB:
(ParamArray 変数名 As データ型[])
とする
- 性質はJavaと同じ。
VariadicFunction.vbPublic Shared Function GetSum(ParamArray Numbers As Integer[]) As Integer Dim Sum As Integer = 0 For i As Integer = 0 To UBound(Numbers) Sum += Numbers(i) Next i Return sum; End Function可変長引数の参考文献
オブション引数
呼び出し時に省略可能な引数。
- Java: (たぶん)言語仕様として持っていない。
- Java 8 から導入された
Optional
型は、全く違う概念なので混同しないこと。- VB:
(Optional 変数名 As データ型 = 既定値)
とする
- 呼び出し時に省略された場合、既定値が渡されたものとみなされる。
- なので既定値は必ず指定しておく必要がある。
- Optionalを指定した引数移行のすべての引数は、Optionalでなければならない(省略できない引数を全て書いた後、Optional引数を書く)
- Optional引数を複数設けること自体はOK。
OptionalArguments.vbPublic Shared Function Calc(Num1 As Integer, Num2 As Integer, Optional CalcMethod As Integer = 0) If CalcMethod = 0 Then Return Num1 + Num2 ElseIf CalcMethod = 1 Then Return Num1 - Num2 ElseIf CalcMethod = 2 Then Return Num1 * Num2 ElseIf CalcMethod = 3 Then Return Num1 / Num2 Else Return 0 End If End Functionこの例では、
Calc(5, 10)
のように呼び出した場合、CalcMethod = 0
のパターン(つまり足し算)が実行される。返り値として複数の値を受け取る
- Java: クラスにまとめて、そのオブジェクトを返すしかない。
ReturnMultiValue.javapublic static Result getResult(int a, int b) { Result result = new Result(); result.setSum(a + b); result.setDiff(a - b); result.setProduct(a * b); result.setQuotient((double) a / b); Return result; }Result.javapublic Class Result { int Sum; int Diff; int Product; double Quotient; // getter / setter }
- VB: タプルを利用して複数の値を返すことができる
- タプル:その場で複数の変数を1つにまとめたもの
- 臨時のクラスを作る、というイメージだと分かりやすいだろうか
Tuple.vbPublic Sub Main() ' タプルを名前付きで宣言 Dim Result As (Sum As Integer, Diff As Integer, Product As Integer, Quotient As Double) Result = GetResult(5, 10) ' タプルに入った値を利用 Debug.WriteLine(Result.Sum) Debug.WriteLine(Result.Diff) Debug.WriteLine(Result.Product) Debug.WriteLine(Result.Quotient) End Sub ' タプルを返すFunctionプロシージャー Public Shared Function GetResult(a As Integer, b As Integer) As (Integer, Integer, Integer, Double) Return (a + b, a - b, a * b, a / c) End Functionエントリポイント
プログラムが起動されたときに、最初に実行されるメソッド。
Javaはmainと名の付くメソッドが必ずエントリポイントになるが、VBではそうとは限らない。Windows Formsプロジェクトを作成すると、最初に作成したフォームがエントリポイントになる。これを変更する方法については、JavaのmainメソッドをVB.NETで作成してみる! | ライズウィルスタッフブログが詳しい。
クラス
構成
- Javaクラス
public class Main{ }
- フィールド
- メソッド
getter
/setter
メソッド※JavaBeansの形式に従った例。
JavaClass.javapublic class JavaClass { // フィールド(オブジェクトの状態/性質を示すもの) private int field; // メソッド(オブジェクトの動作・振る舞いを示すもの) public void method(){ // ... } // メソッド > getter(カプセル化されているprivateフィールドの読み取り機能を提供) public int getField() { return field; } // メソッド > setter(カプセル化されているprivateフィールドへの書き込み機能を提供) public void setField(int value) { this.field = value; } }
- VBクラス
Public Class Main ... End Class
- フィールド(メンバ変数)
- プロパティとの区別のために、
_
を接頭辞として付ける場合がある- プロパティ
Get
プロシージャーSet
プロシージャー- プロシージャ(メソッド)
- イベント
VBClass.vbPublic Class VBClass ' フィールド(メンバー変数) Dim _field As Integer ' プロパティ Property field() As Integer Get Return _field End Get Set(ByVal value As Integer) _field = value End Set End Property ' プロシージャー Public Sub Procedure() ' ... End Sub End Classプロパティについてもっと詳しく
基本
プロパティは、Javaでいうところのgetter/setterメソッドをまとめたもの(Getプロシージャ・Setプロシージャのうち片方だけを実装することもできる)。
Javaと異なるのは、プロパティは当該クラスの外からはフィールドのように扱われるという点である。たとえば、上記サンプルコード
JavaClass.java
の プライベートフィールドfield
に他のクラスからアクセスするときには、次のようなコードを書く必要がある。AccessToField.javapublic class Main { public static void main(String[] args) { JavaClass jc = new JavaClass(); // 以下2行はコンパイルエラーになる int num = jc.field; jc.field = 100; // 代わりに、こう書く int num = jc.getField(); jc.setField(100); } }このように、
オブジェクト変数名.フィールド名
ではアクセスが拒否されるので、代わりにgetterメソッドの返り値としてフィールドの内容を受け取ったり、setterメソッドに値を引数として渡すことでフィールドの内容を書き換えるというやり方になる。これと同じような動きをVBで書くと、こうなる。
AccessToField.vbPublic Class Main Public Shared Sub Main Dim vbc As New VBClass() Dim num As Integer = vbc.field 'Get呼び出し vbc.field = 100 'Set呼び出し End Sub End Classプロパティ名をフィールドのように書くことで、そのプロパティに定義されたGet/Setプロシージャーが暗黙的に呼び出される。
自動実装プロパティ
なお、単に値を返す/書き込むだけのプロパティであれば、自動実装プロパティを使うことでコードを簡略化できる。
AutoImplProperty.vbPublic Class AutoImplProperty Public Property Name As String Public Property Owner As String = "DefaultName" Public Property Items As New List(Of String) From {"M", "T", "W"} Public Property ID As New Guid() End Class(自動実装プロパティ - Visual Basic | Microsoft Docs より)
このとき、プロパティ名に
_
を付けた隠しPrivateフィールド(バッキング フィールド)が自動的に作成される。上記の例では、_Name
,_Owner
,_Items
,_ID
というバッキングフィールドが作成される(従って、自分でこれらと同じ名前のフィールドを宣言するとコンパイルエラーになる)プロパティ:フィールド = 1:n もOK
また、プロパティはフィールドと1対1で対応している必要はない。言い換えると、複数のフィールドから値を拾ってきて、連結して1つのフィールドのように扱うこともできる。また、1つのまとまった値を受け取り、実際には2つ以上のフィールドに分割して格納する、ということもできる。(もちろんそれに見合ったGet/Setプロシージャを定義しておく必要はある)。
Microsoft Docsにわかりやすい例があったので、引用する(クラス内のメンバであることが分かりやすいよう、Public Class
~End Class
を付加している)。次のプロパティは、フル ネームを 2 つの構成要素名 (名と姓) として格納します。 呼び出し元のコードが fullName を読み取ると、Get プロシージャが 2 つの構成要素名を結合し、フル ネームを返します。 呼び出し元のコードが新しいフル ネームを割り当てると、Set プロシージャがそれを 2 つの構成要素名に分割することを試みます。 スペースが見つからない場合は、すべてが名として格納されます。.
Property プロシージャ - Visual Basic | Microsoft DocsCombinedProperty.vbPublic Class CombinedProperty Dim firstName, lastName As String Property fullName() As String Get If lastName = "" Then Return firstName Else Return firstName & " " & lastName End If End Get Set(ByVal Value As String) Dim space As Integer = Value.IndexOf(" ") If space < 0 Then firstName = Value lastName = "" Else firstName = Value.Substring(0, space) lastName = Value.Substring(space + 1) End If End Set End Property End Class呼び出し側:
CallProperty.vbfullName = "MyFirstName MyLastName" MsgBox(fullName)その他、プロパティとメンバ変数の違いについては以下のページも参照。