20210511のJavaに関する記事は12件です。

きょうのにっき

java…javaを…なんか…やらなきゃいけないんで…忘備録します… public static void main(String[] args) →謎フレーズ。  これを書くと色々使えるようになる。 クラス →謎。  クラスごとに目的があるらしい。その目的も謎。 フィールド →謎。  なんかクラスごとの掟を決めるらしい。怖い。 インスタンス化 →謎。  これをすると幽体が実体化するって説明あったけど真偽は不明。めっちゃ怖い。 メソッド →謎。  もうまじで謎。他クラスで使えるのがjavaのいいとこらしい。ちなみにぼくは使えない。 static →魔法の言葉。  これを頭に取り付けるだけでありとあらゆるクラスで使い回せる。バレるとぶちころがされるらしい。要はMDMA。 今日のところはこんなところで。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

多態性(ポリモーフィズム)とは

■ 多態性とは オブジェクトをあいまいに、ざっくりと捉えることで、ある処理を命令したらクラスが違っても同じように振舞ってくれる仕組み 例えばある人物が書いてある紙を、そのままただの「紙」として捉えるのか、肖像画という「絵」として捉えるのか、お金という「紙幣」として捉えるのか、その捉え方によって同じ「使う」という振る舞いでも内容変わってくる、というようなイメージ 曖昧で抽象的なほど利用方法は限定され、逆に具体的に捉えるほどに用途は増えていく 通常のインスタンス化では Athlete a = new Athlete(); という記述で Athlete クラスのオブジェクトを new するが、内容は Athlete 型の変数 a に、new してインスタンス化した Athlete オブジェクトを代入し、変数 a を使用するようになっている つまり Athlete オブジェクトであれば、そのオブジェクトを 「Athlete という性質」のものとして捉えることになるが、多態性という機能はこのオブジェクトの捉え方をよりざっくり(抽象的に)としたものにすることにより様々な機能が使えるようになるというもの Human a = new Athlete(); 本当は 「 Athlete という性質」のオブジェクトだが、あくまで 「 Human という性質」のもの として捉えて利用する Javaではextends や implememts を用いた継承の関係にあるクラス同士について、is-a の関係があると判断し、多態性を利用することができるようになる つまり Item a = new Athlete(); のような is-a の関係に乗っ取らない記述はそもそも継承すべきではないが、同じように多態性の利用もすべきではない ■ 多態性の性質 Human a = new Athlete(); 上記のこのインスタンス化は、new した Athlete オブジェクトを Human として捉えるということだが、そうすることによって本当は中身(オブジェクト)が Athlete であるが、 「Human の一種である何か」という、これまた曖昧な捉え方をJavaはするため、Athlete クラスでのみ定義されているメソッドが使えなくなる(正確に Athlete クラスと認識できていないため、Human として最低限出来ることしかできなくなる) 冒頭に書いた紙幣のイメージに照らし合わせると、紙幣を絵として捉えて使用しているために、本来紙幣が持つ「何かを手に入れるときに対価として支払う」という機能が使えない、ということになる 以下、例 public abstract class Human { public void greet() { System.out.println("人間です。"); } } public class Athlete extends Human { public void introduce() { System.out.println("アスリートです。"); } } Human h = new Athlete(); h.introduce(); Athlete クラスで定義した introduce メソッドは Human 型の変数 h に入れられたことで外部から明確に認識できなくなったため使用できない 「メソッド introduce() は型 Human で未定義です」とエラー この場合、Human は「箱の型」、Athlete は「中身の型」といえる 箱の型は今回のように Human クラスに指定すれば Human として捉え、例えば Human の前のインターフェース、Life に指定すれば Life として捉える、つまり様々な箱に入れ替えることで捉え方を変えることができる 階層が汎化すればするほど、そのオブジェクトを曖昧な捉え方をすることになる 中身の型は、仮にどの箱に入っていたとしてもJavaが外部から明確に認識できなくなるだけでその性質自体が変わることはない そのため、以下 public abstract class Human { public void greet() { System.out.println("人間です。"); } } public class Athlete extends Human { public void greet() { System.out.println("アスリートです。") public void main(String[] args) { Human h = new Athlete(); h.greet(); } この場合は、Athlete クラスと Human クラスの両方に同じ greet メソッドがあるため、Human 型の変数 h に入れてもメソッドが呼び出せるが、この時の処理結果は Human クラスで記述されている「人間です。」ではなく、Athlete クラスで記述されている「アスリートです。」が表示される つまり仕組みとしては 箱の型である Human クラスの greet メソッドが呼び出せるから実行が可能だが、実行できる場合には中身の型である Athlete クラスの本来のメソッドが呼び出されることになる つまり 箱の型:どのメソッドを「呼ぶことができるか」を決定 中身の型:メソッドが呼ばれた場合「どのように処理するか」を決定する ここで多態性の「曖昧に、ざっくり捉える」ということがメリットとなってくることがわかる 各サブクラスでメソッドのオーバーライドをしていれば、必ずサブクラスにも該当のメソッドが存在することになるため、 main メソッドで同じ命令(同じメソッドの呼び出し)を行っても、各サブクラスでオーバーライドしたそれぞれ異なる振る舞いが実行されることになる 呼び出す側は同一視し、呼び出される側は各々決められた動きを行う、という仕組み public interface Employee { public abstract void greet(); } public class EmployeeSales implements Employee { @Override public void greet() { System.out.println("こんにちは営業部。"); } } public class EmployeeManagement implements Employee { @Override public void greet() { System.out.println("こんにちは管理部。"); } } public class EmpMain { public static void main(String[] args) { Employee e1 = new EmployeeSales(); Employee e2 = new EmployeeManagement(); e1.greet(); e2.greet(); introduce(e1); introduce(e2); } static void introduce(Employee emp) { System.out.println("以下、ポリモーフィズム"); emp.greet(); } } main メソッド外に introduce メソッドを用意し、インスタンス化した EmployeeSales、および EmployeeManagement を代入した変数 e1、e2 を、ざっくりとした Employee 型の変数で受け取り、emp.greet()でメソッド内で受け取った変数 e1、e2 が持つ greet メソッドを呼び出し実行する ■ キャストによる強制的なメソッドの使用 先述した Athlete クラス独自の introduce メソッドが呼び出せないということについて Human h = new Athlete(); Athlete a = (Athlete)h; 以上のように曖昧な箱の型に入っている中身を強制的に具体的な型に代入するということをキャストを用いて可能にできる、ダウンキャストと呼ばれる ダウンキャストは元々 Java が代入の失敗の可能性があることを強制的に行うものであり、仮に継承の関係にないものをダウンキャストした場合には ClassCastException というエラーが発生する インスタンスを代入可能か判定するには、instanceof という演算子を使用する if (h intanceof Athlete) { Athlete a = (Athlete)h; a.introduction(); }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

多態性とは

■ 多態性とは オブジェクトをあいまいに、ざっくりと捉えることで、ある処理を命令したらクラスが違っても同じように振舞ってくれる仕組み 例えばある人物が書いてある紙を、そのままただの「紙」として捉えるのか、肖像画という「絵」として捉えるのか、お金という「紙幣」として捉えるのか、その捉え方によって同じ「使う」という振る舞いでも内容変わってくる、というようなイメージ 曖昧で抽象的なほど利用方法は限定され、逆に具体的に捉えるほどに用途は増えていく 通常のインスタンス化では Athlete a = new Athlete(); という記述で Athlete クラスのオブジェクトを new するが、内容は Athlete 型の変数 a に、new してインスタンス化した Athlete オブジェクトを代入し、変数 a を使用するようになっている つまり Athlete オブジェクトであれば、そのオブジェクトを 「Athlete という性質」のものとして捉えることになるが、多態性という機能はこのオブジェクトの捉え方をよりざっくり(抽象的に)としたものにすることにより様々な機能が使えるようになるというもの Human a = new Athlete(); 本当は 「 Athlete という性質」のオブジェクトだが、あくまで 「 Human という性質」のもの として捉えて利用する Javaではextends や implememts を用いた継承の関係にあるクラス同士について、is-a の関係があると判断し、多態性を利用することができるようになる つまり Item a = new Athlete(); のような is-a の関係に乗っ取らない記述はそもそも継承すべきではないが、同じように多態性の利用もすべきではない ■ 多態性の性質 Human a = new Athlete(); 上記のこのインスタンス化は、new した Athlete オブジェクトを Human として捉えるということだが、そうすることによって本当は中身(オブジェクト)が Athlete であるが、 「Human の一種である何か」という、これまた曖昧な捉え方をJavaはするため、Athlete クラスでのみ定義されているメソッドが使えなくなる(正確に Athlete クラスと認識できていないため、Human として最低限出来ることしかできなくなる) 冒頭に書いた紙幣のイメージに照らし合わせると、紙幣を絵として捉えて使用しているために、本来紙幣が持つ「何かを手に入れるときに対価として支払う」という機能が使えない、ということになる 以下、例 public abstract class Human { public void greet() { System.out.println("人間です。"); } } public class Athlete extends Human { public void introduce() { System.out.println("アスリートです。"); } } Human h = new Athlete(); h.introduce(); Athlete クラスで定義した introduce メソッドは Human 型の変数 h に入れられたことで外部から明確に認識できなくなったため使用できない 「メソッド introduce() は型 Human で未定義です」とエラー この場合、Human は「箱の型」、Athlete は「中身の型」といえる 箱の型は今回のように Human クラスに指定すれば Human として捉え、例えば Human の前のインターフェース、Life に指定すれば Life として捉える、つまり様々な箱に入れ替えることで捉え方を変えることができる 階層が汎化すればするほど、そのオブジェクトを曖昧な捉え方をすることになる 中身の型は、仮にどの箱に入っていたとしてもJavaが外部から明確に認識できなくなるだけでその性質自体が変わることはない そのため、以下 public abstract class Human { public void greet() { System.out.println("人間です。"); } } public class Athlete extends Human { public void greet() { System.out.println("アスリートです。") public void main(String[] args) { Human h = new Athlete(); h.greet(); } この場合は、Athlete クラスと Human クラスの両方に同じ greet メソッドがあるため、Human 型の変数 h に入れてもメソッドが呼び出せるが、この時の処理結果は Human クラスで記述されている「人間です。」ではなく、Athlete クラスで記述されている「アスリートです。」が表示される つまり仕組みとしては 箱の型である Human クラスの greet メソッドが呼び出せるから実行が可能だが、実行できる場合には中身の型である Athlete クラスの本来のメソッドが呼び出されることになる つまり 箱の型:どのメソッドを「呼ぶことができるか」を決定 中身の型:メソッドが呼ばれた場合「どのように処理するか」を決定する ここで多態性の「曖昧に、ざっくり捉える」ということがメリットとなってくることがわかる 各サブクラスでメソッドのオーバーライドをしていれば、必ずサブクラスにも該当のメソッドが存在することになるため、 main メソッドで同じ命令(同じメソッドの呼び出し)を行っても、各サブクラスでオーバーライドしたそれぞれ異なる振る舞いが実行されることになる 呼び出す側は同一視し、呼び出される側は各々決められた動きを行う、という仕組み public interface Employee { public abstract void greet(); } public class EmployeeSales implements Employee { @Override public void greet() { System.out.println("こんにちは営業部。"); } } public class EmployeeManagement implements Employee { @Override public void greet() { System.out.println("こんにちは管理部。"); } } public class EmpMain { public static void main(String[] args) { Employee e1 = new EmployeeSales(); Employee e2 = new EmployeeManagement(); e1.greet(); e2.greet(); Greet(e1); Greet(e2); } static void Greet(Employee employee) { System.out.println("以下、ポリモーフィズム"); employee.greet(); } } 同じ greet メソッドで営業部、管理部と別々の内容のメソッドを実行している ■ キャストによる強制的なメソッドの使用 先述した Athlete クラス独自の introduce メソッドが呼び出せないということについて Human h = new Athlete(); Athlete a = (Athlete)h; 以上のように曖昧な箱の型に入っている中身を強制的に具体的な型に代入するということをキャストを用いて可能にできる、ダウンキャストと呼ばれる ダウンキャストは元々 Java が代入の失敗の可能性があることを強制的に行うものであり、仮に継承の関係にないものをダウンキャストした場合には ClassCastException というエラーが発生する インスタンスを代入可能か判定するには、instanceof という演算子を使用する if (h intanceof Athlete) { Athlete a = (Athlete)h; a.introduction(); }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WSL2にArch Linuxを使いたくてインストールしたやつがいるらしい

私です あくまで今回は備忘録なので、基本的に参考記事の通りに動かしたものです。 経緯 この度新社会人となりました。研修でJavaの勉強を改めて勉強しなおしているのですが、動作確認のためにわざわざIDEでやるのは面倒くさいと感じたためターミナル上で動かしたいと思ったのですが、WindowsのターミナルはコマンドプロンプトもPowershellもいまいち使い勝手が悪い(Powershellはあんま好みじゃない)。なのでWSL 上で動かしたいと思ったのですが、WSLとして公式に配布されているディストリビューションにArch Linuxが無い。はてどうしたものか… ツールがあった まあとにかくググってみるのが一番です。それで調べてみるとWSLでArchLinuxを入れて使う記事がありました。この中のあらかじめ作成済みのArch Linuxのイメージを登録してくれるツールを使ってやってみることにします。 ファイルをダウンロードして解凍するとArch2.exeファイルがあり、それを実行することによってインストールができます…が実行するディレクトリがそのままWSLで使用するOSイメージの場所となってしまうので、実行する前に管理しやすいディレクトリに移動して実行することをお勧めします。少なくともダウンロードフォルダに置いたままはあんまり… ArchLinuxとWSLの環境整備 バージョンの更新 インストールすることができたら、wsl -d Arch2とコマンドを実行することでバージョン更新をします。 ミラーリストの変更 デフォルトだとアメリカのミラーを参照するらしいので、/etc/pacman.d/mirrorlistを開いて日本のミラーリストを一番上に持っていきます。 参考 pgp鍵のリセットとpacmanの更新 鍵を更新します。 //鍵の初期化 $ pacman-key --init //鍵の更新 $ pacman-key --populate archlinux $ pacman -Syy archlinux-keyring //パッケージ更新 $ pacman -Syu ユーザー云々 Arch Linux上でのユーザーを作成します。 $ pacman -S vi $ visudo $ useradd -m -s /bin/bash -G wheel <USERNAME> $ passwd <USERNAME> デフォルトユーザーを変更します。powershellでArch2.exeを配置したディレクトリまで移動して以下のコマンドを実行します(今回のケースはC:\User\usr\WSLファイルに実行ファイルを配置しているものとします)。 C:\Users\usr\WSL> .\Arch2.exe config --default-user <USERNAME> Windows Terminalの設定 Windows Terminalを起動して設定を開きます。VSCodeを利用しているとある程度自動的に入力されます。 "profiles": { "defaults": { // Put settings here that you want to apply to all profiles. }, "list": [ { "guid": "{<your uuid>}", "hidden": false, "name": "Arch2", "commandline": "wsl.exe ~ -d Arch2 --user <user name>", "cursorShape": "filledBox", "source": "Windows.Terminal.Wsl" }, ] }, 最後にAURヘルパーをインストールしていきます。 yayのインストール AURヘルパーをインストールするためにはgit cloneコマンドを利用します。カレントディレクトリにそのパッケージのディレクトリが生成されるため、ディレクトリが乱雑に生成されるのが嫌な場合はそれ用のディレクトリを作成し、そこに移動して以下のコマンドを実行することをお勧めします。 //必要なパッケージのインストール $ pacman -S base-devel git //yayのインストール $ git clone https://aur.archlinux.org/yay.git $ cd yay $ makepkg -si Javaの環境構築 ここまで結構時間がかかっているのですが、一応今回の環境構築の理由はJavaをターミナル上で実行できるようにするという理由であるため、Arch LinuxにJavaを入れていきます。 JDKに関しては(Arch Linux Wikiの記事)[https://wiki.archlinux.jp/index.php/Java]を参考にして自分に合ったものを選択してください。 今回私はOpenJDKの最新版を選択しています。パッケージ名に関しては念のためsudo pacman -Ss openjdkで調べておくと良いです。 基本的にはインストールすることでパスは設定されるとは思います。通らなかったらググってください(他力本願) java --versionで確認することができます。 VSCodeで良い感じにする 今この状態だと結局ターミナルを使ってプログラミングすることになるため、これではWSLのメリットがそんなにないのでなんかいい感じにしたいですよね(語彙力無し) VSCodeの拡張機能でRemoteというものがあります。 これはWSLをインストールすると推奨としてポップアップが結構でてきます。これをインストールしてWindows TerminalからWSLにログインした状態でcode .とコマンドを打つと… こんな感じにもう一つVSCodeのウィンドウが開きます。これで編集およびターミナルで動作確認ができるようになります(なお画像の黒塗り部分はそんなに意味はありません。一応ユーザー名なんですけどHNなので隠す理由はほとんどなかったことに塗ってから気づいた)。 まとめ ターミナルで動作確認する例はほとんどありませんが、Hello Worldを表示する環境としては結構良い感じにはなったのではないでしょうか。 まあこれ一か月前に書いて今書き終えたものなので、もうほとんど使ってないのですが 駄文失礼いたしました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Java staticメソッドと非staticメソッド・呼び出しで手こずった件

はじめに メソッドの呼び出しで手こずったので、忘れないようにメモしておきます。 間違いありましたら、コメント頂けますと幸いです。 ということで、staticと非staticの呼び出しについてやっていきます。 staticメソッドについて 調べてみると、staticなメソッドというのはインスタンスを生成しなくも使用できるメソッドだということのようですが、初心者の私にはイマイチstaticと非staticのメソッドの違いがわからず、下記コードを実行しました。 Main.java public class Main { public static void main(String[] args) { String firstName = "hoge"; String lastName = "huga"; //getName関数の呼び出しと出力 System.out.println(getName(firstName, lastName)); System.out.println(); } public String getName(String first_name, String last_name) { return last_name + first_name; } すると、こんなエラーが出ました。 型 Main の非 static メソッド getName(String, String) を static 参照することはできません 解読すると、どうやら「Mainメソッド内で非staticなメソッドであるgetNameは参照できない」ということのようです。 つまり、staticなメソッド(main)から同一クラス(Main)内の非staticなメソッド(getName)へは直接アクセスできない ということです。 では、どうすれば解決できるのかを説明致します。 メソッドの呼び出し Java staticメソッドと非staticメソッドについて 上記記事を参考にやらせていただいた結果、「クラスのインスタンスを生成し、インスタンスを通して実行する」というやり方で解決できました。 クラスのインスタンスを生成し、インスタンスを通して実行する どういうことかというと、下記コードのような状態にして解決しました。 Main.java public class Main { public static void main(String[] args) { String firstName = "hoge"; String lastName = "huga"; //getName関数の呼び出しと出力 //Mainクラスのインスタンスを生成 Main m = new Main();        //インスタンスmのgetNameメソッドの呼び出し System.out.println(m.getName(firstName, lastName)); System.out.println(); } public String getName(String first_name, String last_name) { return last_name + first_name; } このようにすることで、Mainクラスのインスタンスmをmainメソッド内で生成することで、インスタンスmを通してgetNameメソッドを呼び出すことができるのです。 要するに、直接的にアクセスするのではなく、インスタンスを介して間接的にアクセスすることで、mainメソッド外の非staticなメソッドを呼び出すことを可能にするということです。 ぜひ、参考になれば嬉しいです。 参考文献 Java staticメソッドと非staticメソッドについて
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Sublime Text 3でJavaをビルドする

Javaをエディタで手軽に勉強したい。 前提 Windows 10 Pro 64bit Javaのキットをインストール済 Sublime Text 3の設定 Tools -> Build System -> New Build System... でsublime-buildファイルを作成し1、\(Sublime Textのフォルダ)\Data\packages\Userに保存する。これでCtrl+bでコンパイル~実行まで行うことができる。 デフォルトでも「JavaC」が入っているが、エンコードの問題で日本語文字がコンパイルエラーに繋がってしまう。UTF8でソースを作成することを前提に(File -> Save with Encodingで指定できる)、コンパイル時に-encoding utf-8のオプションをつけるように記述している。 Java.sublime-build { "selector": "source.java", "file_regex": "^(.*?):([0-9]*):?([0-9]*):? (.*)", "shell": true, "cmd": ["javac", "-encoding", "utf-8", "$file_name"], "windows": { "encoding": "cp932" }, "variants": [ { "name": "コンパイルして実行", "shell": true, "windows": { "encoding": "cp932", "cmd": "javac -encoding utf-8 $file_name & java $file_base_name" } } ] } Build Systemについてはこちらの記事に色々まとまっている。→Sublime Text 3のBuild Systemについて 動作確認 Build SystemでJavaを選択し、適当なソースを保存してCtrl+Shift+bで「コンパイルして実行」。 標準入力を含む場合はコンパイルだけCtrl+bで行って、コマンドプロンプトから実行する(Sublime Textの実行結果のパネルからは入力できない)。 HelloJP.java public class HelloJP { public static void main(String[] args) { System.out.println("Hello じゃぱん!"); } } Hello じゃぱん! [Finished in 1.2s] Build Systems – Sublime Text 3 Documentation ↩
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Azure Functions + Spring Cloud Function で Spring Retry を使う

QiitaAzure + Java の企画も終わってしまいました、以前、 Azure Functions で Spring Cloud Functionを使う - Qiita という記事を書いたのですが、もうすこし Spring フレームワークの機能を使えないと思い Spring Retry の機能を Azure Function + Spring Cloud で試してみました。 Spring Retry Spring フレームワーク上で、アノテーションベースでリトライ処理を書けたりする便利なライブラリです。Spring Retry 単体でコードベースでリトライを記述することもできます。 GitHub は、以下です。 ここでは、Spring Retry そのものの解説はしないので、ドキュメント等を当たってください。 Azure Function + Spring Cloud 上で使うには 結論から言えば、きちんと使えましたので、どのように実装したかを記録として残しておこうと思います。 ハンドラ(Trigger)から呼ばれる Function があり、そのメソッドに @Retryable アノテーションを指定します。引数には、ハンドルする例外クラスを配列で指定し、試行回数などを指定します。リファレンスは以下の通りです。固定バックオフ、指数関数的バックオフなども指定できます。 Retryable (Spring Retry 1.3.1 API) 以下の例では意図的に、例外をスローしています。関数は Function<I,O> を実装しているのスロー句とかを勝手に拡張できませんので、検査例外を扱いたい場合は、未検査例外 RuntimeException を継承したラッパーを用意する必要があります。 @Retryable(value = { UnwrapedIOException.class }, maxAttempts = 5) public Mono<Greeting> apply(Mono<User> mono) { logger.info("hello function"); if (Math.random() < 0.5) { logger.error("Throw IOException."); throw new UnwrapedIOException(new IOException("File not found :-)")); } return mono.map(user -> new Greeting("Hello, " + user.getName() + "!\n")); } @Recover も指定できます。 @Recover public String recoverBar(UnwrapedIOException exception) { logger.error("----------------- error ---------------------"); return "error"; } まとめ 前回は単純なDIでしたが、Spring Retry も動作確認できました。こういった決まり切った処理をフレームワーク側に任せられるのは便利ですね。また、なにか機能を試したいと思います。 補足&追記 Twitterでご指摘いただいてそれはまさにおっしゃる通りです。元々のサンプルを流量しつつ Spring フレームワークをどこまでAzure Functionで使えるかの実験をしていたので、あまり深く考えてませんでした。 といわけで Reactorのフレームワーク内でRetryできるならそれを使った方が良いでしょうという話です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】ポリモーフィズム:フィールド・メソッドは型とインスタンスのどちらが優先される?

はじめに JavaSilver:継承とポリモーフィズムの問題 ポリモーフィズムについて、 継承関係にある2つのクラス内に同名のフィールド・メソッドがあった場合、 どちらが優先されるのか分からなくなったのでまとめる *「継承関係にある2つのクラス内に同名のフィールド・メソッドがあった場合」というのは、以下のコードのようなものである* public class A{ String val = "A"; public void sample(){ System.out.print(val); } } public class B extends A{ String val = "B"; public void sample(){ System.out.print(val); } } 結論 フィールドを参照した場合 ->変数の型で宣言されたものが優先 メソッドを参照した場合 ->オーバーライドされたものがあるならそちらを優先 ->なければスーパークラスのものを優先 (スーパークラスにそのメソッドがなければコンパイルエラー) 具体例 public class A{ String val = "A"; public void sample(){ System.out.print(val); } } public class B extends A{ String val = "B"; public void sample(){ System.out.print(val); } } public class Main{ public static void main(String[] args){ A a = new A(); A b = new B(); //B型インスタンスをA型に代入 System.out.print(a.val); System.out.print(b.val); a.sample(); b.sample(); } } 出力結果 AAAB ちなみに、ポリモーフィズムでない継承関係については、 もちろんサブクラスの方が優先される class A{ String val = "A"; public void sample(){ System.out.print(val); } } class B extends A{ String val = "B"; public void sample(){ System.out.print(val); } } public class Main{ public static void main(String[] args){ B c = new B(); System.out.print(c.val); c.sample(); } } 出力結果 BB おわりに こちらのQ&Aが個人的にドンピシャだったので載せておきます
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コレクションを操作するメソッドの使い方

コレクションを操作するメソッドの使い方 コレクションを操作する下記のメソッド使い方をListを使用して確認してみようと思います。 ArrayList.add(? e) 引数の値を新しい要素としてリストの最後に追加します。 ArrayList.get(int i) 引数の値のインデックスの要素を返します。 ArrayList.indexOf(? e) 引数と一致する要素がリストに含まれていないかインデックス0から順番に確認し、一致した要素があればインデックスを返します。 一致する要素がない場合は-1を返します。 ArrayList.removeAll(ArryList<?> e) 引数のリストの要素と一致する要素を削除します。 ArrayList.removeIf(Predicate<? super E> filter) 指定された条件を満たす要素を削除します。 ArrayList.replaceAll(UnaryOperator<E> operator) 指定された処理を行い、リストに返します。 ArrayList.sort(Comparator<? super E> c) コンパレーターに従いリストの要素を並び替えます。 forEach(Consumer<? super E> action) 全ての要素を順番に引数にして指定された処理を行います。 ※戻り値は存在しないのでリストの中身は変更されません。 実際に利用してみたコードがこちらになります。 import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> addList = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7,8,9,10)); addList.add(11); System.out.println("add(11)"); System.out.println(addList); List<Integer> getList = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7,8,9,10)); System.out.println("get(5)"); System.out.println(getList.get(5)); List<Integer> indexOftList = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7,8,9,10)); System.out.println("indexOf(6)"); System.out.println(indexOftList.indexOf(6)); List<Integer> removeAllList = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7,8,9,10)); removeAllList.removeAll(new ArrayList<Integer>(Arrays.asList(1,3,4,5))); System.out.println("removeAll(new ArrayList<Integer>(Arrays.asList(1,3,4,5))"); System.out.println(removeAllList); List<Integer> removeIfList = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7,8,9,10)); removeIfList.removeIf( i -> i % 2 == 0); System.out.println("removeIf( i -> i % 2 == 0)"); System.out.println(removeIfList); List<Integer> replaceAllList = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7,8,9,10)); replaceAllList.replaceAll(i -> i * 2 ); System.out.println("replaceAll(i -> i * 2 )"); System.out.println(replaceAllList); List<Integer> sortList = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7,8,9,10)); sortList.sort((Integer i,Integer j) -> j.compareTo(i)); System.out.println("sort((Integer i,Integer j) -> j.compareTo(i))"); System.out.println(sortList); List<Integer> forEachList = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7,8,9,10)); System.out.println("forEach(i -> System.out.print(i + " ") )"); forEachList.forEach(i -> System.out.print(i + " ") ); } } 実行結果 add(11) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] get(5) 6 indexOf(6) 5 removeAll(new ArrayList<Integer>(Arrays.asList(1,3,4,5)) [2, 6, 7, 8, 9, 10] removeIf( i -> i % 2 == 0) [1, 3, 5, 7, 9] replaceAll(i -> i * 2 ) [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] sort((Integer i,Integer j) -> j.compareTo(i)) [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] forEach(i -> System.out.print(i + " ") ) 1 2 3 4 5 6 7 8 9 10 解説 宣言時は全てのリストのパラメータがIntegerに設定されており、要素は1~10の数値になっています。 addList add(11)によって11がリストの要素に加わっています。 getList get(5)によってインデックスが5の要素6が返ってきています。 ※インデックスは0から数えるため indexOftList indexOf(6)によって引数(6)と一致する要素のインデックス5が返ってきています。 ※インデックスは0から数えるため removeAllList removeAll(new ArrayList(Arrays.asList(1,3,4,5))の引数で渡されたListに含まれる要素と一致している要素(1,3,4,5)を削除しています。 removeIfList removeIfメソッドを利用して、偶数の要素を削除しています。 replaceList 全ての要素を二倍にしてリストに返しています。 replaceAllList 降順に並び替える様に設定したコンパレーターを作成し、コンパレーターを利用してリストを並び替えています。 forEachList 要素を一つずつ受け取り、System.out.printによってコンソールに表示させています。 まとめ コレクションを操作するメソッドはjava.utilパッケージに多数用意されており、自分の目的に合ったメソッドを利用する事でだいたいの処理は作成できる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

陣取りのターン数 Java編(解決)【paiza Aランクレベルアップメニュー】

 解決しました。 Main.java import java.util.*; import java.util.Queue; import java.util.ArrayDeque; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int h = sc.nextInt(); int w = sc.nextInt(); int n = sc.nextInt(); String map[][] = new String[h][w]; //陣 Queue<XY> q = new ArrayDeque<>(); //キュー for(int i=0; i<h; i++){ //初期化 String temp = sc.next(); for(int j=0; j<w; j++){ map[i][j] = String.valueOf(temp.charAt(j)); if(map[i][j].equals("*")){ q.add(new XY(i, j, 1)); //スタート地点(初期値のy, x, 1が入っている) } } } int l[] = new int[n]; int lcount = 0; //引数 for(int i=0; i<n; i++){ l[i] = sc.nextInt(); } Arrays.sort(l); //?にする手番を昇順に格納 while(q.size() > 0){ XY xy = q.poll(); int y = xy.y; int x = xy.x; int d = xy.d; String in = "*"; //書き込むテキスト。初期値は*。 if(l[0] == 0 && d == 1 && lcount < n){ //0が入っている。初期地点を?にする場合 map[y][x] = "?"; lcount++; } //dがl[lcount]と同じなら?を入れる //lcountを1増やす //この時nを越えた時点でIndexOutになる。lcountがn-1に来た時点で増加処理を通させない //→一度上限まで来てしまったら判定の必要がないと言える //増加条件を「一致したとき」にしてしまうと、最初の一回でlcountが動いてしまう //l[lcount]の値がdより小さいとき if(l[lcount] < d && lcount < n-1){ //ここが!!! lcount++; } if(l[lcount] == d){ //逆!!! in = "?"; } if(y > 0 && map[y-1][x].equals(".")){ //上 map[y-1][x] = in; q.add(new XY(y-1, x, d+1)); } if(y < h-1 && map[y+1][x].equals(".")){ //下 map[y+1][x] = in; q.add(new XY(y+1, x, d+1)); } if(x < w-1 && map[y][x+1].equals(".")){ //右 map[y][x+1] = in; q.add(new XY(y, x+1, d+1)); } if(x > 0 && map[y][x-1].equals(".")){ //左 map[y][x-1] = in; q.add(new XY(y, x-1, d+1)); } } for(int i=0; i<h; i++){ //出力 for(int j=0; j<w; j++){ System.out.print(map[i][j]); } System.out.println(""); } } } class XY{ int y; int x; int d; XY(int y, int x, int d){ this.y = y; this.x = x; this.d = d; } } if(l[lcount] < d && lcount < n-1){ //ここが!!! lcount++; } if(l[lcount] == d){ //逆!!! in = "?"; }  こういうオチでした。  引数を増やすタイミングが遅かったんですね。 「持ってこられたd(探索深度)が、今参照したいl[lcount](?にしたい探索深度)より大きければ、引数を増やす」  んだから、 「先に今の引数とあってるかどうか確認して、それから増やす」じゃ上手くいかないの当然です。  よし、ようやくハマりを抜けた。  Aランク相当問題にチャレンジ出来るぞう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

陣取りのターン数 Java編(中途)【paiza Aランクレベルアップメニュー】

 昨日の続き、一週間詰まっている本題である。なお本来のAランク相当問題はこの次。  書き出して手間を省いたので、詰まっていた部分はぬるっとクリア出来た(入力例2)。  ただし最後の判定で上手くいってないので、まだ完全解答ではない。  整理するための備忘録。 Main.java import java.util.*; import java.util.Queue; import java.util.ArrayDeque; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int h = sc.nextInt(); int w = sc.nextInt(); int n = sc.nextInt(); String map[][] = new String[h][w]; //陣 Queue<XY> q = new ArrayDeque<>(); //キュー for(int i=0; i<h; i++){ //初期化 String temp = sc.next(); for(int j=0; j<w; j++){ map[i][j] = String.valueOf(temp.charAt(j)); if(map[i][j].equals("*")){ q.add(new XY(i, j, 1)); //スタート地点(初期値のy, x, 1が入っている) } } } int l[] = new int[n]; int lcount = 0; //引数 for(int i=0; i<n; i++){ l[i] = sc.nextInt(); } Arrays.sort(l); //?にする手番を昇順に格納 while(q.size() > 0){ XY xy = q.poll(); int y = xy.y; int x = xy.x; int d = xy.d; String in = "*"; //書き込むテキスト。初期値は*。 if(l[0] == 0 && d == 1 && lcount < n){ //初期地点を?にする場合 map[y][x] = "?"; lcount++; } //dがl[lcount]と同じなら?を入れる //lcountを1増やす //この時nを越えた時点でIndexOutになる。lcountがn-1に来た時点で増加処理を通させない //→一度上限まで来てしまったら判定の必要がないと言える //増加条件を「一致したとき」にしてしまうと、最初の一回でlcountが動いてしまう //l[lcount]の値がdより小さいとき if(l[lcount] == d){ in = "?"; } if(l[lcount] < d && lcount < n-1){ lcount++; } if(y > 0 && map[y-1][x].equals(".")){ //上 map[y-1][x] = in; q.add(new XY(y-1, x, d+1)); } if(y < h-1 && map[y+1][x].equals(".")){ //下 map[y+1][x] = in; q.add(new XY(y+1, x, d+1)); } if(x < w-1 && map[y][x+1].equals(".")){ //右 map[y][x+1] = in; q.add(new XY(y, x+1, d+1)); } if(x > 0 && map[y][x-1].equals(".")){ //左 map[y][x-1] = in; q.add(new XY(y, x-1, d+1)); } } for(int i=0; i<h; i++){ //出力 for(int j=0; j<w; j++){ System.out.print(map[i][j]); } System.out.println(""); } } } class XY{ int y; int x; int d; XY(int y, int x, int d){ this.y = y; this.x = x; this.d = d; } }  入力例2で詰まっていたのはこういうミスだったわけだ。 //この時nを越えた時点でIndexOutになる。lcountがn-1に来た時点で増加処理を通させない //→一度上限まで来てしまったら判定の必要がないと言える //増加条件を「一致したとき」にしてしまうと、最初の一回でlcountが動いてしまう(これ!!! //愚直にこんなことやってたわけだ if(l[lcount] == d && lcount < n-1){ //(?にする処理) lcount++; }  落ち着いて考えてみれば「そりゃそうだ」なのだが、あれこれ一気に考えすぎて忘れる&疲れて見落とす。そういう例。  さて問題は最後の入力である。  入力例そのものはチケット使用(有料)なのでいったん置くが、「狭い陣で1つ刻み。だが最後の一手が?にならない」である。  最後の一回をスルーしてしまうようなので、条件判定を見直さねばならない。  いったんここまで。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】文字数をカウントするGUIを作る

はじめに こんにちは、oni9soupです。初めて自分で作成したプログラムを初めてのQiitaの記事にします。 私の簡単な紹介です * 情報系大学の大学1年生(2021/05/11現在) * プログラミング初学者 * Qiita初心者 大学に入学し1ヶ月ほどがたち、少しずつ余裕が出てきたのでプログラムを書くこと、記事や文章を作成することを練習したくQiitaで記事を書こうと思いました。 初心者ですので間違いの指摘やアドバイスをしていただけるとうれしいです。 プログラミングを始めようと思ってる方、勉強し始めてるけど何が作れるのかイメージがつかない方などに参考になればと思います。 Twitterもはじめました! 作ったもの ボタンを押すとテキストエリアの文章の文字数を表示します。 日本語の文字数と英語の単語数がわかります。 背景 大学に入学して余裕ができたので大学で勉強しているJavaを使って今の自分に必要なものを作りたいと考えていました。 大学にで課題やレポートの作成・提出が多く、それには文字数制限(〇〇文字以上・程度など)があります。そこでメモ帳を使用しレポートの下書きをしていると、文字数を調べたくWebで検索して文字数カウントツールを使用していました。 週に2回ほどはアクセスしていたので、それなら自分で作ってみようと思いました。 開発環境 Windows 10 サクラエディタ 2.4.1 OpenJDK Java8 >ver Microsoft Windows [Version 10.0.19042.928] >java -version openjdk version "1.8.0_282" OpenJDK Runtime Environment (build 1.8.0_282-b08) OpenJDK 64-Bit Server VM (build 25.282-b08, mixed mode)1 コード 文字数カウント countというメソッドに文字列を渡たすと日本語なら文字数・英語なら単語数を返します。 日本語と英語の判断はenCheckで行っています。  文章が英数字と英語で使われる記号のみ → 英語  それ以外            → 日本語 英語の場合はenCounterで半角空白で文章を区切り、配列に入れて.lengthで配列の要素数を調べそれを単語数とします。 日本語ではjaCounterで空白改行を消して、その文字列を.length()で長さを調べそれを文字数としました。 Counter.java import java.util.regex.*; class WordCount { public String count (String doc) { String message = doc; String messageNum = "0語"; if (enCheck(message)) { messageNum = enCounter (message) + "Words"; }else{ messageNum = jaCounter (message) + "語"; } return messageNum; } public int jaCounter (String message) { message = message.replaceAll("[\r\n]", ""); int messageNum = message.length(); return messageNum; } public int enCounter (String message) { String[] messageArray = message.split(" ", 0); int messageNum = messageArray.length; return messageNum; } public boolean enCheck(String target) { boolean result = true; if (target == null || target.isEmpty()) return false ; Pattern pattern = Pattern.compile ("^[A-Za-z0-9,.;:\\-\"\\'!?\\s\\n]+$"); Matcher match = pattern.matcher(target); result = match.matches(); return result; } } 画面表示 GUIはSwingで作成しました。ボタンを押すとテキストエリア内の文字列を取得し先程のWordCountクラスのcountというメソッドに引き渡し、返された文字数(String型)をラベルに表示します。 Counter.java class MyFrame extends JFrame { public JTextArea text = new JTextArea("文字数を調べます。", 20, 80); public JLabel label = new JLabel (); public JButton button = new JButton ("WordCount"); public JScrollPane scroll = new JScrollPane(); public WordCount wordCounter = new WordCount (); public MyFrame() { setTitle ("WordCounter"); setBounds (150, 150, 900, 600); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); text.setLineWrap(true); text.setFont(new Font("MS 明朝", Font.PLAIN, 20)); label.setFont(new Font("MS 明朝", Font.PLAIN, 50)); label.setBounds(10, 10, 450, 580); button.setPreferredSize(new Dimension(200, 40)); button.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { String doc = text.getText(); String num = wordCounter.count(doc); label.setText(num); } }); JPanel p = new JPanel (); JPanel pl = new JPanel (); pl.add(label); p.add(text); scroll.setViewportView(text); p.add(scroll); p.add(button); p.setPreferredSize(new Dimension(10, 10)); Container contentPane = getContentPane(); contentPane.add(p, BorderLayout.CENTER); contentPane.add(pl, BorderLayout.SOUTH); } } public class Counter { public static void main (String[] args) { MyFrame f = new MyFrame(); f.setVisible(true); } } エラーが多く起きたところ(JScrpllPane) レポートなどで使用するので文字数が多くなりテキストエリアを超えてしまうことがありそうだったので、スクロールバーを設置しました。 JScrollPane scroll = new JScrollPane(); scroll.setViewportView(****); //****→追加したいテキストエリアの名前 スクロールバーは上の2行だけでも設置はすることができたが、機能しませんでした。 解決策 手探りでやっていく中で、パネルにテキストエリアを追加したあとにscroll.setViewportView();をしたら解決できました。 JTextArea text = new JTextArea("文字数を調べます。", 20, 80); JScrollPane scroll = new JScrollPane(); JPanel p = new JPanel (); p.add(text); scroll.setViewportView(text); p.add(scroll); 今後したいこと じつはこの文字数をカウントするのにあたってやりたいことがもうひとつあります!英語の単語数を調べるときに使用していたサイトではボタンなどを押さずにも単語数が出てきます。 このようにしたかったのですが、テキストエリア文字が更新されると文字数をカウントするといった形がどうしても取れず、今回はボタンを押されたときに文字数をカウントするようにしました。 上の動画を撮っているときに考えたのですが、1秒とか0.5秒毎にテキストエリアの文章を取得するし文字数を調べるみたいにすればうまくいきそうですね。それも調べてやってみたいです。 参考記事 初めてのGUI制作、Qiita記事作成で大変参考になりました。ありがとうございます! * Let'sプログラミング Swingを使ってみよう * Markdown記法 チートシート おわりに はじめてプログラミングを自分で考えGUIを制作し、Qiitaの記事を書いてみました。もっとプログラムを書いているときにエラーなどのスクショや状況のメモなどを残しておけばよかったので、それは次回からの制作にいかしてみます。 なにかものを作ってみる、記事を書いてみることがなかったので新鮮な気持ちですべてに取り組めました。技術力や文章作成能力の向上を目標としてQiitaで活動したいと思います! 記事作成開始 2021/05/10 記事公開 2021/05/11
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む