Javaデータ型 チートシート

目的別にまとめたJavaのデータ型に関する操作方法一覧

セクション1: プリミティブ型 (Primitive Types)

Javaの基本的なデータ型であるプリミティブ型の宣言、初期化、リテラルについて説明します。

1.1 宣言と初期化

各プリミティブ型の変数を宣言し、初期値を代入する方法です。

// 整数型
byte myByte = 100; // 8ビット (-128 〜 127)
short myShort = 30000; // 16ビット (-32,768 〜 32,767)
int myInt = 2000000000; // 32ビット (-2^31 〜 2^31-1)
long myLong = 9000000000000000000L; // 64ビット (-2^63 〜 2^63-1) - 末尾に L または l
// 浮動小数点型
float myFloat = 3.14f; // 32ビット (単精度) - 末尾に F または f
double myDouble = 3.1415926535; // 64ビット (倍精度) - デフォルト
// 文字型
char myChar = 'A'; // 16ビット Unicode文字 (シングルクォート)
char myUnicodeChar = '\u0041'; // Unicodeエスケープシーケンスでも可 ('A')
// 論理型
boolean myBoolean = true; // true または false
boolean anotherBoolean = false; 

1.2 デフォルト値

変数を宣言しただけで初期化しない場合、フィールド(クラス変数やインスタンス変数)にはデフォルト値が設定されます。ローカル変数は明示的な初期化が必要です。

デフォルト値説明
byte08ビット整数
short016ビット整数
int032ビット整数
long0L64ビット整数
float0.0f32ビット浮動小数点数
double0.0d64ビット浮動小数点数
char'\u0000' (NULL文字)16ビットUnicode文字
booleanfalse真偽値

1.3 リテラル

ソースコード上で直接記述される値のことです。

  • 整数リテラル:
    • 123 (int)
    • 123L (long)
    • 0b101 (2進数, int, Java 7+)
    • 077 (8進数, int)
    • 0xFF (16進数, int)
    • 1_000_000 (桁区切り文字, int, Java 7+)
  • 浮動小数点リテラル:
    • 3.14 (double)
    • 3.14f (float)
    • 3.14d (double)
    • 1.23e4 (指数表記, double)
  • 文字リテラル:
    • 'A'
    • '\n' (改行)
    • '\t' (タブ)
    • '\u03A9' (Unicode文字 Ω)
  • 真偽値リテラル: true, false
  • 文字列リテラル: "Hello, Java!" (これはプリミティブ型ではなく参照型ですが、リテラルとしてよく使われます)

セクション2: ラッパークラス (Wrapper Classes)

プリミティブ型をオブジェクトとして扱うためのクラスです。ジェネリクスやコレクションフレームワークで必要になります。

2.1 ボクシングとアンボクシング (Boxing / Unboxing)

Java 5以降、プリミティブ型とそのラッパークラス間の変換は自動的に行われます(オートボクシング/オートアンボクシング)。

// オートボクシング (primitive -> wrapper)
Integer integerWrapper = 100; // intからIntegerへ自動変換
Double doubleWrapper = 3.14; // doubleからDoubleへ自動変換
Boolean booleanWrapper = true; // booleanからBooleanへ自動変換
Character charWrapper = 'C'; // charからCharacterへ自動変換
// オートアンボクシング (wrapper -> primitive)
int primitiveInt = integerWrapper; // Integerからintへ自動変換
double primitiveDouble = doubleWrapper; // Doubleからdoubleへ自動変換
boolean primitiveBoolean = booleanWrapper; // Booleanからbooleanへ自動変換
char primitiveChar = charWrapper; // Characterからcharへ自動変換
System.out.println("Integer Wrapper: " + integerWrapper);
System.out.println("Primitive int: " + primitiveInt); 

オートアンボクシング時にラッパーオブジェクトが null だと NullPointerException が発生します。

Integer nullWrapper = null;
// int primitiveNull = nullWrapper; // ここで NullPointerException が発生する! 

2.2 ラッパーオブジェクトの生成

valueOf() メソッドを使うことが推奨されます(キャッシュにより効率が良い場合がある)。コンストラクタ (new Integer(10) など) はJava 9以降非推奨です。

Integer i1 = Integer.valueOf(10);
Integer i2 = Integer.valueOf("123"); // 文字列からの変換も可能
Double d1 = Double.valueOf(3.14);
Boolean b1 = Boolean.valueOf("true"); // 文字列 "true" (大文字小文字区別しない) から変換
Character c1 = Character.valueOf('X');
// 非推奨の方法 (Java 9+)
// Integer i_deprecated = new Integer(10);
// Double d_deprecated = new Double(3.14); 

2.3 プリミティブ型への変換

ラッパーオブジェクトから対応するプリミティブ型の値を取得するには、xxxValue() メソッド(例: intValue(), doubleValue())を使用します(オートアンボクシングが使える場面では不要な場合が多い)。

Integer wrapperInt = Integer.valueOf(100);
int primitiveIntVal = wrapperInt.intValue();
Double wrapperDouble = Double.valueOf(3.14);
double primitiveDoubleVal = wrapperDouble.doubleValue();
Boolean wrapperBoolean = Boolean.valueOf(true);
boolean primitiveBooleanVal = wrapperBoolean.booleanValue();
Character wrapperChar = Character.valueOf('Z');
char primitiveCharVal = wrapperChar.charValue();
System.out.println("intValue(): " + primitiveIntVal);
System.out.println("doubleValue(): " + primitiveDoubleVal); 

2.4 文字列との変換

文字列をラッパークラスやプリミティブ型に変換したり、その逆を行うメソッドが用意されています。

目的メソッド例説明
文字列 → プリミティブ型int i = Integer.parseInt("123");
double d = Double.parseDouble("3.14");
boolean b = Boolean.parseBoolean("true");
各ラッパークラスの parseXxx() メソッドを使用。変換できない文字列だと NumberFormatException が発生。
文字列 → ラッパークラスInteger i = Integer.valueOf("123");
Double d = Double.valueOf("3.14");
Boolean b = Boolean.valueOf("true");
各ラッパークラスの valueOf() メソッド(文字列引数版)を使用。
プリミティブ型 → 文字列String s1 = String.valueOf(123);
String s2 = String.valueOf(3.14);
String s3 = String.valueOf(true);
String.valueOf() メソッドを使用するのが一般的。
ラッパークラス → 文字列Integer i = 123; String s1 = i.toString();
Double d = 3.14; String s2 = d.toString();
各ラッパークラスの toString() メソッドを使用。null の場合は NullPointerException に注意。String.valueOf() でも可。
プリミティブ型 → 文字列 (別法)String s = "" + 123;空文字列との連結でも変換できるが、効率は良くない場合がある。

2.5 その他の便利なメソッド

ラッパークラスには、比較、最大/最小値の取得などの便利な静的メソッドがあります。

// 比較
int comparisonResult = Integer.compare(10, 5); // 1 (10 > 5)
int comparisonResult2 = Integer.compare(5, 10); // -1 (5 < 10)
int comparisonResult3 = Integer.compare(10, 10); // 0 (10 == 10)
// 最大・最小
int maxVal = Integer.max(10, 5); // 10
int minVal = Integer.min(10, 5); // 5
double maxDouble = Double.max(3.14, 2.71); // 3.14
// 定数 (最大値、最小値など)
System.out.println("Integer MAX_VALUE: " + Integer.MAX_VALUE);
System.out.println("Integer MIN_VALUE: " + Integer.MIN_VALUE);
System.out.println("Double MAX_VALUE: " + Double.MAX_VALUE);
System.out.println("Double NaN: " + Double.NaN); // Not a Number
System.out.println("Double POSITIVE_INFINITY: " + Double.POSITIVE_INFINITY);
// ビット演算 (Integer, Long)
String binaryString = Integer.toBinaryString(10); // "1010"
int bitCount = Integer.bitCount(10); // 2 (立っているビットの数) 

セクション3: 型変換 (Type Casting/Conversion)

あるデータ型の値を別のデータ型に変換する方法です。

3.1 暗黙的な型変換 (Widening Conversion)

より大きな範囲を持つ型へ自動的に変換されます。情報が失われることはありません。

変換の方向: byteshortintlongfloatdouble

charintlongfloatdouble

int myInt = 100;
long myLong = myInt; // int から long へ (OK)
float myFloat = myLong; // long から float へ (OK, ただし精度が失われる可能性あり)
double myDouble = myFloat; // float から double へ (OK)
char myChar = 'A'; // ASCII/Unicode値は 65
int charToInt = myChar; // char から int へ (OK, charToInt は 65 になる)
System.out.println("int から long: " + myLong);
System.out.println("long から float: " + myFloat);
System.out.println("char から int: " + charToInt); 

longint から floatdouble への変換では、値の大きさは保持されますが、精度(有効桁数)が失われる可能性があります。

3.2 明示的な型変換 (Narrowing Conversion / キャスト)

より小さな範囲を持つ型へ変換する場合、明示的なキャスト演算子 (型名) が必要です。情報が失われたり、値が範囲外になる可能性があります。

変換の方向: doublefloatlongintshortbyte

intchar (数値 → 文字コード)

double d = 123.456;
float f = (float) d; // double から float へキャスト
long l = (long) d; // double から long へキャスト (小数点以下切り捨て → 123)
int i = (int) l; // long から int へキャスト
System.out.println("double: " + d);
System.out.println("double -> float: " + f);
System.out.println("double -> long: " + l);
System.out.println("long -> int: " + i);
int largeInt = 130;
byte b = (byte) largeInt; // int から byte へキャスト (130はbyteの範囲[-128, 127]を超える)
System.out.println("int(130) -> byte: " + b); // 値がラップアラウンドする (-126 になる可能性)
int charCode = 66; // 'B' の文字コード
char c = (char) charCode; // int から char へキャスト
System.out.println("int(66) -> char: " + c); // 'B' が出力される 

縮小変換(Narrowing Conversion)では、元の値が変換先の型の範囲を超える場合、値が切り捨てられたり、予期しない値になったりする(ラップアラウンド)可能性があるため、細心の注意が必要です。

3.3 文字列と数値型の変換まとめ

セクション2.4で触れた内容を再掲します。

変換元変換先方法例注意点
StringintInteger.parseInt("123")NumberFormatException
StringdoubleDouble.parseDouble("3.14")NumberFormatException
StringIntegerInteger.valueOf("123")NumberFormatException
intStringString.valueOf(123) or Integer.toString(123)
doubleStringString.valueOf(3.14) or Double.toString(3.14)
IntegerStringintegerObj.toString() or String.valueOf(integerObj)null の場合 NullPointerException or "null"

セクション4: 配列 (Arrays)

同じ型の複数の要素を格納するための固定長のデータ構造です。

4.1 宣言と初期化

配列変数を宣言し、メモリ領域を確保して初期化します。

// 宣言のみ (サイズ未定)
int[] numbers1;
String[] names1;
// 宣言と領域確保 (デフォルト値で初期化される)
int[] numbers2 = new int[5]; // 要素数5のint型配列 (全要素が0で初期化)
String[] names2 = new String[3]; // 要素数3のString型配列 (全要素がnullで初期化)
boolean[] flags = new boolean[10]; // 要素数10のboolean型配列 (全要素がfalseで初期化)
// 宣言、領域確保、初期化を同時に行う (リテラル記法)
int[] numbers3 = {10, 20, 30, 40, 50}; // 要素数5のint型配列
String[] names3 = {"Alice", "Bob", "Charlie"}; // 要素数3のString型配列
double[] points = new double[]{1.1, 2.2, 3.3}; // new 型[] を省略しない記法も可
// 多次元配列 (例: 2次元配列)
int[][] matrix1 = new int[3][4]; // 3行4列のint型配列 (全要素0)
String[][] table = { {"A1", "A2"}, {"B1", "B2", "B3"}, // 行ごとに要素数を変えることも可能 (ジャグ配列/不整列配列) {"C1"}
}; 

配列の宣言スタイルは 型[] 変数名 (推奨) と 型 変数名[] の両方が可能ですが、前者が一般的です。

4.2 要素へのアクセス

インデックス(添え字)を使って配列の要素にアクセスします。インデックスは 0 から始まります。

int[] scores = {85, 92, 78, 90};
// 要素の取得
int firstScore = scores[0]; // 85 (最初の要素)
int thirdScore = scores[2]; // 78 (3番目の要素)
System.out.println("最初のスコア: " + firstScore);
System.out.println("3番目のスコア: " + thirdScore);
// 要素の変更
scores[1] = 95; // 2番目の要素を92から95に変更
System.out.println("変更後の2番目のスコア: " + scores[1]);
// 多次元配列のアクセス
int[][] matrix = {{1, 2}, {3, 4}};
int element10 = matrix[1][0]; // 2行目(インデックス1)、1列目(インデックス0) の要素 → 3
System.out.println("matrix[1][0]: " + element10); 

存在しないインデックス(例: scores[4]scores[-1])にアクセスしようとすると ArrayIndexOutOfBoundsException が発生します。

4.3 配列の長さ(要素数)の取得

.length フィールドを使って配列の要素数を取得できます。

String[] fruits = {"Apple", "Banana", "Orange"};
int numberOfFruits = fruits.length; // 3
System.out.println("果物の数: " + numberOfFruits);
int[][] matrix = new int[3][5];
int numRows = matrix.length; // 行数 → 3
int numColsFirstRow = matrix[0].length; // 1行目の列数 → 5
System.out.println("行数: " + numRows);
System.out.println("1行目の列数: " + numColsFirstRow); 

.length はメソッドではなくフィールドであることに注意してください(例: length() ではない)。

4.4 配列のループ処理

for ループや拡張 for ループ(for-each)を使って配列の全要素を処理します。

int[] data = {1, 2, 3, 4, 5};
// 通常の for ループ
System.out.println("通常の for ループ:");
for (int i = 0; i < data.length; i++) { System.out.print(data[i] + " "); // 各要素にアクセス
}
System.out.println();
// 拡張 for ループ (for-each)
System.out.println("拡張 for ループ:");
for (int element : data) { System.out.print(element + " "); // 各要素の値が順番に取り出される
}
System.out.println();
// 多次元配列のループ
String[][] users = {{"Taro", "Tokyo"}, {"Jiro", "Osaka"}, {"Saburo", "Fukuoka"}};
System.out.println("ユーザー情報:");
for (String[] user : users) { // 各行 (String配列) を取り出す for (String info : user) { // 各行の要素 (String) を取り出す System.out.print(info + "\t"); } System.out.println();
} 

拡張 for ループは読みやすく簡潔ですが、要素のインデックスが必要な場合や、ループ中に要素の値を変更したい場合には通常の for ループを使います。

4.5 java.util.Arrays クラスのユーティリティメソッド

配列操作に便利な静的メソッドを提供するクラスです。

メソッド使用例説明
sort()int[] arr = {5, 1, 4, 2, 3}; Arrays.sort(arr);配列を昇順にソートします(インプレース:元の配列が変更されます)。オブジェクト配列の場合は要素が Comparable を実装している必要があります。
parallelSort()int[] arr = {5, 1, 4, 2, 3}; Arrays.parallelSort(arr);配列を並列処理でソートします。要素数が多い場合にsort()より高速なことがあります。(Java 8+)
binarySearch()int index = Arrays.binarySearch(arr, 3);ソート済みの配列から指定された値を二分探索します。値が見つかればそのインデックスを、見つからなければ負の値を返します。
equals()boolean isEqual = Arrays.equals(arr1, arr2);2つの配列の内容が等しいか(要素数と全要素が同じか)を比較します。== 演算子は参照が同じかを比較します。
deepEquals()boolean isEqual = Arrays.deepEquals(matrix1, matrix2);多次元配列の内容が等しいかを再帰的に比較します。
fill()Arrays.fill(arr, 0);配列の全要素を指定された値で埋めます。範囲を指定することも可能です。
copyOf()int[] newArr = Arrays.copyOf(arr, arr.length);
int[] truncatedArr = Arrays.copyOf(arr, 3);
配列のコピーを作成します。新しい長さを指定でき、元の配列より長い場合はデフォルト値で埋められ、短い場合は切り捨てられます。
copyOfRange()int[] subArr = Arrays.copyOfRange(arr, 1, 4);配列の指定された範囲(開始インデックス含む、終了インデックス含まず)のコピーを作成します。
toString()String str = Arrays.toString(arr);配列の内容を文字列形式(例: [1, 2, 3, 4, 5])で返します。デバッグなどに便利です。
deepToString()String str = Arrays.deepToString(matrix);多次元配列の内容を文字列形式で返します。
asList()List<String> list = Arrays.asList("A", "B", "C");配列を固定サイズの List に変換します。注意: このリストは元の配列をラップするため、リストへの変更は元の配列にも反映されます。また、要素の追加や削除はできません。プリミティブ型の配列には直接使えません(List<int[]> のような形になる)。
stream()IntStream stream = Arrays.stream(arr);
Stream<String> stream = Arrays.stream(stringArr);
配列からStream APIを生成します。(Java 8+)
import java.util.Arrays;
import java.util.List;
public class ArrayUtilsExample { public static void main(String[] args) { int[] numbers = {5, 1, 4, 2, 3}; System.out.println("Original: " + Arrays.toString(numbers)); // [5, 1, 4, 2, 3] // ソート Arrays.sort(numbers); System.out.println("Sorted: " + Arrays.toString(numbers)); // [1, 2, 3, 4, 5] // 二分探索 (ソート後に行う) int index = Arrays.binarySearch(numbers, 4); System.out.println("Index of 4: " + index); // 3 // コピー int[] numbersCopy = Arrays.copyOf(numbers, numbers.length); System.out.println("Copy: " + Arrays.toString(numbersCopy)); // [1, 2, 3, 4, 5] // 比較 boolean isEqual = Arrays.equals(numbers, numbersCopy); System.out.println("Arrays equal? " + isEqual); // true // 要素の充填 Arrays.fill(numbersCopy, 0, 2, 99); // インデックス0から2(含まない)まで99で埋める System.out.println("Filled: " + Arrays.toString(numbersCopy)); // [99, 99, 3, 4, 5] // Listへの変換 (固定サイズ) String[] names = {"Alice", "Bob", "Charlie"}; List nameList = Arrays.asList(names); System.out.println("List: " + nameList); // [Alice, Bob, Charlie] // nameList.add("David"); // UnsupportedOperationException が発生する names[0] = "Alicia"; // 元の配列を変更 System.out.println("List after modify array: " + nameList); // [Alicia, Bob, Charlie] (Listにも反映される) }
} 

セクション5: 文字列 (Strings)

String クラスは不変(Immutable)な文字列を扱います。一度作成された文字列オブジェクトの内容は変更できません。

5.1 宣言と初期化

文字列リテラルまたは new String() で生成します(リテラルが一般的)。

// 文字列リテラル (推奨)
String greeting = "Hello";
String name = "World";
String emptyString = "";
// new String() コンストラクタ (通常は不要)
String message = new String("Java Programming");
char[] chars = {'a', 'b', 'c'};
String fromChars = new String(chars); // char配列から生成
System.out.println(greeting + ", " + name + "!"); // 文字列連結
System.out.println("Message: " + message);
System.out.println("From chars: " + fromChars); 

文字列リテラルで同じ内容の文字列を作成した場合、メモリ効率のため同じオブジェクトを参照することがあります(String Intern Pool)。new String() は常に新しいオブジェクトを作成します。

5.2 文字列の不変性 (Immutability)

String オブジェクトのメソッド(例: toUpperCase(), replace())は、元の文字列を変更せず、新しい文字列オブジェクトを生成して返します。

String original = " Java ";
String upper = original.toUpperCase(); // 新しい " JAVA " を生成
String trimmed = original.trim(); // 新しい "Java" を生成
String replaced = original.replace('a', 'o'); // 新しい " Jovo " を生成
System.out.println("Original: '" + original + "'"); // 元の文字列は変わらない: ' Java '
System.out.println("Upper: '" + upper + "'"); // ' JAVA '
System.out.println("Trimmed: '" + trimmed + "'"); // 'Java'
System.out.println("Replaced: '" + replaced + "'"); // ' Jovo ' 

5.3 一般的な文字列操作メソッド

String クラスが提供する便利なメソッドの一部です。

メソッド戻り値説明使用例 (s = "Hello World")
length()int文字列の長さ(文字数)を返す。s.length()11
isEmpty()boolean文字列が空(長さが0)かどうかを返す。(Java 6+)s.isEmpty()false, "".isEmpty()true
isBlank()boolean文字列が空または空白文字のみで構成されているか。(Java 11+)" ".isBlank()true, s.isBlank()false
charAt(int index)char指定されたインデックスの文字を返す。s.charAt(0)'H', s.charAt(6)'W'
substring(int beginIndex)String指定されたインデックスから末尾までの部分文字列を返す。s.substring(6)"World"
substring(int beginIndex, int endIndex)String指定された開始インデックス(含む)から終了インデックス(含まない)までの部分文字列を返す。s.substring(0, 5)"Hello"
indexOf(String str)
indexOf(char ch)
int指定された文字列/文字が最初に現れるインデックスを返す。見つからない場合は -1s.indexOf("o")4, s.indexOf("l")2, s.indexOf("z")-1
indexOf(String str, int fromIndex)
indexOf(char ch, int fromIndex)
int指定されたインデックス以降で、指定された文字列/文字が最初に現れるインデックスを返す。s.indexOf("l", 3)3
lastIndexOf(String str)
lastIndexOf(char ch)
int指定された文字列/文字が最後に現れるインデックスを返す。見つからない場合は -1s.lastIndexOf("o")7, s.lastIndexOf("l")9
equals(Object anObject)boolean指定されたオブジェクトと文字列の内容が等しいか(大文字小文字を区別して)比較する。s.equals("Hello World")true, s.equals("hello world")false
equalsIgnoreCase(String anotherString)boolean大文字小文字を区別せずに文字列の内容が等しいか比較する。s.equalsIgnoreCase("hello world")true
compareTo(String anotherString)int文字列を辞書順で比較する。等しい場合は 0、この文字列が引数より前なら負の値、後なら正の値を返す。s.compareTo("Hello") → (正の値), s.compareTo("Hello World")0
compareToIgnoreCase(String str)int大文字小文字を無視して辞書順で比較する。"a".compareToIgnoreCase("A")0
startsWith(String prefix)boolean文字列が指定された接頭辞で始まるか判定する。s.startsWith("Hello")true, s.startsWith("World")false
endsWith(String suffix)boolean文字列が指定された接尾辞で終わるか判定する。s.endsWith("World")true, s.endsWith("Hello")false
contains(CharSequence s)boolean文字列が指定された文字シーケンスを含むか判定する。s.contains("Wor")true, s.contains("Java")false
replace(char oldChar, char newChar)
replace(CharSequence target, CharSequence replacement)
String文字列内のすべての oldChar/targetnewChar/replacement に置換した新しい文字列を返す。s.replace('l', 'X')"HeXXo WorXd"
s.replace("World", "Java")"Hello Java"
replaceAll(String regex, String replacement)String正規表現に一致するすべての部分を置換した新しい文字列を返す。"a1b2c3d".replaceAll("\\d", "*")"a*b*c*d"
replaceFirst(String regex, String replacement)String正規表現に最初に一致した部分を置換した新しい文字列を返す。"a1b2c3d".replaceFirst("\\d", "*")"a*b2c3d"
toLowerCase()Stringすべての文字を小文字に変換した新しい文字列を返す。s.toLowerCase()"hello world"
toUpperCase()Stringすべての文字を大文字に変換した新しい文字列を返す。s.toUpperCase()"HELLO WORLD"
trim()String先頭と末尾の空白文字(スペース、タブ、改行など)を除去した新しい文字列を返す。" abc ".trim()"abc"
strip()String先頭と末尾の空白文字を除去した新しい文字列を返す (Unicode空白を含む)。(Java 11+)"\u2005 abc \u2005".strip()"abc"
split(String regex)
split(String regex, int limit)
String[]正規表現に一致する箇所で文字列を分割し、文字列配列を返す。limit は分割後の配列の最大要素数を指定。"a,b,c".split(","){"a", "b", "c"}
"a:b:c".split(":", 2){"a", "b:c"}
join(CharSequence delimiter, CharSequence... elements)
join(CharSequence delimiter, Iterable<? extends CharSequence> elements)
String (static)指定された区切り文字で要素を連結した文字列を返す。(Java 8+)String.join("-", "A", "B", "C")"A-B-C"
List list = List.of("X", "Y"); String.join(", ", list)"X, Y"
format(String format, Object... args)String (static)指定された書式文字列と引数を使ってフォーマットされた文字列を返す (printf のような機能)。String.format("Name: %s, Age: %d", "Bob", 30)"Name: Bob, Age: 30"
valueOf(...)String (static)様々な型の値を文字列に変換する(オーバーロード多数)。String.valueOf(123)"123", String.valueOf(true)"true"
toCharArray()char[]文字列を文字の配列に変換する。s.toCharArray(){'H','e','l','l','o',' ','W','o','r','l','d'}

5.4 文字列の連結

複数の文字列を結合する方法です。

  • + 演算子:

    最も簡単ですが、ループ内で大量に連結するとパフォーマンスが低下することがあります(内部で StringBuilder が使われるが、ループごとに新しいインスタンスが生成される可能性がある)。

    String s1 = "Java";
    String s2 = " ";
    String s3 = "Rocks";
    String result = s1 + s2 + s3; // "Java Rocks"
    System.out.println(result);
    int version = 8;
    String message = "Version: " + version; // 他の型も連結できる ("Version: 8")
    System.out.println(message); 
  • concat() メソッド:

    + 演算子と同様の機能ですが、null を連結しようとすると NullPointerException が発生します。+ 演算子は null"null" という文字列として扱います。

    String str1 = "Hello";
    String str2 = " ";
    String str3 = "World";
    String result = str1.concat(str2).concat(str3); // "Hello World"
    System.out.println(result);
    // String nullStr = null;
    // String error = str1.concat(nullStr); // NullPointerException 
  • StringBuilder クラス:

    変更可能な文字列を扱うクラス。ループ内での大量の文字列連結など、効率が求められる場合に推奨されます。スレッドセーフではありません。

    StringBuilder sb = new StringBuilder();
    sb.append("Apple");
    sb.append(", ");
    sb.append("Banana");
    sb.append(", ");
    sb.append("Orange");
    String fruitList = sb.toString(); // 最後に String に変換
    System.out.println(fruitList); // "Apple, Banana, Orange" 
  • StringBuffer クラス:

    StringBuilder とほぼ同じ機能ですが、メソッドが同期化されておりスレッドセーフです。その分、若干パフォーマンスが劣るため、シングルスレッド環境では StringBuilder が推奨されます。

    StringBuffer sbf = new StringBuffer();
    sbf.append("One");
    sbf.append(" ");
    sbf.append("Two");
    String numbers = sbf.toString();
    System.out.println(numbers); // "One Two" 
  • String.join() メソッド:

    配列やコレクションの要素を特定の区切り文字で連結する場合に便利です。(Java 8+)

    String[] parts = {"path", "to", "file.txt"};
    String joinedPath = String.join("/", parts);
    System.out.println(joinedPath); // "path/to/file.txt" 

セクション6: 比較 (Comparison)

データ型の値を比較する方法です。プリミティブ型と参照型(オブジェクト)で方法が異なります。

6.1 プリミティブ型の比較

比較演算子 (==, !=, <, >, <=, >=) を使って値そのものを直接比較します。

int a = 10;
int b = 5;
int c = 10;
System.out.println("a == b: " + (a == b)); // false
System.out.println("a == c: " + (a == c)); // true
System.out.println("a != b: " + (a != b)); // true
System.out.println("a > b: " + (a > b)); // true
System.out.println("a < b: " + (a < b)); // false
System.out.println("a >= c: " + (a >= c)); // true
double x = 3.14;
double y = 3.140;
System.out.println("x == y: " + (x == y)); // true (浮動小数点数の比較は注意が必要)
boolean flag1 = true;
boolean flag2 = false;
System.out.println("flag1 == flag2: " + (flag1 == flag2)); // false
char char1 = 'A';
char char2 = 'B';
System.out.println("char1 < char2: " + (char1 < char2)); // true (文字コードで比較) 

浮動小数点数 (float, double) の == での比較は、内部表現による誤差のため、意図した結果にならないことがあります。通常は、許容できる小さな誤差範囲(イプシロン)を設けて比較します。
例: Math.abs(x - y) < epsilon

6.2 参照型(オブジェクト)の比較

参照型の比較には == 演算子と equals() メソッドがあり、意味が異なります。

  • == 演算子:

    2つの参照変数がメモリ上の同じオブジェクトを指しているかどうか(参照が等しいか)を比較します。

  • equals() メソッド:

    2つのオブジェクトの内容が論理的に等しいかどうかを比較します。Object クラスのデフォルト実装は == と同じですが、多くのクラス(String, ラッパークラス, コレクションなど)では内容を比較するようにオーバーライドされています。

// String の比較
String str1 = "hello";
String str2 = "hello";
String str3 = new String("hello"); // new は新しいオブジェクトを生成
System.out.println("str1 == str2: " + (str1 == str2)); // true (文字列リテラルは同じオブジェクトを指すことが多い)
System.out.println("str1 == str3: " + (str1 == str3)); // false (str3は別のオブジェクト)
System.out.println("str1.equals(str2): " + str1.equals(str2)); // true (内容が等しい)
System.out.println("str1.equals(str3): " + str1.equals(str3)); // true (内容が等しい)
// ラッパークラスの比較
Integer int1 = 100; // オートボクシング
Integer int2 = 100; // オートボクシング
Integer int3 = 1000;
Integer int4 = 1000;
Integer int5 = new Integer(100); // 非推奨だが比較のため使用
// オートボクシングでは -128〜127 の範囲の値はキャッシュされるため同じオブジェクトを指すことが多い
System.out.println("int1 == int2: " + (int1 == int2)); // true (キャッシュされている可能性が高い)
System.out.println("int3 == int4: " + (int3 == int4)); // false (キャッシュ範囲外なので別オブジェクトの可能性が高い)
System.out.println("int1 == int5: " + (int1 == int5)); // false (new は別オブジェクト)
System.out.println("int1.equals(int2): " + int1.equals(int2)); // true (内容が等しい)
System.out.println("int3.equals(int4): " + int3.equals(int4)); // true (内容が等しい)
System.out.println("int1.equals(int5): " + int1.equals(int5)); // true (内容が等しい)
// null との比較
String nullStr = null;
System.out.println("str1.equals(nullStr): " + str1.equals(nullStr)); // false
// System.out.println(nullStr.equals(str1)); // NullPointerException が発生する!
// null チェックを行うか、定数や確定している非null変数を左側に置くのが安全
System.out.println("nullStr == null: " + (nullStr == null)); // true 

オブジェクトの内容を比較する場合は、常に equals() メソッドを使用します。== は参照(メモリ上のアドレス)を比較します。

equals() を呼び出す際は、左辺のオブジェクトが null でないことを確認するか、Objects.equals(obj1, obj2) (Java 7+) を使うと安全です。

6.3 compareTo() メソッドによる比較

Comparable インターフェースを実装しているクラス(String, ラッパークラス, Date など)は、compareTo() メソッドを持ちます。これはオブジェクトの大小関係(自然順序)を比較します。

  • obj1.compareTo(obj2) の結果:
    • 0: obj1obj2 が等しい
    • 負の値: obj1obj2 より小さい(前に来る)
    • 正の値: obj1obj2 より大きい(後に来る)
String s1 = "Apple";
String s2 = "Banana";
String s3 = "Apple";
System.out.println("s1.compareTo(s2): " + s1.compareTo(s2)); // 負の値 (AはBより前)
System.out.println("s2.compareTo(s1): " + s2.compareTo(s1)); // 正の値 (BはAより後)
System.out.println("s1.compareTo(s3): " + s1.compareTo(s3)); // 0 (等しい)
Integer i1 = 10;
Integer i2 = 20;
System.out.println("i1.compareTo(i2): " + i1.compareTo(i2)); // 負の値 (10 < 20) 

compareTo() はソート(例: Collections.sort(), Arrays.sort())などで内部的に利用されます。

セクション7: ジェネリクスと型安全性

ジェネリクスは、クラスやメソッドが扱うデータ型をパラメータ化する機能で、コンパイル時の型チェックを強化し、キャストの手間を省きます。

7.1 コレクションにおける型安全性

ジェネリクス登場以前は、コレクション(例: ArrayList)は Object 型で要素を格納していたため、取り出す際にキャストが必要で、実行時エラー(ClassCastException)の危険性がありました。

import java.util.ArrayList;
import java.util.List;
// ジェネリクス未使用 (非推奨)
List oldList = new ArrayList();
oldList.add("Apple");
oldList.add("Banana");
// oldList.add(123); // コンパイルエラーにはならないが、後で問題が発生する
// 要素を取り出す際にキャストが必要
// String fruit = (String) oldList.get(2); // ここで ClassCastException が発生!
// ジェネリクス使用 (推奨)
List<String> newList = new ArrayList<>(); // 型パラメータを指定 (<> はダイヤモンド演算子, Java 7+)
newList.add("Apple");
newList.add("Banana");
// newList.add(123); // コンパイルエラー! String型以外は追加できない
// キャスト不要で安全に要素を取得できる
String firstFruit = newList.get(0);
System.out.println("First fruit: " + firstFruit);
for (String fruit : newList) { System.out.println("Fruit: " + fruit.toUpperCase()); // Stringのメソッドを安全に使える
} 

ジェネリクスにより、List<String> には String 型のオブジェクトしか追加できなくなり、取得時も String 型であることが保証されるため、キャストが不要になり、型安全性が向上します。

7.2 型パラメータの基本

  • List<E>: E は型パラメータ(任意の名前で良いが、慣習的に大文字1文字が多い)。List<String>, List<Integer>のように具体的な型を指定して使う。
  • Map<K, V>: K はキーの型、V は値の型。例: Map<String, Integer>
  • 注意: 型パラメータにはプリミティブ型(int, double など)は指定できません。対応するラッパークラス(Integer, Double など)を使用します。
// List list = new ArrayList<>(); // これはコンパイルエラー
List list = new ArrayList<>(); // ラッパークラス Integer を使う
list.add(10); // オートボクシングにより int -> Integer
list.add(20);
int sum = 0;
for (Integer num : list) { sum += num; // オートアンボクシングにより Integer -> int
}
System.out.println("Sum: " + sum); 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です