otaku-tokyo

 

Java

Javaを学べるWebサイト

https://www.javadrive.jp/start/

Javaを使ったプログラムの作成と保存

Visual Studio Codeというエディタをインストールし、次のコードを記述してください。

class Hello {

public static void main( String[] args ) {

System.out.println( “Hello” );

}

}

作製したプログラムを「クラス名.java」という名前で保存します。保存場所はどこでも構いませんが。今回は「C:\code\javaディレクトリ」の中に保存します。

コンパイル

コンパイルとは、人が読むことが出来るテキスト形式からコンピュータが理解できるバイナリコードで記述された形式に変換することです。コンパイルすることでバイナリコードのファイル、俗にいうクラスファイルが生成されます。コンパイルプログラムはJDKをインストールしたディレクトリの中のbinディレクトリの中にjavac.exeというアプリで行われています。

まず、テキストエディタに下記プログラムを記述し、JSample3_1.javaという名前で「C:\code\java\before」に保存しましょう。

次に、コマンドプロンプトを起動し、先ほどのディレクトリに移動してください。そして、次のように入力し、Enterキーを押してください。

javac JSample3_1.java
クラスファイルが生成されたので、「C:\code\java\before」に行って確認しましょう。〇〇.classというファイルがあるはずです。

プログラムの実行

プログラムの実行はJDKをインストールしたディレクトリの中のbinディレクトリのjava.exeで行われています。

コマンドプロンプトを起動し、「C:\code\java\before」に移動して次のように入力してEnterキーを押してください。.classはいりません。

java JSample3_1
Enterキーを押した後、Helloと出力されたら成功です。

Javaの基礎知識

クラス、メソッド、フィールド

class クラス名 {

void メソッド名() {

int フィールド名 = 0;

}

}

mainメソッド

クラスには必ずmainメソッドが必要です。mainメソッドは次のような書式となっています。

public static void main(String[] args) {}

コメントアウト

/* */もしくは//を使用します。

/** */を使用すると、コメントからドキュメントが自動生成されます。

import文

java.timeパッケージに最初から含まれているLocalDateクラスを使いたいとします。

その場合は下記プログラムを記述します。

import java.time.LocalDate;

class JSample9_1{

public static void main(String[] args){

LocalDate ld = LocalDate.now();

System.put.printIn(ld);

}

}

※SystemクラスやStringクラスのようにimportを使わなくても使用できる例外はあります。

エンコーディング

まず、デフォルトエンコーディングを確認します。

テキストエディタに下記プログラムを記述し、JSample1_1.javaとして保存してください。

class JSample1_1{

public static void main(String[] args){

System.out.printIn(System.getProperty(“file.encoding”));

}

}

コマンドプロンプトを起動して「C:\code\java\encoding」に移動してコンパイルします。

そのあと、「java JSample1_1.java」でプログラムを実行してください。

Windows10の環境ではMS932と表示されるはずです。

デフォルトのエンコーディングがMS932(≒Shift_JIS)なので、UTF-8でソースファイルを作成すると、コンパイルはできますが、プログラムを実行するときに文字化けしてしまいます。

UTF-8を使う場合はコンパイルを行った後で下記プログラムを実行してください。

これで文字化けせずに済みます。

javac -encoding UTF-8 JSample2_1.java
※javac -J-Dfile.encoding=UTF-8 JSample2_1.java でも可能。

リテラル

“”と”

Javaで”を使う場合は、中に一文字しか入れられません。なので、文字列には””を使って下さい。

エスケープシーケンス

改行する場合の処理です。Windows環境では\は¥と表示されます。

System.out.printIn(“こんにちは\nお元気ですか”);

ほかにも、\b(スペース)、\ooo(8進数の文字コード)、\uoooo(16進数の文字コード)などがあります。

整数や小数

“”を付けないでください。文字列として認識されてしまいます。

整数は1_302などと書くことで3桁ごとに区切り文字を入れられます。

小数は5.23e3や2.7e-4で、5230や0.00027を表すことが出来ます。

また、整数はint型、少数はdouble型として認識されます。

変数のつけ方

以前は以下のように変数を付けていました。

データ型 変数 = 値;

予約語は変数名やクラス名に使用できません。予約語とは、Javaであらかじめ用途が決められた単語のことです。記号はアンダーバー(_)と$のみ使用できます。

データ型は整数ならint、少数ならfloatかdouble、論理型(true or false)ならboolean、一文字ならcharを使っていました。他にもshort(-3万~3万の整数)、byte(-128 ~ 127の整数)、longなどがありますが、それぞれ扱える数の範囲が異なります。扱える数字の数が大きくなるほど処理が重くなります。

ちなみに、次のようにfinalを付け足すと、taxには値を再代入できなくなります。

final float tax = o.1F;

しかし、Java10からはデータ型を記述せずに「var 変数  = 値」と書くのが一般的になりました。

ただし、「= 値」の部分を書かないと、データ型がわからずコンパイル時に「エラー: ローカル変数 xxx の型を推論できません」となるので注意しましょう。

データ型の違いで困ったら

次のように書けば、intにも小数を代入できます。

double d = 2.5;
int i = (int)d;

また、intとdoubleを演算する場合はdoubleを使いましょう。

正しい例 double d = 10 * 0.2;

間違った例 int i = 10 * 0.2; //コンパイルエラーになる

ラッパークラス

intにはIntegerがラッパークラス、floatにはFloatがラッパークラスとなる。詳しくはこちらのページを参照。

演算子

インクリメント演算子、代入演算子、マイナス演算子、関係演算子、論理演算子

int num;

num = (10 + 5) * 2;

num++; //または++num;

num *= 2;

System.put.printIn(-num); //-62

System.out.printIn(num >= 60 || num < 5); //true

ビット演算子、シフト演算子

【https://www.javadrive.jp/start/ope/index8.html】

条件演算子

「条件式 ? 式1 : 式2」と書きます。条件式がtrueの場合は式1が実行されます。IF文で代用可能です。

String result = score > 70 ? “OK” : “NG”;

for文

下記プログラムではint i;をなくしてfor (int i = 0; ~~)とすることもできます。

しかし、for文の中で変数宣言するとfor文の中でしか変数iが使えなくなるので、⇦のところでコンパイルエラーになります。

class JSamle {

public static void main(String[] args){

int sum = 0; int i;

for ( i = 0; i < 2; i++) { sum += i; }

System.out.printIn(“繰り返し回数” + i); ⇦

System.out.printIn(“合計” + sum);

}}

配列を使う場合は

String name[] = {“Suzuki”, “Kato”, “Aoki”};

for (int i = 0; i < name.length; i++) {

System.out.printIn(name[i]);

}

for each

String name[] = {“Suzuki”, “Kato”, “Aoki”};

for (String str : name ) {

System.out.printIn(str);

}

While

int num = 1;

while ( num < 100 ) {

num *= 2;

}

while文は条件を満たさなければ、0回で処理が終わることもあります。

下記do while文は最低1回は処理が行われます。

int num = 1;

do{ num -= 2; }while( num > 0);

Continue

ラベル名なし

class JSample10_1 {

public static void main ( String[] args ) {

for ( int i = 0; i < 10; i ++) {

if ( i % 3 == 0 ) { contine; }

System.out.printIn ( “i = ” + i );

}}}

>> i=1 i=2 i=4 i=5 i=7 i=8

ラベル名アリ

class Sample {

public static void main ( String[] args ) {

Outer :

for ( int i = 1; i < 6; i++ ) {

Inner :

for ( int j = 1; j <6; j++ ) {

if ( i * j % 4 == 0 ) { continue Outer; } //Outerへ飛ぶ

System.outer.printIn ( i * j );

}}}}

>>1 2 3 2 3 6 9 5 10 15

if

int[ ] point = { 75, 94, 68 };

String[ ] name = { “Suzuki”, “Yamada”, “Okada” };

for ( int i = 0; i < 3; i++ ) {

System.out.printIn( name[i] + “さんは” );

if ( point[i] > 90 ) { System.out.printIn(“A判定です”); }

else if ( point[i] > 70 ) { System.out.printIn(“B判定です”); }

else { System.out.printIn(“C判定です”); }

}

Switch

int num = 2;

switch ( num ) {

case 1 : System.out.printIn(“A”); break;

case 2 : System.out.printIn(“B”); break;

case 3 : System.out.printIn(“C”);

} >> B

配列

配列の初期化

① int[ ] result = new int[3]; result[0] = 5; result[1] = 8; result[2] = 2;

② int[ ] result = { 5, 8, 2 };

➂ var result = new int[ ]{ 5, 8, 2 };

多次元配列

int[ ][ ] num = new int[2][ ];

num[0] = new int[3]; num[1] = new int[3];

num[0][0] = 87; num[0][1] = 58; num[0][2] = 72; ~~

fill

インポートすれば全ての要素に同じ値を格納できます。

import java.util.Arrays;

int[ ] a = new int[3];

Arrays.fill(a, 10);

配列のコピー

やり方は4つあります。

①int[ ] src = {12, 24, 18}; int[ ] dst = src;

②int[ ] src = {12, 24, 18};int[ ] dst = new int [3];for ( int i = 0; i < src.length; i++ ) { dst[i] = src[i]; }

➂import java.util.Arrays;int[ ] src = {12, 24, 18};int[ ] dst = Arrays.copyOf( src, 3 );

④int[ ] src = {12, 24, 18};int[ ] dst = new int[3];System.arraycopy( src, 0, dst, 0, 3 );

なお、コピーしたい要素が配列の1番目からではない場合は次のようにします。

int[ ] src = {12, 24, 18, 35, 21}; int[ ] dst = Arrays.copyOfRange?(src, 1, 4); //[24, 18, 35]と出力

しかしint型でなく、参照型の場合は次のように記述します。Deepコピーと言います。

Test[ ] src = { new Test(28), new Test(12) };

Test[ ] dst = new Test[2];

for ( int i = 0; < < src.length; i++ ) { dst[i] = new Test( src[i].num ); }

仮にDeepコピーを使わない場合は前者の図のようになります。これだとコピー元の配列(28, 12)が変更されたとき、コピー先の配列も変更されてしまいます。Deepコピーを使えば、コピー元の配列が変更されても、コピー先には反映されません。

2つの配列を連結する

int[ ] src1 = {28, 14, 35}; int[ ] src2 = {17, 40, 23};

int[ ] dst = new int[src1.length + src2.length]; //まず空の配列を用意

System.arraycopy(src1, 0, dst, 0, src1.length);

System.arraycopy(src2, 0, dst, src1.length, src2.length);

2つの配列の要素の値を比較する

java.util.Arrays;

int[ ] a = {85, 78, 92}; int[ ] b = {85, 78, 92};

System.out.printIn(Arrays.equals(a, b)); //true

配列の要素を並び替える

昇順にソートする場合は

import java.util.Arrays;

int[ ] src = {12, 24, 18, 35, 21};

Arrays.sort(src);

System.out.printIn(Arrays.toString(src)); //[12,18,21,24,35]

降順にソートする場合は昇順にソートした後で要素を逆順に並び替えます。

import java.util.Arrays;

int[ ] src = {12, 24, 18, 35, 21};

Arrays.sort(src);

for (int f = 0; l = src.length – 1; f < 1; f++, l– ) {

int temp = src[f]; src[f] = src[l]; src[l] = temp;

}

System.out.printIn(Arrays.toString(src)); //[35, 24, 21, 18, 12]

配列をprintInで出力する

そのまま出力すると参照を表す文字列まで出力されてしまいます。

なのでArrays.toString()を使います。

int[ ] src = {32, 18};

System.out.printIn(src); // [I@372f7a8d

System.out.printIn(Arrays.toString(src)); //[32, 18]

また、多次元配列の場合はArrays.deepToString()を使います。

ちなみに1次元配列の場合はArrays.deepToString()は使えません。

int[ ][ ] src = {{25, 18}, {12, 37}};

System.out.printIn(Arrays.deepToString(src)); //[[25, 18], [12, 37]]

文字列を作成する

Javaでは必ず””を使って下さい。”は1つの文字を表す場合しか使えません。また、Javaの文字列は一度作成すると上書きできません。

String msg = “Hello”; //

数値を文字列に直したい場合もあるでしょう。その時はラッパークラスとtoStringメソッドを使います。+演算子でも同じことが出来ます。

①int i = 1o; String si = Integer.valueOf(i).toString();

②int i = 10; String si = String.valueOf(i);

➂int i = 10; String si = “” + i;

※ラッパークラスとは

intやdoubleのような基本データ型にはメソッドを使うことが出来ません。

なのでメソッドを使いたい場合は基本データ型毎に対応するラッパークラスを使います。

Integer i = Integer.valueOf(16);  // i = 16

ラッパークラスの値を取得したいときはintvalue()メソッドを使います。

int val = i.intValue(); //16

文字列と文字列を比較する

2つの文字列が同じオブジェクトを参照している場合はtrueになります。

int a = 10; int b = 10; System.out.printIn( a == b ); //true

String a = “Hello”; String b = a; System.out.printIn( a == b ); //true

しかし、異なるオブジェクトを参照している場合はfalseとなってしまいます。

String a = “Hello”; String b = new String( a ); System.out.printIn( a == b ); //false

参照しているオブジェクトが異なっていても値が等しいければtrueにしたい場合はこうします。

String a = “Hello”; String b = new String( a ); System.out.printIn( a.equals( b ) ); //true

文字列と文字列の大きさを比較する

次のような4つの文字列があります。

String a = “AAAAA”; String b = “AAAAA”; String c = “AAA”; String d = “ABCD”;

compareTo?メソッドを使うと

(1)文字列の長さが同じで、全ての文字が同じ値の場合は0になります。

System.out.printIn( a.compareTo?( b ) ); //0

(2)文字列の長さは異なるが、短いほうの文字列全体が長い文字列の先頭部分と一致している場合は、対象の文字列.length() – 引数の文字列.length() を返します。

System.out.printIn( a.compareTo?( c ) ); // 2

(3)同じインデックスの文字が異なる値があった場合は、そのインデックス番号をkとすると、対象の文字列.chartAt( k ) – 引数の文字列.chartAt( k )を返します。

System.out.printIn( a.compareTo?( d ) ); //-1 (1番目のインデックスの文字の値が異なります)

※chartAt()とは

String str = “東京都”; System.out.printIn( str.chartAt( 0 ) );  //東

文字列の文字数を取得する

String a = “東京都”;

①System.out.printIn( a.length() ); //3

②System.out.printIn( a.codePointCount(0, a.length()) ); //3

どちらでも3になりますが、サロゲートペアを使用する文字(常用漢字でない漢字)が含まれる文字列の場合は②のコードを書かないと正しい文字列が得られません。

文字列を抜き出す

String a = “東京都”; System.out.printIn( a.substring?( 1, 2 ) ); //京都

文字列の先頭や末尾にある空白文字を取り除く

空白文字とは改行や半角スペースのことです。全角スペースも取り除きたい場合はtrim()ではなく、strip()を使って下さい。

String a = ”  AB  CD  “; System.out.printIn( a.trim() ); //AB  CD

文字列を大文字にする

String a = “Apple”;

System.out.printIn( a.toUpperCase() ); //APPLE

System.out.printIn( a.LowerCase() ); //apple

文字列を連結する

ただ連結する場合は

String a = “Hello”; String b = “World”;

①System.out.printIn( a + b ); //HelloWorld

②System.out.printIn( a.concat( b ) ); //どちらでもいいです

間に指定した区切り文字を挟む場合は

import java.util.List;

String a = String.join( “-“, “Apple”, “Grape”, “Melon” );

System.out.printIn( a );

文字を置き換える

String a = “東京都港区”; System.out.printIn( a.replace( “港区”, “足立区” ) );

置き換えたい文字が複数ある場合は次のようにします。

String a = “AA BB aA Aa CC aa”; String b = “aA|Aa|aa”;

System.out.printIn( a.replceAll( b, “AA” ) ); //AA BB AA AA CC AA

文字列の中で指定した文字が出てくるインデックスを取得する

5番目から後で最初に出てくるインデックスを取得する場合は

①String a = “HelloWorld”; System.out.printIn( a.indexOf( (int) ‘o’, 5 ) ); //6

②System.out.printIn( a.indexOf( (“ld”), 5 ) ); //8

一番最後に出現するインデックスを取得する場合は

String a = “HelloWorld”; System.out.printIn( a.lastIndexOf( (int) ‘o’ ) );  //6

文字列が正規表現パターンとマッチするか調べる

文字列aがAで始まり、eで終わるならtrueにする。

String a = “Apple”; String b = “A.*e”; System.out.printIn( a.matches?(b) ); //true

文字列を分割する

String a = “赤色:青色:黄色”; String b = “;|:”; System.out.printIn( a.split( b ) );

メソッド

メソッドの引数が基本データ型の場合

public static void main(String args[]) { int english = 78; check(“英語”, english); }

private static void check(String subject, int result) {

if ( subject > 80 ) { System.out.printIn(“合格”); } else { System.out.printIn(“不合格”); }

}

メソッドの引数が配列の場合

public static void main(String args[ ]) { int num[ ] = {10, 4}; test(num); }

private static void test( int num[ ]) { System.out.printIn(num[0]); }

return文

returnが実行された時点でメソッドが終了します。

return文を使う場合は引数がintなら、private static int test(){}とします。

※配列の場合はint[ ]です。

使わない場合はprivate static void test(){}とします?

public static void main(String args[]) { int data[ ]; data = test(); }

private static int[] test() { int data[] = new int[2]; data[0] = 10; data[1] = 19; return data; }

可変引数

public static void main(String args[]) { test(10, 7, 8) ;}

private static void test( int… num ) {

for ( int i = 0; i < num.length; i++ ) { System.out.printIn( num[i] ); }

}

固定引数と可変引数を組み合わせることも可能です。

private static void test(String a, String b, int… num) {}

例外処理

class Sample {

public static void main( String args[] ) {

try{ System.out.printIn( args[0] ); }

catch (ArrayIndexOutOfBoundsException e) { System.out.printIn(“ただいまメンテナンス中”); }

}}

プログラムがコンパイルエラーしたときに、エラー画面を顧客に見せると困惑されてしまう。そこでtry & catch処理(例外処理)を行います。

コンパイルする時は「javac Sample.java」でソースファイルを保存した後に「java Sample hello」と打ち込むと「hello」と返ってきます。

正規表現

(.)は任意の一文字、(.*)は任意の長さの文字、(\\d)は0から9までの数値、(\\s)はタブや改行などの空白文字を表します。他にもjpgという文字が文字列の末尾に含まれるかどうか調べる場合は(jpg$)と記述します。

import java.util.regex.*;

Pattern p = Pattern.compile(“g..d”);

Matcher m = p.matcher(“good”);

System.out.printIn(m.matches()); //true

型推論を利用して次のように記述することもできます

var p = Pattern.compile(“g..d”);

var m = p.matcher(“good”);

matches()は全部あっている場合のみtrueを返します。一部だけあっていてもtrueにはなりません。lookingAt()は先頭があっていればtrueを返します。find()は一致している部分があればtrueを返します。start()はあっているところのインデックス番号を返し、group()はあっている箇所を表示します。

import java.util.regex.*;

Pattern p = Pattern.compile(“港区”);

Matcher m = p.matcher(“港区役所”);

System.out.printIn(m.matches()); //false

if ( m.lookingAt() ) { System.out.printIn( m.start() ); } //0

if ( m.find() ) { System.out.printIn(m.group()); } //港区

※String a = “[0-9]{2}”は任意の数値が2つ連続する文字列です。

範囲指定したいときはregion()を使います。

import java.util.regex.*;

class Sample { public static void main(String args[]){

Pattern p = Pattern.compile(“\\b.*?er”);

Matcher m = p.matcher(“dancer singer”);

m.region(7, 13);

if ( m.find() ) { System.out.printIn( m.group() ); } //singer

}}

ファイルを作成する

import java.nio.file.Path;

import java.nio.file.Paths;

import java.nio.file.Files;

import java.io.IOException;

class Text { public static void main(String args[]) {

Path d = Path.get(“C:/java”);

try { Files.createDirectory?(d); } catch (IOException e) { System.out.printIn(e); }

//まずローカルディスクの中にjavaディレクトリを作成します。

//既にファイルが作られている場合は例外処理します

Path p = Paths.get(“C:/java/report.txt”);

try { Files.createFile(p); } catch(IOException e) { System.out.printIn(e); }

//次にjavaディレクトリの中にreport.txtを作成します。

if ( Files.exists?(p) ) { System.out.printIn(“ファイルは存在します”); }

else { System.out.printIn(“ファイルは存在しません”); }

//最後にファイルがきちんとさくせいされたのか確認します。

}}

ファイルやディレクトリを削除する

import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.io.IOException;

Path p = Paths.get(“C:/java/report.txt”);

try { Files.delete(); } catch(IOException e) { System.out.printIn(e); }

//ファイルが存在しない状態では例外処理を行います。

//file名ではなくディレクトリ名にすればディレクトリを削除できます。

カレントディレクトリを取得する

import java.nio.file.Path;

import java.nio.file.Paths;

Path p = Paths.get(“”); //カレントディレクトリの相対パスを取得します

Path cp =p.toAbsolutePath(); //相対パスを絶対パスに直します