##演算子の優先度
式の中に複数の演算子があった場合に、どの演算子から計算するかの順序づけ
##演算子の結合規則
式の中に同じ優先度の演算子が複数ある場合に、左右どちらから計算するか
+と-は優先度同じで結合規則は左
int num = 10 - 5 - 3 + 12
= 5 - 3 + 12
= 2 + 12
= 14
#演算の例
オペラント:演算の対称となる変数やリテラル
リテラル:コード内に書く文字列や数値 0.2F null とか特殊な意味を持たせる事もある
System.out.println(10 / 3);
System.out.println(10 / 3.0);
System.out.println(10 % 3);
String str = "Hello";
int a = 10, b = 20;
System.out.println(str + a);
System.out.println(str + a + b);
System.out.println(str + (a + b));
System.out.println(a + b + str);
出力結果
3 //整数同士の演算の実行結果は整数
3.3333333333333335 //小数を含む演算の実行結果は小数
1 //あまりは整数
Hello10 //文字列と数値では結合した文字列になる
Hello1020 //文字列と数値を結合した文字列にさらに数値を結合
Hello30 //()内の式は数値のみなので計算後、文字列と結合
30Hello //結合規則が左からなので数値同士の計算後、文字列を結合
変数のデータ型や、リテラルの種類によって結果が変わる
演算の順番も結合規則と優先度に左右されるので注意が必要
##++(インクリメント)、--(デクリメント)
変数の前に配置すると他の処理より前に
変数の後に配置すると他の処理より後に行われる
int a = 10, b = 10, c = 10, d = 10;
System.out.println(a++);
System.out.println(++b);
System.out.println(c--);
System.out.println(--d);
a = 10; b = 10; c = 10; d = 10;
b = ++a; // 前置
System.out.println("a = " + a + " b = " + b);
d = c++; // 後置
System.out.println("c = " + c + " d = " + d);
出力結果
10
11
10
9
a = 11 b = 11 bにaを代入する前にaを+1
c = 11 d = 10 dにcを代入した後にcを+1
注意点
変数に対してインクリメント、デクリメントの処理がされている時は
変数の値のコピーに対してではなく、変数自体の値に対して処理を行う
int a = 10;
int b = a++ + ++a - --a
= 10 + 9 - 8
= 11
b = 19
a = 8
また同じ変数が両辺にある場合インクリメント、デクリメントされた変数を一時的な変数として扱う
int a = 10;
a = a++ + ++a + a-- +a
a = 10 + 12 + 12 + 11 //右辺は全て一時変数のaとして共通の処理が行われる
a = 45; //最終的なaの値は一時変数の演算結果が左辺に代入されて確定する
##代入演算子
=は左辺と右辺が等しい事を表しているのではなく
左辺に右辺を代入している
+= A += B //A = A + B と同じ
-= A -= B //A = A - B と同じ
*= A *= B //A = A * B と同じ
/= A /= B //A = A / B と同じ
%= A %= B //A = A % B と同じ
##関係演算子(==)
右辺と左辺を比較し条件に一致するかどうかFalse or True を返す
int a = 10, b = 20, c = 10;
a == b : false
a == c : true
a != b : true
a != c : false
a < b : true
a <= c : true
a > b : false
a >= c : true
##同一性・同値性
javaにおける同じという言葉の意味
1. 同じインスタンスである(同一性)
2. 同じ値である(同値性)
参照型のデータにおいては 1が判定条件となる
→同じ値であっても参照先(実体となるインスタンス)が異なれば一致条件に当てはまらない
プリミティブ型のデータにおいては 2が判定条件となる
ただし上記に加えて条件の評価手順が違うので注意が必要
int a = 10, b = 10, c = 10, d = 10;
boolean result1 = a++ > 10 & ++b > 10;
//a > 10 を評価 False その後 a + 1する
//b + 1 > 10 を評価 True
System.out.println("result1:" + result1 + " a:" + a + " b:" + b);
boolean result2 = c++ > 10 && ++d > 10;
//c > 10 を評価 False その後 c + 1する
//d + 1 > 10 の評価は行われない!
System.out.println("result2:" + result2 + " c:" + c + " d:" + d);
result1:false a:11 b:11
result2:false c:11 d:10
##String・StringBuilder
String型
・データは参照型
・元の文字列は書き換えられず新しい文字列が作成され、参照先が変わる
StringBuilser型
・データは基本データ型
・新しい文字列で上書きする
・文字列を操作するメソッドが多数用意されている
##関係演算子による基本データ型の比較
int n1 = 10; int n2 = 1_0; long n3 = 10L;
byte n4 = 10; char n5 = 'a';
float n6 = 10.0f; double n7 = 10.0;
boolean n8 = true;
System.out.println("n1 == n2 : " + ( n1 == n2 ));
System.out.println("n1 == n3 : " + ( n1 == n3 ));
System.out.println("n1 == n4 : " + ( n1 == n4 ));
System.out.println("n5 == 'a' : " + ( n5 == 'a' ));
System.out.println("n6 == n7 : " + ( n6 == n7 ));
System.out.println("n8 == true : " + ( n8 == true ));
n1 == n2 : true
n1 == n3 : true
n1 == n4 : true
n5 == 'a' : true
n6 == n7 : true
n8 == true : true
#####データ型が異なっても、値が同じならTrue
Float型 :単精度浮動小数点(32bit) 符号1 指数8 仮数23bit
Double型 :倍精度浮動小数点(64bit) 符号1 指数11 仮数52bit
Double型の方がより0に近い正負の小数を表現できる
###関係演算子による参照型データの比較
配列は参照型データに分類される
int[] a1 = {10}; int[] a2 = {10};
//a1とa2は配列の[0]要素に10という数値を持つ配列を参照している
//参照する配列の構造、要素は同一だが a1,a2 は異なる配列を参照している
System.out.println("a1 == a2 : " + ( a1 == a2 ));
int[] a3 = {10}; int[] a4 = a3;
//a4はa3が代入されているので、参照しているのはa3が参照する配列と同一となる
System.out.println("a3 == a4 : " + ( a3 == a4 ));
a1 == a2 : false
a3 == a4 : true
非常にややこしいが図だと分かりやすい
##equals()メソッドによる比較(同一性)
String型(参照型)データ
equal()メソッドは参照先が異なっても、同一の文字列であればTrueを返す
String s1 = "tanaka"; String s2 = "tanaka";
System.out.println("s1.equals(s2) : " + ( s1.equals(s2) ));
String s3 = "TANAKA";
System.out.println("s1.equals(s3) : " + ( s1.equals(s3) ));
s1.equals(s2) : true
s1.equals(s3) : false
##演算子==による比較(同値性)
異なるインスタンスの値であっても値が同一ならtrueを返す
String s1 = "Hello";
String s2 = new String("Hello");
String s3 = "Hello";
String s4 = s2.intern();
System.out.println("s1 == s2 : " + ( s1 == s2 ));
System.out.println("s1 == s3 : " + ( s1 == s3 ));
System.out.println("s1 == s4 : " + ( s1 == s4 ));
System.out.println("s2 == s4 : " + ( s2 == s4 ));
##string型のコンスタントプール
String型データは参照型であるが、参照先の文字列は他のインスタンスと異なりStringクラスの管理領域(プール)にある
new キーワードを使用しない変数宣言では、プール内に同一の文字列が存在すれば、そちらを参照先としてインスタンスが作成される。
new キーワードを使用する場合、プールに同一文字列が存在しても新しい参照先が作成される
##internメソッドによる領域(プール)検索
上記のように、同一の文字列であってもインスタンスが異なれば"=="による同値性の比較ではfalseが返る。
しかしメモリ効率を考えた際、プール内の同一の文字列を集め新しいインスタンスとして参照した方がそれぞれの変数が持つ文字列が統一され効率が良い。
図ではs1,s2がそれぞれ異なるインスタンスの同一文字列"java"を参照している
それに対しs3,s4はstringプールの同一のインスタンス、文字列を参照している
それぞれの文字列を統一したインスタンスの作成にはintern()を使用する
s1.intern() == s3.intern(); //true
###String型とStringBuilder型の注意点
新しい文字列の作成の際、Stringプールに新たな文字列が追加され参照先が変わる場合と
既存の文字列が書き換わる場合がある
###null比較
null:参照型データで何も参照していないことを表すリテラル
String str1 = null;
String str2 = "";
int[] array1 = null;
int[] array2 = new int[1];
System.out.println(str1 == null);
System.out.println(str2 == null);
System.out.println(array1 != null);
System.out.println(array2 != null);
true
false 空白はデータ領域が確保され参照しているためNot null
false 配列やクラスは宣言した段階では領域確保されないためnull
true インスタンス化した数値型の配列には初期化の時点で0が入る