Java/基礎/変数と代入演算

出典: フリー教科書『ウィキブックス(Wikibooks)』

変数と代入[編集]

変数[編集]

プログラミングにおける変数は、値やデータを格納するための記号的な名前です。変数は、メモリ内の特定の場所を参照し、その場所に値を保持します。これにより、プログラム内でデータを操作したり処理したりすることができます。

変数は、プログラム内で使用されるデータの値を表現し、名前を介してそれらの値にアクセスする手段を提供します。また、変数は値を保持するだけでなく、値を変更することもできます。これにより、プログラムが動的に振る舞うことが可能になります。

例えば、プログラムがユーザーの名前や年齢などの情報を取得し、それを後で使用する必要がある場合、変数を使用してその情報を格納し、必要に応じて変更や処理を行うことができます。

Javaにおける変数[編集]

Javaにおける変数とは、データを格納する箱のようなものです。変数は、プログラム内で使用されるデータを保持し、それに名前を付けることができます。これにより、プログラム内で値を簡単に参照したり変更したりできます。

Javaでは、変数を使用する前に、その変数の型(データの種類)を宣言する必要があります。例えば、整数を格納する変数の場合はint型、小数を格納する変数の場合はdouble型、文字列を格納する変数の場合はString型などがあります。

宣言[編集]

変数の宣言は次のように行います:

// 整数を格納する変数の宣言
int age;

// 小数を格納する変数の宣言
double height;

// 文字列を格納する変数の宣言
String name;

これにより、ageheightnameという名前の変数が宣言されます。ただし、この時点ではまだ値は割り当てられていません。

代入[編集]

変数に値を代入するには、以下のようにします:

age = 25;
height = 1.75;
name = "Alice";

これにより、それぞれの変数に値が割り当てられます。

初期化[編集]

また、変数の宣言と初期化を同時に行うこともできます:

int age = 25;
double height = 1.75;
String name = "Alice";

これにより、変数の宣言と初期化を一度に行うことができます。

再代入[編集]

Javaにおいて、再代入とは変数に新しい値を割り当てることを指します。Javaでは、再代入が可能な変数は、その型がプリミティブ型であるか、または参照型であるかによって挙動が異なります。

  1. プリミティブ型の変数の再代入: プリミティブ型の変数は、その型に対応する値を直接保持します。再代入すると、変数が新しい値に更新されます。
    int x = 5; // int型の変数xに初期値5を代入
    x = 10;    // xに新しい値10を再代入
    
  2. 参照型の変数の再代入: 参照型の変数は、オブジェクトへの参照を保持します。再代入すると、変数が新しいオブジェクトへの参照に更新されますが、元のオブジェクトは影響を受けません。
    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";

これらの変数AGENAMEは、一度初期化された後に再代入することができません。このような変数は、プログラム内で定数として使用されることがあります。

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つの形式があります:

  1. 明示的なキャスト(Explicit cast): 明示的なキャストは、変換元のデータ型を指定して行われます。キャストの前に、変換先のデータ型を括弧で囲んで指定します。
    double d = 10.5;
    int i = (int) d; // 明示的なキャスト
    
    この例では、double型の変数dint型の変数iに明示的にキャストしています。このキャストにより、dの小数部分が切り捨てられてiには整数部分のみが格納されます。
  2. 暗黙的なキャスト(Implicit cast): 暗黙的なキャストは、Javaの型変換ルールに従って、自動的に行われます。暗黙的なキャストは、より小さいデータ型からより大きいデータ型への変換に使用されます。
    int i = 10;
    double d = i; // 暗黙的なキャスト
    
    この例では、int型の変数idouble型の変数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
    }
}

用語集[編集]

  1. 変数 (Variable): プログラミングにおける変数は、値やデータを格納するための記号的な名前です。プログラム内でデータを操作したり処理したりする際に使用されます。
  2. 宣言 (Declaration): 変数の宣言とは、変数をプログラム内で使用する準備をすることです。変数の型と名前を指定して、コンピュータにその変数を識別するための領域を割り当てます。
  3. 代入 (Assignment): 代入とは、変数に値を格納する操作です。変数に値を代入することで、その変数がその値を保持することができます。
  4. 初期化 (Initialization): 初期化とは、変数に初期値を設定する操作です。変数を宣言と同時に初期値を設定することで、その変数が宣言された時点で値を持つことができます。
  5. 再代入 (Reassignment): 再代入とは、変数に新しい値を割り当てる操作です。変数には、同じ型の新しい値を代入することができます。
  6. イミュータブル (Immutable): イミュータブルとは、変更不可能なことを指します。Javaでは、final修飾子を使用して宣言された変数や、文字列などの一部のオブジェクトはイミュータブルです。
  7. キャスト (Cast): キャストとは、データ型を変換する操作です。Javaでは、異なるデータ型の間で変換を行う際にキャストが使用されます。
  8. 型推論 (Type Inference): 型推論とは、コンパイラがコードの文脈から変数の型を推測する機能です。Java 10以降では、varキーワードを使用して型推論を行うことができます。
  9. ラムダ式 (Lambda Expression): ラムダ式とは、無名関数を表現するための記法です。Javaでは、関数型インターフェースの実装として使用されます。
  10. ループ変数 (Loop Variable): ループ変数とは、forループや拡張forループで使用される反復変数のことを指します。Java 10以降では、ループ変数の型推論機能が追加されました。
  11. 複雑な型推論 (Complex Type Inference): 複雑な型を返すメソッドを受け取る場合にも、型推論が有用です。Javaでは、flatMap()メソッドなどでの複雑な型推論が行われます。