Skip to content · ⁨Passer au contenu⁩
Subjects · ⁨Sujets⁩
  • 1 Java basics · ⁨Bases du Java⁩
    1.1

    Classes, main & output · ⁨Classes, main & sortie⁩

    English

    Every Java program lives inside a class 类. It starts at a method 方法 named main. System.out.println(...) prints a line; System.out.print(...) prints with no new line.

    • Java is compiled 编译: the compiler 编译器 checks the whole program, then it runs.
    • Every statement 语句 ends with a semicolon ;.
    Français

    Tout programme Java vit à l'intérieur d'une classe 类. Il commence à une méthode 方法 nommée main. System.out.println(...) imprime une ligne ; System.out.print(...) imprime sans nouvelle ligne.

    public class Main {
        public static void main(String[] args) {
            System.out.println("Hello, world!");
            System.out.println("I am learning Java.");
        }
    }
    
    • Java est compilé : le compilateur vérifie tout le programme, puis il s'exécute.
    • Chaque instruction 语句 se termine par un point-virgule ;.
    Les programmes Java vivent dans une classe et commencent par main
    Les programmes Java vivent dans une classe et commencent par main
    1.2

    Variables & types primitifs

    English

    A variable 变量 must declare 声明 its type. Common primitive types 基本类型: int (whole number), double (decimal), boolean (true/false), char (one letter).

    Français

    Une variable 变量 doit déclarer 声明 son type. Types primitifs communs 基本类型 : int (nombre entier), double (décimal), boolean (true/false), char (une lettre).

    public class Main {
        public static void main(String[] args) {
            int age = 17;
            double price = 9.99;
            boolean passed = true;
            System.out.println(age + " " + price + " " + passed);
        }
    }
    
    1.3

    Commentaires & style

    English

    A comment 注释 is // (one line) or /* ... */ (a block). Indent the code inside braces { }. Class names start Capitalised; variables and methods use camelCase 驼峰命名 (lowercase first).

    Common mistakes

    • Every statement ends with a semicolon ;.
    • main must be exactly public static void main(String[] args).
    • println adds a new line; print does not.
    Français

    Un commentaire 注释 est // (une ligne) ou /* ... */ (un bloc). Indentez le code à l'intérieur des accolades { }. Les noms de classes commencent par une Majuscule ; les variables et méthodes utilisent camelCase 驼峰命名 (minuscule en premier).

    public class Main {
        public static void main(String[] args) {
            // greet the user
            String firstName = "Mei";
            System.out.println("Hi, " + firstName);
        }
    }
    

    Erreurs courantes

    • Chaque instruction se termine par un point-virgule ;.
    • main doit être exactement public static void main(String[] args).
    • println ajoute une nouvelle ligne ; print non.
  • 2 Operators & expressions · ⁨Opérateurs & expressions⁩
    2.1

    Arithmétique & affectation

    English

    Java arithmetic 算术 uses + - * / and % (remainder). With two ints, / is integer division 整数除法 — it drops the decimal. +=, -=, and ++ are shortcuts.

    Français

    L'arithmétique Java 算术 utilise + - * / et % (reste). Avec deux int, / est une division entière 整数除法 — elle ignore la décimale. +=, -= et ++ sont des raccourcis.

    public class Main {
        public static void main(String[] args) {
            int a = 7, b = 2;
            System.out.println(a / b);    // 3 (integer division)
            System.out.println(a % b);    // 1
            double x = 7.0 / 2;           // 3.5 (one side is double)
            System.out.println(x);
        }
    }
    
    int/int tronque ; impliquez un double pour un quotient réel
    int/int tronque ; impliquez un double pour un quotient réel
    2.2

    Utiliser des objets : String, Math, wrappers

    English

    Some values are objects 对象 with methods. String has .length(), .substring(), .toUpperCase(). Math has Math.max, Math.sqrt, Math.pow. Wrapper classes 包装类 (Integer, Double) wrap a primitive — e.g. Integer.parseInt("42").

    Math.random() returns a random 随机 double from 0.0 up to (but not including) 1.0. Scale it and cast to get whole numbers — this is the AP idiom:

    • Integer.MAX_VALUE (2147483647) and Integer.MIN_VALUE are the limits of int; going past them wraps around (an overflow).
    • An object variable that points at no object holds null; calling a method on it throws a NullPointerException.
    Français

    Certaines valeurs sont des objets 对象 avec des méthodes. String a .length(), .substring(), .toUpperCase(). Math a Math.max, Math.sqrt, Math.pow. Classes wrapper 包装类 (Integer, Double) enveloppent un primitif — par ex. Integer.parseInt("42").

    public class Main {
        public static void main(String[] args) {
            String s = "Hello";
            System.out.println(s.length());                  // 5
            System.out.println(s.toUpperCase());             // HELLO
            System.out.println(Math.max(3, 9));              // 9
            System.out.println(Integer.parseInt("42") + 1);  // 43
        }
    }
    

    Math.random() renvoie un nombre aléatoire 随机 double de 0.0 jusqu'à (mais sans inclure) 1.0. Mettez-le à l'échelle et castez-le pour obtenir des nombres entiers — c'est l'idiome AP :

    public class Main {
        public static void main(String[] args) {
            // a random whole number from 1 to 6 (a dice roll)
            int roll = (int) (Math.random() * 6) + 1;
            System.out.println(roll >= 1 && roll <= 6);   // true
        }
    }
    
    • Integer.MAX_VALUE (2147483647) et Integer.MIN_VALUE sont les limites de int ; dépasser ces limites provoque un débordement (overflow).
    • Une variable objet qui ne pointe vers aucun objet contient null ; appeler une méthode dessus lance une NullPointerException.
    2.3

    Casting & conversion de type

    English

    A cast 强制转换 changes a value's type. (int) drops the decimal; (double) avoids integer division when you need an exact result.

    Common mistakes

    • Integer division: 5 / 2 is 2, not 2.5. Cast first: (double) 5 / 2.
    • Compare Strings (and other objects) with .equals(), not ==.
    • == on two objects tests whether they are the SAME object, not whether they look equal.
    Français

    Un cast 强制转换 change le type d'une valeur. (int) supprime la décimale ; (double) évite la division entière lorsque vous avez besoin d'un résultat exact.

    public class Main {
        public static void main(String[] args) {
            double pi = 3.99;
            System.out.println((int) pi);            // 3
            int total = 7, n = 2;
            System.out.println((double) total / n);  // 3.5
        }
    }
    

    Erreurs courantes

    • Division entière : 5 / 2 est 2, pas 2.5. Castez d'abord : (double) 5 / 2.
    • Comparez des Strings (et autres objets) avec .equals(), pas ==.
    • == sur deux objets teste s'ils sont le MÊME objet, pas s'ils semblent égaux.
  • 3 Booleans & selection · ⁨Booléens & sélection⁩
    3.1

    if / else

    English

    if runs a block when a condition 条件 is true; else if and else add more cases. The condition goes in ( ), the block in { }.

    Français

    if exécute un bloc lorsqu'une condition 条件 est vraie ; else if et else ajoutent plus de cas. La condition va dans ( ), le bloc dans { }.

    public class Main {
        public static void main(String[] args) {
            int score = 72;
            if (score >= 80) {
                System.out.println("A");
            } else if (score >= 60) {
                System.out.println("B");
            } else {
                System.out.println("fail");
            }
        }
    }
    
    if choisit la branche vraie ; else la branche fausse
    if choisit la branche vraie ; else la branche fausse
    3.2

    Opérateurs logiques & comparaisons

    English

    Compare with ==, !=, <, >, <=, >= — a comparison 比较 gives a boolean. Combine with && (and), || (or), ! (not) — the logical operators 逻辑运算符. For Strings, use .equals(...), not ==.

    Français

    Comparez avec ==, !=, <, >, <=, >= — une comparaison 比较 donne un boolean. Combine avec && (and), || (or), ! (not) — les opérateurs logiques 逻辑运算符. Pour les Strings, utilisez .equals(...), pas ==.

    public class Main {
        public static void main(String[] args) {
            int age = 16;
            boolean member = true;
            System.out.println(age >= 18 && member);   // false
            String a = "hi";
            System.out.println(a.equals("hi"));        // true
        }
    }
    
    3.3

    switch · ⁨interrupteur⁩

    English

    switch chooses among many fixed values. Each case ends with break; default is the fallback.

    Common mistakes

    • A condition must be a boolean; if (x = 5) does not compile (use ==).
    • Each switch case needs a break;, or control falls through to the next case.
    • && and || are the logical operators; & and | are bitwise.
    Français

    switch choisit parmi plusieurs valeurs fixes. Chaque case se termine par break ; default est la solution de repli.

    public class Main {
        public static void main(String[] args) {
            int day = 3;
            switch (day) {
                case 1: System.out.println("Mon"); break;
                case 3: System.out.println("Wed"); break;
                default: System.out.println("other");
            }
        }
    }
    

    Erreurs courantes

    • Une condition doit être un boolean ; if (x = 5) ne compile pas (utilisez ==).
    • Chaque cas switch nécessite un break;, sinon le contrôle passe au cas suivant.
    • && et || sont les opérateurs logiques ; & et | sont des opérateurs bit à bit.
  • 4 Loops · ⁨Boucles⁩
    4.1

    Boucles while

    English

    A while loop repeats while a condition is true. Change something inside, or it loops forever.

    Français

    Une boucle while se répète tant qu'une condition est vraie. Changez quelque chose à l'intérieur, sinon elle boucle indéfiniment.

    public class Main {
        public static void main(String[] args) {
            int n = 1;
            while (n <= 3) {
                System.out.println(n);
                n++;
            }
        }
    }
    
    while vérifie la condition avant chaque passage du corps
    while vérifie la condition avant chaque passage du corps
    4.2

    Boucles for

    English

    A for loop packs the start, the condition, and the step into one line. Best when you know the count.

    Français

    Une boucle for regroupe le début, la condition et l'incrémentation sur une seule ligne. Idéal lorsque vous connaissez le nombre d'itérations.

    public class Main {
        public static void main(String[] args) {
            for (int i = 0; i < 5; i++) {
                System.out.print(i + " ");
            }
            System.out.println();   // 0 1 2 3 4
        }
    }
    
    4.3

    Accumulation

    English

    The accumulator 累加器 pattern: start a variable before the loop, then update it each turn.

    Français

    Le motif accumulateur 累加器 : initialisez une variable avant la boucle, puis mettez-la à jour à chaque tour.

    public class Main {
        public static void main(String[] args) {
            int total = 0;
            for (int i = 1; i <= 5; i++) {
                total += i;
            }
            System.out.println(total);   // 15
        }
    }
    
    4.4

    Boucles imbriquées

    English

    A loop inside a loop is a nested loop 嵌套循环. The inner loop runs fully on each turn of the outer one.

    Common mistakes

    • for (int i = 0; i < n; i++) runs n times (0 to n - 1); using <= runs one extra.
    • Do not put a semicolon right after for (...) or while (...) — it makes an empty loop.
    • Declare the counter in the for header so its scope ends with the loop.
    Français

    Une boucle dans une boucle est une boucle imbriquée 嵌套循环. La boucle intérieure s'exécute en entier à chaque itération de la boucle extérieure.

    public class Main {
        public static void main(String[] args) {
            for (int r = 0; r < 3; r++) {
                for (int c = 0; c < 3; c++) {
                    System.out.print("*");
                }
                System.out.println();
            }
        }
    }
    

    Erreurs courantes

    • for (int i = 0; i < n; i++) s'exécute n fois (de 0 à n - 1) ; utiliser <= en ajoute une de plus.
    • Ne placez pas de point-virgule juste après for (...) ou while (...) — cela crée une boucle vide.
    • Déclarez le compteur dans l'en-tête for pour que sa portée se termine avec la boucle.
  • 5 Strings · ⁨Chaînes de Caractères⁩
    5.1

    Méthodes String

    English

    A String 字符串 is text. Useful methods: .length(), .charAt(i), .substring(a, b), .indexOf(x), .toUpperCase(), .equals(...). Strings are immutable 不可变 — each method returns a new String.

    The methods you will use every day:

    Method Meaning Example → result
    .length() how many characters "Hi".length() → 2
    .charAt(i) one character "Hi".charAt(0) → H
    .substring(a, b) part, stops before b "Python".substring(0, 3) → Pyt
    .substring(a) from a to the end "Python".substring(3) → hon
    .indexOf(x) first position, -1 if absent "banana".indexOf("na") → 2
    .equals(s) same text? "hi".equals("hi") → true
    .compareTo(s) order: negative / 0 / positive "apple".compareTo("banana") → negative

    compareTo puts Strings in dictionary order — the AP exam uses it for sorting questions:

    Français

    Un String 字符串 est du texte. Méthodes utiles : .length(), .charAt(i), .substring(a, b), .indexOf(x), .toUpperCase(), .equals(...). Les chaînes sont immuables 不可变 — chaque méthode retourne un nouvel String.

    public class Main {
        public static void main(String[] args) {
            String s = "Python";
            System.out.println(s.length());          // 6
            System.out.println(s.charAt(0));         // P
            System.out.println(s.substring(0, 3));   // Pyt
            System.out.println(s.toUpperCase());     // PYTHON
        }
    }
    

    Les méthodes que vous utiliserez chaque jour :

    Méthode Signification Exemple → résultat
    .length() combien de caractères "Hi".length() → 2
    .charAt(i) un seul caractère "Hi".charAt(0) → H
    .substring(a, b) partie, s'arrête avant b "Python".substring(0, 3) → Pyt
    .substring(a) de a à la fin "Python".substring(3) → hon
    .indexOf(x) première position, -1 si absent "banana".indexOf("na") → 2
    .equals(s) même texte ? "hi".equals("hi") → true
    .compareTo(s) ordre : négatif / 0 / positif "apple".compareTo("banana") → négatif

    compareTo classe les Strings par ordre alphabétique — l'examen AP l'utilise pour les questions de tri :

    public class Main {
        public static void main(String[] args) {
            String a = "apple", b = "banana";
            System.out.println(a.compareTo(b) < 0);    // true (apple comes first)
            System.out.println(a.compareTo("apple"));  // 0 (equal)
        }
    }
    
    Méthodes clés de String : length, charAt, substring, equals
    Méthodes clés de String : length, charAt, substring, equals
    5.2

    Construire et parcourir des chaînes

    English

    Join strings with + (concatenation 拼接). Visit each character with a loop and .charAt(i).

    When you build a long String in a loop, StringBuilder is much faster: append the pieces, then call .toString() once.

    Common mistakes

    • Strings are immutable: s.toUpperCase() returns a new String, so store the result.
    • Read a character with s.charAt(i); the length is s.length() (a method, with ()).
    • Building a String with += in a big loop is slow; use a StringBuilder.
    Français

    Joignez des chaînes avec + (concaténation 拼接). Parcourez chaque caractère avec une boucle et .charAt(i).

    public class Main {
        public static void main(String[] args) {
            String word = "banana";
            int count = 0;
            for (int i = 0; i < word.length(); i++) {
                if (word.charAt(i) == 'a') count++;
            }
            System.out.println(count);   // 3
        }
    }
    

    Lorsque vous construisez une longue String dans une boucle, StringBuilder est beaucoup plus rapide : ajoutez les morceaux, puis appelez .toString() une seule fois.

    public class Main {
        public static void main(String[] args) {
            StringBuilder sb = new StringBuilder();
            for (int i = 1; i <= 5; i++) {
                sb.append(i).append(" ");
            }
            System.out.println(sb.toString().trim());   // 1 2 3 4 5
        }
    }
    

    Erreurs courantes

    • Les chaînes sont immuables : s.toUpperCase() retourne une nouvelle String, donc stockez le résultat.
    • Lisez un caractère avec s.charAt(i) ; la longueur est s.length() (une méthode, avec ()).
    • Construire une String avec += dans une grande boucle est lent ; utilisez un StringBuilder.
  • 6 Arrays · ⁨Tableaux⁩
    6.1

    Tableaux 1-D

    English

    An array 数组 holds a fixed number of values of one type. Index from 0, and get the size with .length.

    Français

    Un tableau 数组 conserve un nombre fixe de valeurs d'un même type. Indexez à partir de 0, et obtenez la taille avec .length.

    public class Main {
        public static void main(String[] args) {
            int[] scores = {88, 71, 95};
            System.out.println(scores[0]);       // 88
            System.out.println(scores.length);   // 3
            scores[1] = 100;
            System.out.println(scores[1]);       // 100
        }
    }
    
    Un primitif contient sa valeur ; une variable de tableau contient une référence vers l'objet tableau
    Un primitif contient sa valeur ; une variable de tableau contient une référence vers l'objet tableau
    6.2

    Algorithmes sur tableaux

    English

    Walk the array with a loop to find a max, a total, a count, or to search 查找. A for-each loop (for (int x : a)) reads each value in turn.

    Français

    Parcourez le tableau avec une boucle pour trouver un max, un total, un compteur, ou effectuer une recherche 查找. Une boucle for-each (for (int x : a)) lit chaque valeur à son tour.

    public class Main {
        public static void main(String[] args) {
            int[] a = {3, 9, 2, 7};
            int max = a[0], total = 0;
            for (int x : a) {
                if (x > max) max = x;
                total += x;
            }
            System.out.println(max + " " + total);   // 9 21
        }
    }
    
    6.3

    Tableaux 2-D

    English

    A 2-D array 二维数组 is a grid 网格 of rows and columns: grid[row][col].

    Common mistakes

    • An array's size is a.length (no brackets, no ()), and it is fixed when created.
    • Valid indexes are 0 to a.length - 1; a[a.length] throws ArrayIndexOutOfBoundsException.
    • A new int[5] is filled with zeros, not left empty.
    Français

    Un tableau 2-D 二维数组 est une grille 网格 de lignes et colonnes : grid[row][col].

    public class Main {
        public static void main(String[] args) {
            int[][] grid = {{1, 2, 3}, {4, 5, 6}};
            System.out.println(grid[1][2]);   // 6
            for (int[] row : grid) {
                for (int v : row) System.out.print(v + " ");
            }
            System.out.println();             // 1 2 3 4 5 6
        }
    }
    

    Erreurs courantes

    • La taille d'un tableau est a.length (sans crochets, sans ()), et elle est fixe lors de la création.
    • Les index valides vont de 0 à a.length - 1 ; a[a.length] provoque ArrayIndexOutOfBoundsException.
    • Un nouveau int[5] est rempli de zéros, pas laissé vide.
  • 7 ArrayList
    7.1

    Bases d'ArrayList

    English

    An ArrayList is a resizable 可变大小 list — it grows and shrinks as you add or remove items. It stores objects, so use a wrapper 包装类 type like Integer (not int). The <Integer> part is a generic 泛型 type. Key methods: .add(x), .get(i), .set(i, x), .size(), .remove(i).

    Français

    Un ArrayList est une liste 可变大小 redimensionnable — elle grandit et rétrécit selon vos ajouts ou suppressions. Elle stocke des objets, donc utilisez un type wrapper 包装类 comme Integer (pas int). La partie <Integer> est un type générique 泛型. Méthodes clés : .add(x), .get(i), .set(i, x), .size(), .remove(i).

    import java.util.ArrayList;
    
    public class Main {
        public static void main(String[] args) {
            ArrayList<Integer> nums = new ArrayList<Integer>();
            nums.add(10);
            nums.add(20);
            nums.add(30);
            System.out.println(nums.size());   // 3
            System.out.println(nums.get(1));   // 20
            nums.set(0, 99);
            System.out.println(nums);          // [99, 20, 30]
        }
    }
    
    ArrayList : add, get, size sur une liste redimensionnable
    ArrayList : add, get, size sur une liste redimensionnable
    7.2

    Algorithmes ArrayList et le bug remove

    English

    .remove(i) shifts 移动 every later element one place left. If you remove while counting i up, you skip the next element. Fix: loop backwards, or don't increment i after a remove.

    Common mistakes

    • ArrayList uses .size(), .get(i) and .add(...) — not the [] you use on arrays.
    • Removing items while looping forward by index skips the next item (the remove bug). Loop backwards, or use an iterator.
    • Store objects, not primitives: use ArrayList<Integer>, and Java auto-boxes int values.
    Français

    .remove(i) décale 移动 tous les éléments suivants d'une position vers la gauche. Si vous supprimez tout en incrémentant i vers le haut, vous sautez l'élément suivant. Solution : parcourir à rebours, ou ne pas incrémenter i après une suppression.

    import java.util.ArrayList;
    
    public class Main {
        public static void main(String[] args) {
            ArrayList<Integer> nums = new ArrayList<Integer>();
            for (int n : new int[]{4, 7, 4, 9, 4}) nums.add(n);
            // Remove every 4 — loop backwards so removals don't skip items.
            for (int i = nums.size() - 1; i >= 0; i--) {
                if (nums.get(i) == 4) nums.remove(i);
            }
            System.out.println(nums);   // [7, 9]
        }
    }
    

    Erreurs courantes

    • ArrayList utilise .size(), .get(i) et .add(...) — pas le [] utilisé sur les tableaux.
    • Supprimer des éléments tout en parcourant vers l'avant par index saute l'élément suivant (le bug remove). Parcourez à rebours, ou utilisez un itérateur.
    • Stockez des objets, pas des primitifs : utilisez ArrayList<Integer>, et Java effectue l'autoboxing int automatiquement.
  • 8 Writing classes · ⁨Écrire des classes⁩
    8.1

    Champs, constructeur et méthodes

    English

    A class 类 is a blueprint for objects. Its fields 字段 store data, its constructor 构造方法 sets up a new object, and its methods 方法 are the actions. this.name means "this object's name". Create an object with new.

    A static member belongs to the class itself, not to any one object. Call a static method on the class name — like Math.max — and a static field is shared by every object:

    Français

    Une classe 类 est un modèle pour les objets. Ses champs 字段 stockent les données, son constructeur 构造方法 initialise un nouvel objet, et ses méthodes 方法 définissent les actions. this.name signifie "le name de cet objet". Créez un objet avec new.

    public class Main {
        public static void main(String[] args) {
            Dog d = new Dog("Rex", 3);
            System.out.println(d.describe());   // Rex is 3 years old
            d.haveBirthday();
            System.out.println(d.describe());   // Rex is 4 years old
        }
    }
    
    class Dog {
        private String name;
        private int age;
    
        public Dog(String name, int age) {   // constructor
            this.name = name;
            this.age = age;
        }
    
        public String describe() {
            return name + " is " + age + " years old";
        }
    
        public void haveBirthday() {
            age++;
        }
    }
    

    Un membre static appartient à la classe elle-même, pas à un objet particulier. Appelez une méthode statique via le nom de la classe — comme Math.max — et un champ statique est partagé par tous les objets :

    public class Main {
        public static void main(String[] args) {
            System.out.println(Counter.made());   // 0
            new Counter();
            new Counter();
            System.out.println(Counter.made());   // 2
        }
    }
    
    class Counter {
        private static int count = 0;      // shared by ALL Counter objects
    
        public Counter() { count++; }
    
        public static int made() {         // called on the class: Counter.made()
            return count;
        }
    }
    
    Les champs stockent l'état ; le constructeur construit ; les méthodes agissent
    Les champs stockent l'état ; le constructeur construit ; les méthodes agissent
    8.2

    Encapsulation

    English

    Encapsulation 封装 means hiding data behind methods. Mark fields private so outside code can't touch them directly; expose an accessor 访问方法 (getter) to read, and a method to change them safely. The method can guard the data — here a deposit must be positive.

    Common mistakes

    • A constructor has the class name and no return type (not even void).
    • Use this.field to tell a field apart from a parameter with the same name.
    • Make fields private and reach them through getter/setter methods (encapsulation).
    Français

    L'encapsulation 封装 consiste à cacher les données derrière des méthodes. Marquez les champs private pour empêcher le code externe de les toucher directement ; exposez un accesseur 访问方法 (getter) pour lire, et une méthode pour les modifier en toute sécurité. La méthode peut protéger les données — ici, un dépôt doit être positif.

    public class Main {
        public static void main(String[] args) {
            Account a = new Account(100);
            a.deposit(50);
            a.deposit(-999);                       // rejected by the guard
            System.out.println(a.getBalance());    // 150
        }
    }
    
    class Account {
        private int balance;                       // hidden from outside
    
        public Account(int start) {
            balance = start;
        }
    
        public void deposit(int amount) {
            if (amount > 0) balance += amount;     // guard keeps balance valid
        }
    
        public int getBalance() {                  // accessor (getter)
            return balance;
        }
    }
    

    Erreurs courantes

    • Un constructeur a le nom de la classe et aucun type de retour (pas même void).
    • Utilisez this.field pour distinguer un champ d'un paramètre portant le même nom.
    • Rendez les champs private et accédez-y via des méthodes getter/setter (encapsulation).
  • 9 Inheritance & polymorphism · ⁨Héritage & polymorphisme⁩
    9.1

    Héritage

    English

    Inheritance 继承 lets a subclass 子类 reuse a superclass 父类. Write class Cat extends Animal and Cat gets Animal's fields and methods for free. Call the parent constructor with super(...).

    Français

    L'héritage 继承 permet à une sous-classe 子类 de réutiliser une super-classe 父类. Écrivez class Cat extends Animal et Cat hérite gratuitement des champs et méthodes de Animal. Appelez le constructeur parent avec super(...).

    public class Main {
        public static void main(String[] args) {
            Cat c = new Cat("Milo");
            c.eat();      // Milo is eating  (inherited from Animal)
            c.speak();    // Meow            (Cat's own method)
        }
    }
    
    class Animal {
        protected String name;
        public Animal(String name) { this.name = name; }
        public void eat() { System.out.println(name + " is eating"); }
    }
    
    class Cat extends Animal {
        public Cat(String name) { super(name); }     // call Animal's constructor
        public void speak() { System.out.println("Meow"); }
    }
    
    Cat et Dog étendent Animal : ils héritent de ses membres et ajoutent les leurs
    Cat et Dog étendent Animal : ils héritent de ses membres et ajoutent les leurs
    9.2

    Polymorphisme et toString

    English

    A subclass can override 重写 a method to replace the parent's version. Polymorphism 多态 means a Shape variable can hold any subtype, and Java picks the right toString at run time. System.out.println(obj) automatically calls obj.toString().

    Common mistakes

    • An overriding method must match the signature exactly; add @Override so the compiler catches slips.
    • super(...) must be the first line of a subclass constructor.
    • A subclass object IS-A superclass object, but not the other way round.
    Français

    Une sous-classe peut override 重写 une méthode pour remplacer celle du parent. Le polymorphisme 多态 signifie qu'une variable Shape peut contenir n'importe quel sous-type, et Java choisit la bonne toString à l'exécution. System.out.println(obj) appelle automatiquement obj.toString().

    public class Main {
        public static void main(String[] args) {
            Shape[] shapes = { new Circle(2), new Square(3) };
            for (Shape s : shapes) {
                System.out.println(s);          // each calls its own toString
            }
        }
    }
    
    class Shape {
        public String toString() { return "a shape"; }
    }
    
    class Circle extends Shape {
        private int r;
        public Circle(int r) { this.r = r; }
        public String toString() { return "Circle r=" + r; }     // override
    }
    
    class Square extends Shape {
        private int side;
        public Square(int side) { this.side = side; }
        public String toString() { return "Square side=" + side; }   // override
    }
    

    Erreurs courantes

    • Une méthode overriding doit correspondre exactement à la signature ; ajoutez @Override pour que le compilateur détecte les erreurs.
    • super(...) doit être la première ligne d'un constructeur de sous-classe.
    • Un objet de sous-classe IS-A un objet de super-classe, mais pas l'inverse.
  • 10 Recursion · ⁨Récursivité⁩
    10.1

    Récursivité

    English

    Recursion 递归 is a method that calls itself. Every recursion needs a base case 基准情形 (when to stop) and a recursive call 递归调用 that moves toward it. Without a base case it never stops and crashes with a stack overflow.

    Trace it: factorial(5) waits for factorial(4), which waits for factorial(3)… down to factorial(1) returning 1. Then the answers multiply back up: 1 → 2 → 6 → 24 → 120.

    Recursion also works on Strings — peel off one character each call:

    Merge sort 归并排序 is the recursive sort on the AP exam: split the array in half, sort each half recursively, then merge 合并 the two sorted halves. It runs in O(n log n) — far faster than the O(n²) sorts on big arrays.

    Common mistakes

    • Recursion needs a base case, or it throws StackOverflowError.
    • Each recursive call must move CLOSER to the base case.
    • Trace a small example by hand to check the recursion returns the right value.
    • In merge sort, the merge step does the real work; the recursion only splits the array.
    Français

    La récursion 递归 est une méthode qui s'appelle elle-même. Chaque récursion nécessite un cas de base 基准情形 (quand s'arrêter) et un appel récursif 递归调用 qui s'en approche. Sans cas de base, elle ne s'arrête jamais et plante avec une overflow de pile.

    La pile d'appels pour factorial(3) : chaque appel attend, puis retourne dans l'ordre inverse
    La pile d'appels pour factorial(3) : chaque appel attend, puis retourne dans l'ordre inverse
    public class Main {
        public static void main(String[] args) {
            System.out.println(factorial(5));   // 120
        }
    
        public static int factorial(int n) {
            if (n <= 1) return 1;            // base case
            return n * factorial(n - 1);     // recursive call: n * (n-1)!
        }
    }
    

    Tracez-le : factorial(5) attend factorial(4), qui attend factorial(3)… jusqu'à ce que factorial(1) retourne 1. Ensuite, les résultats remontent par multiplication : 1 → 2 → 6 → 24 → 120.

    La récursion fonctionne aussi sur les Strings — retirez un caractère à chaque appel :

    public class Main {
        public static void main(String[] args) {
            System.out.println(reverse("PYTHON"));   // NOHTYP
        }
    
        static String reverse(String s) {
            if (s.length() <= 1) return s;               // base case
            return reverse(s.substring(1)) + s.charAt(0);
        }
    }
    

    Merge sort 归并排序 est le tri récursif à l'examen AP : divisez le tableau en deux, triez chaque moitié récursivement, puis fusionnez 合并 les deux moitiés triées. Il s'exécute en O(n log n) — bien plus rapide que les tris O(n²) sur de grands tableaux.

    import java.util.Arrays;
    
    public class Main {
        public static void main(String[] args) {
            int[] a = {5, 2, 9, 1, 7, 3};
            mergeSort(a, 0, a.length - 1);
            System.out.println(Arrays.toString(a));   // [1, 2, 3, 5, 7, 9]
        }
    
        static void mergeSort(int[] a, int lo, int hi) {
            if (lo >= hi) return;                 // base case: one element
            int mid = (lo + hi) / 2;
            mergeSort(a, lo, mid);                // sort the left half
            mergeSort(a, mid + 1, hi);            // sort the right half
            merge(a, lo, mid, hi);                // merge the two halves
        }
    
        static void merge(int[] a, int lo, int mid, int hi) {
            int[] tmp = new int[hi - lo + 1];
            int i = lo, j = mid + 1, k = 0;
            while (i <= mid && j <= hi) {
                if (a[i] <= a[j]) tmp[k++] = a[i++];
                else              tmp[k++] = a[j++];
            }
            while (i <= mid) tmp[k++] = a[i++];
            while (j <= hi)  tmp[k++] = a[j++];
            for (k = 0; k < tmp.length; k++) a[lo + k] = tmp[k];
        }
    }
    

    Erreurs courantes

    • La récursion a besoin d'un cas de base, sinon elle lance StackOverflowError.
    • Chaque appel récursif doit se rapprocher du cas de base.
    • Tracez un petit exemple à la main pour vérifier que la récursion retourne la bonne valeur.
    • Dans le merge sort, l'étape de fusion fait le vrai travail ; la récursion ne fait que diviser le tableau.
  • 11 Searching & sorting · ⁨Recherche & tri⁩
    11.1

    Recherche linéaire et binaire

    English

    Linear search 线性查找 checks every element — works on any array. Binary search 二分查找 is much faster but needs a sorted 已排序 array: it looks at the middle, then throws away half each step. Both return the index, or -1 if not found.

    Français

    La recherche linéaire 线性查找 vérifie chaque élément — fonctionne sur n'importe quel tableau. La recherche binaire 二分查找 est beaucoup plus rapide mais nécessite un tableau trié 已排序 : elle regarde le milieu, puis rejette la moitié à chaque étape. Toutes deux retournent l'index, ou -1 si non trouvé.

    public class Main {
        public static void main(String[] args) {
            int[] a = {2, 5, 8, 12, 16, 23};      // sorted, so binary search works
            System.out.println(linear(a, 12));    // 3
            System.out.println(binary(a, 12));    // 3
            System.out.println(binary(a, 9));     // -1 (not found)
        }
    
        static int linear(int[] a, int target) {
            for (int i = 0; i < a.length; i++)
                if (a[i] == target) return i;
            return -1;
        }
    
        static int binary(int[] a, int target) {
            int lo = 0, hi = a.length - 1;
            while (lo <= hi) {
                int mid = (lo + hi) / 2;
                if (a[mid] == target) return mid;
                else if (a[mid] < target) lo = mid + 1;
                else hi = mid - 1;
            }
            return -1;
        }
    }
    
    La recherche binaire divise la plage en deux à chaque étape, donc un tableau trié est recherché en O(log n)
    La recherche binaire divise la plage en deux à chaque étape, donc un tableau trié est recherché en O(log n)
    11.2

    Tri par sélection et insertion

    English

    Selection sort 选择排序 repeatedly finds the smallest remaining value and swaps it to the front. Insertion sort 插入排序 takes each value and slides it back into its place among the already-sorted values.

    How the speeds compare:

    Algorithm Time
    linear search O(n)
    binary search O(log n), sorted arrays only
    selection / insertion sort O(n²)
    merge sort (topic 10) O(n log n)

    Common mistakes

    • Binary search only works on a sorted array.
    • Linear search is O(n); binary search is O(log n) but needs the sort first.
    • Selection and insertion sort are O(n²) — clear to learn, slow on big data.
    Français

    Le tri par sélection 选择排序 trouve répétitivement la plus petite valeur restante et l'échange contre le premier. Le tri par insertion 插入 prise chaque valeur et la glisse vers sa place parmi les valeurs déjà triées.

    import java.util.Arrays;
    
    public class Main {
        public static void main(String[] args) {
            int[] a = {5, 2, 9, 1, 7};
            for (int i = 0; i < a.length - 1; i++) {
                int min = i;
                for (int j = i + 1; j < a.length; j++)
                    if (a[j] < a[min]) min = j;
                int t = a[min]; a[min] = a[i]; a[i] = t;   // swap into place
            }
            System.out.println(Arrays.toString(a));   // [1, 2, 5, 7, 9]
        }
    }
    
    import java.util.Arrays;
    
    public class Main {
        public static void main(String[] args) {
            int[] a = {5, 2, 9, 1, 7};
            for (int i = 1; i < a.length; i++) {
                int key = a[i], j = i - 1;
                while (j >= 0 && a[j] > key) {    // shift bigger values right
                    a[j + 1] = a[j];
                    j--;
                }
                a[j + 1] = key;                  // drop key into the gap
            }
            System.out.println(Arrays.toString(a));   // [1, 2, 5, 7, 9]
        }
    }
    

    Comparaison des vitesses :

    Algorithme Temps
    recherche linéaire O(n)
    recherche binaire O(log n), tableaux triés uniquement
    tri par sélection / insertion O(n²)
    merge sort (sujet 10) O(n log n)

    Erreurs courantes

    • La recherche binaire ne fonctionne que sur un tableau trié.
    • La recherche linéaire est O(n) ; la recherche binaire est O(log n) mais nécessite le tri au préalable.
    • Les tris par sélection et insertion sont O(n²) — clairs à apprendre, mais lents sur de grandes quantités de données.
  • 12 Files & the FRQ · ⁨Fichiers & FRQ⁩
    12.1

    Fichiers texte avec Scanner

    English

    A Scanner reads text one line at a time. For a real file you write new Scanner(new File("scores.txt")); here we wrap a String so the example runs anywhere. Use .split(" ") to split 拆分 a line into parts and Integer.parseInt(...) to parse 解析 a number from text.

    Français

    Un Scanner lit du texte une ligne à la fois. Pour un vrai fichier, écrivez new Scanner(new File("scores.txt")) ; ici nous enveloppons un String pour que l'exemple fonctionne partout. Utilisez .split(" ") pour découper 拆分 une ligne en parties et Integer.parseInt(...) pour analyser 解析 un nombre depuis du texte.

    import java.util.Scanner;
    
    public class Main {
        public static void main(String[] args) {
            // Real file:  Scanner in = new Scanner(new File("scores.txt"));
            String data = "Alice 80\nBob 95\nCara 72";
            Scanner in = new Scanner(data);
            int total = 0, count = 0;
            while (in.hasNextLine()) {
                String line = in.nextLine();
                String[] parts = line.split(" ");      // break the line on the space
                total += Integer.parseInt(parts[1]);
                count++;
            }
            System.out.println("average = " + (total / count));   // average = 82
        }
    }
    
    Scanner lit les lignes tant que hasNextLine est true
    Scanner lit les lignes tant que hasNextLine est true
    12.2

    Types de questions FRQ AP

    English

    The AP CS A exam has four free-response 自由作答 questions, each a fixed shape:

    • Q1 — Methods & control: write methods to a given spec; loops, if, String/Math.
    • Q2 — Class design: write a full class (fields, constructor, methods) from a description.
    • Q3 — Array / ArrayList: process a 1-D array or ArrayList (search, count, build a new list).
    • Q4 — 2-D array: traverse a grid by row and column.

    The skill is always the same: read the spec, write the method exactly as described, return the right type.

    Common mistakes

    • nextInt() leaves the newline behind, so a following nextLine() reads an empty line — read it away first.
    • Check hasNext() before reading, to avoid running off the end of the file.
    • In the FRQ, read the method header carefully: match the return type and parameters exactly.
    Français

    L'examen AP CS A compte quatre questions free-response 自由作答, chacune ayant une forme fixe :

    • Q1 — Méthodes & contrôle : écrire des méthodes selon un spécifié donné ; boucles, if, String/Math.
    • Q2 — Conception de classe : écrire une classe complète (champs, constructeur, méthodes) à partir d'une description.
    • Q3 — Tableau / ArrayList : traiter un tableau 1-D ou un ArrayList (recherche, comptage, construction d'une nouvelle liste).
    • Q4 — Tableau 2-D : parcourir une grille ligne par ligne et colonne par colonne.

    La compétence reste toujours la même : lire le spécifié, écrire la méthode exactement comme décrit, retourner le bon type.

    public class Main {
        public static void main(String[] args) {
            // Q1 style: implement a method to a spec, then it is tested.
            System.out.println(countEven(new int[]{4, 7, 10, 3, 6}));   // 3
        }
    
        /** Returns how many values in arr are even. */
        public static int countEven(int[] arr) {
            int count = 0;
            for (int x : arr)
                if (x % 2 == 0) count++;
            return count;
        }
    }
    

    Erreurs courantes

    • nextInt() laisse le retour chariot derrière, donc un nextLine() suivant lit une ligne vide — lisez-le d'abord.
    • Vérifiez hasNext() avant de lire, pour éviter de dépasser la fin du fichier.
    • Dans la FRQ, lisez attentivement l'en-tête de la méthode : faites correspondre le type de retour et les paramètres exactement.

Log in or create account · ⁨Se connecter ou créer un compte⁩

IGCSE, A-Level & AP