変数は宣言する場所によって2種類の呼び方があり,特徴も少し異なります.
一つは,メソッド内で宣言する変数,ローカル変数(local variable),
もう一つは,メソッドの外で宣言する変数,フィールド(field)です.
メソッドもフィールドもどちらも,クラス宣言の直下になければいけません(クラス宣言の括弧({ }
)のすぐ内側).
null
(何も参照していないことを表す予約語).変数名.フィールド名
でアクセスできる.{ }
)のみ.プログラムを書くとき,変数の有効範囲はできるだけ狭く,というのが定石です. そのため,基本的には,ローカル変数を使い,ローカル変数で対応できない場合に,フィールドを利用しましょう.
実体を確認するために,次のプログラムを考えてみましょう.
Date
は日付を表す型です.new Date()
,
もしくは,new Date(year, month, day, hour, minute)
という命令で実体を作成します.与える引数の型は全て Integer
です.
ただし,年月日,時間を指定する場合,年は1900年からの経過年数,
月は0から始まる(0が1月を表す)点に注意してください.
古い時代のもので,互換性のために残されているもので,変な仕様ではありますが,これで確認してみましょう.
また,コンパイル時に「非推奨のAPIを使用または...」という注意が出ますが,無視してください. これはコンパイルエラーではなく,注意(Warning)ですので,コンパイルはできています. お勧めできない古い時代のライブラリを使っている時に出ます.基本的には使わない方が良いのですが, 今回は説明のために用います.
なお,Date
型を利用するときは,import java.util.Date
が
クラス宣言の前に必要になります.import
文が必要な理由は,
FAQ import文とは何かを参照してください.
実際に,入力して,どのような実行結果になるかを考えてから,動かしてみましょう. そして,予想との違いを考えてください.
import java.util.Date;
public class DateExample{
void run(){
// year は 1900年からの経過年数.
// month は 0 から始まる.
Date date1 = new Date(115, 8, 29, 9, 0);
Date date2 = date1;
System.out.printf("date1: %s%n", date1);
System.out.printf("date2: %s%n", date2);
// Year を +1 している.
date1.setYear(date1.getYear() + 1);
System.out.printf("date1: %s%n", date1);
System.out.printf("date2: %s%n", date2);
}
public static void main(String[] args){
DateExample example = new DateExample();
example.run();
}
}
Javaの変数はほぼ全てがポインタとなっています.
ポインタとは,メモリ領域の特定の場所を指し示すだけの変数です.
上のプログラムの date2 = date1
という命令が実行されると, date2
に date1
の参照先が代入されたことを表します.
その結果,date1
と date2
は同じ参照先の実体を指し示すようになり,
一方を変更すると(date1.setYear(...);
),
もう一方も変更されることになります.
下の図をクリックすると図が更新されます.何度かクリックして見て動作を確認しましょう.
基礎プログラミング演習で学習したものとは変数の扱いが異なる場合がありますので,注意してください. Java言語では,全ての変数は,メモリ上のどこかにある実体を参照しているものと思ってください.
先のプログラムの run
メソッドに次のコードを追加して,
実行結果を確認してみましょう.
void run(){
Date date1 = new Date(115, 8, 29, 9, 0);
Date date2 = date1;
date1.setYear(date1.getYear() + 1);
// 以下のプログラムを追加する.
Date date3 = new Date(116, 8, 29, 9, 0);
System.out.println(date1 == date2);
System.out.println(date1 == date3);
System.out.println(date2 == date3);
}
各変数が指し示す Date
型変数の値は全て,2016-09-29 9:00
になっているはずですが,
なぜ true
と false
という違いが現れるのでしょうか.
実は,==
は参照先が同じであるかを判定する演算子であり,値が一致するか否かは判定されません.
以下の画像をクリックし,動作を確認してみましょう.
では,2つの変数の値が一致するかどうかを判定するにはどうすれば良いのでしょうか.
それには,Objects
型のequals
メソッドを利用します.
先ほどと同じく,run
メソッドに次の処理を追加し,実行結果を確認しましょう.
import java.util.Date;
import java.util.Objects;
public class DateExample{
void run(){
// ...
// 次の処理を追加する.
System.out.println(Objects.equals(date1, date2));
System.out.println(Objects.equals(date1, date3));
System.out.println(Objects.equals(date2, date3));
}
// ...
}
このようにすることで,値の一致性を確認できます. Javaで比較する時は,参照の一致か,値の一致か,どちらを判定したいのかを区別して比較しましょう.
なお,Objects
型を利用するときは,クラス宣言の前に import
文が必要です.
import java.util.Objects
と書いてください.