20190710のJavaに関する記事は5件です。

MacでのEclipseを用いたSpring-Bootのビルドまで(Gradle版)

はじめに

環境構築とHelloWorldは開発の9割の時間がかかってしまうので
それを解決するために記事を作成しました。

環境

MacOS Mojave 10.14.3

Eclipse 4.11.0

Gradle 5.5

大まかな環境作成

JDKとEclipseについてはググれば出てくると思うので省略します。

JDKのバージョンは10とか9にするとうまくいかないことがあるので8ぐらいにしとけばいいと思います


Eclipseは最新版をインストール。日本語を落としました。

プロジェクト作成

雛形は楽なのでSpring Initializrを使いましょう。

当然Eclipseからもできますが、
最初は依存関係やらで悩むことになるのである程度使いそうなところをネットに落ちてる記事とかから最初にGUIでぽちぽちやったほうがエラーに悩まないと思います。
image.png

とりあえずGradleを選択、言語はJava、SpringBootのバージョンはそのままでいいです。

Groupにはルートパッケージ名。そんなに深く考えなくていいです。今回はcom.p0ngchang.teamlabとしました。

Artifactはプロジェクト名。作るものの名前をつけてあげるといいです。

image.png


Dependenciesは依存関係です。使うのはWeb, JPA, Thymeleaf, DevTools, MySQLあたりを選んでけばいいと思います。

image.png

落としてきたzipを開くとこんな感じになってると思います。

特に足りないものがなければこれをEclipseにインポートします。

image.png


既存のGraleプロジェクトを選んで、ダウンロードしたzipファイルの解凍したものを
プロジェクトルートディレクトリに選択。あとは次へを連打。

するとこんな感じでプロジェクトが展開できると思います。

image.png


ここまでくればとりあえずプロジェクトが用意できました。
あとはここから実行するだけですね。

ここでおそらく依存関係でMySQLを選んでいるのにデータベースの指定をBuild.Gradleでしていないから1

だと思うのですが、エラーが出て実行できないと思います

以下エラー文章

Description:

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class

Action:

Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).

そこで、

implementation 'org.hsqldb:hsqldb:2.3.2'

この1文Gradle.buildに追加しましょう

plugins {
    id 'org.springframework.boot' version '2.1.6.RELEASE'
    id 'java'
}

apply plugin: 'io.spring.dependency-management'

group = 'com.p0ngch4ng'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
tasks.withType(AbstractCompile)*.options*.encoding = 'UTF-8'
configurations {
    developmentOnly
    runtimeClasspath {
        extendsFrom developmentOnly
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    runtimeOnly 'mysql:mysql-connector-java'
    //ここに追加!
    //
    implementation 'org.hsqldb:hsqldb:2.3.2'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

}

書き足したらこのままでは更新されないのでプロジェクトの上で右クリックして Gradle → Refresh Dependencies を選択。2

これであとはプロジェクトを右クリックして実行→Spring Bootアプリケーションを選択すれば実行できるはずです!!
エンジョイ!JAVAライフ!

参考文献等



https://qiita.com/aono-masashi/items/a0045d8dc7ea8f106cdf


https://qiita.com/keb/items/c039d00c85fd99c2cee1

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

Linux(CentOS7)にJava(jdk1.8)を手動でインストールする手順

2017/06/03に作成した資料をアップします。

Linux(CentOS7)にJavaをインストールする簡単な方法として、yumコマンドやrpmコマンドでインストールする方法があるが、ここでは手動でインストールする方法を紹介する。

1. CentOS7にログインし、rootユーザーにスイッチする。

$ su -
#

2. Oracleのウェブページから「jdk-8u131-linux-x64.tar.gz」をダウンロードする。

# curl -OL --header "Cookie: oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz"

(リンク先のURLは変わっているかも?)
(コマンドではなく、ブラウザからダウンロードしても良い。)

3. 「jdk-8u131-linux-x64.tar.gz」を解凍する。

# tar xvzf ./jdk-8u131-linux-x64.tar.gz

(「jdk1.8.0_131」が作成される。)

4. 「jdk1.8.0_131」を/opt」配下にコピー(移動)

# mv ./jdk1.8.0_131 /opt

5. jdkの今後のバージョンアップによるパス変更を吸収するため、シンボリックリンクを作成する。

# ln -s /opt/jdk1.8.0_131 /opt/java

6. rootユーザーを抜け、ログインしたユーザーに戻る。

# exit
$

7. Java環境ファイルを「.java.env」を作成する。

.java.env
export JAVA_HOME=/opt/java
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.

8. 作成したjava環境ファイルを読み込む。

$ source .java.env

9. Javaコマンドでインストールされたjdkのバージョンを確認する。

$ java –version
(以下が表示される。)
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

10. ログイン時に環境変数が設定されるようにユーザーのホームディレクトリの「.bash_profile」に、以下を追加しておく。

.bash_profile
・・・・・・・・
source .java.env    ←この行を追加

【環境変数について】

今回は「.java.env」を作成し、sourceコマンドで環境を設定したが、「/etc/profile.d」ディレクトリ配下に、以下のファイルを配置するとログイン時に環境変数が設定される。

./etc/profile.d/java.sh
#!/bin/sh
export JAVA_HOME=/opt/java
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.

以上

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

FNLPでMecabのような中国語の形態素解析

概要

日本語の形態素解析(MeCab)のようなことを中国語でもやりたいのでFNLPを利用する

環境

OS : Windows7 64bit
言語: Java8
IDE: Ecplise4.8.0

目的

OpenNLPでMeCabのような英語の形態素解析と同じ

日本語の文章をMecabにかけて得られる「形態素」「品詞」「基本形」を中国語でも行いたい
オープンソースの「FudanNLP(FNLP)」を利用して、中国分から「形態素」「品詞」を取得する

目次

  1. 中国語の事前知識
  2. Javaの実装
    1. 準備
    2. 分かち書き
    3. 品詞分解

1. 中国語の事前知識

文字は2種類

  • 簡体字と繁体字

本記事では、簡体字の文章に限定して考える

時制がない

  • 過去、現在、未来は文脈で判断する
  • 過去形: 我昨天去了上海
    • 私は昨日上海へ行った
  • 現在形: 我去上海
    • 私は上海へ行く
  • 未来形: 我明天要去上海
    • 私は明日上海へ行かなければならない

このため本記事では、中国語の形態素は全て「基本形」で取得できるものとして考える

2. Javaの実装

1. 準備

直接MavenRepository内のfnlp-coreをpom.xmlで指定するとエラーになる為、一度ソースコードをビルドして、fnlp-core-2.1-SNAPSHOT.jarファイルを作成する

※ fnlp-core-2.1-SNAPSHOT.jarの作成は、FNLPで中国語形態素解析の「ダウンロード」「ビルド」を行う

mavenプロジェクトを作成し、作成したfnlp-core-2.1-SNAPSHOT.jarファイルをdicフォルダ配下に配置する

pom.xmlに以下を追加する

<dependency>
    <groupId>net.sf.trove4j</groupId>
    <artifactId>trove4j</artifactId>
    <version>3.0.3</version>
</dependency>
<dependency>
    <groupId>commons-cli</groupId>
    <artifactId>commons-cli</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>org.fnlp</groupId>
    <artifactId>core</artifactId>
    <version>2.1</version>
</dependency>
<dependency>
    <groupId>org.fnlp</groupId>
    <artifactId>core</artifactId>
    <version>2.1</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/dic/fnlp-core-2.1-SNAPSHOT.jar</systemPath>
</dependency>

また、https://github.com/xpqiu/fnlp/releases で公開されているモデルファイル3つ(pos.m, seg.m, dep.m)をダウンロードし、dicフォルダに配置する

2. 分かち書き

CNFactory factory = null;
// モデルファイルのパスを指定し、形態素解析器を呼び出す
try {
    factory = CNFactory.getInstance("./dic");
} catch (LoadModelException lme) {
    lme.printStackTrace();
}
String message = "今天天气真好啊!";
String[][] tokens = factory.tag(message);
System.out.println(Arrays.asList(tokens[0]));
>> [今天, 天气, 真, 好, 啊, !]

3. 品詞分解

CNFactory factory = null;
// モデルファイルのパスを指定し、形態素解析器を呼び出す
try {
    factory = CNFactory.getInstance("./dic");
} catch (LoadModelException lme) {
    lme.printStackTrace();
}
String message = "今天天气真好啊!";
String[][] tokens = factory.tag(message);
System.out.println(Arrays.asList(tokens[1]));
>> [时间短语, 名词, 副词, 形谓词, 语气词, 标点]

参考リンク

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

Java メソッド

学習ログ

メソッドとは

複数の処理をまとめ、それを一つの処理として名前をつけたもの。

メソッドを利用するメリット

・機能単位に記述するため、修正範囲を限定できる。
・プログラムの見通しがよくなり、全体を把握しやすくなる。
・同じ処理を一つのメソッドにまとめることで、作業効率が上がる。

メソッドの定義

public static 戻り値の型 メソッド名(引数){
  メソッドが呼び出された時に実行される具体的な処理
}
//戻り値の型はメソッド内の処理の結果の値のデータ型を記述。処理結果が数値であればint,文字列であればStringになる。

//メソッドの呼び出し
メソッド名(引数); //戻り値を利用できない。

引数とは

メソッドを呼び出す際に呼び出し元から値を渡すことができる。

public static void main(String[] arg) {
  hello("山本"); //helloメソッドを呼び出している。山本という文字列のデータを(実引数)をhelloメソッドに渡している。
  hello("鈴木");
  hello("北村");
}

public static void hello(String name) { //メソッド呼び出しの際、仮引数として山本がSring型の変数nameに代入
  System.out.println(name + "さん、こんにちは"); //変数nameに代入されているデータをここで出力する。
}
//実行結果
  山本さん、こんにちは
  鈴木さん、こんにちは
  北村さん、こんにちは //となる


//引数が複数の場合
public static void main(String[] args) {
  add(100,20); //実行結果 x + y = 120
  add(200,50); //実行結果 x + y = 250
}
//複数の値を受け取るaddメソッド
public static void add(int x, int y) {
  int ans = x + y;
  System.out.println(x + "+" + y + "=" + ans);
}

戻り値とは

呼び出されたメソッドから、呼び出し元のメソッドへ返す値(データ)のことを戻り値または返り値という。

return 戻り値; //こうすることで呼び出し元のメソッドに値を返すことができる。
//この戻り値がそのメソッドの実行結果となる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaのGenerics(ジェネリクス・総称型)は神機能!

この記事を書いた動機

先日、社内の後輩と話していて、「Java の Generics の何がうれしいのかよくわからない」と言われました。自分にとってはあれは神機能なんだけど、Generics が無い時代を未経験の人からすれば、何のための機能なのか、どういう背景で作られた機能なのかがわからないんだろうなと思ったのでQiitaの記事として書き残してみる気になりました。
なのでこの記事は、いつもなんとなく Generics を使っているけど何のためのものなのか、どういう背景で作られたものなのかがよくわかってない。という人向けの記事です。

Genericsって?

そもそも Generics って何?っていう人のために一応書いておきます。

Generics.java
import java.util.ArrayList;
import java.util.List;

public class Generics {
    public static void main(String... args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        for (Iterator<String> itr = list.iterator(); itr.hasNext(); ) {
            String str = itr.next();   // 説明のためにあえて拡張forは使わない
            System.out.println(str);
        }
    }
}

上記コードの<String><>の部分がGenericsです。これで List に格納できる型を制限しています。
(Generics は List だけではなく Map や Set、自作のクラスやメソッドなどでも使えますが、今回は List で説明させていただきます)
2004/9/30 に公開された Java 5 から導入された機能です。右辺の<>はダイヤモンド演算子と呼ばれており、左辺の<String>で型が明示されているので、右辺からは省略できるというものです。これは Java 7 からの機能なので、それまでは左辺と右辺の両方に<String>と書く必要がありました。 面倒くせぇ・・・
ちなみに、ダイヤモンド演算子という名前は公式なものではありませんが、一般的に定着している名前なのでこれで通じます。

Genericsがなかった頃

Genericsがなかった頃は以下のようなプログラムを書いていました。

NoGenerics1.java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class NoGenerics1 {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("a");
        list.add("b");
        list.add("c");
        for (Iterator itr = list.iterator(); itr.hasNext(); ) {
            String str = (String) itr.next();   // 要素取得するときにキャストする必要があった!
            System.out.println(str);
        }
    }
}

<String><>はなく、ループの中で要素を取得する際、キャストする必要がありました((String) itr.next()の部分)。このキャストがかなり厄介で、ClassCastException の温床だったんです。
どういうことか。
以下のようなプログラムがあったとします。Generics がないと1つの List に複数の型を add することができてしまいます(以下の例では String と int)。その後、ループしながら String にキャストしています。当然、2番目の要素である int の1を取得する際にも String にキャストしようとします。その結果、型が違うので ClassCastException が発生します(int → String へのキャスト)。

NoGenerics2.java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class NoGenerics2 {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("a");
        list.add(1);     // Genericsで型を指定していないので、同じListに別の型をaddすることができた。
        list.add("c");
        for (Iterator itr = list.iterator(); itr.hasNext(); ) {
            String str = (String) itr.next();   // ここでClassCastException が起こる。
            System.out.println(str);
        }
    }
}

NoGenerics2.javaの実行結果
a
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    at NoGenerics2.main(NoGenerics2.java:13)

実行結果を見ると、1番目の要素である String の"a"は問題なく取得することができ、無事に System.out されています。
2番目の要素である int の 1 を取得するタイミングで ClassCastException が発生していることがわかります。
今回程度のプログラムであれば原因はすぐわかるでしょうし、修正するのも簡単です。しかし List はしょっちゅう使われる機能であり、メソッドの引数やコンストラクタを通じていろいろなクラスをあっちこっち移動します。規模の大きいシステムであればあるほど移動範囲は広がります。そして呼び出し元に戻ったときには変な要素が追加されていたりして、それに気づかずにループして ClassCastException が発生する・・・ということが本当によく起きていたんです。今では Generics のおかげで ClassCastException を目撃する頻度はかなり減りましたが、昔はよく見るエラーの一つが ClassCastException だったぐらいです(個人的見解)。

Genericsを使うと ClassCastException を事前検知できる

上記のNoGenerics2.javaを Generics を使用するように修正するとどうなるか。
list.add(1); のところでコンパイルエラーになります。

Generics2.java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Generics2 {
    public static void main(String... args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add(1);   // ここでコンパイルエラーになる!
        list.add("c");
        for (Iterator<String> itr = list.iterator(); itr.hasNext(); ) {
            String str = itr.next();   // 説明のためにあえて拡張forは使わない
            System.out.println(str);
        }
    }
}

このコンパイルエラーで教えてくれるのが素晴らしくて、Generics 導入前はプログラマが好きに要素を追加することができてしまっていたから ClassCastException の温床になっていました。ClassCastException は実行時例外なのでテストするまで(実際に動かすまで)バグに気づくことはできません。
それがコンパイルの段階で検知できるようになったのです!すばらしい!

一応今でも・・・

今でも Generics を使わずにプログラムを書くことはできますが、ワーニングが発生します。誰も得しないのでやめましょう。
以下のクラスの List list = new ArrayList(); から for (Iterator itr = list.iterator(); itr.hasNext(); ) { までワーニングだらけです。

Generics3.java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Generics3 {
    public static void main(String... args) {
        List list = new ArrayList();
        list.add("a");
        list.add(1);
        list.add("c");
        for (Iterator itr = list.iterator(); itr.hasNext(); ) {
            String str = (String) itr.next();   // 説明のためにあえて拡張forは使わない
            System.out.println(str);
        }
    }
}

さらに @SuppressWarnings アノテーションを使うことでワーニングを抑止することも一応できます。しかし本当に誰も得しないのでやめましょう。

Generics4.java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Generics4 {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String... args) {
        List list = new ArrayList();
        list.add("a");
        list.add(1);
        list.add("c");
        for (Iterator itr = list.iterator(); itr.hasNext(); ) {
            String str = (String) itr.next();   // 説明のためにあえて拡張forは使わない
            System.out.println(str);
        }
    }
}

結論(?)

こんな昔話みたいなことをしていると自分も年取ったもんだなと思います。でも、こういった背景を知らずにとにかくおまじないのように<String>とか<>を書いている人もいるのか・・・と思うと、こういう知識や経験も積極的に発信していかないと失われてしまうんだなと思ったのでこの記事を書いてみました。
この記事を見て一人でも多くの人が、ちゃんと背景を理解したうえで Generics を使ってくれるようになってくれればいいなと思います。
以上。

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