20200120のJavaに関する記事は7件です。

GradleプラグインのSpotlessでGoogle Java style guideを適用する

Google Java style guideをgradleを使って導入してみました。

ただしインデントの空白文字数は2文字ではなく4文字!!!!

Spltlessを使う

gradleのプラグインでGoogle Java styleを導入する場合、以下のものが便利そうでした。
spotless/plugin-gradle at master · diffplug/spotless · GitHub

適用する

さっそくgradleを書いて、プラグインを適用します。
インデントは4文字の空白文字にしたいので、設定を上書きします。

plugins {
    id "com.diffplug.gradle.spotless" version "3.27.1"
}

spotless {
    java {
        googleJavaFormat('1.7')
        // 設定の上書き
        indentWithSpaces(4)

        target '**/*.java'
    }
}

フォーマットチェックとフォーマット

Spltlessを使ったフォーマットは以下のコマンドで実行できます。IDEに依存しないので良いです。
CIでコードスタイルのチェックもできます。

# Style check
$ gradle spotlessJavaCheck

# Format
$ gradle spotlessJavaApply

でもこれじゃあダメだった・・・

改行の際のインデント空白文字数が8文字になっています。すごく間延びした感がある。

class HogeClass {

    private LocalDateTime now =
            now();
    // ,,,,8文字の空白文字でインデントされている

    private LocalDate date =
            of(2020, 12, 12);
}

Google Java styleでは、「改行は2インデント」を推奨しています。
よって本来であれば、空白文字4文字あけて改行されます。
しかし、今回は1インデントを4つの空白文字と定義を上書きしているので、2 * 4 =8文字インデントになっています。

対策

しかたがないので、eclipse-java-google-style.xml · GitHubフォーマットの定義をソースルートに配置し、以下の部分を修正します。

eclipse-java-google-style.xml
・・・省略・・・
<!— 連続する行のインデント数 default:2 to:1 —>
<setting id=“org.eclipse.jdt.core.formatter.continuation_indentation” value=“1”/>
・・・省略・・・
<!— インデント空白文字数 default:2 to:4 —>
<setting id=“org.eclipse.jdt.core.formatter.tabulation.size” value=“4”/>
・・・省略・・・
<!— 連続する行の配列インデント数 default:2 to:1 —>
<setting id=“org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer” value=“1”/>
・・・省略・・・
<!-- 任意に改行されている行を結合 default:true to:false -->
<setting id=“org.eclipse.jdt.core.formatter.join_wrapped_lines” value=“false”/>
・・・省略・・・
<!-- enumの任意の改行を許可する default:0 to:16 -->
<setting id=“org.eclipse.jdt.core.formatter.alignment_for_enum_constants” value=“16”/>

そして、定義をインポートするようにgradleで記述します。

build.gradle
spotless {
    java {
        eclipse().configFile 'eclipse-java-google-style.xml'
        target '**/*.java'
    }
}

eclipse-java-google-style.xmlはimpot文のスタイルについて記述されていません。
そこで、以下のように追記します。

build.gradle
spotless {
    java {
        eclipse().configFile 'eclipse-java-google-style.xml'
        // importはstaticインポート , 全ての非staticインポートの順序で並べる
        importOrder '\\#', ''
        target '**/*.java'
    }
}

結果

import static java.time.LocalDate.of;
import static java.time.LocalDateTime.now;

import java.time.LocalDate;
import java.time.LocalDateTime;

class HogeClass {

    private LocalDateTime now =
        now();

    private LocalDate date =
        of(2020, 12, 12);
}

Google Java style guideを適用しつつ、インデントは4文字の空白。を実現することができました。

参考

Spotless を使って Java コードのフォーマットチェック、フォーマット適用を実現する - なにか作る
Java/“Google Java Style” とビルドシステムからの一括フォーマッタ “Spotless” 関連メモ - Glamenv-Septzen.net

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

新卒1年目でJavaGold合格できたので勉強法について語っていく

はじめに

Javaの資格で最も難しい試験は?
と聞かれた時にJavaGoldと答えるエンジニアは多いと思います。

その最難関の資格であるJavaGoldを1年目で合格できましたので、

  • 勉強内容
  • 1年目で合格できてどうだったか

についてお話したいと思います。

勉強開始時のスペック

業務経験

  • 新卒1年目(学生時代は文系でプログラミングとは無縁)
  • 3ヶ月間の研修(Java/SQL/JDBC/Servlet/JSPなど)を経て、Javaの案件に配属
    →ただし、当時コードを書くことは殆ど無かった

保有資格

  • 基本情報技術者(1年目の4月に受験し合格)
  • JavaSilver(1年目の8月に受験し合格)

合格体験記は以下参照

受験のきっかけ

  • PJTの利用言語がJavaだった為、Javaに関する知識を身に付けたかった
    →まずは勉強した成果が形に残る資格に挑戦しようと思った

勉強期間

勉強開始時期 試験受験日 当時の状況
2018/10 2019/2/2 PJTが試験行程の為、業務内容はテストを中心
(たまにシェルの製造)

約4ヶ月間、勉強をして合格することができました。(12月は殆ど勉強していないので、実施3ヶ月程度)

試験概要

JavaGoldの試験概要は以下となります。

前提資格 問題数 合格ライン 試験時間
Java SE8 Silver 85問 65% 150分

JavaSilverとの違いとしては、

  • 受験する為にJavaSilverに合格する必要がある
  • 問題数が若干増えている(77問→85問)

の2点が挙げられます。
合格ラインと試験時間に関してはJavaSilverと同様です。

利用した書籍

紫本

オラクル認定資格教科書 Javaプログラマ Gold SE 8
JavaGoldで出題される項目が大体網羅されており、教科書的な存在。

黒本

徹底攻略Java SE 8 Gold問題集[1Z0-809]対応
各分野の問題と模擬試験(二回分)が用意されており、問題集的な存在。

役割としては以下のイメージです。

紫本:各単元の概要理解、黒本で間違えた問題の復習用
黒本:問題演習かつ各単元で出題される機能、メソッドの暗記用

✳︎白本(オラクル認定資格教科書 Javaプログラマ Gold SE 8 スピードマスター問題集)は利用していません。

合格の秘訣

秘訣1: 黒本を徹底的にやり込むこと

黒本の内容をどこまで理解出来るかが合格の鍵となります。

試験問題の難易度自体は高いですが、試験問題の大半が黒本の模擬試験の問題と似ているため、問題をやり込めばやり込むほど合格に近づきます。

✳︎注意点
問題の難易度が高いので解説の内容をきちんと理解する必要があります。

秘訣2:ストリームAPIを攻略すること

JavaGoldの試験はストリームAPIがとても多く出題される印象であり、この分野を攻略できることが合格の鍵となります。
基本的には紫本を読んで概要を理解する→黒本でひたすら演習を繰り返すことで得点できるようになります。
私が勉強した際は以下の課題の発生したため、

  • JavaSilverまで学んだコードと比べてどう動いているかよくわからない
  • 出題される大量のメソッドを覚えることができない

ストリームAPIの分野に関してはプラスαで以下の取り組みも実施しました。

  • JavaSilverまで学んだコードと比べてどう動いているかよくわからない
    サンプルコードの写経
  • 出題される大量のメソッドを覚えることができない
    メソッドの一覧をまとめて隙間時間に読む

スクリーンショット 2020-01-20 16.43.49.png

勉強書籍に関するQ&A

Q1:白本は必要ない?

A1:必要ないです。

私は白本の問題を解いたことがありませんが、評判を聞いている限り、黒本とはまた異なる傾向の問題が出題されるそうな印象を受けました。
黒本の内容を理解出来ていれば合格点に到達しますので、白本で新しい問題に触れるよりは黒本の間違えた箇所を復習して、出来る問題を増やしていくのが良いと思います。

Q2:紫本の模擬試験は解く必要ある?

A2:黒本しっかりやれば必要ないです。

黒本とダウンロードできる模擬試験(合計2回分)をやりこみば十分合格できます。
黒本の問題の解説はとても詳しいので、まずは黒本の内容を100%近く理解できるようにしましょう。
黒本をやり込んだ後に余裕があれば紫本の模擬試験を解くのはありだと思います。


Q3:そもそも紫本自体不要では?

A3:多分あったほうが良いです

紫本は黒本と異なり、サンプルコードと各分野で出題されるメソッドの一覧が豊富なので、実際に動かしてみたいときや、類似のメソッドや機能を比較する時に非常に便利です。
実際に問題が解けるようになるためには黒本が必須ですが、各機能の概要理解や復習に関しては紫本の方が向いているのであったほうがいいです。


Q4:黒本の模擬試験は何割ぐらい取れたら良い?

A4:初見で6割程度が目安だと思います

ただし、間違えた問題の復習は完璧にする前提です。


Q5:紫本に書いてない内容の問題が黒本にいくつか出題されてるんだけど?

A5:黒本に出題された問題は全て覚えるべき内容と割り切って取り組みましょう

黒本を解いている際に、紫本の範囲外の内容の問題が出題される時があります。
せっかく紫本を勉強したのに・・となりますが、ここは割り切って覚えるしかありません。

私が勉強した時は、紫本に記載のない黒本の内容は全て紫本に転記して、参照できるようにしていました。
IMG_1413.JPG


勉強の流れ

紫本を2周する(勉強開始〜2ヶ月目)

土日を中心にとりあえず紫本を一通り読みました。
基本的には読んで理解するだけでしたが、難しいと感じた分野(ストリームAPIなど)に関しては個別に調べたり、サンプルコードの写経やExcleにまとめたりしました。

黒本の1〜10章を解く(3ヶ月目〜)

紫本を一通り読み終えた後は黒本をとき始めました。
ただ、紫本を読んで理解するだけでは黒本の問題を殆ど解くことができませんでした。
殆ど解けなかった時は正直絶望しましたが、一から覚えるものだと割り切って、全問正解できたら次の章の問題を解き始めるといった流れで勉強を進めていきました。

黒本およびPDFの模擬試験を解く(受験日1週間前〜)

模擬試験の問題を解いて仕上げに入りました。
といっても黒本の1〜10章に比べて問題の難易度も高いため、間違えた問題も100%解けるように繰り返し復習を実施しました。(これが一番大事ですが)

試験結果

正答率78%で一発で合格できました。
image.png

模擬試験の結果的には正直厳しいかなと思っていましたが、思った以上に黒本で出題された内容が出てきたので合格ラインを大きく上回ることができました。

1年目でJavaGold合格してどうだった?

自身の技術力

合格当初は業務でJavaに触れる機会がなく、正直技術力が上がった実感がありませんでした。
ただ、2年目に入り大規模な開発を経験する上で、JavaGoldで学んだ内容は当たり前のように登場していたので、勉強してよかったと思う機会が多かったです。(残念ながらラムダ式やストリームAPIは現場で使っていませんが・・)
ただ、知識を知っているからといって、すぐ実装できるわけではありませんでした。
とっかかりとしてJavaGoldの勉強はよかったでしたが、実際にコードを書くのが技術的に一番成長できると思います。

上司の反応

「資格を取ったのはすごいけど、学んだことをどう価値発揮出来たかが大事だよね」
といったことを言われました。

全くもってその通りだと思います。
資格を取得しても、現場では実際にどう価値発揮するかを見ているので、資格をとっただけでは劇的に評価が上がるということはなさそうです。
ただ、高い目標を挙げてコミットしいく姿勢は評価されたかもしれません。

同期の反応

思った以上に驚かれました。
1年目でJavaGoldに合格する人は少ないので、どうやって勉強した?と聞かれることも多かったです。
また、JavaGoldを持っているだけで、ある程度Javaの実装経験できているという印象を持たれます。(実際は合格当時は殆ど実装できていませんでしたが・・。)

終わりに

JavaGoldは難易度の高い試験ですが、新卒1年目で合格することは全然可能です。
資格が全てではないですが、Javaを勉強する際にまずは資格からと考えている方の参考になれば幸いです。

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

クラス、メソッドの呼び出し方

Foodクラスのfruitsメソッド(Food.java)

Food.java
public class Food {
  // 以下のメソッドすべてを、Personクラスに移動してください

  public static String fruits(String fruitsName) {
    return fruitName;
  }

Mainクラスのmainメソッド(main.java)

Food.java内にあるFoodクラスのfruitsメソッドを呼び出し。

Main.java
public class Main {
  public static void main(String[] args) {

    Food.printData(Food.fruits("apple"));
    Food.printData(Food.fruits("straeberry", "Smith"), 65, 1.75, 80.0);
  }
}

別のクラスのメソッドを呼び出すときは、クラス名、メソッド名の前にそれぞれ、呼び出したいクラスの名前を書く必要有。

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

spring-bootでリソースファイルを外出しする方法

解決したいことはタイトル通りです。spring-boot では、DB接続情報などを src/main/resources 配下の application.properties に書くことが多いですが、このファイルを外部に置いて、コンパイル時とは別の定義で動作させる方法説明をします。
以前、『Mavenを使ってリソースファイルをJARの外部に配置する方法』というのを投稿しましたが、それの spring-boot 版です。

解決方法

spring-boot では実に簡単です。外部に配置したいリソースファイル(application.properties等)を別フォルダに配置して、実行時のクラスパスとして指定するだけです。

つまり、my-java-app.jar を実行するとして、external_resource フォルダの application.properties を読み込みたい場合、external_resource フォルダを実行時クラスパスに含めます。

フォルダ構成
my-java-app.jar
external_resource
  └ application.properties
コマンド
java -classpath ./external_resource -jar my-java-app.jar

解説

どうしてこのような動作になるかというと、spring-boot ではリソースファイルの読み込み優先順位が次のようになっているからです。

  1. 実行時のクラスパス
  2. コンパイル時の src/main/resources

実際には、以下で他の方が説明しているように読み込みの優先順位については、もっと詳細な定義があります。

最後に

spring-boot はいい感じにかゆいところに手が届くのでありがたいですね。そして、公式ドキュメントを翻訳してくれた @niwasawa さん、ありがとうございました。

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

何でも言うことを聞いてくれるアカネチャン

聞いてよアカネチャン!

[俺] 良いこと思いつきました!
[ア] なんや?
[俺] 俺, アカネチャンの列挙型をつくります!
[ア] あ ほ く さ
[俺] ...
[俺] ええええええええええええええええええ(ry

元ネタはこちら - 何でも言うことを聞いてくれるアカネチャン

キッカケは友人との会話

その場のノリで話してただけなので,詳しい経緯なんてものは覚えていません.

とりあえず『何でも言うことを聞いてくれるアカネチャンの返事はboolean型みたい』みたいな話をしたんだと思います.

理想は

if (Seyana) {
    System.out.println("True!!")
}

ですが,Seyanaをboolean型の代わりとして直接使うことはできないので,できる範囲でやってみました.お遊びです,何のメリットもありません.

作るよアカネチャン!

アカネチャンのセリフ

アカネチャンのセリフは採用したもの以外は受け付けたくないので,列挙型(enum)にしてします.また,各セリフにboolean型を紐づけたいので,それも決めます.結果以下のようになりました.

  • あほくさ(false)
  • あれな(true)
  • ええで(true)
  • ええんちゃう?(true)
  • ほんま(true)
  • 知らんがな(false)
  • 知らんけど(false)
  • それな(true)
  • そやな(true)
  • わかる(true)

無理やりtrue/falseを決めた部分もありますが,まぁ良いでしょう.

実装

AkaneChan列挙型をつくります.この中に先ほどのセリフを入れ込みます.このとき,列挙型にもprivateなコンストラクタを持たせることで,インスタンスに固有の値を持たせることができるので,それを使いboolean型を紐付けます.また,せっかくなので日本語と英語それぞれの文章も紐づけておきます.

例として「あほくさ」と「あれな」を実装すると以下のようになります.

public enum AkaneChan {
    Ahokusa(false, "Sounds stupid.", "あほくさ"),
    Arena(true, "Exactly...", "あれな"),
    ;

    private boolean agree;
    private String meaning_en;
    private String meaning_jp;

    private AkaneChan(boolean agree, String meaning_en, String meaning_jp) {
    this.agree = agree;
    this.meaning_en = meaning_en;
    this.meaning_jp = meaning_jp;
}
}

あとは,

  • isAgree() -- agreeをreturnするメソッド
  • getMeaning_en() -- meaning_en(英語の意味)をreturnするメソッド
  • getMeaning_jp() -- meaning_jp(日本語の意味)をreturnするメソッド

を作ってあげれば完成です.

使うよアカネチャン!

とてもシンプルです.理想は〜の部分に書いたif文を再現します.

if (AkaneChan.Seyana.isAgree()) {
    System.out.println("True!!");
} else {
    // 呼ばれることはない
    System.out.println("False!!");
}

結論

[俺] いらねぇよ!アカネチャン!!
[ア] せやなーそやなー知らんけどー(棒)

あとがき

先ほど実装したメソッドに加えて,ListenUpAkaneChanメソッドを追加したAkaneChan列挙型と,いくつかの無駄なものをセットにしてGithubに公開しています.

Github - YabPaseri/AKANE-CHAN

Java8環境で作ってますが,固有の何かを使っているわけではないので,問題なく使えるかと思います.

/build のなかに,jarファイル化したアカネチャンや,実際にアカネチャンを使っているプログラムSampleAkaneChan.javaも入っているので,よろしければ...使わないか(笑)

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

VM引数を変更しつつマイクロベンチマークする方法

VM引数を変更しながら、マイクロベンチマークを取りたいケースってあると思うのですが、
JITコンパイラに影響のある引数の場合、ただプログラムを実行して時間を計測するのみでは
うまくその影響を測れません。なぜなら、プログラムの実行中にVMが判断したタイミングでJITコンパイラが走りコードが最適化されるので、どの程度そのVM引数の変更の効果があったのか測れないからです。

JMH の利用

このようなケースでは、ベンチマークツールである JMH を使用するのが便利です。
JMH の使用方法についてはこちらのの記事で説明されていますので、以降では、JMHでのベンチマークの際にVM引数を指定する方法を説明します。

VM引数の指定方法

以下のようにベンチマークを行うメソッドにForkアノテーションを付与し、JvmArgsAppend属性を利用することによってVM引数を指定することができます。
この例では、「-XX:-Inline」を指定ています。

    @Benchmark
    @Fork(jvmArgsAppend = "-XX:-Inline") // アノテーションでVM引数を指定する
    public String インライン展開なし() {
        return execute();
    }

また、以下のように実装することによって、VM引数の有り無しを同時にベンチマークすることができます。

    @Benchmark
    public String インライン展開あり() {
        return execute();
    }

    @Benchmark
    @Fork(jvmArgsAppend = "-XX:-Inline") // アノテーションでVM引数を指定する
    public String インライン展開なし() {
        return execute();
    }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

apkからjavaファイル生成(BytecodeViewer式)

dex2jarでは精度がいまいちだったので精度の良かった物を紹介します

Bytecode Viewer

https://bytecodeviewer.com/

dex2jarの代わり。
GUI操作です。JD-GUIのような類ですね。
普通に便利です。apkやdex、jar、zip、classがデコンパイルできます。
デコンパイル後は好きなデコンパイラーで見れます。
apkから出たclassの保存とか、デコンパイラーでデコンパイルしたjavaの出力とか出来ます。
ただjavaへの出力は不安定です。
これをダウンロードして起動すすると「Drag class/jar/APK/DEX here」と書いてあるところがあるのでそこに.apkをドラッグ・アンド・ドロップしてください。
そしたら処理が終わると完成品が出てくるのでFile->Save As Zipからzipで保存してください。

Procyon

https://bitbucket.org/mstrobel/procyon/wiki/Java%20Decompiler

Bytecode Viewer内臓のデコンパイラーですね。
安定していると思います。

デコンパイル方法は、Bytecode Viewerで出力したzipの拡張子をjarに変更し

java -jar procyon-decompiler-x.x.xx.jar -jar myJar.jar -o out

Procyonのjarファイル名は自分のものに合わせて変えてください。
myJar.jarはBytecode Viewerで出力したファイル名です。
そしてこれを実行。outは出力先ディレクトリですね。ここにjavaファイルが入ります。予め作る必要はありません。

デコンパイラの比較

私は普段Fernflower派なのですが(普段使ってるIDEがIntellij IDEAなので)出来たソースコードを見て比較とかしましたがFernflowerより良いなと思った点が2つ。

  • ソースコードの書き方が簡略化されている
  • class内に書かれていない変数名がわかりやすいネーミング

精度としてはほぼFernflowerと同じで、Fernflowerでは書いてあってProcyonでは書いてなかったり、その逆もあったり。
結構精度は高いと思います。

for文比較
Fernflower

ServiceApiEnvironment[] var1 = values();
int var2 = var1.length;

for(int var3 = 0; var3 < var2; ++var3) {
  ServiceApiEnvironment var4 = var1[var3];
  if (var4.equals(var0)) {
    return var4;
  }
}

Procyon

for (final ServiceApiEnvironment serviceApiEnvironment : values()) {
  if (serviceApiEnvironment.equals(s)) {
    return serviceApiEnvironment;
  }
}

圧倒的にProcyonのほうが見やすいですよね。
なのでProcyonが一番最適かと思います。
エラーの数はFernflowerが大量に吐いてましたがProcyonは1回だけ。

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