Java/基礎/変数と代入演算
変数と代入
[編集]変数
[編集]プログラミングにおける変数は、値やデータを格納するための記号的な名前です。変数は、メモリ内の特定の場所を参照し、その場所に値を保持します。これにより、プログラム内でデータを操作したり処理したりすることができます。
変数は、プログラム内で使用されるデータの値を表現し、名前を介してそれらの値にアクセスする手段を提供します。また、変数は値を保持するだけでなく、値を変更することもできます。これにより、プログラムが動的に振る舞うことが可能になります。
例えば、プログラムがユーザーの名前や年齢などの情報を取得し、それを後で使用する必要がある場合、変数を使用してその情報を格納し、必要に応じて変更や処理を行うことができます。
Javaにおける変数
[編集]Javaにおける変数とは、データを格納する箱のようなものです。変数は、プログラム内で使用されるデータを保持し、それに名前を付けることができます。これにより、プログラム内で値を簡単に参照したり変更したりできます。
Javaでは、変数を使用する前に、その変数の型(データの種類)を宣言する必要があります。例えば、整数を格納する変数の場合はint
型、小数を格納する変数の場合はdouble
型、文字列を格納する変数の場合はString
型などがあります。
宣言
[編集]変数の宣言は次のように行います:
// 整数を格納する変数の宣言 int age; // 小数を格納する変数の宣言 double height; // 文字列を格納する変数の宣言 String name;
これにより、age
、height
、name
という名前の変数が宣言されます。ただし、この時点ではまだ値は割り当てられていません。
代入
[編集]変数に値を代入するには、以下のようにします:
age = 25; height = 1.75; name = "Alice";
これにより、それぞれの変数に値が割り当てられます。
初期化
[編集]また、変数の宣言と初期化を同時に行うこともできます:
int age = 25; double height = 1.75; String name = "Alice";
これにより、変数の宣言と初期化を一度に行うことができます。
再代入
[編集]Javaにおいて、再代入とは変数に新しい値を割り当てることを指します。Javaでは、再代入が可能な変数は、その型がプリミティブ型であるか、または参照型であるかによって挙動が異なります。
- プリミティブ型の変数の再代入: プリミティブ型の変数は、その型に対応する値を直接保持します。再代入すると、変数が新しい値に更新されます。
int x = 5; // int型の変数xに初期値5を代入 x = 10; // xに新しい値10を再代入
- 参照型の変数の再代入: 参照型の変数は、オブジェクトへの参照を保持します。再代入すると、変数が新しいオブジェクトへの参照に更新されますが、元のオブジェクトは影響を受けません。
String str1 = "Hello"; // String型の変数str1に文字列"Hello"を代入 str1 = "World"; // str1に新しい文字列"World"を再代入
変数に再代入された値の型は、変数が宣言された際に指定された型と一致する必要があります。たとえば、int
型の変数には整数値を、double
型の変数には浮動小数点数を再代入する必要があります。再代入された値の型が異なる場合、コンパイルエラーが発生します。
文字列
[編集]Javaにおける文字列は、文字のシーケンスを表現するためのデータ型です。Javaでは、文字列はjava.lang.String
クラスを使用して表現されます。文字列は、ダブルクォーテーション(”)で囲まれた文字のシーケンスとして表現されます。
文字列はイミュータブル(変更不能)であり、一度作成されると変更することができません。つまり、文字列を変更する操作は、新しい文字列を作成することになります。
以下は、Javaで文字列を宣言する例です:
String greeting = "Hello, world!";
この例では、greeting
という名前の変数に文字列"Hello, world!"が代入されています。
final 修飾された変数
[編集]Javaでは、final
修飾子を使って宣言された変数は、イミュータブル(不変)です。final
修飾子を使用すると、その変数に対する再代入ができなくなります。つまり、一度初期化された後はその値を変更することができません。
以下は、final
修飾子を使って宣言されたイミュータブルな変数の例です:
final int AGE = 30; final String NAME = "John";
これらの変数AGE
とNAME
は、一度初期化された後に再代入することができません。このような変数は、プログラム内で定数として使用されることがあります。
final 修飾された参照型変数
[編集]Javaにおいて、final
修飾された参照型変数は、変数の参照先(オブジェクトへの参照)が不変であることを示します。つまり、一度初期化された後は、その変数が参照するオブジェクトを変更することはできませんが、オブジェクト自体の内容は変更可能です。
以下は、final
修飾子を使って宣言された参照型変数の例です:
final StringBuilder builder = new StringBuilder("Hello"); builder.append(", world!"); // オブジェクトの内容を変更する操作 System.out.println(builder.toString()); // 出力: Hello, world!
この例では、final
修飾子が付けられたbuilder
変数は、一度StringBuilder
オブジェクトに初期化された後、その参照先を変更することができません。ただし、StringBuilder
オブジェクト自体の内容を変更することは可能です。
キャスト
[編集]Javaにおけるキャスト(cast)は、データ型を変換する操作を指します。Javaでは、異なるデータ型の間で変換を行う際にキャストを使用します。キャストは、変換元のデータ型を指定し、変換後のデータ型に変換するための演算子です。
キャストは基本的に2つの形式があります:
- 明示的なキャスト(Explicit cast): 明示的なキャストは、変換元のデータ型を指定して行われます。キャストの前に、変換先のデータ型を括弧で囲んで指定します。
double d = 10.5; int i = (int) d; // 明示的なキャスト
- この例では、
double
型の変数d
をint
型の変数i
に明示的にキャストしています。このキャストにより、d
の小数部分が切り捨てられてi
には整数部分のみが格納されます。
- 暗黙的なキャスト(Implicit cast): 暗黙的なキャストは、Javaの型変換ルールに従って、自動的に行われます。暗黙的なキャストは、より小さいデータ型からより大きいデータ型への変換に使用されます。
int i = 10; double d = i; // 暗黙的なキャスト
- この例では、
int
型の変数i
がdouble
型の変数d
に代入される際に、暗黙的なキャストが行われます。Javaはint
型からdouble
型への変換を自動的に行い、i
の値をd
に代入します。
キャストを行う際には、変換元のデータ型と変換後のデータ型が互換性があるかどうかを確認する必要があります。 たとえば、数値型同士のキャストや、参照型の継承関係に基づくキャストが可能ですが、互換性のない型同士のキャストはコンパイルエラーを引き起こします。
型推論 (var)
[編集]Java 10以降、Javaにはローカル変数の型推論機能が追加されました。これは、var
キーワードを使用して変数を宣言する際に、コンパイラが変数の型を自動的に推論する機能です。この機能により、変数の型を明示的に指定する必要がなくなり、コードの冗長性を減らすことができます。
変数の宣言時に初期化子が提供される場合、その初期化子の型に基づいて変数の型が推論されます。推論された型は静的な型であり、実行時に変更されることはありません。
例えば、以下のようにvar
を使用して変数を宣言することができます:
var i = 1;
var
を使用することで、変数の型が明確になる場合には冗長な型の記述を省略できます。ただし、可読性を損なわない範囲での使用が推奨されます。また、var
を使用する場合でも、適切な変数名やコメントを追加することで、コードの理解を助けることが重要です。
ループ変数
[編集]Java 10以降、Javaにはループ変数の型推論機能が追加されました。
これにより、for
ループや拡張for
ループ(拡張for文、拡張forループ)で、ループ変数の型を自動的に推論することができます。
これにより、コードの冗長性を減らし、可読性を向上させることができます。
具体的には、for
ループの初期化部でループ変数を宣言し、その型をvar
キーワードで指定することができます。
この際、初期化式によって型が明示的に指定される場合、その型を推論してループ変数の型を決定します。
拡張for
ループでは、コレクションや配列を反復処理する際に、ループ変数の型を指定せずに、var
キーワードを使用してループ変数を宣言することができます。この場合、コレクションや配列の要素の型がループ変数の型として推論されます。
以下は、for
ループと拡張for
ループでのループ変数の型推論の例です:
// forループでの型推論 for (var i = 0; i < 5; i++) { System.out.println(i); // iの型はintと推論される } // 拡張forループでの型推論 List<String> strings = List.of("foo", "bar", "baz"); for (var str : strings) { System.out.println(str); // strの型はStringと推論される }
var
を使用することで、ループ変数の型を省略し、コードをよりシンプルにすることができます。ただし、適切な変数名やコメントを追加して、コードの可読性を確保することが重要です。
ラムダ式
[編集]ラムダ式の型推論とは、Javaでラムダ式を使用する際に、コンパイラがラムダ式のパラメータの型や戻り値の型を自動的に推論する機能を指します。つまり、ラムダ式のパラメータや戻り値の型を明示的に指定せずに、コンパイラがコードの文脈から型を推測することができます。
var x = (int i) -> i * i;
例えば、次のコードでは、ラムダ式 (int i) -> i * i
のパラメータ i
の型が int
として指定されています。しかし、Javaのコンパイラは、このコードの文脈から i
の型が int
型であることを推論することができます。
var
キーワードを使用することで、変数 x
の型を明示的に指定せずに、コンパイラがラムダ式の型を推論することができます。そのため、コードをよりシンプルに記述することができます。
var
キーワードを使わずに、ラムダ式の型を明示的に指定する場合は、次のようになります:
IntUnaryOperator x = (int i) -> i * i;
このコードでは、IntUnaryOperator
インターフェースを使用してラムダ式を宣言しています。IntUnaryOperator
は、int
型の引数を受け取り、int
型の値を返す関数型インターフェースです。ラムダ式の引数がint
型であるため、このインターフェースを使ってラムダ式を宣言しています。
- IntUnaryOperatorインターフェース
IntUnaryOperator
インターフェースは、Javaの標準ライブラリであるjava.util.function
パッケージに含まれています。このパッケージは、関数型プログラミングをサポートするためのインターフェースやクラスが定義されています。IntUnaryOperator
インターフェースは、引数として整数型を受け取り、整数型の値を返す関数型インターフェースです。具体的には、int applyAsInt(int operand)
メソッドを持ちます。これにより、整数型の引数を受け取り、整数型の結果を返す関数を表現することができます。- Javaの関数型インターフェースは、
java.util.function
パッケージに含まれているため、import java.util.function.IntUnaryOperator;
を使用してインポートすることで利用することができます。
var
によるラムダ式の型推論をつかうと、この調べごとをする必要がなくなります。
複雑な型推論
[編集]複雑な型を返すメソッドを受け取る場合にも、型推論は有用です。以下の例では、flatMap()
メソッドを使用して、文字列のリストを1つの文字列に変換しています。
List<String> list = Arrays.asList("hello", "world"); var result = list.stream() .flatMap(s -> Arrays.stream(s.split(""))) .collect(Collectors.joining());
最後に、ループを用いた具体例を示します。以下の例では、リストを String[]
に変換しています。
List<String> list = Arrays.asList("hello", "world"); var array = new String[list.size()]; var index = 0; for (var element : list) { array[index++] = element; }
附録
[編集]チートシート
[編集]public class Main { public static void main(String[] args) { // 変数の宣言と初期化 int num1 = 10; int num2 = 20; String name = "John"; boolean flag = true; // 変数の使用と演算 System.out.println("num1 + num2 = " + (num1 + num2)); // 30 System.out.println("My name is " + name); // My name is John System.out.println("flag is " + flag); // flag is true // プリミティブ型と参照型 int[] array = {1, 2, 3}; // 参照型の例 char ch = 'a'; // プリミティブ型の例 // プリミティブ型と参照型の違い int num3 = num1; // num1の値をコピーしてnum3に代入(値渡し) int[] array2 = array; // arrayの参照をコピーしてarray2に代入(参照渡し) array[0] = 100; // arrayの値を変更 System.out.println("num3 = " + num3); // num3 = 10 System.out.println("array[0] = " + array[0]); // array[0] = 100 System.out.println("array2[0] = " + array2[0]); // array2[0] = 100 // プリミティブ型と参照型の比較 boolean isEqual = num1 == num3; // プリミティブ型同士の比較 boolean isSameArray = array == array2; // 参照型同士の比較 System.out.println("num1 == num3 : " + isEqual); // num1 == num3 : true System.out.println("array == array2 : " + isSameArray); // array == array2 : true } }
用語集
[編集]- 変数 (Variable): プログラミングにおける変数は、値やデータを格納するための記号的な名前です。プログラム内でデータを操作したり処理したりする際に使用されます。
- 宣言 (Declaration): 変数の宣言とは、変数をプログラム内で使用する準備をすることです。変数の型と名前を指定して、コンピュータにその変数を識別するための領域を割り当てます。
- 代入 (Assignment): 代入とは、変数に値を格納する操作です。変数に値を代入することで、その変数がその値を保持することができます。
- 初期化 (Initialization): 初期化とは、変数に初期値を設定する操作です。変数を宣言と同時に初期値を設定することで、その変数が宣言された時点で値を持つことができます。
- 再代入 (Reassignment): 再代入とは、変数に新しい値を割り当てる操作です。変数には、同じ型の新しい値を代入することができます。
- イミュータブル (Immutable): イミュータブルとは、変更不可能なことを指します。Javaでは、final修飾子を使用して宣言された変数や、文字列などの一部のオブジェクトはイミュータブルです。
- キャスト (Cast): キャストとは、データ型を変換する操作です。Javaでは、異なるデータ型の間で変換を行う際にキャストが使用されます。
- 型推論 (Type Inference): 型推論とは、コンパイラがコードの文脈から変数の型を推測する機能です。Java 10以降では、varキーワードを使用して型推論を行うことができます。
- ラムダ式 (Lambda Expression): ラムダ式とは、無名関数を表現するための記法です。Javaでは、関数型インターフェースの実装として使用されます。
- ループ変数 (Loop Variable): ループ変数とは、forループや拡張forループで使用される反復変数のことを指します。Java 10以降では、ループ変数の型推論機能が追加されました。
- 複雑な型推論 (Complex Type Inference): 複雑な型を返すメソッドを受け取る場合にも、型推論が有用です。Javaでは、flatMap()メソッドなどでの複雑な型推論が行われます。