Tu codes en PHP depuis des années et tu dois te mettre à Java, pour un nouveau poste, une mission ou une application Android ? Bonne nouvelle : tu sais déjà programmer, il te reste à changer de réflexes. Ce guide présente Java pour développeur PHP à travers les différences clés, en pratique : typage, compilation, classes, collections, exceptions, outils et frameworks, toujours avec le code PHP et son équivalent Java côte à côte.

🐘 PHP 8.x☕ Java 25 LTS🔁 Code côte à côte🧰 Composer → Maven🌱 Laravel → Spring Boot⏱️ 25 min

PHP et Java se ressemblent plus qu’on ne le croit : syntaxe héritée du C, classes, interfaces, exceptions, et même les mots-clés public, private, static ou final. PHP moderne a d’ailleurs emprunté beaucoup à Java (types, interfaces, énumérations). Pourtant, les premières semaines sont souvent déroutantes : le compilateur refuse ton code, les tableaux n’ont rien à voir, et ton application ne « meurt » plus à la fin de chaque requête.

Ce guide est pensé pour un développeur PHP qui découvre Java : on part de ce que tu connais pour arriver à son équivalent, en expliquant le pourquoi des différences. À la fin, tu sauras lire et écrire du Java idiomatique, et tu sauras quoi installer pour démarrer.

Java pour développeur PHP : les différences clés en pratique, code PHP et Java côte à côte
Le même code en PHP et en Java : la logique est identique, seuls les réflexes changent.
🎯
Ce que tu vas apprendre

Les différences d’exécution (script contre JVM), le typage statique, la compilation, les classes et les records, les collections qui remplacent le tableau PHP, les exceptions vérifiées, les null, les chaînes, les outils (Maven, Gradle, JUnit) et la correspondance entre l’écosystème Laravel/Symfony et Spring Boot.

Différence n°1 : le modèle d’exécution

C’est la différence la plus profonde, et celle dont on parle le moins. En PHP, chaque requête HTTP lance ton script, qui répond puis disparaît avec toutes ses variables. En Java, l’application démarre une seule fois dans la JVM (machine virtuelle Java) et reste en mémoire pour traiter toutes les requêtes, en parallèle.

Modèle d'exécution PHP (une requête, un script) contre Java (JVM permanente, threads)
Java pour développeur PHP : PHP repart de zéro à chaque requête, Java garde l’application en mémoire.
🐘 PHP☕ Java
Durée de vieLe temps d’une requêteTant que le serveur tourne
Mémoire entre requêtesRien n’est conservé (sauf cache, session)Les objets restent en mémoire
ParallélismePlusieurs processus PHP-FPMPlusieurs threads dans un seul processus
DémarrageInstantanéQuelques secondes (puis très rapide)
Erreur fataleTermine la requête en coursPeut faire tomber toute l’application si elle n’est pas gérée
⚠️
Le piège n°1 du développeur PHP en Java

Une variable static ou un attribut de service Spring est partagé entre toutes les requêtes et tous les utilisateurs. Stocker « l’utilisateur courant » dans un attribut, comme on le ferait sans risque dans un script PHP, mélangerait les données de plusieurs visiteurs. En Java web, l’état propre à une requête se passe en paramètre.

Différence n°2 : le typage statique et la compilation

PHP est dynamiquement typé (même si les types déclarés de PHP 7 et 8 ont beaucoup réduit l’écart). Java est statiquement typé : chaque variable a un type connu à la compilation, et le compilateur refuse le code incohérent avant qu’il ne s’exécute.

<?php
$prenom = "Alice";
$age = 31;
$age = "trente et un";        // autorisé : la variable change de type

function saluer(string $nom): string {
    return "Salut $nom";
}
echo saluer($prenom);
PHP
// Java 25 : un fichier source « compact », lancé avec  java Saluer.java
String saluer(String nom) {
    return "Salut " + nom;
}

void main() {
    String prenom = "Alice";
    int age = 31;
    // age = "trente et un";      // ❌ erreur de compilation : incompatible types

    var ville = "Liège";          // inférence de type : ville est un String, pour toujours

    IO.println(saluer(prenom) + " de " + ville + ", " + age + " ans");
}
Saluer.java (Java 25)

Le mot-clé var (Java 10+) évite de répéter le type quand il est évident, mais le typage reste statique : var n’est pas le $ de PHP. Côté workflow, Java ajoute une étape : le code source .java est compilé en bytecode .class, exécuté par la JVM. Les IDE et Maven/Gradle le font pour toi, et depuis Java 11 tu peux même lancer java Main.java directement.

Type PHPType JavaRemarque
intint / longint sur 32 bits (±2,1 milliards), long sur 64 bits
floatdoublePour l’argent : BigDecimal, jamais double
boolbooleanPas de conversion implicite : if (1) ne compile pas
stringStringImmuable, comparé avec .equals()
arrayList, Map, Set, tableau int[]Voir la différence n°4
?stringString (peut être null)Ou Optional<String> en retour de méthode
mixedObjectÀ éviter : on perd l’intérêt du typage

Différence n°3 : tout est classe (ou presque)

En PHP, un fichier peut contenir des fonctions libres et du code exécuté directement. En Java classique, tout vit dans une classe, et un fichier public porte le nom de sa classe (Utilisateur.java contient public class Utilisateur). Les espaces de noms PHP deviennent des packages, qui correspondent aux dossiers.

<?php
namespace App\Modele;

final class Utilisateur
{
    public function __construct(
        private readonly string $nom,
        private readonly string $email,
    ) {}

    public function nom(): string { return $this->nom; }

    public function salutation(): string
    {
        return "Bonjour {$this->nom}";
    }
}
src/Modele/Utilisateur.php
package be.lmcode.modele;

public final class Utilisateur {
    private final String nom;
    private final String email;

    public Utilisateur(String nom, String email) {
        this.nom = nom;
        this.email = email;
    }

    public String getNom() { return nom; }

    public String salutation() {
        return "Bonjour " + nom;      // pas de $this-> : this est implicite
    }
}
src/main/java/be/lmcode/modele/Utilisateur.java

Pour une simple classe de données, Java propose depuis la version 16 les records, l’équivalent des propriétés promues readonly de PHP 8, avec en prime equals(), hashCode() et toString() générés :

public record Utilisateur(String nom, String email) {
    public String salutation() {
        return "Bonjour " + nom;
    }
}

var alice = new Utilisateur("Alice", "[email protected]");
IO.println(alice.nom());          // accesseur généré : nom(), pas getNom()
IO.println(alice);                // Utilisateur[nom=Alice, [email protected]]
Record Java
PHPJava
namespace App\Modele;package be.lmcode.modele;
use App\Modele\Utilisateur;import be.lmcode.modele.Utilisateur;
$this->nomthis.nom (ou simplement nom)
self::CONSTANTECONSTANTE ou Classe.CONSTANTE
Classe::methode()Classe.methode()
new Utilisateur(...)new Utilisateur(...) (identique !)
instanceofinstanceof, avec pattern matching : if (o instanceof Utilisateur u)
traitPas d’équivalent direct : méthodes default d’interface, ou composition

Différence n°4 : adieu le tableau à tout faire

En PHP, array sert à tout : liste, dictionnaire, pile, ensemble… En Java, chaque usage a sa structure, avec des performances garanties. C’est probablement le plus gros changement d’habitude.

<?php
$langages = ['PHP', 'Java', 'Python'];          // liste
$langages[] = 'Go';

$ages = ['Alice' => 31, 'Bruno' => 27];          // dictionnaire
$ages['Chloé'] = 35;

foreach ($ages as $nom => $age) {
    echo "$nom a $age ans\n";
}

$adultes = array_filter($ages, fn($a) => $a >= 30);
$noms = array_map('strtoupper', array_keys($adultes));
PHP
import java.util.*;

List<String> langages = new ArrayList<>(List.of("PHP", "Java", "Python"));
langages.add("Go");

Map<String, Integer> ages = new HashMap<>(Map.of("Alice", 31, "Bruno", 27));
ages.put("Chloé", 35);

for (var e : ages.entrySet()) {
    IO.println(e.getKey() + " a " + e.getValue() + " ans");
}

List<String> noms = ages.entrySet().stream()
    .filter(e -> e.getValue() >= 30)
    .map(e -> e.getKey().toUpperCase())
    .toList();
Java

Les fonctions array_filter, array_map et array_reduce trouvent leur équivalent dans l’API Stream (filter, map, reduce, collect). Et attention : List.of() et Map.of() créent des collections non modifiables, d’où le new ArrayList<>(...). Pour bien choisir entre ArrayList, HashMap, HashSet ou TreeMap, notre guide des collections Java détaille chaque structure avec schémas et complexités.

Différence n°5 : les chaînes et les comparaisons

String a = "bonjour";
String b = new String("bonjour");

IO.println(a == b);           // false ! == compare les références (les objets)
IO.println(a.equals(b));      // true  : compare le contenu

// Concaténation : + (pas de point comme en PHP)
String message = "Salut " + a + " !";

// Interpolation : String.format ou formatted()
String ligne = "%s a %d ans".formatted("Alice", 31);

// Text blocks (Java 15+) : l'équivalent du heredoc PHP
String html = """
    <p>Bonjour %s</p>
    """.formatted("Alice");
Java : les pièges des chaînes
PHPJava
"Salut " . $nom"Salut " + nom
"Salut $nom""Salut %s".formatted(nom)
strlen($s)s.length()
strtolower($s)s.toLowerCase()
str_contains($s, "x")s.contains("x")
explode(",", $s)s.split(",") (expression régulière !)
implode(", ", $t)String.join(", ", liste)
$a === $ba.equals(b) (ou Objects.equals(a, b) si null possible)
🐛
Le bug classique

Comparer deux String avec == fonctionne parfois (grâce au cache des chaînes littérales)… puis échoue en production avec des chaînes venant d’une base de données ou d’un formulaire. Pour les objets, utilise toujours .equals().

Différence n°6 : null et Optional

PHP 8 a l’opérateur ?-> (nullsafe) et ??. Java n’a ni l’un ni l’autre, et appeler une méthode sur null lève la célèbre NullPointerException. Pour signaler qu’une méthode peut ne rien renvoyer, Java utilise Optional :

<?php
$ville = $utilisateur?->adresse?->ville ?? 'Inconnue';
PHP
Optional<Utilisateur> trouve = depot.findByEmail("[email protected]");

String ville = trouve
    .map(Utilisateur::adresse)
    .map(Adresse::ville)
    .orElse("Inconnue");

// Valeur par défaut simple
String nom = Objects.requireNonNullElse(saisie, "Anonyme");
Java

Différence n°7 : les exceptions vérifiées

La gestion des exceptions ressemble beaucoup à PHP (try, catch, finally, throw), avec une particularité : les exceptions vérifiées (checked exceptions). Si une méthode peut lever une IOException, le compilateur t’oblige à la gérer ou à la déclarer avec throws.

// Le compilateur exige de traiter IOException
static String lireFichier(Path chemin) throws IOException {
    return Files.readString(chemin);
}

void main() {
    try {
        IO.println(lireFichier(Path.of("config.txt")));
    } catch (NoSuchFileException e) {
        IO.println("Fichier introuvable : " + e.getFile());
    } catch (IOException e) {
        IO.println("Erreur de lecture : " + e.getMessage());
    }
}

// try-with-resources : ferme automatiquement la ressource (comme un fclose garanti)
try (var lecteur = Files.newBufferedReader(Path.of("data.csv"))) {
    lecteur.lines().forEach(IO::println);
}
Java

Les exceptions qui héritent de RuntimeException (comme IllegalArgumentException) ne sont pas vérifiées : c’est l’équivalent des exceptions PHP habituelles. Spring Boot les utilise massivement.

Différence n°8 : match, enum et switch

Bonne surprise : l’expression match de PHP 8 a son jumeau en Java avec le switch moderne (Java 14+), et les énumérations PHP 8.1 ressemblent beaucoup aux enum Java.

<?php
enum Statut: string {
    case AFaire = 'a_faire';
    case EnCours = 'en_cours';
    case Terminee = 'terminee';
}

$libelle = match ($statut) {
    Statut::AFaire => 'À faire',
    Statut::EnCours => 'En cours',
    Statut::Terminee => 'Terminée',
};
PHP 8.1
enum Statut { A_FAIRE, EN_COURS, TERMINEE }

String libelle = switch (statut) {
    case A_FAIRE -> "À faire";
    case EN_COURS -> "En cours";
    case TERMINEE -> "Terminée";
};   // le compilateur vérifie qu'aucun cas n'est oublié
Java

Différence n°9 : les outils et l’écosystème Java pour développeur PHP

Tu ne repars pas de zéro : chaque outil de ton quotidien PHP a son équivalent Java.

Équivalences entre PHP et Java : Composer et Maven, Laravel et Spring Boot, PHPUnit et JUnit
Le dictionnaire du Java pour développeur PHP : retrouve tes outils dans l’écosystème Java.

Composer → Maven ou Gradle

Le composer.json devient un pom.xml (Maven) ou un build.gradle (Gradle). Ils gèrent les dépendances et la compilation, les tests et le packaging. Les bibliothèques viennent de Maven Central, l’équivalent de Packagist.

<dependencies>
    <!-- équivalent de : composer require laravel/framework -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- équivalent de : composer require --dev phpunit/phpunit -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
pom.xml (extrait)

Laravel / Symfony → Spring Boot

Spring Boot est le framework web dominant en Java. Si tu connais Symfony, tu seras en terrain familier : injection de dépendances, annotations (attributs en PHP), contrôleurs, services, dépôts. Comparons une petite route d’API :

<?php
use App\Models\Tache;
use Illuminate\Http\Request;

Route::get('/taches/{id}', function (int $id) {
    return Tache::findOrFail($id);
});

Route::post('/taches', function (Request $request) {
    $data = $request->validate(['titre' => 'required|max:150']);
    return response()->json(Tache::create($data), 201);
});
Laravel — routes/api.php
@RestController
@RequestMapping("/taches")
public class TacheController {

    private final TacheRepository depot;

    public TacheController(TacheRepository depot) {    // injection par le constructeur
        this.depot = depot;
    }

    @GetMapping("/{id}")
    public Tache lire(@PathVariable long id) {
        return depot.findById(id)
            .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public Tache creer(@Valid @RequestBody NouvelleTache demande) {
        return depot.save(new Tache(demande.titre()));
    }
}

record NouvelleTache(@NotBlank @Size(max = 150) String titre) {}
Spring Boot — TacheController.java

La structure est plus verbeuse, mais tout est explicite et vérifié à la compilation : le type de l’identifiant, la forme du corps de la requête, les règles de validation. Pour comparer avec une API équivalente en JavaScript, vois notre tutoriel API REST avec Node.js, Express et MySQL.

BesoinÉcosystème PHPÉcosystème Java
Framework webLaravel, SymfonySpring Boot, Quarkus, Micronaut
ORMEloquent, DoctrineJPA / Hibernate, Spring Data
MigrationsLaravel Migrations, Doctrine MigrationsFlyway, Liquibase
Tests unitairesPHPUnit, PestJUnit 5, AssertJ, Mockito
Analyse statiquePHPStan, PsalmLe compilateur + SpotBugs, SonarLint
FormatagePHP-CS-FixerSpotless, google-java-format
Gabarits HTMLBlade, TwigThymeleaf
Interface desktop—JavaFX (voir notre logiciel de restaurant JavaFX)

Installer Java et écrire son premier programme (Java pour développeur PHP)

  1. Installe un JDK 25 (la version LTS actuelle), par exemple la distribution gratuite Eclipse Temurin d’Adoptium.
  2. Vérifie l’installation dans un terminal : java -version.
  3. Choisis un éditeur : IntelliJ IDEA (la référence en Java, édition Community gratuite) ou VS Code avec le pack d’extensions Java.
  4. Crée un fichier Bonjour.java et lance-le directement, sans étape de compilation manuelle.
// Lancer avec :  java Bonjour.java
void main() {
    var langages = java.util.List.of("PHP", "Java");
    for (var langage : langages) {
        IO.println("Bonjour depuis " + langage + " !");
    }
}
Bonjour.java

Depuis Java 25, plus besoin du fameux public static void main(String[] args) ni d’une classe pour un petit programme : la méthode void main() et la classe IO rendent les premiers pas aussi simples qu’un script PHP. Pour un vrai projet, génère un squelette avec Spring Initializr (Spring Boot) ou mvn archetype:generate.

🧰
Configure bien ton éditeur

Si tu restes sur VS Code, installe l’« Extension Pack for Java » de Microsoft en plus de tes indispensables : notre sélection des meilleures extensions VS Code t’aidera à garder un éditeur rapide.

Feuille de route Java pour développeur PHP : 4 semaines

SemaineObjectifExercice conseillé
1Syntaxe, types, classes, records, compilationRéécrire un petit script PHP (calculatrice, convertisseur) en Java
2Collections, Streams, exceptions, OptionalLire un fichier CSV et produire des statistiques
3Maven/Gradle, tests JUnit, organisation en packagesÉcrire les tests de la semaine 2
4Spring Boot : contrôleurs, services, JPARecréer une petite API CRUD que tu as déjà faite en Laravel ou en PHP natif

Java pour développeur PHP : les 8 réflexes à oublier

  1. Mettre un $ devant les variables (le compilateur te le rappellera vite).
  2. Concaténer avec un point : en Java, c’est +.
  3. Comparer des chaînes avec == : utilise .equals().
  4. Utiliser un tableau associatif pour tout : choisis List, Map ou Set.
  5. Compter sur la conversion automatique : "5" + 1 donne "51", et if ("") ne compile pas.
  6. Stocker l’état d’une requête dans un attribut static ou de service : il est partagé entre tous les utilisateurs.
  7. Utiliser double pour de l’argent : préfère BigDecimal.
  8. Ignorer les avertissements de l’IDE : en Java, ils signalent souvent un vrai bug.

FAQ : Java pour développeur PHP

Java est-il difficile à apprendre quand on connaît PHP ?

Non. La syntaxe est très proche (héritée du C) et les concepts orientés objet sont les mêmes. Les vraies nouveautés sont le typage statique, la compilation, les collections et le modèle d’exécution permanent de la JVM. Compte quelques semaines pour être à l’aise.

Quel est l’équivalent de Laravel en Java ?

Spring Boot est le framework le plus utilisé, plus proche de Symfony dans sa philosophie. Quarkus et Micronaut sont des alternatives modernes, plus légères au démarrage.

Quelle version de Java apprendre en 2026 ?

La dernière version LTS, Java 25, sortie en septembre 2025. Elle simplifie beaucoup les débuts avec void main() et la classe IO, tout en restant la version supportée à long terme par les entreprises.

Faut-il apprendre Java ou Kotlin après PHP ?

Pour le développement Android, Kotlin est le langage recommandé par Google. Pour le back-end en entreprise, Java reste majoritaire. Apprendre Java d’abord facilite ensuite le passage à Kotlin, qui tourne sur la même JVM.

Peut-on faire du web avec Java comme avec PHP ?

Oui, mais différemment : on ne dépose pas des fichiers sur un serveur Apache. L’application Spring Boot embarque son propre serveur web et se lance comme un programme, souvent derrière Nginx ou dans un conteneur Docker.

Conclusion

Passer de PHP à Java, ce n’est pas réapprendre à programmer : c’est changer de réflexes. Retiens l’essentiel de ce guide Java pour développeur PHP : l’application vit en permanence dans la JVM, le compilateur vérifie les types avant l’exécution, chaque usage du tableau PHP a sa collection dédiée, les chaînes se comparent avec equals(), et l’écosystème (Maven, JUnit, Spring Boot) a un équivalent pour chacun de tes outils.

Le meilleur moyen de progresser reste de réécrire en Java un projet que tu as déjà réalisé en PHP, par exemple notre application de planning PHP/MySQL. Tu verras vite que la rigueur de Java devient un confort. Pour approfondir, les tutoriels officiels dev.java sont gratuits et à jour.

Comments

No comments yet. Why don’t you start the discussion?

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *