20200225のJavaに関する記事は13件です。

Hinemosについて

今回は統合運用管理のOSS Hinemosについて
調査してきました。

HinemosのWebサイトを参照させていただきました。

Hinemosとは

統合運用管理ソフトウェアで下記の機能が行えるソフトウェアです。
・ログの収集、蓄積
・見える化・分析
・対応フローの自動化
などが可能な統合管理ソフトウェアで、自社サーバを管理されている方なども非常にありがたいOSSです。

HinemosはJavaで開発されているOSSで、
ライセンスはGNU General Public Licenseです。

Hinemosの強み あらゆる環境に対応

物理環境だけでなく、仮想化やクラウドなどにも対応しており、
マルチプラットフォーム対応です。
また、収集、監視、自動化などといった多機能なため
極めていけば他のOSSとの連携もかなりの相乗効果が期待できます。

Hinemosの導入事例

下記URLをご覧いただくと分かる通り、
様々な業種にご利用されております。
Hinemos導入事例
金融や自治体などにも導入されており、信頼性が高く評価されていることが分かります。

Hinemosのダウンロード先

・HinemosのGitHub
https://github.com/hinemos/hinemos

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

「ヤジが飛んでくるマインクラフト」DeepLearningで適当テキスト生成 ~modで動かす~

DeepLearningの力を借りて、マイクラのプレイ中、ゲームに関係のある文章を読み上げてくれるソフトを作った。

↓こんなやつ
でもミニ.gif

実際に遊んでいる動画

1つの記事にまとめるのが困難なため、いくつかの記事に分けます。
ここでは、アプリケーション部分について説明します。

↓他の記事

やりたいこと

マインクラフトで、近くにゾンビがいるか判定。
ゾンビがいたら、ゾンビに関連する文章を表示。

(文章そのものを用意するところは別の記事へ)

マインクラフトmod

マインクラフトは有志の方が制作した、modというものがある。
mod を使えば、かなり自由にゲームを改造することができる。

MCreator を使えば、すぐにmod制作が始められる。
簡単な変更なら、コードすら書く必要がない。

Python プログラムを組み込みたい

マインクラフト mod は Java で書かれている。

  • Java あまり分からない。
  • DeepLearningのモデルも動かしたいので、Python が使いたい。

Raspberry Jam Mod(mcpi)

Pythonからマインクラフトを一部操作できる。
いろんなことができる。
しかし、ゲーム情報を取得する部分は微妙。

Python と Java で通信

mcpiのコードを見てみる。
Socket通信でやりとりしているらしい。
ポートを指定してごにょごにょするらしい。

近くにゾンビがいるかどうか調べる

ようやく、modの実装。
MCreator1.9.1 を使用した。

MCreator で新しいワークスペースを作ると mod の雛形が作成される。

  • GUIで、新しいコマンドを作れる。空のコマンドを作成。

    • hogehogeCommandExecuted みたいなやつの、executeProcedure関数に書く。
  • やりたいことを別の関数に詰め込む。

    • Socketを準備
    • 継続して、データを取得・送信・受信
  • コマンド実行時に、別のプロセスで、作った関数を実行するようにする。

ゲーム内情報取得

Minecraft mc = Minecraft.getMinecraft()
WorldClient world = mc.world;
List<Entity> entities = world.getEntities(Entity.class, (entity)->!entity.isInvisible());

これで、ワールド内で透明でない敵mobや動物mobが取得できる。

Entity player = world.getEntityByID(mc.player.getEntityId());

そして、プレイヤーのインスタンスもとる。

String minecraftData;
for (Entity e: entities) {
    if (e.getDistance(player) < 8.0f) {
        minecraftData += e.getName() + ",";
    }
}

getDistanceで Entity 同士の距離が分かる。
近くにいる Entity の名前をgetNameで取得して、送信用の文字列に加えている。

表示

マインクラフト内のチャットに文字を出す。

MinecraftServer mcserv;
mcserv.getPlayerList().sendMessage(new TextComponentString("hogehoge"));

参考になりそうなサイト

mod で気をつけること

バージョンによって少しずつ、ライブラリの仕様が異なる。
ライブラリのソースは、MCreatorからでも見られる。分かる人は直接読んでみてもいいと思う。

文字列を用意する。

あらかじめ、どのオブジェクトに関係のある文か分けてあるので、mod からのデータを元にランダムに選ぶ。
その文章の先頭単語を生成モデルに入れて、文を生成してみた。
詳しくは別記事参照。

おまけ

表示するだけでは、味気ない。
ゆっくりに喋らせてみた。
簡単に、こんな感じでやった(windows)。

subprocess.call("start C:\hoge\softalk\SofTalk.exe /R: /W: "+"読ませたい文章", shell=True)

まとめ

マインクラフトのmodは有名なので、解説記事が充実しているかと思ったが、そうでもなかった。

MCreator を使わない環境構築が面倒で、出来ていない。
ガチガチにコーディングしようと思うと不便な気がするので、どうにかしたい。

マインクラフトはかなり可能性を秘めているので、みんなもやってみてほしい。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

java シェルソート

java シェルソート

今回はシェルソートについてコードを書いていく。
※自分のアウトプット用の記事です。間違いなどがあったら指摘してください。

ShellSort.java
public class ShellSort {
    public static void sort(int[] array) {
        int h;

        for(h=1;h<array.length/9;h=h*3+1) {

        }

        for(;h>0;h/=3) {
            for(int i=h;i<array.length;i++) {
                int j=i;
                while(j>=h && array[j-h]>array[j]) {
                    int temp = array[j];
                    array[j] = array[j-h];
                    array[j-h] = temp;
                    j -= h;
                }
            }
        }
    }
    public static void main(String args[]) {
        int[] array = {3,2,4,5,1};
        sort(array);
        for(int i=0;i<array.length;i++) {
            System.out.print(array[i]);
        }
    }
}

次回はクイックソートを試してみようと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ローカル環境で、Go、C#、Java、Pythonそれぞれで簡易サーバを実装して、クラウドサービスのWebhookの通知を受ける

1. やること

ローカル環境のWindows, Mac, Linuxなどの上で、
Go、C#、Java、Pythonのいずれかの言語で簡易サーバを作ります。
作ったローカル環境の簡易サーバで、
クラウドベースの各種チャットサービスやSNSなどのリアルタイムの通知をWebhookで受けます。

2. 必要なもの

インターネットにつながるWindows、Mac、Linuxなどが必要です。
中から外に繋がればいいので、Webhook用のpublicなURL(外からアクセスできるhttpsサーバなど)は必要ありません
インターネット上のWebサイトが見れるような環境であればOKです
ngrok(後述)とプログラミング言語を利用するので、それらをサポートしている環境である必要はあります。

3. ngrokの準備と起動

かなり、ざっくりな説明をすると、
ngrokは、インターネットに抜けられるローカルの環境(インターネット上のWebサイトが見れるような環境)で、
public URLへのリクエストを受けられるトンネリングサービスです。
TCPのトンネリングもできますが、今回はhttpのトンネリングに関してのみ触れます。
あえて日本語で読むと、「エングロック」になります。

こちらが公式サイトです:
https://ngrok.com/

無償版、有償版があります。
無償版では、1分間当たり40コネクション(40リクエストではありません)までですが、
ちょっとしたテストをする分には、充分だと思います。
有償版ではプランによって、できることが増えていきます。

3.1. ngrokのダウンロード

公式サイトの[DOWNLOAD]ページからダウンロードできます。

https://ngrok.com/download

ダウンロードしたら、適当なディレクトリに解凍しましょう。

ngrokのアカウントを作らずに動作させた場合は、アプリ起動ごとに8時間のみ動作します。
起動しなおせば、再度8時間利用できますが、無償アカウントを作っておいた方が制限も緩和されるのでよいと思います。
公式サイトの[SING UP]からアカウントの作成ができます。

3.2. ngrokのアカウントに接続する

ngrokのアカウントを作った場合は、今後、ngrokを起動する場合にアカウントと関連付くようにします。
<YOUR_AUTH_TOKEN>は、SING UP後やLOGIN後に取得できます。
LOGIN後のページトップに『Setup & Installation』が表示されて、
『(3) Connect your account』にまさに実行すべきコマンドがそのまま書かれています。

Windows
> .\ngrok authtoken <YOUR_AUTH_TOKEN>
Mac/Linux
$ ./ngrok authtoken <YOUR_AUTH_TOKEN>

このコマンドを実行すると、各OSのユーザのホームディレクトリ配下の以下の場所に(Ver 2.xの場合)、
{userhome}/.ngrok2/ngrok.yml
というファイルが出来上がって、そこに上記のアカウントのトークン情報などが保存されます。
ngrok.ymlには、その他さまざま設定を書くこともできますが、説明は省略します。
--configオプションで、設定ファイルのパスも指定できるので、例えば、ngrokをdockerコンテナで実行する場合に、
ホスト側のディレクトリに設定ファイル置いて、マウントさせて設定参照などもできます。

3.3. ngrokを起動する

Webhook用のpublicなURLは、ngrok側が準備してくれます。
Webhook用にTLSを利用しない、httpを使うのは、通常はおろかな行為なので、httpsだけ準備されるようにオプションを指定(--bind-tls=true)します。
以下コマンドの、8080は、ローカル環境のサーバのポート番号です。使っていない適切なポート番号を指定します。
この時点では、まだローカル側のサーバは作っていませんが、空いている適切なポートを指定しましょう。

Windows
> .\ngrok http 8080 --bind-tls=true
Mac/Linux
$ ./ngrok http 8080 --bind-tls=true

うまく行くと、以下のような出力が得られるはずです。
{random-id}の部分は、実行するたびに変わります(有償版では、この部分を指定することもできます)。
Regionも指定できますが、今回はデフォルトでよいと思います。

出力例
ngrok by @inconshreveable                                                     (Ctrl+C to quit)

Session Status                online
Account                       Your Name (Plan: Free)
Version                       2.x.yz
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    https://{random-id}.ngrok.io -> http://localhost:8080

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00

3.4. ここまでの手順でngrokがやってくれること

Forwarding https://{random-id}.ngrok.io -> http://localhost:8080という出力が示すように、
ngrokサービスが、publicなURLであるhttps://{random-id}.ngrok.ioを準備してくれています。
このURLへの要求は、ローカル環境(ngrokコマンドを実行したマシン)のhttp://localhost:8080にフォワードされます。

つまり、ローカルマシン上では、http://localhost:8080(http://127.0.0.1:8080)へのリクエストを受けられるようにアプリを実装すればよいです。
有償版ではプランによって、ローカルのhttpsサーバ(ローカル側がTLSあり)にフォワードすることもできますが、今回は、ローカル側はTLSなしのhttpサーバとします。

ざっくり図解すると、今回のオプション指定では、以下のような接続になっています。
矢印の方向は接続開始時の要求の方向を示しています。リクエストとレスポンスを処理するので、データのやりとりの観点では双方向です。

Ngrok.png

ローカルにあるngrokのアプリが、クラウドにあるngrokサービスとセキュアに常時接続しています。
ngrokのpublicなURLにリクエストがあると、この常時接続を通じて、ローカル側のngrokのアプリにリクエストが通知されて、
ローカル側のngrokのアプリが、ローカル側のサーバにリクエストを出します。
ngrokが準備したPublicなURLがhttpsの場合は、ここのTLSのサーバ証明書はngrok側のものになります。
この証明書チェーンは、標準的な環境では信頼済みのものであるので、これが非常に便利な場合もあります。

ngrokサービス提供元を信頼するという前提の下では、通信経路は暗号化されてTLSのレベルでデータが守られるということになると思います。

3.5. Web Interfaceも便利

Web Interface http://127.0.0.1:4040と出力されていると思いますが、テストではこれは便利に使えます。
(オプションでWeb Interfaceを無効にすることもできます。)

http://127.0.0.1:4040
にアクセスすることで、ngrokを経由した通信内容を閲覧したりできます。
例えば、httpのリクエストとレスポンスのヘッダやBodyの中身を調べたりすることができます。

また、[Replay]機能が非常に便利で、ngrok経由で過去に行われたhttpなどのリクエストを、
再度ローカルのサーバに好きなタイミングで送信することができます。
リクエストを編集して送信することもできます。
テストでは結構便利で、Webhookの実際の通知を再度発生させることなく、以前の通知内容をちょっと変えて試すということもできます。
(本格的なテストを行うときは、ngrokで本機能を使うのではなく、より高度なテストの自動化をする場合が多いと思います。)

Ngrok_Web_Interface.png

3.6. APIもあります

Web Interfaceを有効にしているとAPIも使えます。

APIの詳細はこちらのページ(https://ngrok.com/docs#client-api)に記載されています。

ngrokサービスが割り当ててくれるpublicなURLは、無償版ではランダムになりますが、
APIで何を割り当ててもらったかを取得することもできます。

Web Interfaceの
http://127.0.0.1:4040/api/tunnelsに、HTTP GETのリクエスト投げると、レスポンスで各種情報が得られます。
リクエスト時には、AcceptContent-Typeを、application/jsonにしておくと、JSON形式でレスポンス返ってきます。

例えば、以下のような感じです。
metricsも興味深いですが、今回は中身省略して記載しています。

/api/tunnels
{
    "tunnels": [
        {
            "name": "command_line",
            "uri": "/api/tunnels/command_line",
            "public_url": "https://{random-id}.ngrok.io",
            "proto": "https",
            "config": {
                "addr": "http://localhost:8080",
                "inspect": true
            },
            "metrics": {
            }
        }
    ],
    "uri": "/api/tunnels"
}

今回はngrok起動コマンドで、明示的にhttpsのみ指定したので、"tunnels"配列には、1つのオブジェクトのみ含まれます。
そのオブジェクトの"public_url"から、ngrok側が割り当てたpublicなURLが取得できます。
"config"オブジェクトの"addr"からは、フォワード先のローカル側のURLが取得できます。

また、先ほどWeb Interfaceで説明したリクエストやレスポンスのヘッダやBodyの中身の時系列での情報取得や、
Replayを行うAPIもあります。

4. ここまでで、もうWebhookの通知は受けられます

ngrokサービスが準備してくれた、public URLをWebhookの通知先として、各種チャットサービスやSNSなどのAPIサービス側に登録すれば、実際に動作するはずです。
この時点ではローカル側にまだサーバーがないので、正常なレスポンスを返すことができませんが、
Web Interface ( http://127.0.0.1:4040 )から、Webhookで通知されたリクエストのヘッダやBodyの中身は確認できます。

Forwarding https://{random-id}.ngrok.io -> http://localhost:8080のように出力されている場合は、
https://{random-id}.ngrok.io/webhook
などを、Webhookの通知先のURLとして登録します。
{random-id}の部分は、ngrokコマンドを実行した環境によって、また無償版では(有償版で指定していない場合も)、起動ごとに変わります。
後ろにくっつけたパス部分の、/webhookは好きなパスに指定できます。
/とかでも良いですが、この後のコードでは、https://{random-id}.ngrok.io/webhookのように、パスは/webhookを指定したものとして記載します。

Webhookの通知先の登録方法は利用するクラウドサービスなどによって異なります。
開発者用のサイトから登録できるものや、APIで登録する場合などあります。
試してみたいサービスごとに登録方法は確認する必要があります。

サービスによっては、登録作業を行った瞬間に、Webhookの通知先にリクエストを出して、
適切なレスポンスを返さないと、登録に失敗する仕組みのものもあります。
こちらの場合でも、登録時のリクエスト内容は、上記のWeb Interfaceで確認できます。

また、ここで、Webブラウザなどで、同じマシンからでも、別のマシンからでも、
https://{random-id}.ngrok.io/webhookにアクセスすると、
ngrokコマンドを実行しているコンソールや、Web Interfaceにも出力があるはずです。
HTTP GET以外でもいろいろ試してみたい場合は、Postman などを使って、とりあえず、動作を見ることはできると思います。

5. 各種言語で簡易サーバを実装する

今のままでは、ngrokがローカルにフォワードする先のサーバがないので、簡易サーバを作っていきます。
httpのリクエストに対して、どんなレスポンスを返すべきかは、サービスごとにことなるので、
今回は、とりあえず、200 OKで、Bodyは以下のようなJSONを固定で返すことにします。
サービスによっては、204 No Contentで、Bodyなしで返せばよいものもあります。

とりあえず、レスポンスBodyに入れる内容(実際は利用するサービスによって適切なものを返す必要あり):

今回の例で固定で返すレスポンスBody
{
  "status" : "OK"
}

この後、例として記載するいずれかのコードを実行した上で、ngrokを実行して、
ngrokが準備したhttpsのURLを元にしたURL(https://{random-id}.ngrok.io/webhookとか)を、
対象のクラウドサービス側にWebhook通知先として登録すると動作します。
例では、ngrokが準備したURLに、"/webhook"のパスが追加されている前提のコードになっています
例では、サービスからの通知されたリクエストのBodyを表示して、固定のレスポンスを返しているだけですが、
利用するサービスに応じて、処理を少し追加すると、いろいろできると思います。

今回は、さくっと例を記載したいだけなので、処理に成功したかどうかのチェック等は省略しています。
煩雑になりすぎないように、必要最小限に近いくらいのコードになるようにしていますが、実際のアプリでは各種チェックが必要になります。

また、Webhookは、クラウドサービスの場合は、publicなURLで受ける場合が多いので、
偽装した通知が送られるような場合も想定しておく必要があると思いますが、その辺りの対策も今回の実装例には盛り込んではいません。

関連してですが、(いろんな意見あると思いますが)、個人的には、偽装通知する人のヒントになるような、
404 Not Foundとか405 Method Not Allowedとかも返すべきでないと思っていますが、その辺も今回の実装例には盛り込んでいません。
不正な通知に対しては、「204 No Contentで成功で返す」、
「レスポンス自体返さず相手はレスポンス待ち状態にする(TCPのコネクションは切断しない)」、
「レスポンスは返さず、TCPのコネクションを切断する」などの対処があると思います。
ただし、コネクションを切断しないパターンは、
サーバ側の残りの接続数やスレッドプール数に悪影響がでやすい(リソースを枯渇させる攻撃が考えられる)ので、
一般的には実装が難しいです(TCP/Socketレベルで実装考えないといけなくなると思います)。

5.1. Goでの実装の例

標準の、net/httpパッケージを利用した例です。
※ 説明用にコメントは多めに書いています。

go1.13 + Windows 10 Pro 64bitで動作確認しています。

webhook_listener.go
package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

// Webhookに通知が来た時に呼ばれるハンドラ。
func handleWebhook(w http.ResponseWriter, r *http.Request) {

    // Webhook通知元の仕様にもよるが、HTTPのPOSTかGETかで通知が来る前提にして、
    // それ以外は、"204 No Content"を返す。
    if r.Method != http.MethodPost && r.Method != http.MethodGet {
        w.WriteHeader(http.StatusNoContent)
        return
    }

    // Bodyの内容を読み込んで表示するだけ。
    body, _ := ioutil.ReadAll(r.Body)
    fmt.Println("ReceivedData:", string(body))

    ////////////////////////////////////////////////////////////////
    // 以下、レスポンスで何を返すべきかは通知元のサービス側の仕様にもよる。

    // "204 No Content"を返せばいい場合は、以下にコメントアウトした1行だけでBody出力不要。
    // w.WriteHeader(http.StatusNoContent)

    // レスポンスヘッダで、Content-Type: application/jsonにする。
    w.Header().Set("Content-Type", "application/json")

    // レスポンスのBodyは決め打ち。
    fmt.Fprint(w, "{\"status\" : \"OK\"}")
}

func main() {

    // ローカルサーバの"/webhook"にリクエストが来た時に呼ばれるハンドラを登録。
    http.HandleFunc("/webhook", handleWebhook)

    // ローカルの8080番ポート(ngrok起動時のオプションで指定した番号)で待ち受け開始。
    // ngrokが同じローカルマシンで動いているので、"127.0.0.1"だけで待ち受ければよい。
    // (外部の環境からリクエストを受ける必要がない)
    http.ListenAndServe("127.0.0.1:8080", nil)
}

5.2. C#での実装の例

.NET Core 2.0以降や、.NET Frameworkなどで利用できるSystem.Net.HttpListenerを利用した例です。
※ 説明用にコメントは多めに書いています。

.NET Core 2.0 + Windows 10 Pro 64bitで動作確認しています。

WebhookListener.cs
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace WebhookListener
{
    class Program
    {
        static void Main(string[] args)
        {
            // System.Net.HttpListenerを利用してサーバを実装します。
            using (var listener = new HttpListener())
            {
                // ローカルの8080番ポート(ngrok起動時のオプションで指定した番号)で待ち受け開始。
                // ngrokが同じローカルマシンで動いているので、"127.0.0.1"だけで待ち受ければよい。
                // (外部の環境からリクエストを受ける必要がない)
                // また、"/webhook"のパスも入れておく。Prefix指定時は、"/"で終わるようにしておく必要がある。
                listener.Prefixes.Add("http://127.0.0.1:8080/webhook/");

                // HttpListenerの待ち受けを開始します。
                listener.Start();

                // スレッドプール上で待ち受けるようにする。
                // 今回は1スレッドだが、例えばループで64回Task作成すれば、64スレッドで待ち受けるようになる。
                Task.Run(
                    async () =>
                    {
                        // HttpListenerが待ち受け中はループする。
                        while(listener.IsListening)
                        {
                            ////////////////////////////////////////////////////////////////
                            // このサンプルの実装では、whileブロック内で例外が発生すると後続の待ち受けも中断されます。
                            // 実際には、適切に例外を処理する必要があります。
                            // どの例外をcatchすべきかは、whileブロック内での処理内容にもよります。
                            // catchしすぎると、意図せずループが続く場合もあるので注意が必要です。
                            // 基本的には、例外が発生しても待ち受けを継続したいような場合の例外は、whileブロックの中、
                            // 待ち受けを継続しても意味がないような例外は、whileブロックの外側で受けるように実装します。

                            // 先ほど登録したアドレス、ポート、パスに合致するリクエストが来ると、処理用のContextが取得できる。
                            var context = await listener.GetContextAsync();

                            // リクエストとレスポンス処理用のインスタンス取得。
                            var request  = context.Request;
                            var response = context.Response;

                            try
                            {
                                if (request.HttpMethod != "POST" && request.HttpMethod != "GET")
                                {
                                    // Webhook通知元の仕様にもよるが、HTTPのPOSTかGETかで通知が来る前提にして、
                                    // それ以外は、"204 No Content"を返す。
                                    response.StatusCode = 204;
                                }
                                else
                                {
                                    // Bodyの内容を読み込んで表示するだけ。
                                    if (request.HasEntityBody)
                                    {
                                        using (var reader = new StreamReader(request.InputStream, request.ContentEncoding))
                                        {
                                            Console.WriteLine("RequestData: {0}", reader.ReadToEnd());
                                        }
                                    }

                                    ////////////////////////////////////////////////////////////////
                                    // 以下、レスポンスで何を返すべきかは通知元のサービス側の仕様にもよる。

                                    // "204 No Content"を返せばいい場合は、以下にコメントアウトした1行だけでBody出力不要。
                                    // response.StatusCode = 204;

                                    // レスポンスヘッダで、Content-Type: application/jsonにする。
                                    response.ContentType = "application/json";

                                    // レスポンスのBodyは決め打ちで書き込む。
                                    using (var writer = new StreamWriter(response.OutputStream))
                                    {
                                        writer.Write("{\"status\" : \"OK\"}");
                                    }
                                }
                            }
                            finally
                            {
                                // ResponseはClose()を呼ぶ必要があります。
                                response.Close();
                            }
                        }
                    });

                // 何かキーを押したら終了させる。
                Console.WriteLine("終了するには何かキーを押してください。");
                Console.ReadKey(false);
            }
        }
    }
}

5.3. Javaでの実装の例

Java 1.6以降利用可能なcom.sun.net.httpserver.HttpServerを利用した例です。
パッケージは、com.sun.net配下になっていますが、OpenJDKでも利用できます。
※ 説明用にコメントは多めに書いています。

OpenJDK11(AdoptOpenJDK) + Windows 10 Pro 64bitで動作確認しています。

WebhookListener.java
package thrzn41.samples;

import java.io.IOException;
import java.net.InetSocketAddress;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

public class WebhookListener {

    /**
     * リクエストが来た時に処理するハンドラクラス。
     */
    private static class WebhookHandler implements HttpHandler {

        /**
         * HttpServer.createContext()で登録したパスにHTTPリクエストがあると、このメソッドが呼ばれる。
         */
        @Override
        public void handle(HttpExchange exchange) throws IOException {

            // Webhook通知元の仕様にもよるが、HTTPのPOSTかGETかで通知が来る前提にして、
            // それ以外は、"204 No Content"を返す。
            String method = exchange.getRequestMethod();

            if( !method.equals("POST") && !method.equals("GET") ) {
                exchange.sendResponseHeaders(204, -1);
                return;
            }

             // Bodyの内容を読み込んで表示するだけ。
            try(var input = exchange.getRequestBody()) {

                // 本来は、ちゃんとリクエストヘッダのエンコーディングを見た方がいいですが、
                // 今回は、"utf-8"である前提で変換しています。
                String body = new String(input.readAllBytes(), "utf-8");

                System.out.printf("RequestData: %s%n", body);
            }


            ////////////////////////////////////////////////////////////////
            // 以下、レスポンスで何を返すべきかは通知元のサービス側の仕様にもよる。

            // "204 No Content"を返せばいい場合は、以下にコメントアウトした1行だけでBody出力不要。
            // exchange.sendResponseHeaders(204, -1);

            // レスポンスのBodyは決め打ちで書き込む。
            var responseBytes = "{\"status\" : \"OK\"}".getBytes("utf-8");

            try(var output = exchange.getResponseBody()) {

                // レスポンスヘッダで、Content-Type: application/jsonにする。
                exchange.getResponseHeaders().set("Content-Type", "application/json");
                exchange.sendResponseHeaders(200, responseBytes.length);

                output.write(responseBytes);
            }
        }

    }

    public static void main(String[] args) {

        try {
            // ローカルの8080番ポート(ngrok起動時のオプションで指定した番号)で待ち受けます。
            // ngrokが同じローカルマシンで動いているので、"127.0.0.1"だけで待ち受ければよい。
            // (外部の環境からリクエストを受ける必要がない)
            var server = HttpServer.create(new InetSocketAddress("127.0.0.1", 8080), -1);

            // ローカルサーバの"/webhook"にリクエストが来た時に呼ばれるハンドラを登録。
            server.createContext("/webhook", new WebhookHandler());

            // 今回はデフォルトのExecutorを利用してHTTPリクエストを処理するように指定(null)。
            server.setExecutor(null);

            // HttpServerの待ち受けを開始します。
            server.start();

            System.out.println("終了するには何かキーを押してください。");
            System.in.read();

            // HttpServerの待ち受けを停止します。
            server.stop(0);

        } catch(IOException ioex) {
            ioex.printStackTrace();
        }
    }

}

5.4. Pythonでの実装の例

標準のhttp.serverモジュールを使っても実装できますが、今回はflaskを使っちゃいます。
※ 説明用にコメントは多めに書いています。

flask入ってなかったら、以下でインストール(pip使う場合の例)。

pip使ってflaskインストールする例
$ pip install flask

Python 3.6 + flask 1.1 + Windows 10 Pro 64bitで動作確認しています。

webhook_listener.py
from flask import Flask, request

# 起動時の自分の名前からFlaskのインスタンス作成。
app = Flask(__name__)

# Webhookに通知が来た時に呼ばれるハンドラ。
# 以下の指定では、"/webhook"に対するHTTP POST, GET, PUT, DELETEリクエストの場合に呼ばれます。
# パスが違うと"404 Not Found", リストにないメソッドの場合は、"405 Method Not Allowed"が返ります。
@app.route("/webhook", methods=["POST", "GET", "PUT", "DELETE"])
def handle_webhook():

    # Webhook通知元の仕様にもよるが、HTTPのPOSTかGETかで通知が来る前提にして、
    # それ以外は、"204 No Content"を返す。
    if request.method != 'POST' and request.method != 'GET':
        # レスポンスのBodyとStatus Codeをタプルで返します(make_response()でタプル指定するのと同じ)。
        return ('', 204)

    # Bodyの内容を読み込んで表示するだけ。
    print(request.get_data(as_text=True))


    # ==============================================================
    # 以下、レスポンスで何を返すべきかは通知元のサービス側の仕様にもよる。

    # "204 No Content"を返せばいい場合は、以下にコメントアウトした1行だけでBody出力不要。
    # return ('', 204)

    # レスポンスのBodyは決め打ち。
    # ディクショナリで返せば、jsonに変換(jsonify()を呼ぶのと同じ)して、Content-Typeヘッダも"application/json"にしてくれます。
    # より厳密には、make_response()が呼ばれて、その中でjsonify()が呼ばれて、その中で、Content-Typeが"application/json"に設定される。
    return { 'status' : 'OK' }


if __name__ == '__main__':

    # ローカルの8080番ポート(ngrok起動時のオプションで指定した番号)で待ち受け開始。
    # ngrokが同じローカルマシンで動いているので、"127.0.0.1"だけで待ち受ければよい。
    # (外部の環境からリクエストを受ける必要がない)
    app.run('127.0.0.1', 8080)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Java添加excelデータ検証

Excelでは、データ検証を利用してデータの入力に一定の制限条件を加えることができます。たとえば、データ検証の基本設定によって、セルは整数、小数、時間、日付などしか入力できなくなります。プルダウンメニューのオプションも作成できます。この文ではSpire.XLS for Javaを使用したデータ検証を紹介します。

import com.spire.xls.*;

public class ShapeAsImage {
    public static void main(String[] args) {
        // Workbookオブジェクトを作成
        Workbook workbook = new Workbook();

        //最初のシートを取得
        Worksheet sheet = workbook.getWorksheets().get(0);

        //セルB2にデジタル認証を設定します。3-6までの数だけ入力できます
        sheet.getCellRange("B1").setText("Input Number(3-6):");
        CellRange rangeNumber = sheet.getCellRange("B2");
        rangeNumber.getDataValidation().setCompareOperator(ValidationComparisonOperator.Between);
        rangeNumber.getDataValidation().setFormula1("3");
        rangeNumber.getDataValidation().setFormula2("6");
        rangeNumber.getDataValidation().setAllowType(CellDataType.Decimal);
        rangeNumber.getDataValidation().setErrorMessage("Please input correct number!");
        rangeNumber.getDataValidation().setShowError(true);
        rangeNumber.getCellStyle().setKnownColor(ExcelColors.Gray25Percent);

        //セルB 5に日付認証を設定します。1/1/2020から3/1/2020までの間の日付を入力するだけです
        sheet.getCellRange("B4").setText("Input Date:(1/1/2020 to 3/1/2020)");
        CellRange rangeDate = sheet.getCellRange("B5");
        rangeDate.getDataValidation().setAllowType(CellDataType.Date);
        rangeDate.getDataValidation().setCompareOperator(ValidationComparisonOperator.Between);
        rangeDate.getDataValidation().setFormula1("1/1/2020");
        rangeDate.getDataValidation().setFormula2("3/1/2020");
        rangeDate.getDataValidation().setErrorMessage("Please input correct date!");
        rangeDate.getDataValidation().setShowError(true);
        rangeDate.getDataValidation().setAlertStyle(AlertStyleType.Warning);
        rangeDate.getCellStyle().setKnownColor(ExcelColors.Gray25Percent);

        //セルB 8で文字長検証を設定します。5文字以内のテキストのみ入力できます
        sheet.getCellRange("B7").setText("Input Text:");
        CellRange rangeTextLength = sheet.getCellRange("B8");
        rangeTextLength.getDataValidation().setAllowType(CellDataType.TextLength);        rangeTextLength.getDataValidation().setCompareOperator(ValidationComparisonOperator.LessOrEqual);
        rangeTextLength.getDataValidation().setFormula1("5");
        rangeTextLength.getDataValidation().setErrorMessage("Enter a Valid String!");
        rangeTextLength.getDataValidation().setShowError(true);
        rangeTextLength.getDataValidation().setAlertStyle(AlertStyleType.Stop);
        rangeTextLength.getCellStyle().setKnownColor(ExcelColors.Gray25Percent);

        sheet.autoFitColumn(2);

        workbook.saveToFile("output/DataValidation.xlsx", ExcelVersion.Version2010);
    }
}

効果図:
DataValidation.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Java 基数の変換方法

10進数からn進数へ変換

int x = 11;
int baseNumber = 2;
String result = Integer.toString(x, baseNumber);
System.out.println(result); // 1011

n進数から10進数へ変換

String x = "1e"; // 1e = 16進数
int baseNumber = 10;
int result = Integer.parseInt(x, baseNumber);
System.out.println(result); // 30
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Javaのデフォルトエンコード設定をUTF-8にするための覚書

テキストエディタを変えたらデフォルト設定がS-JISからUTF-8に変わりました。
世間では(おそらく)UTF-8の方が標準ではないかと思ったので、これを機にJavaをUTF-8に合わせようと思い調べたことの備忘録です

方法

環境変数 _JAVA_OPTIONSにエンコードしたい文字種別を設定する。


-Dfile.encoding=MS932
-Dfile.encoding=UTF-8

Windowsならsetコマンドでこの設定が可能です。


set JAVA_OPTIONS=-Dfile.encoding=MS932
set _JAVA
OPTIONS=-Dfile.encoding=UTF-8

ただしこのsetコマンドは再起動すると消えてしまうので、半永久的に設定するなら環境変数に手動設定しておくのがよさそう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初心者から始めるJavaーTeraPadで書いたコードがエラーで動かない

はじめに

TeraPadで書いたコードを、コマンドプロンプトでコンパイルしたらエラーだらけになった。
他のテキストエディタで書いたらちゃんと動いたので、そのまま放置している。
備忘録としてここに残しておこうと思い、記事にする。

実行環境

Java11
 JDK(Java Development Kit)のみ、eclipseは導入していない
TeraPad
 有名な無料テキストエディタ。
 Windows10のメモ帳でも同様の現象が起きていた。
Windows10
 コマンドプロンプトでコードがちゃんと動くことを確認。

起きていた問題

 TeraPadで作ったjavaファイルをコンパイルするとき、エラーを吐いてclassファイルが生成されない。
 出力ファイル形式の指定ではUTF-8に設定していたはずだが、うまくいかない。

helloWorldのコンパイルから実行まで,Terapad版
C:Users>cd C:JavaSample
C:JavaSample>javac helloWorld.java

helloWorld.java:1: エラー: この文字(0xEF)は、エンコーディングwindows-31jにマップできません
?サソclass helloWorld
^
helloWorld.java:1: エラー: classinterfaceまたはenumがありません
?サソclass helloWorld
         ^
helloWorld.java:3: エラー: classinterfaceまたはenumがありません
        public static void main(String[] args)
                      ^
helloWorld.java:6: エラー: classinterfaceまたはenumがありません
        }
        ^
エラー4

 ネットで検索をかけたところ、エンコード設定をUTF-8と記述すればコンパイルできるとあったが、結果は以下の通り。

helloWorldのコンパイルから実行まで,Terapad2回目
C:Users>cd C:JavaSample
C:JavaSample>javac -encoding UTF-8 helloWorld.java
helloWorld.java:1: エラー: '\ufeff'は不正な文字です
?class helloWorld
^
helloWorld.java:1: エラー: classinterfaceまたはenumがありません
?class helloWorld
       ^
helloWorld.java:3: エラー: classinterfaceまたはenumがありません
        public static void main(String[] args)
                      ^
helloWorld.java:6: エラー: classinterfaceまたはenumがありません
        }
        ^
エラー4

現在(2020/2/25)

 テキストエディタをBracketsSublimeText3の両方入れて、それぞれでファイルを作ってみた。
結果、改善されて上手くコンパイルしてくれるようになった。
また、メモ帳で書いたコードでもちゃんと動くことを確認した。

helloWorldのコンパイルから実行まで,別テキストエディタの場合
C:Users>cd C:JavaSample
C:JavaSample>javac helloWorld.java
C:JavaSample>java helloWorld
Hello,World!

感想

 なぜTeraPadに限ってこのような現象が起きたか分からない。
 TeraPadの設定だが、PHPに関する書籍の指示に従って各種設定をして使っていた。
 「TeraPadのUTF-8化」のページで初期文字コード・保存文字コードをUTF-8Nに設定した。
 何度か読み返してみてもわからなかったし、ほかのテキストエディタなら問題がないので、現在は放置している。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Javaのプリミティブ型と参照型について

前書き

 プリミティブとラッパークラスについて、そしてその周辺の内容も含めて、自分なりにまとめた記事です。
 現在、Java Silverの資格取得に向けて学習中で、あくまでそのレベルで理解出来ていることなので、多少の厳密さや正確さを欠いている場合があります。ご了承下さい(間違っていたら、そっと教えてください)。

対象読者

・Javaの資格取ろうかなって思っている人
・プリミティブとか、ラッパークラスとかオートボクシングとか、ちょっと何言っているか分からないってなった人

キーワード

プリミティブ型、参照型、ラッパークラス、オートボクシング、アンボクシング

プリミティブ(型)とは?

[ざっくりした定義]
・Javaのデータ型の一つ
・Javaのいわゆる基本な型のことで、値型とも言う
・メモリのスタック領域に値が入っている

[種類]
全部で8種類あります。
表現できる値の範囲は、覚えなくてもいいかなと思います(なので途中で書くのやめました )。
ビット数は覚えてもいいかと思います、ビット数が大きいほど表現できる範囲は広いです1

データ型 表現できる値や範囲 ビット(bit) 具体例
boolean true, false 1
byte -128 ~ 127 の整数 8
char \u0000 ~ \uFFFF のUnicode文字列 16
short -32768 ~ 32767 の整数 16
int 整数 32
float 実数(単精度不動小数点数) 32 2f, 100F
long 整数 64 10l, 5L
double 実数(倍精度不動小数点数) 64

参照型とは?

[ざっくりした定義]
・Javaのデータ型の一つ
・Stringとか、配列とか、Listとかのこと
・メモリのピープ領域に変数の参照値が、スタック領域に参照値が指す値が入っている

最後の定義をもっと細かく書くと、newして生成したオブジェクト(≒インスタンス)はスタック領域に、そのオブジェクトへのポインタ(メモリ上のアドレス)は参照値としてピープ領域に代入される、らしい(参考4の、プリミティブ型と参照型より)。

プリミティブ型と参照型について、代入の際の挙動の違いは参考2がとても詳しいので、そちらをご覧ください
(今回の本題はそこではないので、先に進みます)

ラッパークラスとは?

[ざっくりした定義]
・参照型に分類される、プリミティブ型たちの進化系クラス ← 強そう
・それぞれのクラスに、便利なメソッドが用意されている
・プリミティブ型っぽく振る舞うけど、中身はnullの可能性がある(なので、ヌルポに注意)

プリミティブ型をラップしている(包んでいる)から、ラッパークラスなのでしょうね!中身はプリミティブ型という訳です。
こちらも、プリミティブ型に対応付ける形で表にしてみます(一部を除いて、プリミティブ型と同じ形をしていますね!)。

プリミティブ型 ラッパークラス
boolean Boolean
byte Byte
char Character
short Short
int Integer
float Float
long Long
double Double

 便利なメソッドと書きましたが、例えばIntegerなら、Integer.parseInt(String)で文字列をint型に変換、Integer.valueOf(int)でint型を文字列に変換するなど、色々用意されています(後者は、明示的にInteger型に変換する場合でも使います、詳しくは次章で)。

オートボクシング・アンボクシングとは?

ここまでの説明を踏まえて、定義を書くと

 オートボクシング:プリミティブ型からラッパークラスへの自動変換
 アンボクシング :ラッパークラスからプリミティブ型への自動変換2

です!スポーツのボクシングとは関係ないと思います、知らんけど3
プリミティブ型を自動でラップする( = 箱に入れる)からオートボクシング、その逆に箱から取り出すからアンボクシングなんだと思います。

実際のコードだと、こんな感じ(参考7より引用)。

// オートボクシング
int numInt = 10;
Integer numInteger = numInt;

// アンボクシング
Integer numInteger = new Integer(10);
int numInt =  numInteger;

オートボクシング・アンボクシングを図解すると、こんな感じ。

          オートボクシング
            ==>  
  [プリミティブ型]        [ラッパークラス]  
            <==
          アンボクシング

あ、ちなみにですが、上記で自動変換と書いたということは、明示的にオートボクシング、アンボクシングを行うこともできます(参考7より引用)。

// オートボクシング
int numInt = 10;
Integer numInteger = new Integer(numInt);
// または以下
Integer numInteger = Integer.valueOf(numInt);

// アンボクシング
Integer numInteger = new Integer(10);
int numInt =  numInteger.intValue();

執筆中

何か書くかもしれませんし、書かないかもしれません、未定です。

終わりに

最後まで読んで下さり、ありがとうございます!

おまけ

試験情報(参考1より)

科目:Java SE 8 Programmer I
試験番号:1Z0-8084
試験時間:150分
問題数:77問
合格ライン:65%

参考

本記事を書くにあたり、下記の書籍・サイトを参考にしました。この場を借りて、感謝申し上げます。
どの参考も、私の説明よりずっとずっと分かりやすいので、ご一読オススメします!

  1. 志賀澄人 (2019) 「徹底攻略 Java SE 8 Silver 問題集 [1Z0-808] 対応」 ㈱インプレス 発行
  2. 【Java】値(プリミティブ)型と参照(オブジェクト)型の違いをコードと図で解説《講義1日目》
  3. プリミティブ型【変数の型】(「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典)
  4. 図で理解するJavaの参照
  5. 【Java入門】Integerとラッパークラスの基礎の基礎をわかりやすく解説!
  6. ラッパークラスの種類
  7. 【Java】オートボクシング、アンボクシング

  1. 例えば、byteなら16ビットなので、|2^(16-1)|の範囲の整数を表現できます(符号で1バイト使うので乗数は1少ないです)。 

  2. オートアンボクシングではないんですね、不思議。 

  3. 語源的な意味では、関係あるかもですね . . . 。 

  4. 日本語での試験ってことなら、「1Z0-808 JPN」みたいです(試験の申込ページでは、そんな区分でした)。 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】エスケープシーケンス

エスケープシーケンス

りんご 
"みかん" 
メロン

みかんだけ " "(ダブルクオーテーション) で強調したいときはどのように記入すればよいでしょうか・・・?:thinking:

test.java
public class Main {
    public static void main(String[] args) {
        System.out.println("りんご");
        System.out.println(""みかん"");
        System.out.println("メロン");
    }
}

上記のようにみかんだけ " " をさらにつけてみるとコンパイルエラーとなってしまいました:weary:
このようなときに使用するのがエスケープシーケンスです:smile:
エスケープシーケンスをつかった下記のコードに修正してみると・・・

例.java
public class Main {
    public static void main(String[] args) {
        System.out.println("りんご");
        System.out.println("¥"みかん¥"");
        System.out.println("メロン");
    }
}
コンソール.
りんご 
"みかん" 
メロン

ちゃんと表示してくれました:laughing:

さっきはなぜエラーになってしまったのかというと
パソコンくんは " から " までを文字列として判断するのです。

つまり ""みかん"" だと
" から " まで文字が何も入ってないぞ??
みかんって書いてあるけど、これはなんだ??
また " から " まで文字が何も入ってないぞ??
・・・差し戻します。
ということになるのです:scream:

それを回避するために " の前に ¥ をつけて、これは文字列の " じゃないんだよ。
文字として表示してほしいための " なんだよ。
だから区別するために ¥" と記入するから文字として表示してね。
ってことです:smile:

なので表示してほしい記号の前に ¥ をつけると文字として表示されます。
一部ですが下記に記載しますね:smile:

表記 意味
¥" "(ダブルクオーテーション)
¥' '(シングルクォーテーション)
¥¥ ¥(円マーク)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】変数と型の種類

変数とは

:sunny: データを入れる箱のようなもの
:sunny: その箱には自由に名前をつけることができる
:sunny: 変数を使うためには、これから変数を使いますよーという宣言が必要

例.java
public class Main {
    public static void main(String[] args) {
        int number;
        number = 10;
        System.out.println(number);
    }
}

int number;
 → number という名前の箱を用意しましたー!

number = 10;
 → その number という箱に 10 をいれてくださーい!

System.out.println(number);
 → number の中身を出力してくださーい!

コンソール.
10

と表示されます。
もう少し中身を詳しく説明しますね:smile:

int number;
この int number; で変数の宣言をしています。
int は 型(またはデータ型) と呼ばれるものでデータの種類をあらわします。
number は 変数名 といって変数に自由に名前をつけることができます。

number は私が勝手に名前をつけた変数名だけで、例えば age や day などでも大丈夫です。
自由に名前をつけれるといっても多少のルールがあって

・int や public などすでにjavaに組み込まれている単語は使用してはいけない。
・基本的には小文字で始まる英単語の名詞を使用(ローマ字や漢字や数字で始まるものは推奨しない)
・1文字の変数名はさける
・複数の単語をつなげて使用する場合は2単語目の先頭を大文字にする(myAgeなど)

というのが主なルールでしょうか。
型については後ほど説明しますね:smile:

number = 10;
変数名number に 10 という値を入れていますが
変数に値や文字などを入れることを代入といいます。

余談ですが、この = がついている場合は左から読んだほうがわかりやすいです。
10 という値を number という変数名の箱に入れる。
みたいな。
学校では = は等しいという意味で習ったかと思いますが
プログラミングでは == が等しいの意味を表します。
== のときは右から読んでください:smile:

System.out.println(number);
()に入ってるのは変数名です。
この変数名に入っているものを呼び出します。
これを取得といいます。

変数の上書き

例.java
public class Main {
    public static void main(String[] args) {
        int number;
        number = 10;
        System.out.println(number);
        number = 20;
        System.out.println(number);
    }
}

上記のように 変数number に 10 を代入し
そのあと再度 変数number に 20 を代入しました。
どのように表示されるでしょうか?:thinking:

コンソール.
10
20

変数number に 20 が代入され上書きされてしました。
このようにすでに値が入っている変数に値を代入すると
古い値は消滅し、新しい値が上書きされます:smile:

変数の初期化

例.java
int number;
number = 10;

さきほど上記のように変数の宣言と変数の代入を2行にわたり記入していました。
もちろんこれはこれで問題ないのですが、これを1行にまとめて記入する方法があります。

変数の初期化.
型 変数名 = 代入するデータ;

とすることで1行にまとめて記入することができます。
ではさきほどのコードをまとめてみましょう:smile:

例.java
int number = 10;

このように変数の宣言と同時に値を代入することを変数の初期化といいます。

型の種類

整数

さきほど変数名の前に int という単語が表示されていたかと思います。
この int というのは簡単に言うと データの種類で整数型 を意味します。

int number;

というのは
変数名 number という箱に整数が入りますよー
ということなのです。

つまり、小数や文字はこの箱に入ることができません。
整数のみです。
小数や文字を代入したいときは別の型を使う必要があります。

小数や文字の型はあとで説明するとして
さきに整数の型を説明しますね。

int はデータの種類では整数とさきほどお伝えしました。
整数には違いないのですが整数だけでもいろいろと種類があるのです・・・:sweat_smile:

型名 格納可能な整数の範囲 消費メモリ
byte -128〜127 の整数 1バイト
short -32768〜32767 の整数 2バイト
int -2147483648〜2147483647 4バイト
long -9223372036854775808〜9223372036854775807 8バイト

テストの点数であれば0〜100点なので byte を使えば消費メモリが1バイトですみますよね:smile:
でも5教科の合計点・・・となれば short にすれば消費メモリが2バイトですみそうです。

でもそれだと消費メモリを気にして型名を毎回変えなければいけないの?:thinking: となってしまいます。

よほど大きな数字を扱わないかぎりは基本は int で問題ないです:smile:
昔のPCならいざ知らず、最近のPCはメモリを多く搭載してるので、そこまで厳密に使い分ける必要はないかと思います:smile:

ちなみに long を使うときは数字のあとに L もしくは l をつけます(10000L,10000l など)

小数

小数を扱う型にも2種類の型が存在します。
float と double です。
何が違うのか?と言えば消費メモリが違います。
格納可能な小数の範囲も違うのですが説明がちょっと面倒なので省きます:sweat_smile:
少し調べると出てくるかと思います:smile:

型名 消費メモリ 記入方法
float 4バイト 数字のあとに F もしくは f をつける
double 8バイト 数字のあとに D もしくは d をつけるが基本は省略してもよい

double は float よりは厳密な計算ができます。
厳密な・・・というのはどういうことなのかというとパソコンさんは数字しかわからないので小数点が理解できません。
そのため私達が計算するような小数の計算ではなくパソコンさんが理解できるように別の計算方法で小数を表しているのですが、その計算方法では近似値を表すため、どうしても少々誤差が生じてしまうのです。

とても小さな誤差なので通常はそれでも大丈夫なのですが、それが積み重なると大きな問題に発展しかねないので注意が必要です。

ちなみに普段は double を使用で問題ないです:smile:

真偽値

真偽値をあらわすには boolean という型を使います。
マルかバツか 本当か嘘か など二者択一のときに使用します。

文字(1文字のみ)

1文字のみ扱いたいときには char という型を使います。
全角・半角問わず1文字のみです。
使用するときは ' ' を使います(例:'山' '1' 'あ' など)
いままで文字は ""(ダブルクオーテーション) を使用していましたが
char を使用するときは ''(シングルクォーテーション)を使用します。

文字列

2文字以上扱いたいときは String を使用します。
文字は ""(ダブルクオーテーション)で囲みます。

定数

変数の上書き で説明したとおり、変数は上書きできてしまいます。
しかし上書きしてほしくない場合もあります。
そのときは 定数 を使用します。
定数を使用すれば、値を上書きされる心配がありません。

定数の宣言.
final 型 定数名 = 初期値;

なんだかややこしそう・・・と思ってしまいますが
作成してしまえば、全然ややこしくないです:smile:
ちなみに定数名はすべて大文字で記入する必要があります。

例.java
public class Main {
    public static void main(String[] args) {
        final int NUMBER = 10;
        System.out.println(NUMBER);
    }
}
コンソール.
10

変数の初期化の記入方法に似てると思いますが
一番最初に final をつけて 定数名をすべて大文字にするだけです:smile:
ちなみに定数を上書きしようとするとコンパイルエラーとなり上書きできません:smile:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】System.out.println()

System.out.println()

:sunny: () の中に文字や数字を入力したものが出力される
:sunny: 文字を出力したい場合は "" で文字を囲む

例.java
public class Main {
    public static void main(String[] args) {
        System.out.println("りんご");
    }
}
コンソール.
りんご

3行目に System.out.println("りんご"); と記入することで りんご と表示されました:smile:
りんご は文字なので "" で囲みます。
"" で囲むのを忘れるとエラーになりプログラムが実行されません:tired_face:

例.java
public class Main {
    public static void main(String[] args) {
        System.out.println(5);
    }
}
コンソール.
5

今度は数字の 5 を()に入力してコンソールへ出力してみました。
今回は数字なので "" で 5 を囲む必要がありません:smile:

ではこの 5 を出力するプログラムの下に以下のような命令文を記入します。
するとどのように表示されるのでしょうか・・・??:thinking:

例.java
public class Main {
    public static void main(String[] args) {
        System.out.println(5);
        System.out.println(5 + 2);
        System.out.println("5 + 2");
        System.out.println("5" + "2");
        System.out.println("りんご" + "ジュース");
    }
}
コンソール.
5
7
5 + 2
52
りんごジュース

System.out.println(5);
 → これはさきほどの説明どおり 5 を出力しただけの命令文です。

System.out.println(5 + 2);
 → これは 5+2 の結果を表示してくださいという命令文なので 5 と 2 を足した結果の 7 が表示されます

System.out.println("5 + 2");
 → 5+2 の結果の 7 が表示されるのでは??と思ってしまいますが、"" で囲っているため、これは文字なんだ!とパソコンが認識します。そのため 5 + 2 とそのまま表示されるのです。

System.out.println("5" + "2");
→ "5" という文字と "2" という文字を連結して 52 と表示されます。

System.out.println("りんご" + "ジュース");
 → "りんご" という文字と "ジュース" という文字を連結して りんごジュース と表示されます。

その他の計算

例.java
public class Main {
    public static void main(String[] args) {
        System.out.println(5 + 2);
        System.out.println(4 - 3);
        System.out.println(3 * 2);
        System.out.println(6 / 3);
        System.out.println(6 % 4);
    }
}
コンソール.
7
1
6
2
2

もちろん足し算の他にも計算できます:smile:
一部学校でならった記号と違うのでそこだけ注意です。

+ ・・・ 足し算
- ・・・ 引き算
* ・・・ 掛け算
/ ・・・ 割り算
% ・・・ 割り算の余り

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】基本的構造

Java の基本的構造

例.java
public class Main {
    public static void main(String[] args) {
        System.out.println("hello, world!");
    }
}

1行目の public class Main { 

から

5行目の } まで
クラスブロック といいます。

2行目の public static void main(String[] args) {

から

4行目の } まで
メソッドブロック といいます

3行目はパソコンに何をしてほしいかという命令文を書いていきます。
イメージとしては下の画像のような感じでしょうか。
スクリーンショット 2020-02-24 12.24.40.png

クラスブロックという箱のなかにメソッドブロックの箱と命令文の箱が入っている。
メソッドブロックの箱の中には命令文の箱が入っている。
いわゆるロシアのお人形さんのような入れ子式というものです:smile:

matryoshkas.png

しばらくはこの3行目の命令文の部分をアウトプットしていきたいと思います。
クラスブロックとメソッドブロックはいずれ・・・私の勉強が進んだらアウトプットしていきます:sweat_smile:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む