MyEnigma

とある自律移動システムエンジニアのブログです。#Robotics #Programing #C++ #Python #MATLAB #Vim #Mathematics #Book #Movie #Traveling #Mac #iPhone

C++, PythonユーザのためのJava入門

目次

はじめに

Javaは、元サン・マイクロシステムズ、

今はオラクルという会社が開発している

プログラミング言語です。

Java - Wikipedia

 

元々は、PCのアプリや、

サーバサイドのツールとして良く使われていますが、

最近はAndroidの影響で、

モバイルにも広く使われるようになっています。

 

今回は、C++ユーザの自分が、

Javaを勉強した時のメモを残しておきたいと思います。

Javaの特徴

Javaは

Write Once, Run Anywhere

という言葉があり、

同じコードを様々なプラットフォームで動かせることを売りにしています。

java.com: あなたとJava

また、C++と同じで

オブジェクト指向のプログラミング言語です。

加えて、C++と同様、

事前にコードをコンパイルして

実行ファイルを生成する形になっています。

インストール

それぞれのOSに対するインストールは下記を参照下さい。

Ubuntu

Windows

Mac

Javaの種類

Javaには用途に応じて、いくつかの種類があるため

インストールの際には注意が必要です。

Java SE: Standard Edition

いわゆる一般的なデスクトップで使用するJavaです。

Java ME: Micro Edition

携帯電話や家電などの組み込み向けのJavaです。

組み込み向けJavaと聞くと、Androidを思い浮かべますが、

このJava MEはAndroidとは異なり、互換性は無いようです。

Java EE: Enterprise Edition

企業用のフルセットのJavaです。

Java SEよりも使用できる機能が増えており、

特に大規模サーバ向けの機能が拡張されています。

Java Platform, Enterprise Edition - Wikipedia

C++ユーザが注意すべき所

JavaはC(C++)言語を元に設計されたので、

C(C++)を使ったことがある人は、

あまり迷うことは無いかと思いますが、

それでも設計思想の違いなどで、

JavaとC(C++)には違う部分もあります。

 

そこで、C(C++)ユーザのために

Javaを使う上で注意すべき所をまとめておきます。

真偽値型はboolean

true / falseの真偽値はC++ではboolですが、

javaではbooleanです。

boolean flag = true;

1Byteの数値データ型はbyte

C++では、1Byteの数値はchar型を使うことが多いですが、

Javaではcharは一文字の文字列しか格納出来ないので、

byteという型を使います。

byte bval = 127;// -128 〜 128

floatとlongに値を代入する時は数値の末尾にFとLを付ける。

float a = 1.23F;
long d = 9223372036854775807L;

Stringと数値を連結させると数値が文字列になる

自動的に数値が文字列に変換されるので便利です。

String a="Num:";
String b=a+100; // Num:100となる

 

ちなみに、2進数は0bを頭につけて、

16進数は0xを頭につけて、コードを埋め込むことができます。

桁の区切りをわかりやすくするために、_ (アンダーバー)を入れてもOKです。

10nはEnで表すことができます。

int a=0b11101110;
int b=0x000F;
int c=0b1110_1110;
int d=12.34E-2;

 

Javaの配列

Cの配列と異なり、配列のサイズなどのフィールドがあり、

STLのvectorのように使うことができます。

int sales[]= new int[4];

for(int i=0;i<sales.length;i++){
    sales[i]=1*10;
}

 

また、javaの配列は、

一次元: int ten; int ten;

二次元: int tens; int tens;

のように、カギカッコを変数名の前と後のどちらにおいても

同じように配列を宣言できます。

一般的に変数名の前にカッコを置くのが普通のようです。

 

また、二次元の配列は一定である必要はありません。

下記のような配列もOKです。

int [][] arr = {
    {3,14,159,26,},
    {3,14,},
    {3,14,159,},
};

 

また、配列をループさせる場合は、

C++11のforeachのように、

添字無しで簡単にアクセスすることができます。

for (String s : args){
    System.out.println(s);
}

クラスメソッドで、メンバ変数(フィールド)にアクセスする時はthisを使う

C++ではthisポインタみたいな感じですね。

class User{
    String name;

    User(String name){
        this.name=name;
    }
}

クラスの継承

クラスの継承に関しては、C++とJavaで書き方が異なります。

Javaの場合、クラスを継承する場合、

extendsという予約語を使い、

親クラスのコンストラクタをアクセスする場合は、

superというコマンドを使います。

 

またJavaではアクセス修飾子(publicなど)で

メンバ変数のアクセスを制御する場合、

それぞれのフィールドにアクセス修飾子を付ける必要があります。

class User{
    String name;

    User(String name){
        this.name=name;
    }
}

class SuperUser extends User{

    private int age;
    
    SuperUser(String name){
        super(name);
    }
}

また、親クラスの関数をオーバライドするには、

@Overrideというデコレータを関数宣言の前におくと、

コンパイラが、関数名のタイポなどを検出し、

ちゃんとoverrideできているかチェックしてくれます。

(@overrideは無くても良い)

 

インスタンスのprintlnのフォーマットを規定する

Pythonのstrと同じ働きをJavaで実装するには、

下記のように、 クラスの中でtoString関数をオーバライドする必要があります。

@Override
public String toString(){
    return name+"は"+score+"点です";
}

staticフィールドとstaticメソッド

staticが付いたフィールドとメソッドは、

クラス名.フィールド or メソッド

で利用できますが、

付いていないフィールドとメソッドは、

インスタンス名.フィールド or メソッド

でしかアクセスできません。

 

staticイニシャライザとインスタンスイニシャライザ

staticなフィールドの初期化には、staticイニシャライザが使えます。

staticイニシャライザは、下記のようにstaticのあとに中括弧で囲った中で定義できます。

static int rank;  
static {  
    rank = 12;   
}  

インスタンスイニシャライザは、コンストラクタみたいなものですが、中括弧のみで定義できます。

int rank;  
{  
    rank = 12;   
}  

インスタンスイニシャライザは、コンストラクタの前に実行されるので、

複数のコンストラクタが存在している時に、

共通の処理をインスタンスイニシャライザにまとめる用途などで使用されます。

 

別クラスのインポート

C++では別クラスを利用する時は、includeを使いますが、

Javaの場合はimport文を使います。

ちなみに数学関連のMathクラスはインポートせずに使えます。

import java.util.Calendar;

 

継承とコンストラクタ

Javaのコンストラクタでは、

自動的にスーパークラスの引数なしコンストラクタが呼ばれます。

もし、呼ばれるコンストラクタを指定したい場合はsuper()を使います。

多重継承

javaは多重継承をサポートしていないようです。

しかし、インターフェースを使うと、多重継承っぽいことを実現できます。

 

C++のconstを使いたい時は、

finalを変数の型の前に置けば、その変数は変更できなくなるので、

C++のconstのような働きをしてくれます。

 

しかし、Javaのfinalは代入が不可能になるだけで、

オブジェクトそのものは変更可能なので、

注意が必要です。

 

例外

C++と異なり、exceptionを投げる可能性がある関数には、

throws exception_nameと宣言する必要があります。

 

また、例外起きようとも、起きなくても

try catch finallyのfinallyの部分は実行されるような機能があります。

C++ではこのfinallyは存在しませんが、

下記のような方法で実行可能です。

 

また、Javaにはコンパイル時にチェックされる例外と、

実行時にチェックされる例外が存在します。

 

インターフェース

C++で言う所の抽象クラスは、Javaにも存在していますが、

同じような機能のとしてinterfaceも存在します。

 

インターフェースはクラスのように、フィールドやメソッドを定義できますが、

  • インターフェースがもつフィールドは必ず定数

  • インターフェースのメソッドは抽象メソッド

  • インターフェースはインスタンスを作れない

というルールがあります。

このインターフェースの実装にはimplementsという予約語を使います。

 

Javaにおける抽象クラスとインターフェイスの使い分けとしては、

インターフェイスは外部向けのAPIを規定するものであり、

抽象クラスは、内部で複数クラスの共通部分をまとめるのに使われることが多いようです。

そのため、インターフェイスはpublicなメソッドしか定義できず、

抽象クラスはprotectedまで定義できます。

また、複数のインターフェイスを一つのクラスで実装することもできるため、

より一層、外部向けのAPI用であると言えるでしょう。

【詳解】抽象クラスとインタフェースを使いこなそう!! - Qiita

 

マルチスレッドプログラミング

Javaでマルチスレッドの処理をする場合は、

Threadクラスをextendする方法と、

Runnableインターフェースをimplementsする方法があります。

 

また関数の前にsynchronizedをつけると、

複数のスレッドで同時に実行できなくなり、排他制御が可能になります。

ここで、synchronizedはメソッドではなく、

インスタンスがロックされるイメージであることに注意が必要です。

 

関数にsynchronizedをつけることもできますし、

ブロックで一部のコードに排他制御を入れることもできます。

 

スレッド制御の関数としては、

スレッドを止めたいときは、Thread.stop(),

スレッドが終わるのを待つ場合は、Thread.join

スレッドを作ってすぐ、制御が戻したい場合は Thread.startは

スレッドの計算終了を待ちたい場合は、Thread.run

を使います。

 

Javaのマルチスレッドについては下記を参照ください。

myenigma.hatenablog.com

 

パッケージ管理

Javaのpackageは名前空間を作るものです。

C++のnamespaceに似ています。

 

Javaでは、Importで、package内のpublicのクラスなどを使えるようにできます。

C++ ではincludeを使いますが、

Javaのimportではアスタリスク(*)を使って、すべてのpublicクラスをインポートできます。

しかし、再帰的には読み込んでくれないので注意が必要です。

 

Javaのアクセス制御としては、

  • private 自分のクラスのみ

  • なし 自分のパッケージのみ

  • protected パッケージだけでなく、サブクラスにも公開

  • public みんなに見せるもの

といった、使い方をします。

 

また、一つ注意点としては、

一つのソースファイルには、一つのpublicクラスしか置けません。

そのため、同じパッケージに、複数のpublicクラスを置きたい場合は、

複数のソースコードに同じパッケージ名のpackage宣言をして、

一つにまとめることになります。

 

最後に、

パッケージの名前をユニークにするために、

会社のURLを逆にして、パッケージ名の前につける方法がよく取られるそうです。

例) http://google.com -> com.google.hoge

 

ファイルの読み込み

fileを読むときに、FileReaderインスタンスをそのまま使うのではなく、

BufferedReaderを噛ませると、メモリ上にデータをバッファしてくれるため、

一行ずつデータを読む時でも、ディスクからの読み込みが早くなります。

 

また、文字コードがUnicodeでないデータをやり取りする時には、

InputStreamReaderと、OutputStreamWriterで、

文字コードを変換しつつ、データをやり取りできます。

 

データ構造

Javaの生配列は、一度作るとサイズを増やせないので、

処理をしながら、データサイズを変更したい場合は、

ArrayListを使いましょう(C++の生配列とSTL::vectorと同じ感じです)

代表的なコレクションとしては、

vector: ArrayList,

Stack, queue:LinkedList

Map: HashMap

があります。

 

型パラメータを使って、型宣言する機能をジェネリクスといいます。

Javaではコレクションの型では、基本型を使えないので、

下記のようなラッパークラスを使います。

基本型 ラッパークラス
boolen Boolen
byte Byte
char Character
double Double
float Float
int Integer
short Short
void Void

JavaのStream

Pythonのリスト内包表記などのように、

Arrayにまとめて処理をするAPI群です。

qiita.com

 

ちなみに、JavaのIDEであるIntelijを使うと、

こんな感じでデバックできます。

 

C++と同じような所

C++と同じような所もメモしておきます。

  • スーパクラスのPrivate メソッドは継承しても、サブクラスは使えない

  • オーバーライド 上書き定義 スーパークラスのメソッドを変更すること

  • オーバロード 多重定義 同じメソッド名で引数で、複数の関数にディスパッチすること

 

Javaパッケージの配布形式(JAR, WAR, EAR)

Javaには、複数のコードをまとめて、zip形式で配布する方法があります。

代表的なものとして、JAR, WAR, EARなどがありますが、

その違いに関しては下記を参考ください。

qiita.com

 

.jarファイルも、.warファイルも下記のように、javaコマンドで実行可能です。

$ java -jar test.war

 

初心者勉強用おすすめ資料

ドットインストールのJava入門クラス

まず初めにおすすめなのは

下記のドットインストールのJavaのクラスです。

Javaの基本的な言語的な部分は、

このクラスのスクリーンキャストを見ることで理解できると思います。

 

JavaのGUIツールSwingの説明ページ

JavaのGUIツールSwingに関しては、

下記のページが初めから一つ一つ説明しているためおすすめです。

より詳しいSwingの説明に関しては、

下記の書籍もおすすめです。

 

下記の書籍

非常に参考になりました。

myenigma.hatenablog.com

 

参考資料

本記事は下記の資料を元に作成しました。

myenigma.hatenablog.com

myenigma.hatenablog.com

myenigma.hatenablog.com

myenigma.hatenablog.com

myenigma.hatenablog.com

MyEnigma Supporters

もしこの記事が参考になり、

ブログをサポートしたいと思われた方は、

こちらからよろしくお願いします。

myenigma.hatenablog.com