HOです。


 前回、キーボード入力されたデータをそのまま計算しようとすると、

 型の関係でエラーが出てきました。


 これから何回かの記事にかけて、

 基本データ型(boolean、byte、short、int、long、float、double、char)において、

 型を変換できるパターンと、できないパターンをまとめていきたいと思います。


 この型変換に関する仕組みは、"Stringの森"のように、結構奥深いものです。

 ですので、遭難しない範囲で"型変換の洞窟"を探索してみたいと思います。




まずは、いくつか型変換をテストするプログラムをコンパイルして、

どのようになるか見てみたいと思います。


まずboolean型から他の基本データ型への変換です。

----------------------------------------------------

class TypeTest_Boolean{


public static void main(String args[]){


boolean test = false;


//booleanから各型へ変換
boolean bl = test;
byte bt = test;
short s = test;
int i = test;
long l = test;
float f = test;
double d = test;
char c = test;

}


}

----------------------------------------------------

このプログラムは、boolean型の変数testを宣言し、

それを他の基本データ型に入れるプログラムです。


早速、コンパイルしてみましょう。
ドリームサポートネットーワークのブログ-h03 型変換(boolean)

・・・おもしろいぐらいにコンパイルエラーとなりました!(^_^;)

それでは、エラーの詳細を確認してみましょう。

エラーとなったのは、boolean型以外の基本データ型すべてでした。

エラー内容はすべて「互換性のない型」です。


ここからわかったのは、

boolean型は他の基本データ型に型変換することはできないということです。







それでは、続いてint型から他の基本データ型に変換してみましょう。

----------------------------------------------------

class TypeTest_Int{


public static void main(String args[]){


int test = 1;


//intから各型へ変換
boolean bl = test;
byte bt = test;
short s = test;
int i = test;
long l = test;
float f = test;
double d = test;
char c = test;


}


}

----------------------------------------------------

このプログラムは、

変数testをint型として宣言し、他の基本データ型に入れるものです。

このプログラムもコンパイルしてみましょう。



ドリームサポートネットーワークのブログ-h04 型変換(int)

先ほどのプログラムよりはエラーの数は減りましたね。


1つ目のエラーは、int型からboolean型へは型変換できないというものです。

boolean型と他の基本データ型は型変換できないので、

これは先ほどと同じものですね。




残り3つのエラー内容は、「精度が落ちている可能性」というものです。


「精度が落ちている可能性」というのは、どういう意味でしょうか?


以前基本データ型のデータの範囲を取り上げましたが、(こちら

int型の範囲は「-2147483648~+2147483647」でした。

それに対し、

byte型は「-128~+127

short型は「-32768~+32767

と、int型より範囲が狭くなります。


このように、ある型の値を、それより有効な値の範囲が狭い型に変換する事を、

縮小交換(ナローイング交換)」と言います。


縮小交換すると、データが失われる可能性があります。


例えば、「int型で宣言した変数」に「40000」という値を入れたとしましょう。

「40000」という値は、byte型の最大値「127」、short型の最大値「32767」より大きい値になります。

それなのに、この「40000」という値をbyte型やshort型入れようとすると、

「40000」という値は失われてしまいます。


もちろん「int型で宣言した変数」に「1」を入れたとすれば、

byte型もshort型も問題なく入れることができます。


しかし、縮小交換をすると、値によってはデータが失われる場合があるため、

Javaのコンパイラは、縮小交換をエラーとして判定します。

それで、「精度が落ちている可能性」というエラー内容が表示されたわけです。




もう一点、char型に関してですが、これも「精度が落ちている可能性」とあります。


char型は1文字を表しますが、

これは、Unicode文字を4桁の16進数で表現しています。

そのため、char型の値を数字として対応することができます。

しかし、byte型、short型と同じく、データが失われる可能性があるため、

「精度が落ちている可能性」というエラー内容が表示されていました。




最後にこのプログラムで取り上げておきたい点が、

エラーとならなかった型変換は何かと言う点です。


int型から、long型・float型・double型への型変換はエラーとなっていません!


どうしてでしょうか?

これらの型の値の範囲を比較すると、その理由が見えてきます。(こちら


int型の範囲は「-2147483648~+2147483647」なのに対し、

long型が「-9223372036854775808~+9223372036854775807」、

float型が「±3.40282347E+38~±1.40239846E-45」、

double型が「±1.79769313486231570E+308~

 ±4.94065645841246544E-324」です。

つまりこれらは、int型の値の範囲より、範囲が広い型です。


このようにある型の値を、その型より有効な値の範囲が広い型に変換するのを、

拡張変換(ワイドニング交換)」と言います。







拡張変換はエラーが出ないということですから、

最後に、様々な拡張変換を試してみましょう。

----------------------------------------------------

class KakutyouTest{


public static void main(String args[]){


//①拡張変換

byte bt = 1;

short s = bt;

char c = s;

int i = c;

float f = i;

long l = f;

double d = l;


//②結果を表示する
System.out.println("byte => " + bt +
"\nshort => " + s +
"\nchar => " + c +
"\nint => " + i +
"\nfloat => " + f +
"\nlong => " + l +
"\ndouble => " + d);


}


}

----------------------------------------------------


コンパイル結果は・・・
ドリームサポートネットーワークのブログ-h05 拡張変換

2つだけエラーとなりました。

それは、short型からchar型への変換と、

float型からlong型への変換です。

逆に言うと、それ以外の型変換は問題なかったということを意味します。


この2つのエラーの意味については、次回取り上げたいと思います。





今回のポイントです。


「boolean型は他の基本データ型に型変換できない」

サイズの大きな型から小さい型に変換することを

  「縮小変換(ナローイング変換)」といい、

サイズの小さな型から大きい型に変換することを

  「拡張変換(ワイドニング変換)」という。

HOです。


 前回、演算子の種類について概観してみました。

 今回は、いよいよ第3段階の目標であるキーボードで受け取ったデータを用いて、希望する計算結果を表示するプログラムを作成して見たいと思います。



以下は、第二段階で作成したプログラムです。

--------------------------------------------------------------------
class InputTest{

  public static void main(String args[]){

    java.io.BufferedReader myReader =
    new java.io.BufferedReader( new java.io.InputStreamReader(System.in),1);


    try{

      System.out.println("レシピにある分量を記してください");
      String myStringA = myReader.readLine();

      System.out.println(myStringA + "は、何人分か記してください");
      String myStringB = myReader.readLine();


      System.out.println("知りたい分量は何人分か記してください");
      String myStringC = myReader.readLine();

      System.out.println("レシピの分量=「" + myStringA + "」");
      System.out.println("レシピの人数=「" + myStringB + "人分」");
      System.out.println("知りたい分量=「" + myStringC + "人分」");

    }catch(java.io.IOException e){
    }

  }

}
--------------------------------------------------------------------

このプログラムはキーボードで入力されたデータを、

そのまま画面に表示するという単純なものでしたが、

今回は、ここで得たデータを使って、計算結果を表示するようにしたいと思います。




作成するにあたって、
以下の第3段階(その1)で作成したプログラムも参考にしたいと思います。

----------------------------------------------------------

class TestKeisan{

  public static void main(String args[]){

    // ①

    double bunryou = 25;

    int ninzuuA = 2;

    int ninzuuB = 10;


    double kekka;


    // ②

    kekka = bunryou / ninzuuA * ninzuuB;


    // ③

    System.out.println(ninzuuB + "人分の分量は、" + kekka + "です。");


  }

}

----------------------------------------------------------




まあ、ふたつのデータをあわせるだけですから簡単簡単!

--------------------------------------------------------------------
class InputTest2{

  public static void main(String args[]){

    java.io.BufferedReader myReader =
    new java.io.BufferedReader( new java.io.InputStreamReader(System.in),1);


    try{

      // ①

      System.out.println("レシピにある分量を記してください");
      String myStringA = myReader.readLine();

      System.out.println(myStringA + "は、何人分か記してください");
      String myStringB = myReader.readLine();


      System.out.println("知りたい分量は何人分か記してください");
      String myStringC = myReader.readLine();


      // ②

      double bunryou = myStringA;

      int ninzuuA = myStringB;

      int ninzuuB = myStringC;


      double kekka;

      kekka = bunryou / ninzuuA * ninzuuB;


      // ③

      System.out.println(ninzuuB + "人分の分量は、" + kekka + "です。");


    }catch(java.io.IOException e){
    }

  }

}
--------------------------------------------------------------------
と簡単に作成できてしまいました!


このプログラムを解説しますと、

まずクラス名を「InputTest2」としました。

そして①で一問一答方式でキーボード入力してもらい、

②で受け取ったデータを、計算する用の変数に当てはめて、計算しています。

③でその結果を画面に表示します。


まあ、これぐらい朝飯前ていうところですかね!





では、このプログラムをコンパイルしてみます。


ドリームサポートネットーワークのブログ-h02 コンパイル失敗
!!ええっ!!

コンパイルエラーとなりました!しかも3個も!!

特にエラーになりそうなことはしていないはずなんですが・・・


・・・とりあえず落ち着いてエラーの内容を読んでみたいと思います。



まず「InputTest2.java:26」とあります。

これは、エラーとなったところがどこかを示しています。

「InputTest2.java」の中の「26行目」ということですね


続いてエラー内容が「互換性のない型」とあります。

具体的には、

「検出値 : java.lang.String」

「期待値 : double」

「double bunryuo = myStringA;」とあります。


どうやら型に関するエラーとなっているようです。(型についてはこちら




「mySringA」というのは、String型変数として宣言していました。

そして「bunryou」というのは、double型変数として宣言しています。

それで、double型である変数bunryouに、

String型変数のデータを入れようとしたことが、

エラーとなった原因でした。





実は、Javaは強く型付けされている言語です。

基本データ型(boolean、byte、short、int、long、float、double、char)や

参照型(Stringなど)と、様々な型があります。
Javaの場合、変数は、どの型か宣言しなければなりません。

そして、ある型のデータを、別の型に変換できる場合と、できない場合があります。


先ほどの、String型からdouble型へは変換できません。

そのため、エラー内容が「互換性のない型」となったのでした。



詳しくは次回以降で取り上げたいと思います。

次回は、基本データ型の組み合わせごとに変換可否について取り上げます。




今回のポイントです。

 データを変数に入れる場合、型をよく考えて作成する必要がある。

HOです。


 11月8日23時目標と宣言していましたが、

 結局2日遅れのアップとなってしまいましたm(_ _;)m


 前回、簡単な計算プログラムを作成しました。

 今回、その際に登場した「演算子」について詳しく取り上げたいと思います。



 Javaで利用できる演算子には以下のものがあります。



優先

順位

結合

規則

種類 演算子 オペランドの型 役割
1

後置

演算子

.



[ ]

メソッド(引数)

++

- -

obj.value

obj.method()


array[3]

readLine()

p++

p- -

オブジェクト、メンバー



配列、int

メソッド、引数リスト

変数

オブジェクトの

メンバーのアクセス


配列要素のアクセス

メソッドの呼び出し

後置のインクリメント

後置のデクリメント

2

単項

演算子

++

- -

+

-

~

!

++p

- -p

+n

-n

~i

!b

変数

数値

整数

ブール

前置のインクリメント

前置のデクリメント

単項プラス

単項マイナス

ビットごとの補数

論理否定

3

生成

キャスト

new

()

new String("test")

(int) 3.14

クラス、引数リスト

型、任意

オブジェクトの生成

キャスト(型変換)

4

算術

演算子

(積商)

*

/

%

n1 * n2

n1 / n2

n1 % n2

数値、数値

乗算

除算

剰余

5

算術

演算子

(和差)

文字列

連結

+

-

+

n1 + n2

n1 - n2

"ABC" + "DEF"

数値、数値

文字列、任意

加算

減算

文字列の連結

6

シフト

演算子

<<

>>

>>>

i1 << i2

i1 >> i2

i1 >>> i2

整数、整数

左シフト

符号拡張を伴う右シフト

ゼロ拡張を伴う右シフト

7

関係

演算子

<

<=

>

>=

instanceof

n1 < n2

n1 <= n2

n1 > n2

n1 >= n2

s instanceof String

数値、数値

参照、型

~より小さい

~以下

~より大きい

~以上

型の比較

8

等値

演算子

= =

!=

= =


!=


d1 = = d2

d1 != d2

r1 = = r2


r1 != r2


基本型、基本型

参照、参照



等しい(値が同一)

等しくない(値異なる)

等しい

(同一オブジェクト参照)

等しくない

(異なるオブジェクト参照)

9

ビット

論理積

演算子

&


&


i1 & i2


b1 & b2


整数、整数


ブール、ブール


ビットごとの論理積

(AND)

ブールの論理積

(AND)

10

ビット

排他的

論理和

演算子

^


^


i1 ^ i2


b1 ^ b2


整数、整数


ブール、ブール


ビットごとの

排他的論理和

(XOR)

ブール型の

排他的論理和

(XOR)

11

ビット

論理和

演算子

|


|


i1 | i2


b1 | b2


整数、整数


ブール、ブール


ビットごとの論理和

(OR)

ブール型の論理和

(OR)

12

論理積

演算子

&&

b1 && b2

ブール、ブール

条件付きの論理積

(AND)

13

論理和

演算子

||

b1 || b2

ブール、ブール

条件付きの論理和

(OR)

14

条件

演算子

? :

b ? x : y

ブール、任意、任意 条件式(三項式)
15

代入

演算子


複合

代入

演算子

=



*=

/=

%=

+=

-=

<<=

>>=

>>>=

&=

^=

|=

p = x



p *= n

p /= n

p %= n

p += n

p -= n

p <<= i

p >>= i

p >>>= i

p &= b

p ^= b

p |= b

変数、任意



変数、任意

代入


演算を伴う代入

(複合代入演算子)

16

順次

演算子

,

a = 3, b =5

式、式

for文で使用する。




優先順位


 演算が行われる順番を表しています。


 例えば、「10 - 35 / 7」という式の場合、

 「-」は優先順位は「5」、「/」は優先順位は「4」です。


 それで、優先順位の高い「35/7」を計算し、続いて「10 - 5」を計算します。




結合規則


 同じ優先順位の演算子が複数ある場合、この規則により順番が決まります。


 例えば、「33 - 15 + 27」という式の場合、

 「-」「+」ともに優先順位は「4」です。

 同じ優先順位の演算子が2つありますので、計算する順番は結合規則によりますので、

 優先順位「4」の結合規則は、「左」から計算するタイプです。


 それで、まず「33 - 15」を計算し、続いて「18 + 27」を計算します。




オペランドの型


 その演算子の対象となる値や変数を「オペランド」と言います。

 その「オペランド」の型と、オペランドの数を表します。


 例えば、優先順位「2」にある「単項マイナス」の「-」は、「-1000」などと使います。

 この演算子は、オペランドの型は「数値(boolean以外の基本データ型 )」で、

 オペランドの数は「1つ」のみです。

 オペランド1つのだけ操作する演算子を「単項演算子」と言います。


 また、優先順位「4」にある「乗算」の「*」は、「3 * 5」などと使います。

 この演算子のオペランドの型は「数値、数値」で、

 オペランドの数は「2つ」あります。(例では「(3」「5」の2つ)

 オペランド2つの演算子のことを「二項演算子」と言います。


 最後に、優先順位「14」にある「条件式(三項式)」の「 ? : 」は、「(i < 100) ? i : 100」などと使います。

 この演算子のオペランドの型は「boolean、任意、任意」で、

 オペランドの数は「3つ」あります。(例では「(i < 100)」「i」「100」の3つ)

 オペランド3つの演算子のことを「三項演算子」と言います。



以上が簡単な説明となります。

さらに詳しくは、今後プログラム作成の必要に応じて、取り上げて行きたいと思います。




さて、前回取り上げたプログラムにはいくつ演算子があったでしょうか?


このプログラムでした。

----------------------------------------------------------

class TestKeisan{

public static void main(String args[]){

// ①

double bunryou = 25;

int ninzuuA = 2;

int ninzuuB = 10;


double kekka;


// ②

kekka = bunryou / ninzuuA * ninzuuB;


// ③

System.out.println(ninzuuB + "人分の分量は、" + kekka + "です。");


}

}

----------------------------------------------------------





この中で、演算子をすべて太字で表示してみると・・・

----------------------------------------------------------

class TestKeisan{

public static void main(String args[]){

// ①

double bunryou = 25;

int ninzuuA = 2;

int ninzuuB = 10;


double kekka;


// ②

kekka = bunryou / ninzuuA * ninzuuB;


// ③

System.out.println(ninzuuB + "人分の分量は、" + kekka + "です。");


}

}

----------------------------------------------------------


全部で14ありました。

こんな簡単なプログラムでもたくさんの演算子が関係しているのですね。




今回、演算子について概要を理解できましたので、

次回は、第2段で作成したキーボードで受け取ったデータを計算して、

希望する値を表示できるように改良したいと思います。




今回のポイントです。

 ・計算する式を作るには、2つの要素が必要。

  1つは、計算する記号を表わす「演算子」と、

  もうひとつは、その演算子の対象となる値または変数である「オペランド」。


 ・オペランドを1つだけ操作する演算子を「単項演算子

  2つ操作する演算子を「二項演算子

  3つ操作する演算子を「三項演算子」という。