静岡理工科大学 菅沼ホーム C/C++ と Java 目次

Java 概説

    1. 1.データ型
    2. 2.演算子
      1. A.算術演算子と代入演算子
      2. B.関係演算子,等値演算子,及び,論理演算子
      3. C.ビット演算子とシフト演算子
    3. 3.制御文
      1. A.分岐
      2. B.繰り返し
    4. 4.配列
    5. 5.クラス定義
    6. 6.継承
    7. 7.メソッド
      1. A.基本型
      2. B.配列の引き渡し
      3. C.配列を戻り値
      4. D.main メソッド
  1. データ型(「 C/C++ と Java 」の第3章及び第4章参照)
    型名           バイト数  値の範囲
    byte             1       -128 ~ 127
    char             2       2バイトの文字
    short            2       -32,768 ~ 32,767
    int              4       -2,147,483,648 ~ 2,147,483,647
    long             8       -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
    float            4       3.4E±38(7 桁)
    double           8       1.7E±308(15 桁)
    boolean                  true, false
    			
  2. 演算子(「 C/C++ と Java 」の第3章及び第4章参照)

    1. 算術演算子代入演算子
      + : 加算(文字列の結合にも使用される)
      - : 減算
      * : 乗算
      / : 除算
      % : 余り(整数演算に対してだけ使用可能)
      = : 代入
      ++ : インクリメント演算子( 1 だけ増加)
      -- : デクリメント演算子( 1 だけ減少)
      				
    2. 関係演算子等値演算子,及び,論理演算子
      >  より大きい  a > b   式 a の値が式 b の値より大きいとき真
      <  より小さい  a < b   式 a の値が式 b の値より小さいとき真
      >= 以上     a >= b  式 a の値が式 b の値以上のとき真
      <= 以下     a <= b  式 a の値が式 b の値以下のとき真
      == 等しい    a == b  式 a の値と式 b の値が等しいとき真
      != 等しくない  a != b  式 a の値と式 b の値が等しくないとき真
      || 論理和  x || y  式 x が真か,または,式 y が真のとき真
      && 論理積  x && y  式 x が真で,かつ,式 y が真のとき真
      !  否定    ! x      式 x が偽のとき真
      				
    3. ビット演算子シフト演算子
      | 論理和      x | y   対応するビットのいずれかが 1 のとき真.
      & 論理積      x & y   対応するビットの双方が 1 のとき真
      ^ 排他的論理和 x ^ y   対応するビットが異なるのとき真
      ~ 1の補数     ~ x      ビット毎に 1 と 0 を反転する
      << 左にシフト  x << 3  3 ビット左にシフト.x を 23 倍することに相当.
      >> 右にシフト  x >> 3  3 ビット右にシフト.x を 23 で割ることに相当.
      >>> 右にシフト  x >> 3  3 ビット右にシフト( C++ における符号無しの整数を右シフトする場合に相当).
      				

  3. 制御文(「 C/C++ と Java 」の第5章参照)

    1. 分岐

      1. if 文
        if (論理式) {
        	文1(複数の文も可)
        }
        else {
        	文2(複数の文も可)
        }
        					
      2. else if 文
        if (論理式) {
        	文1(複数の文も可)
        }
        else if (論理式) {
        	文2(複数の文も可)
        }
          ・・・
        else {
        	文n(複数の文も可)
        }
        					
      3. switch 文
        switch (式) {
        	[case 定数式1 :]
        		[文1]
        	[case 定数式2 :]
        		[文2]
        	 ・・・・・
        	[default :]
        		[文n]
        }
        					
    2. 繰り返し

      1. for 文
        for (初期設定; 繰り返し条件; 後処理) {
        	文(複数の文も可)
        }
        					
      2. while 文
        while (繰り返し条件) {
        	文(複数の文も可)
        }
        					
      3. do while 文
        do {
        	文(複数の文も可)
        } while (繰り返し条件) ;
        					

  4. 配列(「 C/C++ と Java 」の第6章参照)

      Java においては,以下に示すように,new 演算子を使用して配列を定義します.例えば,
    int x[] = new int [4];   // int [] x = new int [4] でも可能
    			
    によって,int 型のデータを 4 つだけ記憶するのに必要な領域を確保されます.配列変数 x の各要素は,C++ などの配列や new 演算子によって確保された領域と同様の方法で参照可能となります.しかし,Java においては,C++ における delete 演算子に相当するものがありません.不必要になった時点で,システムが適当に領域を解放してくれます.また.Java には,ガーベッジコレクション機能がありますので,開放された領域を有効に利用可能です.

      Java には,ポインタという概念がありません.従って,C++ におけるアドレス演算子や間接演算子に相当するものがありません.しかし,次のプログラムの断片,
    int x[] = new int [4];
    int y[];
    x[2] = 300;
    y    = x;
    y[2] = 200;
    			
    における x と y との関係はその右図(「 y[2] = 200 」を実行した後の状態)のようになっています.明らかに,x と y は,ポインタとして機能しています.配列の宣言方法は,C++ における,
    int *x = new int [4];
    			
    とほとんど同じであり,変数 x の機能もポインタそのものです.Java には,表面上,ポインタやアドレスといった概念がありませんが,その実体は違います.この点に,十分注意してください.

  5. クラス定義(「 C/C++ と Java 」の第10章参照)

      住所録を作成する際のように,氏名,住所,電話番号などをまとめて一つのデータとして扱いたい場合があります.数学の例で言えば,複素数などが相当します.複素数は,実数部と虚数部という 2 つの実数データの組からなっており,それらのデータは常に一緒に扱われます.

      クラスの内部には,データだけではなく,そのデータを処理するためのメソッド( C/C++ などの関数に相当し,データを受け取り処理結果を返す)も定義できます.そして,データやメソッドの対して参照制限を設けることが可能です.クラスの定義方法を一般的に記述すれば以下のようになります.
    [クラス修飾子] クラス識別子 {
    	クラス本体(変数やメソッドの定義)
    }
    			
      クラス修飾子は,以下のいずれかから選択します.クラス修飾子を使用せずにクラスを定義すると,同じパッケージ内にあるクラスだけがこのクラスにアクセスできるものと自動的に判断されます.

    1. public  すべてのクラスからアクセス可能になります.一つのアプレット,ファイル内で public 宣言できるのは一つのクラスだけです.
    2. abstract  抽象クラスであることを示します.
    3. final  このクラスからほかのクラスを派生できないことを宣言するために使用します(次節参照).

      C++ のように関数や変数をまとめてそのアクセス権等を定義するようなことはせず,個々のメソッドや変数の定義に修飾子として直接記述します.メソッドを定義するための修飾子は 8 つあり,以下の 3 つのグループの中から一つづつ選択して使用します(必ず,3 つを指定しなければならないわけではありません).ただし,修飾子の組み合わせによっては,矛盾が生じるような場合もありますので注意してください.

    1. public,protected,private (何も指定しないと,同じパッケージからだけアクセス可能となる)

      • public  このメソッドをすべてのクラスからアクセスできます.異なるパッケージからアクセスしたい場合は,必ず指定する必要があります.
      • protected  同じパッケージ及びクラスの派生クラスだけからアクセスできます(次節参照).
      • private  クラスのオブジェクトだけからアクセスできます.

    2. static

      • static  通常のメソッドは,各オブジェクトに結びつき,そのオブジェクトにアクセス可能ですが,static 指定されたメソッドは,クラスに結びつき,特別に指定しない限りオブジェクトからはアクセスできません.したがって,アクセスも,「オブジェクト名.メソッド名」ではなく,「クラス名.メソッド名」というようにして行います.例えば,三角関数や対数関数の値を計算するために利用される Math クラスのメソッドは static 宣言されています.したがって,ある値 x の正弦を計算したいときには「 Math.sin(x) 」のような形で使用します.

    3. abstract,final,native,synchronized

      • abstract  抽象メソッドであることを意味しています.
      • final  階層の最も下のメソッドであることを意味し,それより下位のクラスでは,同じ名前のメソッドを定義しオーバーライド(他で定義された関数を,書き換えて再定義すること)することができません.
      • native  他の言語で記述されたメソッドであることを意味します.
      • synchronized  オブジェクトが複数のオブジェクトから同時に実行されることを制限するために使用されます.

      変数の修飾子は 7 つあります.以下の 2 つのグループから一つずつを選択して使用します.メソッドの修飾子と同様,必ず修飾子を付けなければならないわけではありません.

    1. public,protected,private (何も指定しないと,同じパッケージからだけアクセス可能となる)

      • public  この変数をすべてのクラスからアクセスできます.異なるパッケージからアクセスしたい場合は,必ず指定する必要があります.
      • protected  同じパッケージ及びクラスの派生クラスだけからアクセスできます(次節参照).
      • private  クラスのオブジェクトだけからアクセスできます.

    2. static,final,transient,volatile

      • static  メソッドの場合と同様,クラスに結びついた変数です.したがって,オブジェクトごとに値を変化させるようなことはできません.アクセスも,「オブジェクト名.変数名」ではなく,「クラス名.変数名」というようにして行います.例えば,Math クラスの PI(π) などが相当します.
      • final  クラスのオブジェクト全体で使用可能な定数となります.
      • transient  未使用.
      • volatile  非同期方式の多重処理で使用され,この変数は使われるたびにメモリからロードされ,また,メモリに格納されます.

      全てのデータを private に指定し,また,全てのメソッドのアクセス権を指定しないで Complex というクラスを定義すると,以下のようになります.

    import java.io.*;
    
    class Test {
    	public static void main (String[] args)
    	{
    		Complex x = new Complex (1.0, 0.0);   // 初期設定を行う場合
    		Complex y = new Complex ();   // 初期設定を行わない場合
    
    		x.print();
    		y.set(5.1, 1.5);
    					// 以下の処理は不可能
    					//	y.real      = 5.1;
    					//	y.imaginary = 1.5;
    		y.print();
    	}
    }
    			// クラス Complex
    class Complex {
    	private double real;
    	private double imaginary;
    					// 引数のないコンストラクタ
    	Complex() {};
    					// 引数のあるコンストラクタ
    	Complex(double a, double b)
    	{
    		real      = a;
    		imaginary = b;
    	}
    					// 値の設定するためのメソッド
    	void set(double a, double b)
    	{
    		real      = a;
    		imaginary = b;
    	}
    					// 出力するためのメソッド
    	void print()
    	{
    		System.out.println("実数部 = " + real + ", 虚数部 = " + imaginary);
    	}
    }
    			

      コンストラクタとは,main メソッドの最初の 2 行に示すように,クラスのインスタンスが生成されたとき( Complex 型の変数が定義されたとき),最初に呼ばれるメソッドです.初期設定を行うメソッドと言って良いかもしれません.この例では,引数の無い場合とある場合に対する 2 種類のコンストラクタを定義しています.なお,Java においては,デストラクタは存在しません.また,演算子のオーバーロードも不可能です.

      Java においては,上の例に示すように,インスタンスを生成するためには必ず new 演算子を利用します.この方法は,C++ における,
    Complex *x = new Complex (1.0, 0.0);   // 初期設定を行う場合
    Complex *y = new Complex ();   // 初期設定を行わない場合
    			
    の形式と非常に良く似ています.実際,以下のプログラム例(全てのデータやメソッドに対してアクセス権を指定していない)に示すように,変数 y1 や y2 は,生成されたオブジェクトへのポインタと考えた方が妥当です.右図は,y2 に y1 が代入され( y1 と y2 が同じアドレスを指すようになる),「 y2.imaginary = 4.0; 」を実行した後の状態を示しています.

    import java.io.*;
    
    class Test {
    	public static void main (String[] args)
    	{
    		Complex y1 = new Complex (5.0, 0.0);
    		Complex y2;
    
    		System.out.println("y1 : 実数部 = " + y1.real + ", 虚数部 = " + y1.imaginary);
    		y2 = y1;
    		System.out.println("y2 : 実数部 = " + y2.real + ", 虚数部 = " + y2.imaginary);
    		y2.imaginary = 4.0;
    		System.out.println("y1 : 実数部 = " + y1.real + ", 虚数部 = " + y1.imaginary);
    		System.out.println("y2 : 実数部 = " + y2.real + ", 虚数部 = " + y2.imaginary);
    	}
    }
    			// クラス Complex
    class Complex {
    	double real;
    	double imaginary;
    					// 引数のないコンストラクタ
    	Complex() {};
    					// 引数のあるコンストラクタ
    	Complex(double a, double b)
    	{
    		real      = a;
    		imaginary = b;
    	}
    }
    			

  6. 継承(「 C/C++ と Java 」の第13章参照)

      クラスにおいて,継承は重要な機能です.Window のプログラムを考えてみてください.多くのアプリケーションにおいて Window を利用していますが,その基本的構成はほとんど同じです.もし,Window アプリケーションを作成するたびに,その全てに関するプログラムを書かなければならないとしたら大変な作業になります.基本的な Window の機能を持つクラスを定義しておき,個々の Window アプリケーションは,そのクラスを利用できるとしたら非常に便利です.

      継承を利用すれば,指定されたクラス(単一のクラスだけ)の機能を受け継ぎ,新しいクラスに必要な機能の追加・修正だけを行えばよくなります.例えば,以下のプログラム(あまり良い例ではありませんが)においては,クラス Number は,クラス Base を継承しています.このとき,元になったクラス( Base )をスーパークラス,そのクラスを継承したクラス( Number )をサブクラスと呼びます.

      スーパークラスにおいて,「 protected 」指定されたデータやメソッドは,そのクラスを継承したサブクラスだけから参照可能です.また,すべてのメンバーがほとんどそのままの状態( private は private,public は public 等)で継承されます.

      また,コンストラクタは継承されませんので,スーパークラスにパラメータを必要とするコンストラクタが存在する場合は,super を使用して明示的に呼び出します.

    import java.io.*;
    
    class Test {
    	public static void main (String[] args)
    	{
    		Number x = new Number (10, 2);
    		Number y = new Number (5, 4);
    
    		x.add();
    		x.print();
    		y.sub();
    		y.print();
    	}
    }
    			// クラス Base
    class Base {
    	protected int n;
    	protected int step;
    					// コンストラクタ
    	Base (int sp)
    	{
    		step = sp;
    	}
    					// 出力
    	void print() { System.out.println("value = " + n); }
    					// 加算
    	void add() { n += step; }
    					// 減算
    	void sub() { n -= step; }
    }
    			// クラス Number
    class Number extends Base   // Base の継承
    {
    					// コンストラクタ
    	Number (int n1, int sp)
    	{
    		super(sp);   // スーパークラスのコンストラクタの呼び出し
    		n = n1;
    	}
    }
    			

      Java には,C++ のように,派生クラスに関して多重継承の機能がありません.そこで,その機能の一部を補うのがインタフェースです.クラスの階層構造の中で,上下関係にない複数クラス間で情報を交換する(共通の変数やメソッドの利用する)ための機能であり,クラスと同様以下のようにして定義されます.
    public interface インタフェース名 extends 親インタフェース名 [ , ・・・ ] {
    	// 変数:static final とみなされる
    	// メソッド宣言:abstract とみなされる
    }
    			
      クラスは,複数のインタフェースを継承可能です( implements の後ろに複数のインタフェースをカンマで区切って並べることができます).ただし,継承可能なものは,メソッドの宣言と static な変数だけであり,継承したクラスが抽象クラスでない限り,インタフェース内で宣言されたメソッドの内容を定義(オーバーライド)してやる必要があります.

  7. メソッド(「 C/C++ と Java 」の第7章参照)

      Java においては,main メソッドも含み,全てのプログラムがいずれかのクラスに含まれています.従って,C++ におけるメンバー関数に相当するもの(以後,メソッドと呼びます)だけが存在します.メソッド内では,与えられた情報(引数リスト)に基づき何らかの処理を行い,その結果を戻り値( 1 つの値)として返します.メソッド名は,同じクラス内で唯一の名前である必要がありますが,引数や戻り値が異なる場合は同じ名前のメソッドが存在しても構いません(多重定義,オーバーロード).

    1. 基本型

        メソッドにデータを渡し,その結果を得るためには様々な方法が考えられます.最も簡単な方法は,以下に示すプログラム例( 2 つのデータの和を求めるメソッド)のように,引数としてデータ(厳密には,データのコピー)を渡し,戻り値として結果を受け取る方法です.なお,main メソッドから他のメソッドを呼ぶと,main メソッドが static メソッドであるため,メソッド add も static にしなければならず,

      import java.io.*;
      
      class Test {
      					// メソッド main
      	public static void main (String[] args)
      	{
      		int x = 10, y = 20;
      
      		System.out.println("和 = " + add(x, y));
      	}
      					// メソッド add
      	static int add(int a, int b)
      	{
      		return a + b;
      	}
      }
      				

      のように記述する必要があります.そこで,以下の例においては,次のプログラムに示すように,main メソッドの中で Example クラスのインスタンスを生成してメソッドの例を示します.

      import java.io.*;
      
      class Test {
      					// メソッド main
      	public static void main (String[] args)
      	{
      		Example ex = new Example();
      	}
      }
      
      class Example {
      					// コンストラクタ
      	Example()
      	{
      		int x = 10, y = 20;
      
      		System.out.println("和 = " + add(x, y));
      	}
      					// メソッド add
      	int add(int a, int b)
      	{
      		return a + b;
      	}
      }
      				

    2. 配列の引き渡し

        引数としてデータを渡す場合,その値がコピーされて渡されるため,メソッド内において引数(上の例における a や b )の値を変更しても,メソッドを呼んだ側の x や y の値はその影響を受けません.上の例のように,1 つの結果だけを求める場合は問題ありませんが,例えば,和と差のように,複数の結果を得たい場合はどのようにすればよいでしょうか.その一つの方法は,配列を利用することです.配列を引数にすることは,アドレスを引数にすることに相当し,アドレスがコピーされて渡されてもその指す場所は同じであるため,配列要素をメソッド内で変更できるからです.下の例では,和と差を配列に入れて返しています.

      import java.io.*;
      
      class Test {
      					// メソッド main
      	public static void main (String[] args)
      	{
      		Example ex = new Example();
      	}
      }
      
      class Example {
      					// コンストラクタ
      	Example()
      	{
      		int x = 10, y = 20;
      		int z[] = new int [2];
      
      		add(x, y, z);
      		System.out.println("和 = " + z[0] + "  差 = " + z[1]);
      	}
      					// メソッド add
      	void add(int a, int b, int c[])
      	{
      		c[0] = a + b;
      		c[1] = a - b;
      	}
      }
      				

    3. 配列を戻り値

        上の例では,結果を引数として返していましたが,アドレスを使用すれば,以下に示す例のように,戻り値を利用して複数データを返すことも可能です.

      import java.io.*;
      
      class Test {
      					// メソッド main
      	public static void main (String[] args)
      	{
      		Example ex = new Example();
      	}
      }
      
      class Example {
      					// コンストラクタ
      	Example()
      	{
      		int x = 10, y = 20;
      		int z[];
      
      		z = add(x, y);
      		System.out.println("和 = " + z[0] + "  差 = " + z[1]);
      	}
      					// メソッド add
      	int [] add(int a, int b)
      	{
      		int c[] = new int [2];
      
      		c[0] = a + b;
      		c[1] = a - b;
      
      		return c;
      	}
      }
      				

        クラスのオブジェクトをメソッドの引数とする場合もあります.C++ においては,幾つかの方法を利用できましたが,Java においては,記述的には上で示したプログラムにおける変数 a や b と同じ方法で渡します.しかし,その実態は,C++ における参照渡しによく似ています.従って,記述方法においては変数 a や b と同じですが,何も指定しなければ,メソッド内でオブジェクトの値を変更可能です.

    4. main メソッド

        例えば,
      java add 2 3
      				
      とキーボードから入力すると,3 つの値 2 と 3 の和を計算し,その結果をディスプレイに出力したいような場合が存在します(下に示すプログラム例).このような場合,2 や 3 が main メソッドの引数とみなされます.ただし,main メソッドの場合は,引数の受け渡し方が以下のように決まっており,args に各引数に対応する文字列が入ります.
      public static void main ( String args[] )
      				
      import java.io.*;
      
      public class Test {
      	public static void main(String args[]) throws IOException
      	{
      		int i1, k, sum = 0;
      	/*
      		 引数の内容の出力
      	*/
      		System.out.println("     引数の数 " + args.length);
      
      		for (i1 = 0; i1 < args.length; i1++) {
      			k = Integer.parseInt(args[i1]);   // 文字を整数に変換
      			System.out.println("     " + (i1+1) + " 番目の引数 " + k);
      			sum += k;
      		}
      	/*
      		 結果の表示
      	*/
      		System.out.println("結果=" + sum);
      	}
      }
      				

静岡理工科大学 菅沼ホーム C/C++ と Java 目次