- 投稿日:2020-07-29T23:42:57+09:00
タグ付きクラスよりクラス階層を選ぶ
タグ付きクラス
public class Figure { enum Shape {RECTANGLE, CIRCLE}; final Shape shape; // shapeがRECTANGLEである場合にだけこれらのフィールドは使われる double length; double width; // shapeがCIRCLEである場合にだけこのフィールドは使われる double radius; // 円のコンストラクタ Figure(double radius) { shape = Shape.CIRCLE; this.radius = radius; } // 長方形のコンストラクタ Figure(double length, double width) { shape = Shape.RECTANGLE; this.length = length; this.width = width; } double area() { switch (shape) { case RECTANGLE: return length * width; case CIRCLE: return Math.PI * (radius * radius); default: throw new AssertionError(shape); } } }タグ付きクラスに対するクラス階層による書き換え
abstract class Figure { abstract double area(); } class Circle extends Figure { final double radius; Circle(double radius) { this.radius = radius; } @Override double area() { return Math.PI * (radius * radius); } } class Rectangle extends Figure { final double length; final double width; Rectangle(double length, double width) { this.length = length; this.width = width; } @Override double area() { return length * width; } }
- 投稿日:2020-07-29T23:19:29+09:00
【StreamAPIとラムダ式】何でもできるスーパーマン登場!!
java経験者のOさんはこう言った…
Streamとラムダ式でなんでも1行で書くことができる…と。もちろん、基礎ができた後にやるのを忘れずに。
【Streamとラムダ式】サンプルコード
public class TestStarter { public static void main(String[] args){ String[] s = {"1","2","3"}; //中間操作はなんでもしてくれるスーパーマン かつ 1度に条件をなんでもかける Arrays.asList(s).stream().filter(i -> i.equals("1")).forEach(System.out::println); } }これは、
❶.fillerで「true,false」なら何でも条件を設定できる(メソッドも参照可)
❷.forEachはfor文をぶん回し全部出力してくれる
❸System.out::printlnってのもラムダ式の書き方他にも.mapという配列の中身をいじくれるメソッドなんかもある。
【超ムズ】ラムダ式を活用したサンプルコードと問題
以前、この記事内で紹介しました。
配列でソートしたいけど、配列が全部文字列!?
https://qiita.com/Fallstag_Atsugi/items/88b1b4f3da75ae5ab191StreamAPI
答えは最後の章で!
ラムダ式
答えは最後の章で!
各章の答え
- 投稿日:2020-07-29T22:48:49+09:00
【探索アルゴリズム】ハッシュ探索法
【探索アルゴリズム】ハッシュ探索法
・ハッシュ探索法は、データを探す探索アルゴリズムの1つ
・探索しやすいようにあらかじめ関数を用いてデータを格納しておく
・格納するのに使った関数を用いて、一発でデータを探索する他の探索アルゴリズムとの違い
・これまでの線形探索法や二分探索法では、何のデータがどこの要素に入ってるかは全くわからない状態から探索を始める、というのが前提条件であった。
・ハッシュ探索法は、データの「中身」と格納先の「要素」をあらかじめ紐づけしておくおkとで、ごく短時間に探索できるように工夫したアルゴリズム。import java.util.Arrays; /** * ハッシュ探索法のアルゴリズム */ public class Algorithm { public static void main(String[] args) { int[] arrayD = {12, 25, 36, 20, 30, 8, 42}; int[] arrayH = new int[11]; Arrays.fill(arrayH, 0); //初期値として0をセットする System.out.println("今回扱うデータ" + Arrays.toString(arrayD)); System.out.println("初期化された格納先の配列" + Arrays.toString(arrayH)); int k; for (int i = 0; i < arrayD.length; i++) { //iが7になったら格納処理は終了 if (i < arrayD.length) { k = arrayD[i] % 11; while (arrayH[k] != 0) { k = (k + 1) % 11; //格納する配列先の要素数を超えた場合に最初[0]から格納先「0の値の場所」を探す } arrayH[k] = arrayD[i]; //格納先が「0」であれば値を代入する } } for (int result : arrayH) { //arrayHのデータを先頭から順に出力 System.out.print(result +","); } } } /*出力結果 今回扱うデータ[12, 25, 36, 20, 30, 8, 42] 初期化された格納先の配列[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 42,12,0,25,36,0,0,0,30,20,8, */
- 投稿日:2020-07-29T22:10:28+09:00
*Android*ピンチイン・ピンチアウトを検知する
はじめに
こんにちは.今回は,Androidでピンチ操作を検知しようと思います.ピンチイン・ピンチアウトを判別する方法について解説します.
前提
開発環境は以下の通りです.
*Android Studio 4.0.1
*targetSdkVersion 28
*Google Nexus 5xピンチイン・ピンチアウトの判別
ピンチ操作の検知には,
ScaleGestureDetector
を使用します.第一引数にContext,第二引数には,OnScaleGestureListener
インタフェースを実装したクラスのオブジェクトを指定します.今回は,匿名クラスを使用して,インタフェースを実装します.this.scaleGestureDetector = new ScaleGestureDetector(this, new ScaleGestureDetector.OnScaleGestureListener() { // ピンチ操作中に繰り返し呼ばれる @Override public boolean onScale(ScaleGestureDetector detector) { return true; } // ピンチ操作を開始したときに呼ばれる @Override public boolean onScaleBegin(ScaleGestureDetector detector) { return true; } // ピンチ操作を終了したときに呼ばれる @Override public void onScaleEnd(ScaleGestureDetector detector) { } });次に,
onTouchEvent
メソッドを用意し,onTouchEvent
メソッドが呼ばれた際に、ScaleGestureDetector.onTouchEvent
が呼ばれるようにすることで,ピンチ操作を検知することができます.@Override public boolean onTouchEvent(MotionEvent motionEvent){ this.scaleGestureDetector.onTouchEvent(motionEvent); return true;ピンチ操作を検知できたら,次にピンチイン・ピンチアウトを判別します.ピンチ操作では,画面に2本の指を触れています.指間の距離を測定するメソッドとして
getCurrentSpan()
が用意されているので,それを使用します.指間の距離の変化を利用することで,ピンチイン・ピンチアウトを判別することができます.ピンチイン・ピンチアウトの誤判定を防ぐために,閾値として指間の距離xを指定し,x以上変化した場合にピンチイン・ピンチアウトの判定を行います.@Override public boolean onScale(ScaleGestureDetector detector) { distance_current = detector.getCurrentSpan(); return true; }ピンチ操作中の指間の距離の正確性
ピンチ操作中の指間の距離を取得するには
getCurrentSpan()
を使用します.取得した指間の距離は,スマートフォンの画面の対角線の長さより小さいはずです.誤った距離を取得してしまった場合に取り除くために,スマートフォンの対角線の長さと比較して,それより小さいもののみを指間の距離とします.ここでは,Navigation bar を除いた画面の領域から,対角線の長さを求めます.画面の対角線の長さを取得するには以下のようにします.WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); Point size = new Point(); Display disp = wm.getDefaultDisplay(); disp.getSize(size); screen_width = this.size.x; screen_height = this.size.y; //対角線の長さを求める int screen_diagonal = (int) Math.sqrt((int)(Math.pow(screen_width, 2)) + (int)(Math.pow(screen_height, 2)));サンプルコード
AndroidManifest.xml?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapplication"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>activity_main.xml<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>MainActivity.javapackage com.example.myapplication3; import androidx.appcompat.app.AppCompatActivity; import android.graphics.Point; import android.os.Bundle; import android.view.Display; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.WindowManager; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private ScaleGestureDetector scaleGestureDetector; private long time_elapsed; private long time_start; private long time_current; private float distance_current; private float distance_start; private Boolean flg_pinch_out; private Boolean flg_pinch_in; private WindowManager wm; private Display disp; private Point size; private int screen_width; private int screen_height; //画面の対角線の長さ private int screen_diagonal; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.wm = (WindowManager) getSystemService(WINDOW_SERVICE); this.size = new Point(); this.disp = wm.getDefaultDisplay(); this.disp.getSize(size); screen_width = this.size.x; screen_height = this.size.y; //対角線の長さを求める screen_diagonal = (int) Math.sqrt((int)(Math.pow(screen_width, 2)) + (int)(Math.pow(screen_height, 2))); this.scaleGestureDetector = new ScaleGestureDetector(this, new ScaleGestureDetector.OnScaleGestureListener() { @Override public boolean onScale(ScaleGestureDetector detector) { time_current = detector.getEventTime(); time_elapsed = time_current - time_start; if (time_elapsed >= 0.5){ distance_current = detector.getCurrentSpan(); if (distance_start == 0){ distance_start = distance_current; } flg_pinch_out = (distance_current - distance_start) > 300; flg_pinch_in = (distance_start - distance_current) > 300; if (flg_pinch_out){ Toast.makeText(getApplicationContext(), "Pinch out", Toast.LENGTH_LONG).show(); time_start = time_current; distance_start = distance_current; } else if (flg_pinch_in){ Toast.makeText(getApplicationContext(), "Pinch in", Toast.LENGTH_LONG).show(); time_start = time_current; distance_start = distance_current; } else { //pass } } return true; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { distance_start = detector.getEventTime(); if (distance_start > screen_diagonal){ distance_start = 0; } time_start = detector.getEventTime(); return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { } }); } @Override public boolean onTouchEvent(MotionEvent motionEvent){ this.scaleGestureDetector.onTouchEvent(motionEvent); return true; } }
- 投稿日:2020-07-29T21:40:23+09:00
【総集編】7月ふりかえり.md
はじめに
今月のふりかえりです。
月1で振り返り
今後は何を勉強するかを決めます。
7月 1週目
2020/07/01 【統計学】ふつうのエンジニアが統計学の勉強を始めてみた
2020/07/05 【統計学】ふつうのエンジニアが統計学の勉強を始めてみた- part2
7月 2週目
2020/07/08 【キニナル話】jexcel使ってみた.xlsx
2020/07/12 JavaとJavaScript 間違えられやすい問題
2020/07/15 【UiPath】 UiPathを使いはじめての所感やメモ
7月 3週目
2020/07/19 【勉強】エンジニアの学び方を考える
2020/07/22 C#のノート
7月 4週目
2020/07/26 Python3のノート
先月に宣言したことについてのFB
- DBスペシャリストになる為SQL頑張る。
職場で散々触っているからあまり勉強しなくても良いかなと
思いましたが、DBで仕事していることもあるので
仕事以外でも勉強しようと考えるようになりました。
- AWSをうまく扱えるようにガンガン活用してみる。
正直なところ、触れていないというのが現状
それどころかAzureを触りにいく始末ただ、Azureを触ってみたところ多少の手ごたえを感じた。
Azure Learnningを活用してもっと探りを入れながらも
ノートを作成したいと思う。
あわよくば、バックエンドにAzureをおきたい。(置くことが目的にならないように注意)
- Pythonでデータ分析ができるように数学を復習する。
数学やって分析の「ぶ」の字をやっていたら
ソースコード解析という分野にのめりこんでしまった。
きっかけは自身の仕事の効率化
レビュー時にソースコードを読んだりドキュメントの更新したりが
結構大変で今後は全自動とまではいかなくでも
ドキュメントの自動更新やソースコード解析のスキームを仕上げる。
- PHP案件を受ける為今後も引き続き勉強して発信する。
一応、PHP案件は受領しましたが中身がなんともレガシー(笑)
オンプレだからまぁそうなるんだろうなとは思っていました。
まぁプライベートでうまいこと使いたいなと思います。
今後
- DBスペシャリストになる為SQL頑張る。
- Azureで 使えるDBを実際に使ってみる。
- 職場でPythonによるデータ分析をする。
- 受領したPHP案件をクリアする。
- RPAでロボットを大量生産する。
- 令和2年度キタミ式イラスト塾の読破
おわり
来月から週1更新にして記事作成ではなく
記事更新を中心にやります。
(毎週日曜日更新)
- 投稿日:2020-07-29T21:40:23+09:00
【総集編】7月ふりかえり
はじめに
今月のふりかえりです。
月1で振り返り
今後は何を勉強するかを決めます。
7月 1週目
2020/07/01 【統計学】ふつうのエンジニアが統計学の勉強を始めてみた
2020/07/05 【統計学】ふつうのエンジニアが統計学の勉強を始めてみた- part2
7月 2週目
2020/07/08 【キニナル話】jexcel使ってみた.xlsx
2020/07/12 JavaとJavaScript 間違えられやすい問題
7月 3週目
2020/07/15 【UiPath】 UiPathを使いはじめての所感やメモ
2020/07/19 【勉強】エンジニアの学び方を考える
7月 4週目
2020/07/22 C#のノート
2020/07/26 Python3のノート
先月に宣言したことについてのFB
- DBスペシャリストになる為SQL頑張る。
職場で散々触っているからあまり勉強しなくても良いかなと
思いましたが、DBで仕事していることもあるので
仕事以外でも勉強しようと考えるようになりました。
- AWSをうまく扱えるようにガンガン活用してみる。
正直なところ、触れていないというのが現状
それどころかAzureを触りにいく始末ただ、Azureを触ってみたところ多少の手ごたえを感じた。
Azure Learnningを活用してもっと探りを入れながらも
ノートを作成したいと思う。
あわよくば、バックエンドにAzureをおきたい。(置くことが目的にならないように注意)
- Pythonでデータ分析ができるように数学を復習する。
数学やって分析の「ぶ」の字をやっていたら
ソースコード解析という分野にのめりこんでしまった。
きっかけは自身の仕事の効率化
レビュー時にソースコードを読んだりドキュメントの更新したりが
結構大変で今後は全自動とまではいかなくでも
ドキュメントの自動更新やソースコード解析のスキームを仕上げる。
- PHP案件を受ける為今後も引き続き勉強して発信する。
一応、PHP案件は受領しましたが中身がなんともレガシー(笑)
オンプレだからまぁそうなるんだろうなとは思っていました。
まぁプライベートでうまいこと使いたいなと思います。
今後
- DBスペシャリストになる為SQL頑張る。
- Azureで 使えるDBを実際に使ってみる。
- 職場でPythonによるデータ分析をする。
- 受領したPHP案件をクリアする。
- RPAでロボットを大量生産する。
- 令和2年度キタミ式イラスト塾の読破
おわり
来月から週1更新にして記事作成ではなく
記事更新を中心にやります。
(毎週日曜日更新)
- 投稿日:2020-07-29T21:06:18+09:00
【Java】スーパークラス/サブクラスのコンストラクタあれこれ
目次
- はじめに
- 前提知識
- 継承クラスについて
- コンストラクタ
- 今回のキモ
- 暗黙的なコンストラクタ実行
- おわりに
はじめに
どうも駆け出しエンジニアです。
先日会社でコーディングをしていた際に人の書いたコードの続きを書かなくちゃいけなくなったんですが、
その時にクラスの継承,コンストラクタでドツボにはまってしまいかなりの時間を使ってしまいまして....
もう一回頭から学習しなおした所、わからないことがボロボロ出てきてヒドかったので再度まとめることにしました。なお、本記事は
・「現在Javaを触っている人」
・「もう一度内容を復習したい人」
向けとなっております。
各クラス名/変数名は適宜読み替えてください。前提知識
継承クラスについて
- 継承クラス=新しいクラスを作るとき、以前作った機能と共通する部分を引き継ぐクラス
- 継承元のクラスのことを「親クラス」、継承先のクラスのことを「子クラス」と呼ぶ。
- 同意義で「スーパークラス」「サブクラス」とも呼ぶ ※本記事ではスーパー/サブで表現。
- 継承クラスのインスタンスを作成することで、継承クラスのメソッド/フィールドにアクセスできる。
- ↓↓↓↓記述の仕方は↓↓↓↓
Super.javaclass Super { public void exampleSuper(){ //何らかの処理 } }Sub.javaclass Sub extends Super(){ //クラス名 extends 継承元クラス名 で継承。 public void exampleSub(){ //何らかの処理 } }コンストラクタ
- コンストラクタ=クラスのインスタンスを作成したときに自動で必ず呼び出されるメソッドのこと
- クラス名と同じ名前のメソッドのこと
- 通例コンストラクタ名は上記理由から先頭は大文字
- 戻り値はもともと想定していないので、voidは書いちゃダメ(→コンパイルエラー)
- 主にそのクラスのフィールド(メンバ変数)を初期化するのに用いられる。
- というか通例として/暗黙的にそうらしいので、それ以外の余計なことはしない方が吉。
→大規模開発における可読性/保守性の向上につながる
- ↓↓↓↓記述の仕方は↓↓↓↓
Smple.javaclass Sample{ public Sample(){ //ここがコンストラクタ } public void exampleMethod(){ //これはただのクラスメソッド } }今回のキモ
暗黙的なコンストラクタ実行
- クラスのインスタンス化時、継承階層の最上位から下方向へ、順番にインスタンス化されていく
- サブクラスのコンストラクタは最初にスーパークラスのコンストラクタを呼び出す
- スーパークラスのコンストラクタを明示的に呼び出さないとき、自動的に引数のないコンストラクタが呼び出される。
- コンストラクタの呼び出し時はsuper()メソッドが暗黙的に(自動的に)実行されている
●super();
スーパークラスのコンストラクタを呼び出すメソッド。
サブクラスのコンストラクタは"言語実装として"暗黙的(自動的)にスーパークラスのコンストラクタを実行するので、
必ず記述が必要なものではない
- ↓↓↓↓具体例↓↓↓↓
Super.javaclass Super { Super() { System.out.println("スーパークラスです!"); } }Sub.javaclass Sub extends Super { Sub() { // 暗黙的にスーパークラスのコンストラクタが実行される System.out.println("サブクラスです!"); } }Main.javaclass Main { public static void main(String[] args) { Sub obj = new Sub(); }//実行結果 スーパークラスです! サブクラスです!"暗黙的スーパーコンストラクターは未定義です"
- スーパークラスのコンストラクタが引数を持つもののみ定義されている場合、暗黙的に実行される「super();」メソッドだけではコンパイルエラー。
▽解決方法
①スーパークラスに引数を持たないコンストラクタを作成するSuper.javaclass Super { public name; public Super(){ //コンストラクタをオーバーロードさせる } public Super(String name){ this.name = name; } }②サブクラスのコンストラクタ内で、スーパークラスのコンストラクタの引数に合わせたsuper();メソッドで、明示的にスーパークラスのコンストラクタを呼び出す。
Super.javaclass Sub { public name; public Super(String name){ // メイン->サブ->スーパーの順で渡ってきたname変数の値をフィールドにセット this.name = name; } }Sub.javaclass Sub extends Super { Sub(String name) { //メインクラスのStrin型変数nameと対応->スーパークラスのコンストラクタへ受け渡し super(name); } }Main.javaclass Main { public static void main(String[] args) { Sub obj = new Sub(String name); } }終わりに
今回も長くなりましたが読んでいただきありがとうございました。
次回はtry-catchでの例外処理についてかければな~と思ってます。
では。
- 投稿日:2020-07-29T20:00:07+09:00
Apache Camel のroute構築で用いる Java DSL の個人的なコーディング規約
Apache Camel では「route」を作成する際、用意されたメソッドをひたすら繋げるという独自のDSLで書く。このDSLは条件分岐やループなどにも対応している。
ただ、Javaのスタイルガイドに従って書くと、条件分岐やループの内部処理を作るメソッドも同じインデントになってしまい、DSLとして非常に読みづらい。なので自前でインデントを追加した方が良いと考えられる。
また、他の部分についても複数の書き方ができたりするが、読みやすい側に統一したい。というわけで、個人的に決めているコーディング規約をまとめた。使ったことのある機能のみしか決められないので、今後経験が増えたら追加・修正していくつもり。
RouteBuilder
基本となるroute全体の形について。
configure()
の中身だけ示す。from("direct:sample").routeId("MySampleRoute") // some process .to("mock:aaa").id("SamplePartA") .log(LoggingLevel.DEBUG, "very long text...") // another process .to("mock:bbb") ;
- 基本は1行1メソッド(1処理)とする
- ただし直前のを修飾するものは同じ行を推奨
- 例えば
id()
は同じ行(XMLのDSLの場合を考えればいい)routeId()
はrouteにIDを設定するので、from()
と同じ行、せめて次の行- 処理のグループ単位を表したければ空行を設ける
- 継続行はインデントを2段(※)つける
- Javaのスタイルに準拠
- メソッドの引数を改行する場合もインデント2段
- 引数が長すぎる場合は、定数に切り出すことも検討すること
- 逆に言えば始まりの
from()
だけ2段飛び出す- DSLで構造化する際はさらにインデントする(後述)
- 終わりを示す
;
は行を分ける
- 処理を追加した際、diffで余計な変更が出なくなる
※ インデント1段 = 4スペース(checkstyle)または1タブ、これは別途規約を定めること
構造化
条件分岐やループなどを作るものは、基本的に
xxx()
~end()
となっている。共通ルールは以下の通り。
- その内部を1段インデントする
- ブロックを視覚的に認識しやすくする
- Javaの同機能の構文に合わせる
end()
を省略しない
- 後段に処理を追加する際、
end()
を忘れると意味が変わってしまう- なお、
endXxx()
が用意されていても使わないこと(使い道が違う?)- オプションは
xxx()
と同じ行にする(長くなる場合は次の行にして1段下げる)choice
switch文に相当する(breakは不要)。ただしwhen側に条件式を書くので、SQLやRubyでできる式の無いcase文のほうがより似ている。
https://camel.apache.org/components/latest/eips/choice-eip.html
from("direct:sample") .choice() .when(new MyPredicateA()) .to("mock:aaa") .when(new MyPredicateB()) .to("mock:bbb") .otherwise() .to("mock:zzz") .end() ;
when()
やotherwise()
は1段、内部処理はさらに1段下げる
- Javaのswitch文に合わせた書き方
- ちなみにRubyのcase式だとwhenは下げない(elsifと同じという考え方のため)
when()
の引数に条件を書く
when().simple(...)
などは禁止するotherwise()
は処理が無い場合は省略する条件には
Predicate
のインスタンスを指定する。(ドキュメント)
- 自作したクラスを使う
header(name)
やsimple("${expr}")
などで直接booleanを得る(ValueBuilder)header(name).isEqualTo(value)
のようにbooleanを導く(PredicateBuilder)filter
分岐が
when()
1個のみの場合は、choice()
の代わりにfilter()
の使用を検討する。行数やインデントが減り読みやすくなる。ガード節を書く際などは特に有用。https://camel.apache.org/components/latest/eips/filter-eip.html
ガード節の例// ガード節無しだと読みにくい(※これはcamelに限らない) from("direct:noGuard") .choice() .when(new MyPredicate()) .to("mock:doNothing") .otherwise() .to("mock:doSomething1") .to("mock:doSomething2") .to("mock:doSomething3") .end() ; // choiceでもガード節は作れるけど、ちょっと大げさ from("direct:guardByChoice") .choice() .when(new MyPredicate()) .to("mock:doNothing") .stop() .end() .to("mock:doSomething1") .to("mock:doSomething2") .to("mock:doSomething3") ; // filterだと簡潔 from("direct:guardByFilter") .filter(new MyPredicate()) .to("mock:doNothing") .stop() .end() .to("mock:doSomething1") .to("mock:doSomething2") .to("mock:doSomething3") ;split
foreach文に相当する。Listなどの中身を個別に新しいexchangeに詰めて処理する。
https://camel.apache.org/components/latest/eips/split-eip.html
from("direct:sample") .split(body()).parallelProcessing() .log("content: ${body}") .to("mock:abc") .end() ;
split()
の引数に、分割するものを書く
split().body()
などは禁止するloop, while
ループ回数をインデックス参照できる(0始まり)。for文のように回数指定する場合は
loop()
、while文のように条件指定する場合はloopDoWhile()
を使う。https://camel.apache.org/components/latest/eips/loop-eip.html
from("direct:sample") .loop(100).copy() .log("index: ${exchangeProperty[CamelLoopIndex]}") .to("mock:abc") .end() ;try … catch … finally
例外処理もある。
https://camel.apache.org/manual/latest/try-catch-finally.html
これもJavaの文法に合わせて、
doTry()
,doCatch()
,doFinally()
,end()
を同じインデント、それぞれの内部を1段下げることとする。TryProcessorMultipleExceptionTest.javafrom("direct:start") .doTry() .process(new ProcessorFail()) .to("mock:result") .doCatch(IOException.class, IllegalStateException.class) .to("mock:catch") .doFinally() .to("mock:finally") .end() ;引数かメソッドチェーンか
以下のメソッドはexchangeにデータを入れるためのもの。
setHeader()
setProperty()
setBody()
これらは入れる値を「引数で指定する」方法と「メソッドチェーンで指定する」方法がある。規約では「引数で指定する」ほうに統一する。routeを構成する1メソッドがそのまま1処理になっているほうが分かりやすいと思う。
構造化のところで
when()
やsplit()
などに対し引数で指定しているのも、同じ考え方に基づく。// disliked from("direct:dislikedSample") .setHeader("foo").expression(new MyExpression()) .setProperty("bar").header("foo") .setBody().exchangeProperty("bar") ; // preferred from("direct:preferredSample") .setHeader("foo", new MyExpression()) .setProperty("bar", header("foo")) .setBody(exchangeProperty("bar")) ;引数には
Expression
のインスタンスを指定する。(ドキュメント)
- 自作したクラスを使う
constant(obj)
で直接Javaオブジェクトを指定するheader(name)
やsimple("${expr}")
などで値を得る規則の例外
ただし引数指定だと煩雑になる場合はメソッドチェーンにする。この際はなるべく同じ行に続けて書く。
例えば
marshal()
。引数に文字列を渡す方法もあるが、タイポなどを防ぐためにできれば用意された定数などを使いたい。そうすると引数の場合の方が長くなってしまう。from("direct:marshalSample") .marshal().json(JsonLibrary.Gson) .marshal(new JsonDataFormat(JsonLibrary.Gson)) ;式展開
log()
の引数の文字列では、simple()
と同じ式展開(と呼ぶのかは分からない…)が書ける。https://camel.apache.org/components/latest/languages/simple-language.html
from("direct:loggingSample") .log("foo :: ${header[foo]}") .log("bar :: ${exchangeProperty[bar]}") .log("baz :: ${body}") ;
- headerやpropertyの要素は、
.name
,:name
,[name]
のどれででも参照できる
- exchangeの中ではこれらは Map なので、連想配列らしく
[name]
が良い気がする- 必要ない限りは、キーをクォートで括らない
- headerの要素の参照時には、変数
header
を使いheaders
は使わない
- route構築に使っているメソッド名に合わせる
メソッド呼び出しなどさらに強力な式も書けるのだが、まだ詳細な規約は決められていない。
→ https://camel.apache.org/components/latest/languages/ognl-language.html状況に応じた選択
似たことを異なる方法でできる場合がある。目的に合ったもの、目的に特化したものを選ぶほうが可読性が高い。
ログ出力
2通り用意されている。用途が異なるので迷うことは無いはず。
- Log EIP ← 人間向けのメッセージを出力
- Log component ← exchangeの情報を出力
from("direct:start") .log(LoggingLevel.DEBUG, "org.apache.camel.sample", "any message") .to("log:org.apache.camel.sample?level=DEBUG&showAll=true&multiline=true") ;choiceかfilterか
構造化のところで説明した通り。
filter()
はif文1個(else無し)の分岐だけを書けると思っていい。式展開かメソッド組合せか
Simple Expression Languageは式展開(?)を使えば様々な値や条件式を作れる。一方で、普通の値(ValueBuilder)に対して操作できるメソッドもある。メソッドで書けばコンパイル時点で単純なミスに気付ける可能性が高まるが、良いメソッドが無いと長くなりやすい。どちらが読みやすいかは状況によるので参考程度に。
from("direct:simpleOrValue") // create same strings .setHeader("sample1", simple("hoge: ${header[hoge]}")) .setHeader("sample2", header("hoge").prepend("hoge: ")) // check same conditions .choice() .when(simple("${header[CamelSqlRowCount]} != 1")) .log("record not unique!") .when(header(SqlConstants.SQL_ROW_COUNT).isNotEqualTo(1)) .log("record not unique!") .end() ;
- 投稿日:2020-07-29T18:14:50+09:00
【Java入門】クラスについて(クラスの定義、インスタンス化、コンストラクタ)
目的
Java言語を含めたプログラミングの学習を始めたばかりの方、既学習者の方は復習用に、
今回はクラスについて学ぶために書いています。【Java入門目次】
・変数と型
・型変換
・変数のスコープ
・文字列の操作
・配列の操作
・演算子
・条件分岐
・繰り返し処理
・クラスについて ←今ここ
・抽象クラス(準備中)
・インターフェース(準備中)
・カプセル化(準備中)
・モジュールについて(準備中)
・例外処理について
・ラムダ式について
・Stream APIについてクラスとは
属性(変数)
: そのクラスを元に生成された実体のデータに当たるもの。
- メンバ変数と呼ばれ、インスタンス変数とstatic変数(クラス変数)の2種類があります。
操作(メソッド)
: そのクラスを元に生成された実体の属性を処理するもの。
- メンバメソッドと呼ばれ、インスタンスメソッドとstaticメソッド(クラスメソッド)の2種類があります。
上記をまとめた設計図(雛形)の様なものです。
クラスの定義方法
構文(修飾子) class クラス名 { // メンバ変数 // メンバメソッド }変数の宣言方法
構文と例// (修飾子) データ型 変数名 String name; private int age = 5; // 初期化をする事も可能メソッドの定義方法
構文// (修飾子) 戻り値の型 メソッド名(引数) { 処理 };戻り値の型には、メソッドを呼び出し値を返す場合、その返す結果のデータ型を記述します。
(int型同士の計算結果を返したいならint、String型の文字列結合を行って返したいならString)戻り値を何も返さなくて良い場合は、voidと記述します。
何かしら値を返す場合(void以外の時)、処理の最後に
return 戻す値(データ型は戻り値の型)
としなければいけません。メソッドの記述例// 引数に何も受け取らず、戻り値としてString型を返す public String getName() { return // String型の値 } // 引数にString型の値を受け取り、戻り値は何も返さない public void setName(String name) { } // 引数にint型の値を受け取り、戻り値はint型の配列を返す private int[] getNumbers(int i) { return // int型の配列 }修飾子についての詳しい説明は、別記事にてまとめる予定ですので本記事では割愛します。
では、クラスを作成します。
クラスの例public class Animal { String name; // インスタンス変数 static int count; // static変数(クラス変数) // コンストラクタの定義(コンストラクタについては後述) Animal() { count++; // countをインクリメント } // インスタンスメソッド(nameを取得するため) public String getName() { return name; } // インスタンスメソッド(nameに値を代入するため) public void setName(String name) { this.name = name; } // staticメソッド(countを取得するため) public static int getCount() { return count; } }これでAnimalクラスの定義は完了です。
オブジェクトとは
クラス(設計図)を元に作成された実体の事です。
設計図だけではプログラムを動かす事が出来ないので、オブジェクトを作成する必要があります。
クラスからオブジェクトを作成するには、newキーワードを用います
。これをインスタンス化と言います。構文データ型 変数名 = new クラス名();先ほどのAnimalクラスを元にインスタンス化してみます。
インスタンス化の例// Animalクラスを定義 class Animal { String name; static int count; Animal() { count++; } public String getName() { return name; } public void setName(String name) { this.name = name; } public static int getCount() { return count; } } // Mainクラスを定義 class Main { public static void main(String[] args) { // catという変数名でオブジェクトを作成(インスタンス化) Animal cat = new Animal(); cat.setName("きなこ"); // catのnameをセット System.out.println(cat.getName()); // catのnameを取得 System.out.println(Animal.getCount()); // Animalクラスのcountを取得 // dogという変数名でオブジェクトを作成(インスタンス化) Animal dog = new Animal(); dog.setName("小太郎"); // dogのnameをセット System.out.println(dog.getName()); // dogのnameを取得 System.out.println(Animal.getCount()); // Animalクラスのcountを取得 } }実行結果きなこ 1 小太郎 2Animalクラス(設計図)を元にcat、dog(オブジェクト)を作成しています。
Animalクラスで定義されている各メソッドを呼び出し、name変数への代入や値の取得、static変数(クラス変数)の値の取得が出来ています。コンストラクタとは
新たなオブジェクトを作成(インスタンス化)する時に一番初めに実行される処理の事です。
コンストラクタの定義方法は以下になります。
1.クラス内で明示的に定義する
2.明示的に定義しなかった場合はコンパイラによって追加される(クラス内に1つもコンストラクタがない時)。明示的に定義する方法はメソッドと似ていますが、以下のルールに注意しなければいけません。
- コンストラクタ名はクラス名と同じ
- 戻り値は持たないので戻り値の型宣言もしない
- 引数を受け取る事が出来る
コンストラクタの処理には、インスタンス化された時に同時に行っておきたい事を記述します。
構文(修飾子) コンストラクタ名(引数) { // 処理 }コンストラクタの呼び出し方法は以下になります。
コンストラクタの呼び出し方new コンストラクタ名() new コンストラクタ名(引数)先ほどのAnimal cat =
new Animal()
;は、コンストラクタを呼び出していたという事になります。
クラス内に定義していなかったので、コンパイラによって追加されていたのです。
これをデフォルトコンストラクタ
と呼びます。(明示的にコンストラクタを定義した場合、デフォルトコンストラクタは作成されなくなる。)では、コンストラクタを明示的に定義して、インスタンス化時に行ってもらいたい処理を記述してみます。
コンストラクタの例class Animal { String name; // コンストラクタを定義 Animal(String name) { this.name = name; // 引数で受け取った値をインスタンス変数に代入している } public String getName() { return name; } public void setName(String name) { this.name = name; } } class Main { public static void main(String[] args) { Animal cat = new Animal("きなこ"); // コンストラクタを呼び出し、値を渡している // cat.setName("きなこ"); ← コンストラクタがnameをセットしてくれるため、不要になった System.out.println(cat.getName()); // Animal dog = new Animal(); // 引数に何も書かないとコンパイルエラーになる(デフォルトコンストラクタがなくなった為) Animal dog = new Animal("小太郎"); // dog.setName("小太郎"); ← コンストラクタがnameをセットしてくれるため、不要になった System.out.println(dog.getName()); } }この様に初期化作業など行えるため、先ほどは3行で行っていた処理を2行で行う事が出来ました。
オーバーロード
初期化はしたくない時は、何も処理をしない用のコンストラクタを定義しましょう。
明示的にコンストラクタを定義したため、引数なしのデフォルトコンストラクタをコンパイル時に用意してくれなくなった為です。コンストラクタを複数定義する例class Animal { String name; // コンストラクタを定義 Animal(String name) { this.name = name; } // コンストラクタを定義2 ←追加 Animal() { } public String getName() { return name; } public void setName(String name) { this.name = name; } } class Test { public static void main(String[] args) { Animal cat = new Animal("きなこ"); System.out.println(cat.getName()); // Animal dog = new Animal("小太郎"); Animal dog = new Animal(); // ←追加 引数に何も書かなくてもエラーにならない dog.setName("小太郎"); // ←追加 その代わりに、名前を忘れずにセットする事 System.out.println(dog.getName()); } }この様に
引数の順番やデータ型、数が異なっている
という条件を満たしている場合、
同じ名前のコンストラクタを複数定義する事が可能です。これをオーバーロードと呼び、
メソッドも同様に条件を満たしていれば複数定義する事が可能です。
条件を満たしていない場合は、コンパイルエラーになるので注意しましょう。
メソッドのオーバーロードの例class Animal { String name; public String getName() { return name; } // OK! public String getName(String str, int num) { return name; } // OK! public String getName(int num, String str) { return name; } // NG! オーバーロード出来ずコンパイルエラー // public String getName() { // return name; // } }終わりに
オブジェクト指向において基本となるクラスについて学びました。
基本ですのでしっかり理解を深めておきたいですね。
修飾子や継承やインターフェースとまだまだ学ぶ事は多いと感じました。参考サイト
- 投稿日:2020-07-29T13:21:43+09:00
Kotlinから使えないJavaコード(社内勉強会用)
- 概要
- 業務でハマった問題について発表します
- 実際のところ私もよく分ってないので、ぜひ分かる方はコメント下さい
- 前提
- Android Kotlin/JVMで、Java製のLibraryをKotlinから利用
実際にハマったコード
Desk.javapackage library_package; abstract class BaseDesk { public enum Color { BLUE, ORANGE } } public class Desk extends BaseDesk { private Color color; public Desk(Color color) { this.color = color; } }こういうJava実装を、Javaから使うのは、当然うまくいく。
javanew Desk(Desk.Color.BLUE);Kotlinから使うと、Compile Errorになる。
kotlinDesk(Desk.Color.BLUE) // Unresolved reference: Colorkotlinimport library_package.BaseDesk // Cannot access 'BaseDesk': it is package-private in 'library_package' Desk(BaseDesk.Color.BLUE) // Cannot access 'Color': it is public in 'BaseDesk'
どう回避したか
この問題を解決するために(だろうか?)
getColorEnum()
という static method が用意されていた。Desk.javapackage library_package; abstract class BaseDesk { public enum Color { BLUE, ORANGE } public static Color getColorEnum(String name) { return Color.valueOf(name); } }kotlin@Suppress("INACCESSIBLE_TYPE") // suppress warning は必要だが Desk(Desk.getColorEnum("BLUE")) // DeskコンストラクタにColorインスタンスを入れることが出来た
なぜエラーになったり/ならなかったり?
どういうケースでエラーとなるのか見てみると...
Foo.javaclass BaseFoo { public static int i = 0; public static int inc() { return ++i; } public static class FooFoo { public static int j = 0; } } public class Foo extends BaseFoo {}javaint foo_i = Foo.i; int foo_inc = Foo.inc(); int foo_foo_j = Foo.FooFoo.j;kotlinval foo_i = Foo.i val foo_inc = Foo.inc() val foo_foo_j: Int = Foo.FooFoo.j // Unresolved reference: FooFooKotlinでは、super class の static inner class にアクセスできないようだ。
根拠となる言語仕様を軽く調べてみたが、わからなかった。
なぜメソッドの戻り値としては使えたのか?
Javaは、もともと不可視なクラスを戻り値に定義できるようだ。
public class Bar { public static InternalBar getBar() { return new InternalBar(); } private static class InternalBar extends Bar {} } Bar bar = Bar.getBar(); // OKKotlinでは、こんな事はできない。
open class Baz { companion object { fun getInternalBaz(): InternalBaz { // 'public' function exposes its 'private' return type InternalBaz return InternalBaz() } fun getBaz(): Baz { // OK return InternalBaz() } } private class InternalBaz : Baz() }
INACCESSIBLE_TYPE warning とは?
参照できない場合にエラーとするKotlin Compilerの挙動が、前述のようなJavaの仕様と上手く合致せずにコンパイルできない問題があり、いまはCompile ErrorではなくWarningにしているが、今後適切に、本当にアクセス不可な場合だけコンパイルエラーとするように再変更する予定、ということらしい。
https://youtrack.jetbrains.com/issue/KT-11398 を参照。
もし Library 側に getColorEnum() が用意されてなかったら?
自分でJavaでUtility Methodを作ればよい。
DeskColorResolver.javaimport library_package.Desk; public class DeskColorResolver { public static Desk.Color getColor(String name) { return Desk.Color.valueOf(name); } }kotlinval desk = Desk(DeskColorResolver.getColorEnum("BLUE"))と書ける。
本当にこれが正解だろうか...?
thanks!
- 投稿日:2020-07-29T11:05:28+09:00
51歳(現52)からのプログラミング 備忘 VScodeでjava.awt javax.swing // Java 11 or more recent is required to run
VScodeでjavaを復習してたんだけれど
JFrameの挙動を確認しようとしたらVScode「vscode Java 11 or more recent is required to run...」
私「うーむ」
VScodeでjava.awt javax.swing をimportする
僕の場合には、eclipseで使ってるjdkがver8なので、VScodeもver8で揃えたいのが前提
- windows側の環境設定で jdk 8のパスを指定(省略)
- VScode側のsettings.jsonで2項目を指定
- VScode側のLanguage Suport for javaのバージョン変更
をやってきます
なお、このエラーには、2020-9月のJDK更新時と、それにVScodeが対応した時に修正されるのかな?なので、この記事はそれまでの限定記事。
2.setting.json
java.homeでjdkの指定
java.configuration.runtimesでjdkの指定"java.home": "C:\\Program Files\\AdoptOpenJDK\\jdk-8.0.262.10-openj9", "java.configuration.runtimes": [ { "default":true, "name": "JavaSE-1.8", "path": "C:\\Program Files\\AdoptOpenJDK\\jdk-8.0.262.10-openj9", }, ],3.Language Supprt for java
何故か分からないけど、この拡張機能のバージョンを下げないと、エラーになってしまう。intelisense(コード補完機能)に対応させるなら、ver0.57以上ということなので、そこまで下げた。
エラー要因
要因の1つはJDK11のAPI(awt/swing)とwindowsの相性に問題があってエラー。これを改善するには2020年9月のjdk更新まで待つか、jdk8などの古いバージョンで対応するのだけれど、2つ目の要因としてVScodeの仕様でJDK11を求められてしまう。
VScodeはeclipseに準拠してて、eclipseは最新のjdkを推奨するようなのですけど、VScodeは、より強くそういうところを要求するらしいのですよね。なのでVScode側で指定するjdkが推奨バージョンと異なると、実行時エラーにするような仕様のよう。これを回避するには、javaの実行構成を指定するのですね。VScodeの拡張機能(LanguageSupportForJava)のバージョンを下げる理由は分からないけれど、もしかしたらバージョン毎に対応するjdkが違うってことなのかも。