Skip to content

PHP 与 Java 关键差异速查

面向 PHP 开发者的 Java 概念对照速查手册。建议先读这篇,建立基本认知后再阅读其他文档。


1. 语言层面差异

强类型 vs 弱类型

php
// PHP:弱类型,变量类型自动转换
$count = "5";   // string
$count += 3;    // int(8),PHP 自动转换类型
java
// Java:强类型,每个变量、参数、返回值都必须声明类型
String count = "5";   // 编译通过
// count += 3;        // ❌ 编译错误:String 不能 + int
int number = Integer.parseInt(count) + 3;  // 必须先转换

对开发的影响:

  • Java 中类型错误在编译时就暴露,PHP 在运行时才发现
  • Java 函数签名包含类型信息,本身就是文档
  • 更多的键盘输入(类型声明),换来更安全的重构

JVM 编译执行 vs PHP 解释执行

特性PHPJava
执行方式解释执行(OPcache 缓存 opcode)先编译成字节码,JVM 运行时解释/编译
修改代码保存文件后下次请求即生效需要重新编译(mvn compile),DevTools 可自动触发 restart
启动速度ms 级(PHP-FPM 常驻)秒级(Spring Boot 需启动 JVM + Tomcat + 加载所有 Bean)
运行性能每次请求都要走框架初始化一次启动持续处理请求,同类任务性能通常优于 PHP

静态类型检查

PHP 开发者最需要适应的一点:Java 编译器会拦截很多看似"正常"的代码

php
function divide($a, $b) {
    return $a / $b;
}
echo divide(10, "0");  // PHP 只会给出 Division by zero 警告
java
// Java 必须在调用前就处理好类型问题
public double divide(int a, int b) {
    return a / b;
}
// 调用:divide(10, 0);  // 编译通过,运行抛 ArithmeticException

2. 语法层面对比

命名空间

php
// PHP:使用 \ 作为分隔符
namespace App\Http\Controllers;
use App\Models\User;
java
// Java:使用 . 作为分隔符,且必须与目录结构一致
package com.example.myapp.controller;
import com.example.myapp.model.User;
特性PHPJava
分隔符\.
关键字namespacepackage
导入useimport
与目录关系松散关联(PSR-4 自动加载)强制对应(编译器要求)
根命名空间通常 App\通常是 com.公司名.项目名

类与对象

php
// PHP
class UserService {
    public function __construct(
        private UserRepository $repository  // PHP 8+ 构造器属性提升
    ) {}
    
    public function find(int $id): ?User {
        return $this->repository->find($id);
    }
}
java
// Java
public class UserService {
    private final UserRepository repository;  // final 对应 readonly

    // 构造器注入(对应 PHP 的构造器属性提升)
    public UserService(UserRepository repository) {
        this.repository = repository;
    }
    
    public User find(int id) {            // 返回值不能为 null(除非显式 Optional)
        return repository.findById(id)
            .orElseThrow(() -> new RuntimeException("User not found"));
    }
}

接口

php
// PHP:接口可以有常量,PHP 8+ 可以有默认方法
interface Logger {
    public function log(string $message): void;
    public function error(string $message): void;  // PHP 8.1 可以定义
}
java
// Java:接口更强大,可以有默认方法和静态方法
public interface Logger {
    void log(String message);                    // 默认就是 public abstract
    
    default void error(String message) {         // 对应 PHP 的 trait 或接口默认方法
        log("[ERROR] " + message);
    }
    
    static Logger getDefault() {                 // 工厂方法
        return new ConsoleLogger();
    }
}

泛型(PHP 没有直接对应)

php
// PHP:没有编译期泛型,只有 PHPDoc 注解
/**
 * @return Collection<User>
 */
function getUsers(): Collection {
    return User::all();
}
java
// Java:真正的编译期泛型
public List<User> getUsers() {
    return userRepository.findAll();
    // 返回 List<User> 保证了每个元素都是 User 类型
}

public <T> T findById(Long id, Class<T> type) {
    // 泛型方法:调用时确定返回类型
    return (T) repository.findById(id).orElse(null);
}

注解(Annotation)vs PHP Attribute

PHP 8.0 引入了 Attribute,语法上与 Java 注解极其相似:

php
// PHP 8+ Attribute(从 Laravel 角度看,类似 Route 注解)
#[Route('/api/users', methods: ['GET'])]
public function index() { ... }
java
// Java Annotation(注意:没有 # 号,用 @ 开头)
@GetMapping("/api/users")
public List<User> index() { ... }

关键差别:

  • Java 注解在运行时可通过反射读取(Spring Boot 大量依赖这一机制)
  • PHP Attribute 同样在运行时读取,但 Spring Boot 的注解体系更庞大、更底层
  • Java 中几乎所有"魔法"(路由、依赖注入、事务、缓存)都通过注解实现

3. 生态与工具对比

Maven / Gradle vs Composer

特性ComposerMavenGradle
配置文件composer.jsonpom.xmlbuild.gradle
依赖存储vendor/~/.m2/repository/~/.gradle/caches/
命令示例composer installmvn installgradle build
镜像源composer config repossettings.xml mirrorsbuild.gradle repositories
速度较慢(但稳定)快(支持增量编译)

包管理仓库

xml
<!-- Maven 配置阿里云镜像(类比 composer 配置中文镜像) -->
<!-- 在 ~/.m2/settings.xml 中添加 -->
<mirrors>
    <mirror>
        <id>aliyun</id>
        <mirrorOf>central</mirrorOf>
        <url>https://maven.aliyun.com/repository/central</url>
    </mirror>
</mirrors>

IDE 工具链

工具PHP 版Java 版
IDEPhpStormIntelliJ IDEA(同一家公司,快捷键通用)
调试器Xdebug内嵌在 IDE 中,无需额外配置
代码补全良好极佳(类型系统更完善,补全更精确)
重构能力基本强(重命名、提取、移动都能全项目安全执行)

4. 框架层面差异

MVC 模式

概念LaravelSpring Boot
路由routes/web.php 集中定义注解在控制器方法上(@GetMapping
控制器继承 Controller 基类无需继承,@RestController 注解即可
模型Eloquent Model(Active Record)Entity + Repository(Data Mapper)
模板引擎Blade(PHP 语法扩展)Thymeleaf(HTML 友好)
DI 容器app()->bind() / app()->make()@Component + @Autowired

请求响应对比

操作LaravelSpring Boot
获取参数$request->input('name')@RequestParam String name@RequestBody
返回 JSONresponse()->json($data)return userService.getUsers()(自动序列化为 JSON)
异常处理App\Exceptions\Handler@ControllerAdvice + @ExceptionHandler
中间件php artisan make:middlewareHandlerInterceptorFilter

依赖注入对比

特性LaravelSpring Boot
注册服务$this->app->bind()@Component / @Service(扫描注解自动注册)
注入方式__construct 自动注入@Autowired 或构造器注入
单例$this->app->singleton()@Service 默认就是单例
门面\DB::table()无对应(通常注入 Bean 使用)

5. 常见"水土不服"场景

场景:修改代码后不生效

php
// PHP:修改 → 保存 → F5 刷新 → 生效
java
// Java:修改 → 保存 → IDE 自动编译(或手动 mvn compile)
//       → Spring Boot DevTools 检测到变化自动重启(2-5 秒)
//       → F5 刷新

场景:null 安全

php
// PHP:几乎不用担心 null
$user = User::find($id);
return $user->name;  // 如果 $user 为 null,返回 null,不会抛异常
java
// Java:null 是最大的问题来源
User user = userRepository.findById(id).orElse(null);
// user.getName();  // ❌ 如果 user 是 null,抛出 NullPointerException

// 正确做法:用 Optional 避免 NPE
User user = userRepository.findById(id)
    .orElseThrow(() -> new ResourceNotFoundException("User not found"));

场景:数组操作

php
// PHP:数组即一切
$users = User::all()->toArray();
$names = array_column($users, 'name');
java
// Java:数组、List、Set、Map 是不同的类型
List<User> users = userService.getAllUsers();
List<String> names = users.stream()
    .map(User::getName)           // 类比 array_map
    .collect(Collectors.toList()); // 转回 List
// Java 8+ 的 Stream API 类似 PHP 的 array_map / array_filter / array_reduce

6. 快速决策指南

如果你在 Php/Laravel 中这么做在 Java/Spring Boot 中应该
$user = User::find($id)userRepository.findById(id)
$request->input('name')@RequestParam String name
return response()->json(...)return ResponseEntity.ok(...)
Route::middleware('auth')->group(...)@PreAuthorizeWebConfig.addInterceptors()
config('app.name')@Value("${app.name}")
Log::info('message')log.info("message")(通过 LoggerFactory)
Cache::remember('key', 3600, fn() => ...)@Cacheable("key")
php artisan make:model User手动创建 User.java
composer require vendor/pkgpom.xml 中添加 <dependency>
dd($variable)System.out.println()log.debug()(不推荐,应使用断点调试)

💡 阅读建议: 后续文档中遇到不理解的概念,随时回到此页查阅对照关系。

面向 PHP 开发者的 Spring Boot 文档