diff --git a/src/utils/java/java-version.ts b/src/utils/java/java-version.ts
new file mode 100644
index 0000000..944d445
--- /dev/null
+++ b/src/utils/java/java-version.ts
@@ -0,0 +1,91 @@
+/**
+ * Represents a Java version.
+ */
+export class JavaVersion {
+    /**
+     * The name of the Java version.
+     */
+    private readonly _name: string;
+
+    /**
+     * The version number of the Java version.
+     */
+    private readonly _versionNumber: number;
+
+    /**
+     * Creates a new {@link JavaVersion} instance.
+     *
+     * @param versionNumber - The version number of the Java version.
+     */
+    constructor(versionNumber: number) {
+        this._name = `Java ${versionNumber}`;
+        this._versionNumber = versionNumber;
+    }
+
+    /**
+     * Parses a Java version from a string.
+     *
+     * @param java - The string representation of the Java version.
+     *
+     * @returns A {@link JavaVersion} instance, or `undefined` if the string cannot be parsed.
+     */
+    static parse(java: string): JavaVersion | undefined {
+        if (!java) {
+            return undefined;
+        }
+
+        const match = java.match(/(\d+)\s*$/);
+        if (!match) {
+            return undefined;
+        }
+
+        return new JavaVersion(+match[1]);
+    }
+
+    /**
+     * Casts the given value to a {@link JavaVersion} instance.
+     *
+     * @param java - The string representation of the Java version, its version number, or a {@link JavaVersion} instance.
+     *
+     * @returns A {@link JavaVersion} instance, or `undefined` if the input could not be casted to such.
+     */
+    static of(java: string | number | JavaVersion): JavaVersion | undefined {
+        if (java instanceof JavaVersion) {
+            return java;
+        }
+
+        if (typeof java === "number") {
+            return new JavaVersion(java);
+        }
+
+        return JavaVersion.parse(String(java));
+    }
+
+    /**
+     * Gets the name of the Java version, e.g., "Java 8".
+     */
+    get name(): string {
+        return this._name;
+    }
+
+    /**
+     * Gets the version number of the Java version, e.g., 8 for Java 8.
+     */
+    get versionNumber(): number {
+        return this._versionNumber;
+    }
+
+    /**
+     * Returns the string representation of the Java version.
+     */
+    toString(): string {
+        return this._name;
+    }
+
+    /**
+     * Returns the string representation of the Java version.
+     */
+    toJSON(): string {
+        return this._name;
+    }
+}
diff --git a/tests/unit/utils/java/java-version.spec.ts b/tests/unit/utils/java/java-version.spec.ts
new file mode 100644
index 0000000..11df758
--- /dev/null
+++ b/tests/unit/utils/java/java-version.spec.ts
@@ -0,0 +1,95 @@
+import { JavaVersion } from "@/utils/java";
+
+describe("JavaVersion", () => {
+    describe("constructor", () => {
+        test("constructs a new instance with the given version number", () => {
+            const javaVersion = new JavaVersion(8);
+
+            expect(javaVersion.versionNumber).toBe(8);
+            expect(javaVersion.name).toBe("Java 8");
+        });
+    });
+
+    describe("parse", () => {
+        test("returns a JavaVersion instance when given a valid string", () => {
+            const validInputs = ["Java 8", "Java 1.8", "java 1.8", "1.8", "8"];
+
+            for (const input of validInputs) {
+                const javaVersion = JavaVersion.parse(input);
+
+                expect(javaVersion).toBeDefined();
+                expect(javaVersion.versionNumber).toBe(8);
+                expect(javaVersion.name).toBe("Java 8");
+            }
+        });
+
+        test("returns undefined when given an invalid string", () => {
+            const invalidInputs = ["Java", "1.abc", "abc"];
+
+            for (const input of invalidInputs) {
+                const javaVersion = JavaVersion.parse(input);
+
+                expect(javaVersion).toBeUndefined();
+            }
+        });
+
+        test("returns undefined when given null or undefined", () => {
+            expect(JavaVersion.parse(null)).toBeUndefined();
+            expect(JavaVersion.parse(undefined)).toBeUndefined();
+        });
+    });
+
+    describe("of", () => {
+        test("returns a JavaVersion instance as is", () => {
+            const javaVersion1 = new JavaVersion(8);
+            const javaVersion2 = JavaVersion.of(javaVersion1);
+
+            expect(javaVersion2).toBe(javaVersion1);
+        });
+
+        test("returns a JavaVersion instance when given a number", () => {
+            const javaVersion = JavaVersion.of(8);
+
+            expect(javaVersion).toBeDefined();
+            expect(javaVersion.versionNumber).toBe(8);
+            expect(javaVersion.name).toBe("Java 8");
+        });
+
+        test("returns a JavaVersion instance when given a valid string", () => {
+            const javaVersion = JavaVersion.of("Java 16");
+
+            expect(javaVersion).toBeDefined();
+            expect(javaVersion.versionNumber).toBe(16);
+            expect(javaVersion.name).toBe("Java 16");
+        });
+
+        test("returns undefined when given an invalid input", () => {
+            const invalidInputs = ["Java", "1.abc", "abc"];
+
+            for (const input of invalidInputs) {
+                const javaVersion = JavaVersion.of(input);
+
+                expect(javaVersion).toBeUndefined();
+            }
+        });
+
+        test("returns undefined when given null or undefined", () => {
+            expect(JavaVersion.of(null)).toBeUndefined();
+            expect(JavaVersion.of(undefined)).toBeUndefined();
+        });
+    });
+
+    describe("toString", () => {
+        test("returns the string representation of the Java version", () => {
+            const javaVersion = new JavaVersion(8);
+
+            expect(javaVersion.toString()).toBe("Java 8");
+        });
+    });
+
+    test("should be converted to JSON as a Java version string", () => {
+        const javaVersion = new JavaVersion(11);
+
+        expect(JSON.stringify(javaVersion)).toBe("\"Java 11\"");
+    });
+});