20191023のJavaに関する記事は10件です。

どうしても「new T()」したい!(しかも検査例外なしで)

結論

T型のインスタンスを生成する関数型インターフェースのインスタンスを、引数で受け取る。

// newT()が必要なメソッド
<T> T doSomething(Supplier<T> supplier) {
    T instance = supplier.get();
    return instance;
}

// doSomethingを呼び出すメソッド
void caller() {
    Test instance = this.doSomething(() -> new Test());
}

解説

そもそも new T()がアンチパターンなのはわかっていても、 new T() したいときもある。
そのときの解決法としてよく提示されるのが以下のパターン。

ClassインスタンスをもらってnewInstance()する

<T> T doSomething(Class<T> clazz) throws InstantiationException, IllegalAccessException {
    T instance = clazz.newIntance();
    return instance;
}

void caller() {
   Test instance = this.doSomething(Test.class);
}

このコードの問題点は検査例外をスローすること。

検査例外をスローする

上述のコードの通り、 InstantiationExceptionIllegalAccessExceptionをスローする。
Class.newInstance() 側としては妥当な設計だとは思うが、使う側としてはコンストラクタが例外をスローしないことを確信できる場合もあるわけで…。
そうするとわざわざ上記例外を try-catch したり throws したりするのは面倒くさい。
さらに検査例外なので、streamと相性が悪く1、内部でtry-catchが必要になる

<T extends SuperTest> List<T> doSomething(Class<T> clazz, List<String> valueList) throws InstantiationException, IllegalAccessException {
    return valueList.stream()
        .map(value -> {
            // せっかくstreamでスマートに書きたいのにtry-catch…
            try {
                T obj = clazz.newInstance();
                obj.setValue(value);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        })
        .collect(Collectors.toList());
}

その点、関数型インターフェースは余計な検査例外が発生しないので比較的綺麗にかける(コンストラクタにthrowsがある場合は別)。

余談

コンストラクタが引数をとる場合はFunction<T, R>のインスタンスを使う。
2つならBiFunction<T, U, R>
3つ以上の場合は、引数のためのクラスを作るなり、java.util.Mapを使うなりする。

引数が1つ
// newT()が必要なメソッド
<T> T doSomething(Function<String, T> func) {
    T instance = func.apply("コンストラクタの引数");
    return instance;
}

// doSomethingを呼び出すメソッド
void caller() {
    Test instance = this.doSomething((str) -> new Test(str));
}
引数が2つ
// newT()が必要なメソッド
<T> T doSomething(BiFunction<String, Integer, T> func) {
    T instance = func.apply("コンストラクタの引数", 1);
    return instance;
}

// doSomethingを呼び出すメソッド
void caller() {
    Test instance = this.doSomething((str, number) -> new Test(str, number));
}

  1. 正確には関数型インターフェースと相性が悪い。 

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

EclipseにLombokを設定する方法

  • 環境
    • Windows10 Pro 64bit
    • java version 1.8.0_231
    • Eclipse Oxygen.3a Release (4.7.3a)
  • 設定対象 : Lombok Version : 1.16.18

事前準備

  1. Eclipseを開いている場合は閉じる

ダウンロードする

  1. projectlombok.orgからjar(lombok-1.16.18.jar)ファイルをダウンロードする

Eclipseに設定する

  1. $ java -jar /path/to/lombok-1.16.18.jar でjarを実行してダイアログを開く
    1. jarファイルをダブルクリックしても開く
  2. 表示されたEclipseにチェックを入れて[Install/Update]ボタンでインストールする
    1. 設定対象のEclipseが表示されない場合は[Specify location...]ボタンからEclipseのインストールディレクトリを指定する
    2. image.png
    3. 画像はMacで設定したときのものなので参考程度に見てください
  3. eclipse.iniに-javaagent:lombok.jarが追記される
  4. [Quit Installer]ボタンでダイアログを閉じる
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Kotlin】「is~」で始まるメソッドでBoolean?を返す場合AssertTrue / AssertFalseでバリデーションできない【BeanValidation】

記事内容はタイトル通りです。

こうなる原理は以下の記事をご参照ください。

概要

メソッドにAssertTrueを付けた場合、バリデーションできる/できないは以下のようになります。

// バリデーションできる
@AssertTrue
fun getHoge(): Boolean? = false

// バリデーションできない
@AssertTrue
fun isHoge(): Boolean? = false

// バリデーションできる
@AssertTrue
fun isFuga(): Boolean = false

原因

以下は上記コードのデコンパイル結果です。

KotlinBoolean?型をjava.lang.Booleanにコンパイルします。
そして、冒頭に貼り付けた記事の通り、java.lang.Booleanはオブジェクトなので、BeanValidationis~から始まるメソッドを無視してしまうため、バリデーションは機能しません。

@AssertTrue
@Nullable
public final Boolean getHoge() {
   return false;
}
@AssertTrue
@Nullable
public final Boolean isHoge() {
   return false;
}
@AssertTrue
public final boolean isFuga() {
   return false;
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Spring Boot 2.2.0でLazy Initializationを試してみた

Spring Boot v2.2.0

Spring Boot v2.2.0がリリースされ、GAとなりました。

なので、その機能の一つであるLazyInitializationについて検証してみます。

Spring Boot 2.2.0
Release v2.2.0.RELEASE · spring-projects/spring-boot · GitHub
Spring Boot 2.2 Release Notes · spring-projects/spring-boot Wiki · GitHub
Spring Boot Reference Documentation

環境

  • Windows10
  • OracleJDK 13(build 13)
  • Spring Boot 2.2.0 RELEAS

Projectの作成

ひながたとなるProjectは、Spring Initializrから作成します。

spring-initializr.PNG

Gradle

Spring Initializrで作成したGradleプロジェクトでは、Gradle 5.6.2が適用されることを確認しました。

> gradlew -version

------------------------------------------------------------
Gradle 5.6.2
------------------------------------------------------------

Build time:   2019-09-05 16:13:54 UTC
Revision:     55a5e53d855db8fc7b0e494412fc624051a8e781

Kotlin:       1.3.41
Groovy:       2.5.4
Ant:          Apache Ant(TM) version 1.9.14 compiled on March 12 2019
JVM:          13-ea (Oracle Corporation 13-ea+33)
OS:           Windows 10 10.0 amd64

Lazy Initialization

ApplicationContextで管理するBeanの生成を、アプリケーションの起動時(≒ApplicationContextの初期化時)ではなくて、対象のBeanの呼び出しがされる際に行うのが、Lazy Initializationです。

この機構は以前のバージョンからもありますが、v2.2.0からはpropertyspring.main.lazy-initializationにtrueを適用することで、一律LazyInitializationが適用されます。

  • application.yml
spring:
  main:
    lazy-initialization: true
  • Bean class
package jp.co.musako.domain.model;

public class LazyInitializationDemoBean {

    private String message;

    public LazyInitializationDemoBean(String message) {
        this.message = message;
        System.out.println("call constructor " + this.message);
    }

    public void writer(String message){
        System.out.println(this.message + " is " + message);
    }
}
  • config class
package jp.co.musako.config;

import jp.co.musako.domain.model.LazyInitializationDemoBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Config {

    @Bean("lazyInitializationDemoBean1")
    public LazyInitializationDemoBean lazyInitializationDemoBean1(){
        return new LazyInitializationDemoBean("create lazyInitializationDemoBean1");
    }

    @Bean("lazyInitializationDemoBean2")
    public LazyInitializationDemoBean lazyInitializationDemoBean2(){
        return new LazyInitializationDemoBean("create lazyInitializationDemoBean2");
    }
}
  • main class
package jp.co.musako;

import jp.co.musako.domain.model.LazyInitializationDemoBean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
        System.out.println("Initialize Application Context");

        LazyInitializationDemoBean bean1 = ctx.getBean("lazyInitializationDemoBean1", LazyInitializationDemoBean.class);
        bean1.writer("first bean");

        LazyInitializationDemoBean bean2 = ctx.getBean("lazyInitializationDemoBean2", LazyInitializationDemoBean.class);
        bean2.writer("second bean");
    }
}

実行結果

>gradlew bootRun

> Task :bootRun

2019-10-23 18:16:37.620  INFO 12708 --- [           main] jp.co.musako.Application                 : Started Application in 4.295 seconds (JVM running for 4.933)
Initialize Application Context
call constructor lazyInitializationDemoBean1
lazyInitializationDemoBean1 is first bean
call constructor lazyInitializationDemoBean2
lazyInitializationDemoBean2 is second bean

ここで、以下の順序で処理がされていることがわかります。

  1. アプリケーション起動
    • 起動後に「Initialize Application Context」を出力
  2. Beanの生成
    • Beanのコンストラクタ内で「call constructor lazyInitializationDemoBean1」を出力
  3. 生成したBeanのwriterメソッドが呼び出される
    • writerメソッドで「lazyInitializationDemoBean1 is first bean」を出力

Lazy Initializationの適用除外

spring.main.lazy-initialization=trueを設定してLazyInitializationをプロジェクトに適用しつつ、特定のBeanをLazyInitializationの対象外とするには以下の方法があります。

  1. @org.springframework.context.annotation.Lazy(false)をBeanに設定する
  2. org.springframework.boot.LazyInitializationExcludeFilterに対象外とするBeanを登録する
  • config class
package jp.co.musako.config;

import jp.co.musako.domain.model.ExcludeLazyInitializationDemoBean;
import jp.co.musako.domain.model.LazyInitializationDemoBean;
import org.springframework.boot.LazyInitializationExcludeFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

@Configuration
public class Config {

    @Bean
    static LazyInitializationExcludeFilter integrationLazyInitExcludeFilter() {
        return LazyInitializationExcludeFilter.forBeanTypes(ExcludeLazyInitializationDemoBean.class);
    }

    // Lazy Initialization適用対象
    @Bean("lazyInitializationDemoBean1")
    public LazyInitializationDemoBean lazyInitializationDemoBean1(){
        return new LazyInitializationDemoBean("lazyInitializationDemoBean1");
    }

    // Lazy Initialization適用対象外
    @Bean("lazyInitializationDemoBean2")
    @Lazy(false)
    public LazyInitializationDemoBean lazyInitializationDemoBean2(){
        return new LazyInitializationDemoBean("lazyInitializationDemoBean2");
    }

    // Lazy Initialization適用対象外
    @Bean
    public ExcludeLazyInitializationDemoBean ExcludeLazyInitializationDemoBean(){
        return new ExcludeLazyInitializationDemoBean("excludeLazyInitializationDemoBean");
    }
}
  • main class
package jp.co.musako;

import jp.co.musako.domain.model.ExcludeLazyInitializationDemoBean;
import jp.co.musako.domain.model.LazyInitializationDemoBean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
        System.out.println("Initialize Application Context");

        LazyInitializationDemoBean bean1 = ctx.getBean("lazyInitializationDemoBean1", LazyInitializationDemoBean.class);
        bean1.writer("first bean");

        LazyInitializationDemoBean bean2 = ctx.getBean("lazyInitializationDemoBean2", LazyInitializationDemoBean.class);
        bean2.writer("second bean");

        ExcludeLazyInitializationDemoBean ExcludeLazyInitializationBean = ctx.getBean("ExcludeLazyInitializationDemoBean", ExcludeLazyInitializationDemoBean.class);
        ExcludeLazyInitializationBean.writer("third bean");
    }

}

  • 実行結果
>gradlew bootRun

> Task :bootRun

call constructor lazyInitializationDemoBean2
call constructor excludeLazyInitializationDemoBean
2019-10-23 18:52:52.464  INFO 6004 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-10-23 18:52:52.468  INFO 6004 --- [           main] jp.co.musako.Application                 : Started Application in 2.978 seconds (JVM running for 3.454)
Initialize Application Context
call constructor lazyInitializationDemoBean1
lazyInitializationDemoBean1 is first bean
lazyInitializationDemoBean2 is second bean
excludeLazyInitializationDemoBean is third bean

上記のように、Config.javaで定義した3つのBeanのうち、lazyInitializationDemoBean1のみがLazyInitializationの対象となることがわかります。

ソースコードはこちら:GitHub - forests-k/spring-boot-lazy-initialization
: Spring Boot v2.2.0 lazy-initialization sample

Lazy Initializationの適用時の検討事項

Lazy Intializationを導入するメリットは、アプリケーション起動時の速度が向上すること、必要な時に初期化するため無駄にメモリを消費しないことにあります。

しかし、必要な時にBeanを初期化してコンテナにBeanを保持するということは、これまでのBeanのライフサイクルが一部変更となり、コンテナ内で保持するBeanの最大となりうる数量(=メモリ占有量)がみえないことがあるので、CPUへの負荷やロードアベレージへの影響がある、すなわちLazyInitializationを過信しすぎてはいけない、という可能性があるかもしれないです。

そのため、テスト環境や本番同等の環境で一時的にLazy Initializationを無効化するなどのテストを実施することも視野に入れるべきと思われます。

ref

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

Spring Boot 2.2.0でLazy Initializationを試してみる

Spring Boot v2.2.0

Spring Boot v2.2.0がリリースされ、GAとなりました。

なので、その機能の一つであるLazyInitializationについて検証してみます。

Spring Boot 2.2.0
Release v2.2.0.RELEASE · spring-projects/spring-boot · GitHub
Spring Boot 2.2 Release Notes · spring-projects/spring-boot Wiki · GitHub
Spring Boot Reference Documentation

環境

  • Windows10
  • OracleJDK 13(build 13)
  • Spring Boot 2.2.0 RELEAS

Projectの作成

ひながたとなるProjectは、Spring Initializrから作成します。

spring-initializr.PNG

Gradle

Spring Initializrで作成したGradleプロジェクトでは、Gradle 5.6.2が適用されることを確認しました。

> gradlew -version

------------------------------------------------------------
Gradle 5.6.2
------------------------------------------------------------

Build time:   2019-09-05 16:13:54 UTC
Revision:     55a5e53d855db8fc7b0e494412fc624051a8e781

Kotlin:       1.3.41
Groovy:       2.5.4
Ant:          Apache Ant(TM) version 1.9.14 compiled on March 12 2019
JVM:          13-ea (Oracle Corporation 13-ea+33)
OS:           Windows 10 10.0 amd64

lazy-initialization

ApplicationContextで管理するBeanの生成を、アプリケーションの起動時(≒ApplicationContextの初期化時)ではなくて、対象のBeanの呼び出しがされる際に行うのが、Lazy Initializationです。

この機構は以前のバージョンからもありますが、v2.2.0からはpropertyspring.main.lazy-initializationにtrueを適用することで、一律LazyInitializationが適用されます。

  • application.yml
spring:
  main:
    lazy-initialization: true
  • Bean class
package jp.co.musako.domain.model;

public class LazyInitializationDemoBean {

    private String message;

    public LazyInitializationDemoBean(String message) {
        this.message = message;
        System.out.println("call constructor " + this.message);
    }

    public void writer(String message){
        System.out.println(this.message + " is " + message);
    }
}
  • config class
package jp.co.musako.config;

import jp.co.musako.domain.model.LazyInitializationDemoBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Config {

    @Bean("lazyInitializationDemoBean1")
    public LazyInitializationDemoBean lazyInitializationDemoBean1(){
        return new LazyInitializationDemoBean("create lazyInitializationDemoBean1");
    }

    @Bean("lazyInitializationDemoBean2")
    public LazyInitializationDemoBean lazyInitializationDemoBean2(){
        return new LazyInitializationDemoBean("create lazyInitializationDemoBean2");
    }
}
  • main class
package jp.co.musako;

import jp.co.musako.domain.model.LazyInitializationDemoBean;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
        System.out.println("Initialize Application Context");

        LazyInitializationDemoBean bean1 = ctx.getBean("lazyInitializationDemoBean1", LazyInitializationDemoBean.class);
        bean1.writer("first bean");

        LazyInitializationDemoBean bean2 = ctx.getBean("lazyInitializationDemoBean2", LazyInitializationDemoBean.class);
        bean2.writer("second bean");
    }
}

実行結果

>gradlew bootRun

> Task :bootRun

2019-10-23 18:16:37.620  INFO 12708 --- [           main] jp.co.musako.Application                 : Started Application in 4.295 seconds (JVM running for 4.933)
Initialize Application Context
call constructor lazyInitializationDemoBean1
lazyInitializationDemoBean1 is first bean
call constructor lazyInitializationDemoBean2
lazyInitializationDemoBean2 is second bean

ここで、以下の順序で処理がされていることがわかります。

  1. アプリケーション起動
    • 起動後に「Initialize Application Context」を出力
  2. Beanの生成
    • Beanのコンストラクタ内で「call constructor lazyInitializationDemoBean1」を出力
  3. 生成したBeanのwriterメソッドが呼び出される
    • writerメソッドで「lazyInitializationDemoBean1 is first bean」を出力

Lazy Initializationの適用除外

spring.main.lazy-initialization=trueを設定してLazyInitializationをプロジェクトに適用しつつ、特定のBeanをLazyInitializationの対象外とするには以下の方法があります。

  1. @org.springframework.context.annotation.Lazy(false)をBeanに設定する
  2. org.springframework.boot.LazyInitializationExcludeFilterに対象外とするBeanを登録する
  • config class
package jp.co.musako.config;

import jp.co.musako.domain.model.ExcludeLazyInitializationDemoBean;
import jp.co.musako.domain.model.LazyInitializationDemoBean;
import org.springframework.boot.LazyInitializationExcludeFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

@Configuration
public class Config {

    @Bean
    static LazyInitializationExcludeFilter integrationLazyInitExcludeFilter() {
        return LazyInitializationExcludeFilter.forBeanTypes(ExcludeLazyInitializationDemoBean.class);
    }

    // Lazy Initialization適用対象
    @Bean("lazyInitializationDemoBean1")
    public LazyInitializationDemoBean lazyInitializationDemoBean1(){
        return new LazyInitializationDemoBean("lazyInitializationDemoBean1");
    }

    // Lazy Initialization適用対象外
    @Bean("lazyInitializationDemoBean2")
    @Lazy(false)
    public LazyInitializationDemoBean lazyInitializationDemoBean2(){
        return new LazyInitializationDemoBean("lazyInitializationDemoBean2");
    }

    // Lazy Initialization適用対象外
    @Bean
    public ExcludeLazyInitializationDemoBean ExcludeLazyInitializationDemoBean(){
        return new ExcludeLazyInitializationDemoBean("excludeLazyInitializationDemoBean");
    }
}
  • 実行結果
>gradlew bootRun

> Task :bootRun

call constructor lazyInitializationDemoBean2
call constructor excludeLazyInitializationDemoBean
2019-10-23 18:52:52.464  INFO 6004 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-10-23 18:52:52.468  INFO 6004 --- [           main] jp.co.musako.Application                 : Started Application in 2.978 seconds (JVM running for 3.454)
Initialize Application Context
call constructor lazyInitializationDemoBean1
lazyInitializationDemoBean1 is first bean
lazyInitializationDemoBean2 is second bean
excludeLazyInitializationDemoBean is third bean

上記のように、Config.javaで定義した3つのBeanのうち、lazyInitializationDemoBean1のみがLazyInitializationの対象となることがわかります。

ソースコードはこちら:GitHub - forests-k/spring-boot-2.2.0: Spring Boot v2.2.0 sample

Lazy Initializationの適用時の検討事項

Lazy Intializationを導入するメリットは、アプリケーション起動時の速度が向上すること、必要な時に初期化するため無駄にメモリを消費しないことにあります。

しかし、必要な時にBeanを初期化してコンテナにBeanを保持するということは、これまでのBeanのライフサイクルが一部変更となり、コンテナ内で保持するBeanの最大となりうる数量(=メモリ占有量)がみえないことがあるので、CPUへの負荷やロードアベレージへの影響がある、すなわちLazyInitializationを過信しすぎてはいけない、という可能性があるかもしれないです。

そのため、テスト環境や本番同等の環境で一時的にLazy Initializationを無効化するなどのテストを実施することも視野に入れるべきと思われます。

ref

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

「基本からしっかり身につくAndroidアプリ開発入門」やってみた

基本からしっかり身につくAndroidアプリ開発入門

はじめに

 やあ、大学の課題地味に多くて忙しいのであるが、時間が余ってもどうせしょうもないことにしか時間を使わないので、何かをしようと思った私だ。いや誰だ。俺か。

ちなみに、大学ではいつも一人です(ぼっち自慢)。超どうでも良い(笑)。

前述した通り暇だからなんかしようと考えたのである。

大学の図書館にある技術書を読み漁りつつ評価とメモをqiitaに書いていく。

ということを思いついて、今回手にしたのは重厚で現代的な表紙の「Androidアプリ開発入門」だ。
すでにRuby on Railsでなんちゃって開発はできるので、アプリ開発もできたら、サービスを展開する時幅が広がるので時間を削って学習するメリットはあると考えた。

内容

    開発環境

  • OS:(俺は)Mac
  • 言語:Kotlin
  • 使用ソフト:Android Studio

chapter1 

Android studioのインストールから開発環境設定まで。

chapter2

Kotlinの書き方基礎


  • 変数と型の宣言

  • 配列、リスト、マップ

  • 条件式(if,when)とレンジ

  • 繰り返し文(while)

  • 関数(デフォルト引数、可変長引数...etc)
  • クラス...etc

chapter3

計算機アプリ(割引計算アプリ)を作る。
AndroidStudioにLabelForがないこと以外は、非常によい掴みになっている。


  • ファイル構造の把握

  • GUIの作り方

  • システムの作り方

  • 画面遷移のやり方

  • 多言語対応、デバックのやり方...etc

chapter4

データの保存とデータベースの使いかた。
SharedPreferences/リストビュー

chapter5

世界時計アプリを作る。

chapter6

アプリの通信とバックグランドでの処理について。
(Thred/Handler/AsyncTask...etc)
リサイクラービュー

chapter7

外部ストレージ

chapter8

デプロイ

つまづいたところ

chapter3 - activity_main.xml

アプリのヘッダーの部分が表示されない。
1.目のマークをクリック
Android_2.png
2.全てにチェックを入れる。

chapter4 - 文字列リソースの定義

view all attributesを開いてもlabelForの欄がない。

chapter5 -リストビュー用ミニアプリ

レイアウトファイルを作る時、Root elementをandroidx.constraintlayout.widget.ConstraintLayoutすることに注意!!

textClockがPaletteを選ぶ場所になかったので
DesignタブからTextタブに切り替えて、下のソースコードを追加。

<TextClock
android:id="@+id/textClock"
android:layout_width="173dp"
android:layout_height="89dp"
android:textSize="64sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.100000024"
tools:text="10:00" />

エラー文を見ると「TextClockが使えるバージョンにしよう」みたいなことを言われるので、v17/activity_main.xmlactivity_main.xml(v17)のファイルの生成を要求されるので従う。
次からはv17/activity_main.xml activity_main.xml(v17)のファイルを編集する。

chapter6-リサイクラー用ミニアプリ

RecyclerViewをDesignタブのAttributeタブで編集できない。
Textタブに切り替えて、
android:id="@+id/timeZoneList"
をタグの中に追加
layout_width,layout_heightも同様。

感想

Kotlin書籍1冊目だから比較ができないが、非常に読みやすいと感じた。
特にクラスや関数、メソッドあたりが自分の中でごちゃごちゃしていたので、こんなかんじで設計したり使ったりするんだなーってのがわかった。
また、スクリーンショットが複数あるので、基本的にストレスなくスムーズに進めながらアプリ開発の基礎を理解することができた気がする。
しかし、メソッドが豊富に使われているので記憶が定着しているうちに読み進めるか、何周かしたほうがいいと考える。

    よかったところ

  • Kotlinの基本文法の解説が詳しい。また、それぞれのコードの例とその結果が文法理解に役立つ。
  • コードの例が豊富
  • 文法解説は簡潔でわかりやすいと感じた(主観)
  • 小物アプリ開発のtutorialが複数用意されている。また、常にスクリーンショットが用意されており開発GUI操作でつまづかない
  • 複数のアプリ開発でフローを理解できる
  • 初心者でもとっつきやすい

    よくなかったところ

  • Android StudioのGUIが書籍のスクリーンショットと少し差異がある。(しょうがない)
  • 書籍が分厚い(しょうがない)
  • なんでかしらんけどlabelForがAttributeにない。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Java]Stringクラスを使って特定の文字列の手前までを取得する方法

文字列の取得の方法としてメモ書き。

Stringクラスには、最初に出現する文字列を取得する場合にはindexOfメソッドを、最後に出現する文字列を取得する場合はlastIndexOfメソッドを使用することで特定の文字列を取得することができる。

基本的な書き方はこんな感じ。

最初に出現する位置 = オブジェクト.indexOf(値)

最後に出現する位置 = オブジェクト.lastIndexOf(値)

今回はStringクラスでの使用方法についてまとめてみる。

⑴indexOfメソッド

・indexOf(int ch)
(戻り値の型はint)

この文字列内で、指定された文字が最初に出現する位置のインデックスを返します。値chを持つ文字がこのStringオブジェクトによって表される文字シーケンス内にある場合、最初に出現する位置のインデックス(Unicodeコード単位)が返されます。chの値が0から0xFFFFの範囲にある場合、次の式がtrueとなるような最小値kが返されます。
this.charAt(k) == ch
がtrueである。chがほかの値の場合、次の式がtrueとなるような最小値kです。
this.codePointAt(k) == ch
がtrueである。該当する文字がこの文字列内にない場合は、-1が返されます。
パラメータ:
ch - 文字(Unicodeコード・ポイント)。
戻り値:
このオブジェクトによって表される文字シーケンス内で、指定された文字が最初に出現する位置のインデックス。文字がない場合は-1。

・indexOf(int ch, int fromIndex)
(戻り値の型はint)
この文字列内で、指定されたインデックスから検索を開始し、指定された文字が最初に出現する位置のインデックスを返します。
値chを持つ文字が、このStringオブジェクトによって表される文字シーケンスのfromIndexより大きいか同じインデックス位置にある場合、該当する最初のインデックスが返されます。chの値が0から0xFFFFの範囲にある場合、次の式がtrueとなるような最小値kが返されます。
(this.charAt(k) == ch) && (k >= fromIndex)

がtrueである。chがほかの値の場合、次の式がtrueとなるような最小値kです。
(this.codePointAt(k) == ch) && (k >= fromIndex)

がtrueである。いずれの場合も、そのような文字がこの文字列内の位置fromIndexかそれより後に存在しない場合は、-1が返されます。
fromIndexの値に対して制約はない。負の値の場合は、ゼロの場合と同じ結果になります。この文字列全体が検索されます。この文字列の長さより大きい場合は、この文字列の長さに等しい場合と同じ結果になり、-1が返されます。
すべてのインデックスは、char値(Unicodeコード単位)で指定されます。
パラメータ:
ch - 文字(Unicodeコード・ポイント)。
fromIndex - 検索開始位置のインデックス。
戻り値:
このオブジェクトによって表される文字列で、指定された文字がfromIndexと同じかこれより大きいインデックス位置にある場合は、最初に出現した位置のインデックス。文字がない場合は-1。

(2)lastIndexOfメソッド
・lastIndexOf(int ch)
この文字列内で、指定された文字が最後に出現する位置のインデックスを返します。ch値が0から0xFFFFの範囲にある場合、返されるインデックス(Unicodeコード単位)は、次の式に該当する最大値kです。
this.charAt(k) == ch
がtrueである。chがほかの値の場合、次の式がtrueとなるような最大値kです。
this.codePointAt(k) == ch
がtrueである。該当する文字がこの文字列内にない場合は、-1が返されます。Stringの検索は最後の文字から開始され、先頭方向に行われます。
パラメータ:
ch - 文字(Unicodeコード・ポイント)。
戻り値:
このオブジェクトによって表される文字シーケンス内で、指定された文字が最後に出現する位置のインデックス。文字がない場合は-1。

・lastIndexOf(int ch, int fromIndex)
(戻り値の型はint)

この文字列内で、指定された文字が最後に出現する位置のインデックスを返します(検索は指定されたインデックスから開始され、先頭方向に行われる)。ch値が0から0xFFFFの範囲にある場合、返されるインデックスは、次の式に該当する最大値kです。
(this.charAt(k) == ch) && (k <= fromIndex)
がtrueである。chがほかの値の場合、次の式がtrueとなるような最大値kです。
(this.codePointAt(k) == ch) && (k <= fromIndex)
がtrueである。いずれの場合も、そのような文字がこの文字列内の位置fromIndexかそれより前に存在しない場合は、-1が返されます。
すべてのインデックスは、char値(Unicodeコード単位)で指定されます。
パラメータ:
ch - 文字(Unicodeコード・ポイント)。
fromIndex - 検索開始位置のインデックス。fromIndexの値に対して制約はない。この文字列の長さと同じかこれより大きい場合は、この文字列の長さより1小さい場合と同じ結果になり、この文字列全体が検索される。負の値の場合は、-1の場合と同じ結果になり、-1が返される。
戻り値:
このオブジェクトによって表される文字シーケンス内で、指定された文字がfromIndexと同じかこれより小さいインデックス位置に最後に出現する位置のインデックス。指定された文字がその位置より前にない場合は-1。

参考サイト
・Java(tm) Platform Standard Edition 8 クラスString
https://docs.oracle.com/javase/jp/8/docs/api/index.html?overview-summary.html

・すぐに使える!JavaのindexOfとlastIndexOf - エンジニアの入り口
https://eng-entrance.com/java-indexof

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

Spring Bootを触ってみたメモ

Spring Bootの特徴

兎に角、アノテーションによって他の言語と同じようにサーブレットの存在を無視したプログラミングができるようになっていることが大きな特徴なよう。


参照先

アノテーション 概要
@ Conponent DIコンテナにBeanとして登録する最も基本的なアノテーション
@ Configuration Bean定義をJavaベースで行うためのアノテーション ※言っている意味わからないので後ほど解説
@ Repository データの保存や読み込みなどを扱うためのクラスを示すアノテーションです。Spring Dataなど使いデータベースを利用する場合には、このアノテーションを指定することで自動的にテーブルにアクセスできるようにするなど、特別な意味を持つケースがあります。
@ Controller MVCのコントローラークラスであることを示すアノテーション。
@ Service ビジネスロジックなどを扱うためのクラスを示すアノテーション。

各サブプロジェクトで特別なものとして、これらのアノーテーションを上書きして別のアノテーションが定義される。

アノテーション 概要
@ SpringBootApplication Spring Bootのアプリケーションのmainプログラムを指定するための慣習として利用されるアノテーション
@ RestController REST用のコントローラとして登録するためのアノテーション
@ RestControllerAdvice 各コントローラで共通の入力データ形式の変換やエラー処理などの共通処理を定義するためのアノテーション。

※コーディングの際は@ と アノテーション名の間にはスペース不要

  • mavenを利用する場合
    • pom.xlmファイルに依存関係のパッケージを記載すると自動的に必要なパッケージを読み込んでくれる
    • application.properties 各パッケージで使用する設定をまとめて記載する場所
  • gradleを利用する場合
    • これから使ってみる予定

Entity周りのアノテーション概要

https://qiita.com/ughirose/items/5d691adc677aa08636b8

Spring Bootログ周りの設定概要

https://qiita.com/NagaokaKenichi/items/34356c72e8ac0279e1a0

RestAPI作成時の記載方法

https://qiita.com/MizoguchiKenji/items/2a041f3a3eb13274e55c

JpaRepositoryの使い方

http://terasolunaorg.github.io/guideline/5.5.1.RELEASE/ja/ArchitectureInDetail/DataAccessDetail/DataAccessJpa.html
さらに条件を加えて検索したいときの利用方法
https://qiita.com/ksh-fthr/items/44ecc0550a77f4280ea7

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

Java 単体テスト 同一日判定 ArDate,Date,Calendar,longが時刻を無視して同一日かを判定する

目次 ⇒ Java単体テストライブラリ-Artery-サンプル

Q05_02.java
package jp.avaj.lib.test;

import java.util.Date;

import jp.avaj.lib.algo.ArDate;
import jp.avaj.lib.algo.ArDateUtil;

/**
 Java 単体テスト 同一日判定 ArDate,Date,Calendar,longが時刻を無視して同一日かを判定する

 ・このサンプルではArDateとDateを比較するサンプル示すが、上記のどの組み合わせでも比較可能.
 ・注、ArDateは日付のみを保持しており、時刻は扱わない.
*/
public class Q05_02 {
  public static void main(String[] args) {
    // テストケースを開始する.
    ArTest.startTestCase("Q05_02");

    // 当日
    ArDate arDate0 = new ArDate();
    // 当日、当時刻
    Date date1 = new Date();
    // これを比較すれば同一日
    ArTest.sameDate("ArDate vs Date","arDate0",arDate0,"date1",date1);

    // date1を一時間進める、引数は日→時間→分の指定、このメソッドはCalendar,longでも使用可能.
    date1 = ArDateUtil.forward(date1,0,1,0,0);
    // (このテストを23時以前に実行すれば)同一日となる
    ArTest.sameDate("ArDate vs Date","arDate0",arDate0,"date1",date1);

    // arDate0を一日進める
    arDate0.forward(1);
    // 両方を比較すれば、同一日ではない
    ArTest.notSameDate("ArDate vs Date","arDate0",arDate0,"date1",date1);

    // date1を一日進める、
    date1 = ArDateUtil.forward(date1,1,0,0,0);
    // 再び同一日となる
    ArTest.sameDate("ArDate vs Date","arDate0",arDate0,"date1",date1);
    //
    // テストケースを終了する
    ArTest.endTestCase();
  }
}


結果は次の通り

result.txt
**** Q05_02 start ****
OK ArDate vs Date:arDate0=2019/10/23:date1=2019/10/23 06:37:09
OK ArDate vs Date:arDate0=2019/10/23:date1=2019/10/23 07:37:09
OK ArDate vs Date:arDate0=2019/10/24:date1=2019/10/23 07:37:09
OK ArDate vs Date:arDate0=2019/10/24:date1=2019/10/24 07:37:09
**** Q05_02 summary ****
test count = 4
success    = 4

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

Windows 版 Amazon Corretto インストール手順

Windows 版 OpenJDK インストール手順 - Qiita の二番煎じ。

調べ方

前提

  • サポートされている Windows であること。

備考

  • 新しいバージョンの OpenJDK をダウンロード, 展開した場合は, JAVA_HOME の変数値を変更するだけで OK.
    • Path は %JAVA_HOME%\bin のままとする。

インストール手順

  1. Amazon Corretto Production-ready distribution of OpenJDK にアクセスする。
    • 日本語版のサイトは情報が古い場合があるため, 画面上部より English を選択する。
  2. 画面右の Download Amazon Corretto 11 ボタンを押下する。
  3. Windows x64JDK に記載された zip ファイルをクリックする。
    • 今回は amazon-corretto-11.0.5.10.1-windows-x64.zip をクリックしたものとする。
  4. ダウンロードしたファイルを右クリックし, すべて展開 をクリックする。
    • 圧縮 (ZIP 形式) フォルダーの展開 ウィンドウが開く。
  5. ファイルを下のフォルダーに展開する 欄に, C:\ と入力し, 展開 ボタンを押下する。
    • 上記は, OS やブラウザーによってはコロン (:) の次にバックスラッシュが表示される場合があるが, 日本語キーボードの場合は円記号で OK.
    • C ドライブ直下に, jdk11.0.5_10 というフォルダーが展開される。
  6. ダウンロードしたファイルを削除する。
  7. 展開したフォルダーに移動し, アドレスバーよりパスをコピーする。
    • 今回のパスは C:\jdk11.0.5_10 となる。
  8. スタート - 設定 を開く。
    • Windows の設定 ウィンドウが表示される。
  9. 検索窓に 環境変数 と入力する。
    • 環境変数を編集システム環境変数の編集 が候補として表示される。
  10. 環境変数を編集 をクリックする。
    • 環境変数 ウィンドウが表示される。
  11. ユーザー環境変数新規 ボタンを押下する。
    • 新しいユーザー変数 ウィンドウが表示される。
  12. 以下の通りに入力し, OK ボタンを押下する。
    • 変数名: JAVA_HOME
    • 変数値: (先ほどコピーしたパスを貼り付ける。)
      • 今回の場合は C:\jdk11.0.5_10 を貼り付けることになる。
  13. 環境変数 ウィンドウに戻るので, ユーザー環境変数Path をクリックし, 編集 ボタンを押下する。
    • 環境変数名の編集 ウィンドウが表示される。
  14. 新規 ボタンを押下し, %JAVA_HOME%\bin と入力, OK ボタンを押下する。
    • 環境変数 ウィンドウに戻る。
  15. そのまま OK ボタンを押下する。
    • Windows の設定 ウィンドウは閉じても OK.
  16. コマンドプロンプトを開き, javajavac コマンドが利用できることを確認する。

    • > java -version
    openjdk version "11.0.5" 2019-10-15 LTS
    OpenJDK Runtime Environment Corretto-11.0.5.10.1 (build 11.0.5+10-LTS)
    OpenJDK 64-Bit Server VM Corretto-11.0.5.10.1 (build 11.0.5+10-LTS, mixed mode)
    
  • > javac -version

    javac 11.0.5
    

どっとはらい。

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