Javaのnullチェックでif文を使いたくない(解決せず)

解決した(2018/08/04 追加)

Javaのnullチェックでif文を使いたくない(個人的には解決) - ikhrのブログ

最近の悩み

public class TestNull {
    @SuppressWarnings("unused")
    public static void main(String[] args) {
        //何らかの処理の戻り値ParentBeanの値がnullと仮定
        ParentBean parentBean = null;
        //悩みの種
        if (parentBean != null && parentBean.getChildBean() != null) {
            System.out.println(parentBean.getChildBean().getGrandChildBean().getName());
        }
    }
}

Java SE8でOptionalというものが追加された

public class TestNull {
    public static void main(String[] args) {
        Optional<ParentBean> parentBean = Optional.ofNullable(null);
        //isPresent
        //今までと同じことに。。
        //parentBeanの中身もOptionalでラップしてもらう必要がある。。※面倒臭いので割愛
        if (parentBean.isPresent()) {
            System.out.println(parentBean.get().getChildBean().getGrandChildBean().getName());
        }

        //ifPresent
        //これもやってること変わらない気がする。
        parentBean.ifPresent(bean -> System.out.println(bean.getChildBean().getGrandChildBean().getName()));
    }
}

参考

https://docs.oracle.com/javase/jp/8/docs/api/java/util/Optional.html

所感

Optionalは個々の実装で扱うものではないなと感じました。 今回悩みは解決に至りませんでした。

awkで変数を定義する

はじめに

ログ分析等でawkを利用することが多い。どのサーバのログかが分かるよう、出力結果にホスト名等を含めたいことがある。試行錯誤(というほど考えていないが。。)した結果、pwdの結果をawkに渡すのが汎用的かなと思って、その紹介です。

pwd

単純にpwdするとカレントディレクトリのフルパスになるので、カレントディレクトリだけ抜粋したい。
コマンド

$ pwd

結果

/Users/ユーザ名/Documents/blog_awk/host1


basename

ディレクトリ名を除いた文字列を返すコマンド。
コマンド

$ basename 

結果

usage: basename string [suffix]
       basename [-a] [-s suffix] string [...]


pwd + basename + awk

コマンド

$ awk -v host=$(basename $(pwd)) '{print host, $1}' test.txt 

結果

host1 aaa
host1 bbb
host1 ccc

Gradleのinitプラグインに触れた

Gradleには色々なプラグインが存在する。その中でタスク、ライフサイクルが定義されており、ちょっとしたことをする上で、これらの理解が必要となる雰囲気。この環境のGradleのバージョンは4.3である。

initプラグインがサポートするtypeはメッセージ的には次の通り。
この中の内、java-libraryjava-applicationbasicについてディレクトリ構造とbuild.gradleファイルの内容を確認する。

Supported types: 'basic', 'groovy-application', 'groovy-library', 'java-application', 'java-library', 'pom', 'scala-library'.

java-libraryで作る

$ gradle init --type java-library

BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed

$ tree
.
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
    ├── main
    │   └── java
    │       └── Library.java
    └── test
        └── java
            └── LibraryTest.java

7 directories, 8 files

java-libraryのbuild.gradle

$ cat build.gradle 
/*
 * This build file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Java Library project to get you started.
 * For more details take a look at the Java Libraries chapter in the Gradle
 * user guide available at https://docs.gradle.org/4.3.1/userguide/java_library_plugin.html
 */

// Apply the java-library plugin to add support for Java Library
apply plugin: 'java-library'

// In this section you declare where to find the dependencies of your project
repositories {
    // Use jcenter for resolving your dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}

dependencies {
    // This dependency is exported to consumers, that is to say found on their compile classpath.
    api 'org.apache.commons:commons-math3:3.6.1'

    // This dependency is used internally, and not exposed to consumers on their own compile classpath.
    implementation 'com.google.guava:guava:23.0'

    // Use JUnit test framework
    testImplementation 'junit:junit:4.12'
}

java-applicationで作る

ユーザーガイドでは--test-frameworkの指定をしているが、無しで。

$ gradle init --type java-application
Starting a Gradle Daemon (subsequent builds will be faster)

BUILD SUCCESSFUL in 5s
2 actionable tasks: 2 executed

$ tree
.
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
    ├── main
    │   └── java
    │       └── App.java
    └── test
        └── java
            └── AppTest.java

7 directories, 8 files

java-applicationのbuild.gradle

$ cat build.gradle 
/*
 * This build file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Java project to get you started.
 * For more details take a look at the Java Quickstart chapter in the Gradle
 * user guide available at https://docs.gradle.org/4.3.1/userguide/tutorial_java_projects.html
 */

// Apply the java plugin to add support for Java
apply plugin: 'java'

// Apply the application plugin to add support for building an application
apply plugin: 'application'

// In this section you declare where to find the dependencies of your project
repositories {
    // Use jcenter for resolving your dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}

dependencies {
    // This dependency is found on compile classpath of this component and consumers.
    compile 'com.google.guava:guava:23.0'

    // Use JUnit test framework
    testCompile 'junit:junit:4.12'
}

// Define the main class for the application
mainClassName = 'App'

applicationってそういうapplicationなのね。

basicで作る

$ gradle init --type basic

BUILD SUCCESSFUL in 0s
2 actionable tasks: 2 executed

$ tree
.
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle

2 directories, 6 files

basicのbuild.gradle

$ cat build.gradle 
/*
 * This build file was generated by the Gradle 'init' task.
 *
 * This generated file contains a commented-out sample Java project to get you started.
 * For more details take a look at the Java Quickstart chapter in the Gradle
 * user guide available at https://docs.gradle.org/4.3.1/userguide/tutorial_java_projects.html
 */

/*
// Apply the java plugin to add support for Java
apply plugin: 'java'

// In this section you declare where to find the dependencies of your project
repositories {
    // Use 'jcenter' for resolving your dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}

// In this section you declare the dependencies for your production and test code
dependencies {
    // The production code uses the SLF4J logging API at compile time
    compile 'org.slf4j:slf4j-api:1.7.25'

    // Declare the dependency for your favourite test framework you want to use in your tests.
    // TestNG is also supported by the Gradle Test task. Just change the
    // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add
    // 'test.useTestNG()' to your build script.
    testCompile 'junit:junit:4.12'
}
*/

所感

Gradeのプラグインを触りつつも、自分でGroovy書かないと、Gradleすげーってならない気がしてきた。

GitHub Gistを使って.gitignoreを管理&ダウンロードする

.gitignoreを都度作り直すのが面倒だった。
Gistで単一ファイルのバージョン管理が出来ることを知った。
GistのRAWのURLをwgetすればカレントディレクトリにダウンロードできる。

$ wget https://gist.githubusercontent.com/ikhr/5452bcba318ec1d89b32ffc2bf898370/raw/9e9aad05f5e9c8d71408988f06e2902c6961d986/.gitignore

URLの後半のハッシュ値がリビジョンを示しているようで、最新ファイルのダウンロードにはならない。

Macへコマンドをインストールする

Mactreewgetをインストールした記録です。

Macへコマンドを追加する方法としてHomebrewと呼ばれるMac OS用のパッケージマネージャーがあるそうです。RedHatLinuxで言うところのRPMYum等の仲間です。
Homebrewは奥さんがインストールを済ませておいたらしいので割愛します。

treeを追加する。

$ brew install tree
Error: Cannot write to /usr/local/Cellar

世の中そんなに甘くないようで、エラーになりました。
ではsudoで。

$ sudo brew install tree

WARNING: Improper use of the sudo command could lead to data loss
or the deletion of important system files. Please double-check your
typing when using sudo. Type "man sudo" for more information.

To proceed, enter your password, or type Ctrl-C to abort.

Password:
Error: Cowardly refusing to 'sudo brew install'
You can use brew with sudo, but only if the brew executable is owned by root.
However, this is both not recommended and completely unsupported so do so at
your own risk.

親切設計。
brewのオーナーがrootではなかった為、止めてくれました。
書き込めなかったディレクトリのオーナーを確認し、suして再実行。

$ brew install tree
==> Downloading https://homebrew.bintray.com/bottles/tree-1.7.0.el_capitan.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring tree-1.7.0.el_capitan.bottle.1.tar.gz
🍺  /usr/local/Cellar/tree/1.7.0: 7 files, 112.4K

続いてwget

$ brew install wget
==> Installing dependencies for wget: openssl
==> Installing wget dependency: openssl
==> Downloading https://homebrew.bintray.com/bottles/openssl-1.0.2f.el_capitan.bottle.tar.gz
######################################################################## 100.0%
==> Pouring openssl-1.0.2f.el_capitan.bottle.tar.gz
==> Caveats
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
  /usr/local/etc/openssl/certs

and run
  /usr/local/opt/openssl/bin/c_rehash

This formula is keg-only, which means it was not symlinked into /usr/local.

Apple has deprecated use of OpenSSL in favor of its own TLS and crypto libraries

Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:

    LDFLAGS:  -L/usr/local/opt/openssl/lib
    CPPFLAGS: -I/usr/local/opt/openssl/include

==> Summary
🍺  /usr/local/Cellar/openssl/1.0.2f: 466 files, 11.9M
==> Installing wget
==> Downloading https://homebrew.bintray.com/bottles/wget-1.17.1.el_capitan.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring wget-1.17.1.el_capitan.bottle.1.tar.gz
🍺  /usr/local/Cellar/wget/1.17.1: 9 files, 1.5M

少し賢くなりました。

Hello Gradle

Gradle日本語ドキュメントを見て手を動かす。

$ git clone https://github.com/ikhr/gradlestudy
Cloning into 'gradlestudy'...
warning: You appear to have cloned an empty repository.
$ cd gradlestudy/
$ cat build.gradle 
task hello {
  doLast {
    println 'Hello world!'
  }
}
$ gradle -q hello
Hello world!

せっかくなのでGitHubで管理しておきたい。

$ git add .
$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   .gradle/4.3.1/fileChanges/last-build.bin
    new file:   .gradle/4.3.1/fileHashes/fileHashes.bin
    new file:   .gradle/4.3.1/fileHashes/fileHashes.lock
    new file:   .gradle/4.3.1/taskHistory/taskHistory.lock
    new file:   .gradle/buildOutputCleanup/buildOutputCleanup.lock
    new file:   .gradle/buildOutputCleanup/cache.properties
    new file:   build.gradle

邪魔そうなのがaddされてしまったので、addを取り消す。

$ git reset HEAD .
fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

怒られてオプションを減らす。

$ git reset
$ cat .gitignore 
# Gradle
.gradle
!gradle-wrapper.jar
$ git add .
$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   .gitignore
    new file:   build.gradle

$ git commit -m "first commit"
[master (root-commit) 9fc8c18] first commit
 2 files changed, 8 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 build.gradle
$ git push -u origin master
Username for 'https://github.com': ikhr
Password for 'https://ikhr@github.com': 
Counting objects: 4, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 331 bytes | 0 bytes/s, done.
Total 4 (delta 0), reused 0 (delta 0)
To https://github.com/ikhr/gradlestudy
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

微妙に修正してcommitしてみる。

$ gradle -q hell
Hello world!!
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   build.gradle

no changes added to commit (use "git add" and/or "git commit -a")
$ git add build.gradle
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   build.gradle

$ git diff

add後のdiffは--cachedが必要。

$ git diff --cached
diff --git a/build.gradle b/build.gradle
index 153d849..3481f2b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,5 @@
 task hello {
   doLast {
-    println 'Hello world!'
+    println 'Hello world!!'
   }
 }

GitHubへpushするのも四苦八苦

$ git push -u origin master
Branch master set up to track remote branch master from origin.
Everything up-to-date
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   build.gradle

$ git commit -m "commit"
[master 71ff171] commit
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git push origin master
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 319 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/ikhr/gradlestudy
   9fc8c18..71ff171  master -> master

参考

第6章 ビルドスクリプトの基本

.5 Git の基本 - リモートでの作業