💬

Java 基礎

2024/04/30に公開

Java 勉強中につき、基本的な各重要概念をサンプルプログラムとともに残しておこうと思う

クラス

引数や戻り値のあるメソッドのコードサンプル
class Point{
    int x;
    int y;

    void mulutiply(int n){
        this.x=x*=n;
        this.y=y*=n;
    }

    boolean isSamePosition(Point p) {
        if (this.x==p.x && this.y==p.y) {
            return true;
        } else {
            return false;
        }
    }
}


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

        Point p1=new Point();
        p1.x=2;
        p1.y=4;

        Point p2=new Point();
        p2.x=4;
        p2.y=8;

        if(p1.isSamePosition(p2) == true){
            System.out.println("same!!!");
        }else{
            System.out.println("different!!!");
        }

        p1.mulutiply(2);

        if(p1.isSamePosition(p2) == true){
            System.out.println("same!!!");
        }else{
            System.out.println("different!!!");
        }
    }
}
  • クラス変数
    • クラスが持つ変数でインスタンス全体で共有され、変数宣言時にstaticをつける。
    • インスタンスを生成しなくても利用できる。
クラス変数サンプルコード

class Point{
    static int counter=0;
    int x;
    int y;

    Point(int x,int y){
        System.out.println("Point クラスのコンストラクタが生成されました");
        this.x=x;
        this.y=y;
        Point.counter++;
    }
}


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

        Point p[] = new Point[5];

        for(int i=0;i<p.length;i++) {
            p[i]=new Point(i, i);
            System.out.println("Point Counter: " + Point.counter);
        }
    }
}
  • ポリモーフィズム
    • スーパークラスを型とする変数にはサブクラスのインスタンスを代入できる。
    • 同じ型の変数に代入されたインスタンスに対して同一のメソッドを呼び出しているのに結果が異なることから多態性(ポリモーフィズム)と呼ぶ。
    • 配列で複数のインスタンスを管理する場合に便利。
ポリモーフィズム
## コード
class Person{
    void work() {
        System.out.println("私は人です");
    }
}

class Teacher extends Person{
    void work() {
        System.out.println("私は先生です");
    }
}

class Doctor extends Person{
    void work() {
        System.out.println("私は医者です");
    }
}

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

        Person[] persons=new Person[3];
        persons[0] = new Person();
        persons[1] = new Teacher();
        persons[2] = new Doctor();

        for(int i=0;i< persons.length;i++){
            persons[i].work();
        }
    }
}

## 実行結果
私は人です
私は先生です
私は医者です

アクセス修飾子

クラスやフィールド、メソッドへのアクセス制御をするための修飾子をアクセス修飾子と呼び、クラスやフィールド、メソッドの宣言前にそれぞれ付与することでアクセス制御を行うことができる。

  • public
    • 他の任意のクラスからアクセス可能
  • protected
    • 現在のクラス、及び、サブクラスからアクセス可能
  • 無し
    • 現在のクラス、及び、同一パッケージ内のクラスからアクセス可能
  • private
    • 現在のクラスからのみアクセス可能

インターフェース

インターフェース
## コードサンプル
interface HasGetAreaMethod{
    double getArea();
        }

abstract class Shape{
    abstract void draw();
}

class Rectangle extends Shape implements HasGetAreaMethod{
    void draw(){System.out.println("■");}

    public double getArea(){
        System.out.println("RectangleクラスのgetAreaメソッドが返却されました");
        return 1.0;
    }
}

class Circle extends Shape implements HasGetAreaMethod{
    void draw(){System.out.println("●");}

    public double getArea(){
        System.out.println("CircleクラスのgetAreaメソッドが返却されました");
        return 1.0;
    }
}

class Polyline extends Shape {
    void draw(){System.out.println("N");}

}

class Polygon extends Polyline implements HasGetAreaMethod{
    void draw(){System.out.println("凸");}

    public double getArea(){
        System.out.println("PolygonクラスのgetAreaメソッドが返却されました");
        return 1.0;
    }
}

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

        HasGetAreaMethod closed[]=new HasGetAreaMethod[3];
        closed[0]=new Rectangle();
        closed[1]=new Circle();
        closed[2]=new Polygon();

        for(int i=0;i<closed.length;i++) {
            closed[i].getArea();
        }

    }
}

## 実行結果
RectangleクラスのgetAreaメソッドが返却されました
CircleクラスのgetAreaメソッドが返却されました
PolygonクラスのgetAreaメソッドが返却されました

例外処理

0で割り算するなど、想定外の処理をするとJava上でエラーが発生する。(ランタイムエラー)
例外のエラーハンドリングをjava上で処理する方法としてtry,catch,finallyブロックを利用する必要がある。

try~catch文
try{
	tryブロック
	本来実行したい処理
}
catch(例外の型 変数名) {
	catchブロック
	例外が投げられた時の処理
}
finally {
	finallyブロック
	最後に必ず行う処理
}
sample1(0除算)
public class test1 {

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
		int a=2;
		int b=100;

		try {
			int c = b/a;
			System.out.println(c);
		}
		catch(ArithmeticException e) {
			System.out.println("例外発生");
			System.out.println(e);
			return;
		}
		finally {
			System.out.println("End Program");
		}
	}
}
sample2(非存在配列指定)
class SimpleClass{
	void doSomething() {
		int array[] = new int[3];
		array[10]=999;
		System.out.println("doSomethingメソッドを終了します");
	}
}

public class test2 {
	public static void main(String[] args) {
		SimpleClass obj = new SimpleClass();
		try {
			obj.doSomething();
		}
		catch(ArrayIndexOutOfBoundsException e) {
			System.out.println("例外発生");
			System.out.println(e);
			return;
		}
		finally {
			System.out.println("End Program");
		}
	}
}

enum

定数をenumという型にまとめたもので、定義したもの以外を呼び出そうとするとコンパイルエラーになるのでプログラムのbug等の発生を抑止できる。例えば下記の例だと、定義した定数以外の値を考慮して case 分でその他(default)を定義する必要がない。

public class test1 {

    protected enum week {
        Sunday,
        Monday,
        Tuesday,
        Wednesday,
        Thursday,
        Friday,
        Saturday
    };

    public static void main(String[] args) {
        week week_day = week.Sunday;

        switch(week_day) {
            case Sunday:
                System.out.println("日曜日");
                break;
            case Monday:
                System.out.println("月曜日");
                break;
            case Tuesday:
                System.out.println("火曜日");
                break;
            case Friday:
                System.out.println("金曜日");
                break;
        }
	}
}

マルチスレッディング

これまでのプログラムはスレッドが1つだけだった。このスレッドはmainメソッドから処理を開始し、上から順番に命令文を実行する。このスレッドをmainスレッドと呼ぶ。これをシングルスレッドプログラムと呼ぶが、一度に2つ以上の命令を同時に実行するプログラムを作ることも可能。これをマルチスレッドプログラムと呼ぶ。プログラムの処理の流れが2本以上あり、それぞれ同時並行で進行するイメージ。

以下は銀行の口座に対して1人当たり1万円振込を実行して100人分の金額の合計値を表示するプログラム。
マルチスレッドプログラムを実行するためには、Threadクラスを継承してrunメソッドをオーバーライドして所定の処理を定義する必要がある。
mainメソッド内でThreadクラスのインスタンスを作成して、startメソッドを呼び出せば最終的には実行できる。

またスレッドの処理が終わるのを待つためにjoinメソッド、一度に1つのスレッドしかメソッドを実行できなくするためにaddOneYenメソッドにはsyncronized修飾子をつけることで排他制御を行なっている。

マルチスレッド例
class Bank{

	static int money=0;
	static synchronized void addOneYen() {
		money++;
	};

}
class Customer extends Thread {
	public void run() {
		for(int i=0;i<10000;i++) {
			Bank.addOneYen();
		}
	}
}
public class test4 {
	public static void main(String[] arg) {
		Customer[] customer=new Customer[100];

		for ( int i=0;i<100;i++) {
			customer[i]=new Customer();
			customer[i].start();
		}
		for(int i=0;i<100;i++) {
			try {
				customer[i].join();
			}catch(InterruptedException e) {
				System.out.println(e);
			}
		}
		System.out.println(Bank.money);
	}


}


ファイル入出力

ファイルからの読み込み処理

順序:

  1. ファイル
  2. FileReader
    • ストリームオブジェクト
    • ファイルから文字列を読み込んで後続のバッファに渡す
  3. BufferedReader
    • ストリームオブジェクト
    • 文字列を蓄えておきプログラムの要求に応じて渡すバッファ
  4. プログラム
import java.io.*;

public class FileReadExample {
    public static void main(String[] args){
        try{
            // Step1 中身を読み込みたい File オブジェクトを定義
            File file=new File("/tmp/test.txt");

            // Step2 File オブジェクトを引数に文字列を受け取るFileReaderオブジェクトを定義
            FileReader fr=new FileReader(file);

            // Step3 FileReaderオブジェクトを引数に文字列を受け取るBufferedReaderオブジェクトを定義
            BufferedReader br=new BufferedReader(fr);
            String s;

            // Step4 BufferedReaderオブジェクトのreadlineメソッドで1レコードずつファイルから文字列を読み取る
            while((s=br.readLine()) != null){
                System.out.println(s + "を読み込み");
            }
            
            // Step5 BufferedReaderオブジェクトのcloseメソッドで読み込みストリームを閉じる
            br.close();

        }catch(IOException e){
            System.out.println(e);
        }
    }
}

ファイルへの書き込み処理

順序:

  1. プログラム
  2. PrintWriter
    • ストリームオブジェクト
    • プログラムから渡される文字列に必要に応じて改行を付与しバッファに渡す
  3. BufferedWriter
    • ストリームオブジェクト
    • PrintWriterオブジェクトから渡される文字列を蓄えFileWriterオブジェクトへ渡すバッファ
  4. FileWriter
    • ストリームオブジェクト
    • ファイルに書き込みを行う
  5. ファイル
import java.io.*;

public class FileWriteExample {
    public static void main(String[] args){
        try{
            // Step1 書き込み対象の File オブジェクトを定義
            File file=new File("/tmp/test.txt");

            // Step2 File オブジェクトを引数に文字列を受け取るFileWriterオブジェクトを定義
            FileWriter fw=new FileWriter(file);

            // Step3 FileWriterオブジェクトを引数に文字列を受け取るBufferedWriterオブジェクトを定義
            BufferedWriter bw=new BufferedWriter(fw);

            // Step4 書き込み対象のオブジェクトを適宜書き換えることができるPrintWriterメソッドを定義
            PrintWriter pw=new PrintWriter(bw);

            // Step5 PrintWriterオブジェクトのprintlnメソッドで1レコードずつ改行つきでファイルに対して文字列を書き込む
            for (int i=0;i<100;i++){
                pw.println("[" + i + "]");
            }
            
            // Step6 PrintWriterオブジェクトのcloseメソッドで書き込みストリームを閉じる
            pw.close();

        }catch(IOException e){
            System.out.println(e);
        }
    }
}

Maven

java プロジェクトのビルドツール

Project 作成

ディレクトリが配下にプロジェクトが構成される。

mvn archetype:generate \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false \
-DgroupId=sample \
-DartifactId=hello1

サンプルで main メソッドのソースコードが作成される

# cat hello1/src/main/java/sample/App.java 
package sample;

/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
    }
}

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.sample</groupId>
  <artifactId>hello</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <properties>
        <java.version>1.8</java.version>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <maven.compiler.source>${java.version}</maven.compiler.source>
  </properties>
  <name>hello</name>
  <url>http://maven.apache.org</url>
  <dependencies>

    ~~~<適宜XMLを追加>~~~

  </dependencies>
</project>

コンパイル

mvn compile

クリーンアップ

target ディレクトリごとクリア

mvn clean

依存ライブラリを収集

配下の target/dependenciy にかき集められる。javaプログラムを実行するときにクラスパスを通すと良い

mvn dependency:copy-dependencies

java プログラム実行

java -cp target/classes/:target/dependency/* sample.App

Discussion