きり丸の技術日記

技術検証したり、資格等をここに残していきます。

Javaで1行でNull許容の配列を作りたかった

結局、願ったとおりに動かなかったので、思考錯誤したときのメモだけ残します。

環境

  • Java
    • 17

対応

Collections.singletonList(T o)を使用することで、1行でnull許容した配列を作成できます。

動作確認

1行で配列を作成する方法は、List.of(), Arrays.asListのどちらもありますが、NotNull制約があるので、作成できません。

ArrayListはnullも追加可能ですが、初期配列の作成時には使えません。そもそも、初期配列の作成時のパラメータ自体が配列となるため、内部処理にてエラーが発生します。

var sample = new ArrayList<>();
assertAll(
    () -> assertThatThrownBy(() -> List.of(null))
        .isInstanceOf(NullPointerException.class),
    () -> assertThatThrownBy(() -> Arrays.asList(null))
        .isInstanceOf(NullPointerException.class),
    () -> assertThatThrownBy(() -> new ArrayList<>(null))
        .isInstanceOf(NullPointerException.class),
    () -> Collections.singletonList(null),
    () -> sample.add(null)
);

本当にやりたかったこと

戻り値としては配列で返却したいものの、内部の処理としては単数で受け取るメソッドがあるとします。現状、それを処理するためには4行の処理が必要だったので、1行に短縮したかったのです。

@Service
@RequiredArgsConstructor
public class SalesService {
  private final SalesComponent component;

  // NOTE: このコードは動かないので、イメージです
  public List<String> execute() {
    // あまり意味がないけど、4行必要
    var list = new ArrayList<String>();
    var result = component.execute();
    list.add(result);
    return list;

    // 1行でシンプル!
    return Collections.singleton(component.execute());
  }
}

なお、配列にNullを許容するメリットはあるかというと、ありませんでした。

Springの設定で、nullの場合は値を出力しない設定があります。

spring.jackson.default-property-inclusion: NON_EMPTY

こちらの設定をすることで、配列にnullを許容しつつ、JSONのResponseBodyには影響しないと考えていました。しかし、上記の設定では期待とおりの設定はできません。インスタンスのフィールドが一部nullだった時の挙動だけが変わりました。インスタンスそのものがNullとして設定されていた場合は、出力されてしまいます。しかも、空文字列や空配列になるのではなく、nullと出力されてしまいました。

{
  "salesList": [null]
}

結局、素直にnullが入らないように処理しています。

@Service
@RequiredArgsConstructor
public class SalesService {
  private final SalesComponent component;

  public List<String> execute() {
    var result = component.execute();
    if (result == null) {
      return List.of();
    } else {
      return List.of(result);
    }
  }
}

ソースコード

細かい挙動確認等々は、次のソースコードを確認してください。

終わりに

1行で書きたかったです…。もしくは、初期設定時やaddするときのパラメータは許容するものの、配列としてはパラメータを無視するようなメソッドがあるとうれしいのですが。まぁ、限定的な要望ですので、素直に処理するのが簡単ですね。

類似情報

IntelliJ IDEA ULTIMATEでOpen APIのコードを生成する

小ネタ。以前、OpenAPI Generatorをカスタマイズしたコードを生成する(Swagger Codegenとほぼ同じ)という記事を書きました。

上記の記事では、openapi-generatorのjarをCLIで実行してソースコードを生成しています。その検証中に、IntelliJ IDEA ULTIMATEの機能を使えば、簡単にソースコード生成ができることが分かったので、ブログにします。

環境

  • IntelliJ IDEA
    • 2022.2.3

対応

下準備

OpenAPIで用意しているサンプルファイルをダウンロードします。

ファイルを開く

有効なOpen APIのファイルをIntelliJ IDEAで開いていると、エディタの左上に実行ボタンと、生成設定の編集ボタンが表示されます。

基本的には、何も設定せず、デフォルトのまま生成できます。強いていえば、言語がjavaになっていますが、普段使用しているフレームワークに合わせてspringに変更するくらいでしょうか。

詳細設定タブを選択したときには、カスタムテンプレートパスを設定できます。もし、前回の記事のように、生成コードをカスタマイズしたい場合には、ここにパスを設定してください。

ソースコード

特になし。

終わりに

必ずしも、IntelliJ IDEA、しかもULTIMATEで開発できる環境にいるとは限らないので、前回の記事で十分な内容ではあります。

ただ、ULTIMATEにはOpen APIのようなエコシステムも簡単に対応してくれるので、非常に便利ですね。

参考情報

類似情報

何をもってN月第1週とする?

普段N月M週という表現で何となく通じていますが、具体的な定義があるかをしらべました。

結論を先に述べると、明確な定義をしている表現はありませんでした。ですが、週について色々と調べたのでまとめておきます。

木曜日を起点として1年を週に分割する(ISO 8601/JIS X0301の定義)

正規表現で「YYYY-Www-D」と表記する方法があります。こちらの定義では、「最初の木曜日を含む週が、その年の第1週である」としています。

この定義に合わせて、最初の木曜日を含む週がその月の第1週と表現しても問題ないでしょう。ただし、あくまで1年間を週として分割する際の定義ですので、月に関してまでは厳密に定義はしていません。

曜日コードを基準にする(月曜日を起点・カレンダー通り)

曜日に関してはISO 8601でコードとして定義されています。月曜日は1、日曜日は7です。

曜日コードとしては月曜日が起点ですので、月初1日が月曜日の場合は第1週、それ以外の場合は最初の月曜日を含む日付までを第1週として起算したほうが良さそうです。

難しいこと書いていますが、基本的には日本の大多数のカレンダー通りです。(アメリカに関しては日曜始まりのカレンダーが多いらしいので、定義がズレてしまいますが)

歴週を基準とする(日曜日を起点)

歴週という日曜日から土曜日までを一週間とする考えがあります。

一九八八年に施行された「労働基準法の一部を改正する法律(昭和六二年法律第九九号)」でも、こちらの歴週を扱うような記載がありました。ただ、現在の労働基準法に該当の記載はなかったので、どこかのタイミングで改正はされたとは思います。

また、病院の診療報酬における「1週につき1回算定」とは特に断りがない場合には歴週のことを指すらしいです。

終わりに

具体的な定義はないようですが、色々調べてみると面白かったです。セクションとしては用意していませんでしたが、地動説から生まれた曜日から考えると、土曜日始まりの定義も昔はあったようです。

元々はこちらのツイートを見てからの再度色々調査をしていたのですが、官公庁から出ている調査等も見つかって面白かったです。ぜひ、参考情報の方も見ていただけると面白いのではないかと思います。

twitter.com

参考情報