サンプルコードで身につける: .java・.class・バイトコード・javac
解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。
1用語早見表: ソースから .class、クラスから main まで
このレッスンの用語の早見表です。前半はファイルと道具の名前、後半はソースの中に書くものの名前です。TypeScript との対応は位置や形のたとえで、 と .js のように中身の性質が違うものもあります。
用語 | 一言で手元では: 何として見えるか近いもの: Node / NestJS で近いものソース(.java)| 人が書く Java のコード手元では: Main.java のようなテキストファイル近いもの: .tsjavac | .java を読んで .class を作るコンパイラ手元では: JDK の bin/javac近いもの: tscコンパイル | javac でソースを .class に変える作業手元では: javac Main.java近いもの: tsc での変換.class | javac の出力。JVM が読むファイル手元では: Main.class。先頭4バイトは CAFEBABE近いもの: tsc が出す .js(弱い対応。当たらない点は本文)バイトコード | .class の中の、JVM 向けの命令列手元では: javap という道具で読める形にできる近いもの: V8 が実行時に中で作るバイトコードクラス | フィールドとメソッドをまとめた型の定義手元では: class PoliteGreeter { ... }近いもの: TypeScript の classオブジェクト | クラスから new で作った実体手元では: new PoliteGreeter("Hello")近いもの: new で作ったインスタンスメソッド | クラスの中に書く、呼び出せる処理手元では: greet(String name)近いもの: class のメソッドstatic | クラスに属し、オブジェクト無しで呼べる印手元では: PoliteGreeter.shout(...)近いもの: TypeScript の staticmain | JVM が最初に呼ぶメソッド手元では: public static void main(String[] args)近いもの: 無い(Node はファイルを上から実行する)
2最小の Hello を1語ずつ読む
画面に1行出すだけの最小のプログラムです。このコースのサンプルが動く 22 では、この1行のためにと を書きます。 void main(String[] args) の各語が何を表すかをコメントに書きました。引数を渡さずに起動するので、args.length は 0 と出ます。
3javac の前と後でフォルダを見る
レッスン本体のコードを prog.java という名前で置き、 にかける前後でフォルダの中を見た記録です。ソース1つから .class が3つできています。起動するときは、ファイル名ではなく main を持つクラスの名前(Main)を に渡します。
$ lsprog.java$ javac prog.java$ lsGreeter.classMain.classPoliteGreeter.classprog.java$ java MainHello, SpringGood evening, SpringNO OBJECT NEEDED!g1 is a PoliteGreetersame class = truesame object = false
4同じものを TypeScript で書くと
レッスン本体と同じ内容を TypeScript で書いたものです。class、、、static の形はほぼ対応します。違いは、TypeScript ではファイルの一番外に文を書けて main が要らないことと、interface が tsc を通すと消えることです。Java の Greeter は Greeter.class というファイルになって実行時にも残ります。
interface Greeter {
greet(name: string): string;
}
class PoliteGreeter implements Greeter {
constructor(private readonly prefix: string) {}
greet(name: string): string {
return `${this.prefix}, ${name}`;
}
static shout(s: string): string {
return s.toUpperCase() + "!";
}
}
// ここから下はファイルの一番外。Java ではこの位置に文を書けないので、main メソッドの中に書く
const g1: Greeter = new PoliteGreeter("Hello");
const g2: Greeter = new PoliteGreeter("Good evening");
console.log(g1.greet("Spring"));
console.log(g2.greet("Spring"));
console.log(PoliteGreeter.shout("no object needed"));
5混同しやすいもの: main の書き方は JDK の版で違う
同じソースを JDK 22 と JDK 25 で動かした結果です。public static void main(String[] args) はどちらでも動きます。void main() だけのクラスや、クラス宣言を書かないファイルは JDK 25 でだけ動きました。文だけを書いたファイルは、どちらでもコンパイルエラーです。JDK 25 向けに書かれたサンプルは、JDK 22 では動かないことがあります。
class Classic { public static void main(String[] args) { ... } }JDK 22 : 動くJDK 25 : 動くclass InstanceMain { void main() { ... } }JDK 22 : Error: Main method not found in class InstanceMain, please define the main method as:public static void main(String[] args)JDK 25 : 動くクラス宣言を書かず、void main() { ... } だけのファイルJDK 22 : Compact.java:1: error: implicitly declared classes are a preview feature and are disabled by default.JDK 25 : 動くSystem.out.println("x"); の1行だけのファイルJDK 22 : Bare.java:1: error: class, interface, enum, or record expectedJDK 25 : Bare.java:1: error: class, interface, annotation type, enum, record, method or field expectedmain が無いクラスを java で起動JDK 22 : Error: Main method not found in class NoMain, please define the main method as:public static void main(String[] args)JDK 25 : JDK 22 と同じ文面