上一篇建立了 PHP-Java Bridge 環境。本篇實作「編寫自訂 Java 類 → 編譯 → 放入 classpath → PHP 實例化呼叫」完整流程,並解決型別映射、例外處理、效能等實戰議題。
// 檔名: PhpTest.java (類名必須與檔名一致)
package com.example; // 建議加套件名,避免預設套件問題
public class PhpTest {
// 公開欄位:PHP 可直接讀寫
public String foo = "初始值";
// 公開方法:PHP 可呼叫
/**
* 接收字串,空字串回傳預設訊息
*/
public String test(String str) {
if (str == null || str.isEmpty()) {
return "Your string was empty.";
}
return "Java received: " + str;
}
/**
* 回傳欄位值
*/
public String whatIsFoo() {
return "foo is " + foo;
}
// 靜態方法:PHP 可透過類名呼叫
public static String staticGreet(String name) {
return "Hello from static Java, " + name + "!";
}
// main 方法:命令列測試用,PHP 不會呼叫
public static void main(String[] args) {
PhpTest p = new PhpTest();
if (args.length == 0) {
System.out.println(p.test(""));
} else {
for (String arg : args) {
System.out.println(p.test(arg));
}
}
}
}
# 1. 進入原始碼目錄
cd /path/to/java/src
# 2. 編譯 (產生 com/example/PhpTest.class)
javac -d /path/to/classes com/example/PhpTest.java
# 3. 確認 class 檔位置
ls -la /path/to/classes/com/example/PhpTest.class
# 4. 設定 classpath (php.ini 或執行時)
# php.ini [java] 區段
java.class.path = "/path/to/classes:/usr/share/php/java/php_java.jar"
# 或運行時動態設定 (需在 new Java() 前)
ini_set('java.class.path', '/path/to/classes:' . ini_get('java.class.path'));
<?php
// 1. 載入 Java 擴充 (php.ini 已啟用 extension=java.so)
// 2. 實例化 Java 類 (完整類名含套件)
$javaObj = new Java("com.example.PhpTest");
// 3. 呼叫實例方法
echo "Test result: " . $javaObj->test("Hello World") . "\n";
// 輸出: Java received: Hello World
// 4. 讀寫公開欄位
$javaObj->foo = "新的字串值";
echo "Foo value: " . $javaObj->foo . "\n";
// 5. 呼叫另一實例方法
echo "whatIsFoo: " . $javaObj->whatIsFoo() . "\n";
// 輸出: foo is 新的字串值
// 6. 呼叫靜態方法 (PHP 5.3+ 支援)
echo "Static greet: " . Java("com.example.PhpTest")->staticGreet("PHP") . "\n";
// 或
$class = new Java("com.example.PhpTest");
echo $class->staticGreet("PHP") . "\n";
// 7. 型別轉換關鍵:PHP 弱型別 → Java 強型別
// 整數傳給 String 參數會報錯,必須強制轉字串
$javaObj->foo = (string) 123456; // 正確
$javaObj->foo = "123456"; // 正確
// $javaObj->foo = 123456; // 錯誤: Java 端接收 String,無法自動轉換
// 8. 例外處理
try {
$result = $javaObj->test(null); // Java 端拋出例外會轉為 PHP Exception
} catch (JavaException $e) {
echo "Java 例外: " . $e->getMessage() . "\n";
} catch (Exception $e) {
echo "PHP 例外: " . $e->getMessage() . "\n";
}
| Java 型別 | PHP 對應 | 注意事項 |
|---|---|---|
| boolean | bool | 自動轉換 |
| byte, short, int, long | int | PHP int 為 64-bit (64位元系統),long 安全 |
| float, double | float | 精度可能差異 |
| char | string (長度1) | |
| String | string | PHP 傳數字需 (string) 強轉 |
| Object[] / List | array | 索引陣列自動轉 Java 陣列/ArrayList |
| Map | array (關聯) | 關聯陣列轉 HashMap |
| null | null |
php.ini java.class.path、ini_get()、實際檔案存在性。(string)$val、(int)$val、(float)$val。mb_convert_encoding()。new Java() 會啟動/連接 JVM。單例模式重用實例,或使用 PHP-Java Bridge Servlet 模式 (Tomcat + Java 端常駐)。<?php
class JavaBridge {
private static $instances = [];
public static function get($class_name) {
if (!isset(self::$instances[$class_name])) {
self::$instances[$class_name] = new Java($class_name);
}
return self::$instances[$class_name];
}
}
// 使用
$test = JavaBridge::get("com.example.PhpTest");
$test->foo = "value";
echo $test->test("input");
PHP-Java Bridge (PECL java) 已多年未更新,相容性差。新專案建議:
exec('java -jar app.jar arg1 arg2'),簡單任務適用。PHP 呼叫自訂 Java 類核心流程:寫 Java → javac 編譯 → 放入 classpath → new Java("完整類名") → 強制型別轉換 → 呼叫方法/存取欄位。關鍵坑點在 classpath 設定 與 PHP→Java 強型別轉換。現代架構強烈建議改用微服務/REST/gRPC替代進程內橋接,獲得更好維護性、擴展性與故障隔離。