プログラミングにおける変数は、値やデータを格納するための記号的な名前です。変数は、メモリ内の特定の場所を参照し、その場所に値を保持します。これにより、プログラム内でデータを操作したり処理したりすることができます。
変数は、プログラム内で使用されるデータの値を表現し、名前を介してそれらの値にアクセスする手段を提供します。また、変数は値を保持するだけでなく、値を変更することもできます。これにより、プログラムが動的に振る舞うことが可能になります。
例えば、プログラムがユーザーの名前や年齢などの情報を取得し、それを後で使用する必要がある場合、変数を使用してその情報を格納し、必要に応じて変更や処理を行うことができます。
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!"が代入されています。
Javaでは、final修飾子を使って宣言された変数は、イミュータブル（不変）です。final修飾子を使用すると、その変数に対する再代入ができなくなります。つまり、一度初期化された後はその値を変更することができません。
以下は、final修飾子を使って宣言されたイミュータブルな変数の例です:
 
final int AGE = 30;
final String NAME = "John";
これらの変数AGEとNAMEは、一度初期化された後に再代入することができません。このような変数は、プログラム内で定数として使用されることがあります。
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に代入します。
キャストを行う際には、変換元のデータ型と変換後のデータ型が互換性があるかどうかを確認する必要があります。
たとえば、数値型同士のキャストや、参照型の継承関係に基づくキャストが可能ですが、互換性のない型同士のキャストはコンパイルエラーを引き起こします。
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 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 list = Arrays.asList("hello", "world");
var result = list.stream()
        .flatMap(s -> Arrays.stream(s.split("")))
        .collect(Collectors.joining());
 
最後に、ループを用いた具体例を示します。以下の例では、リストを String[] に変換しています。
List 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()メソッドなどでの複雑な型推論が行われます。