Programmation Orientee Objets Java
PARTIE A : GENERALITES
Presentation
Le cours de "Programmation Orientee Objets Java" a fourni une formation complete en programmation orientee objet avec Java. En tant que l'un des langages de programmation les plus populaires pour les applications d'entreprise, les services web et le developpement Android, l'independance de plateforme de Java et son ecosysteme etendu en font un langage essentiel pour le developpement logiciel moderne.
Annee Universitaire : 2023-2024
Semestre : 7
Categorie : Programmation
PARTIE B : PARTIE DESCRIPTIVE
Details de l'experience
Environnement et contexte
Le cours couvrait les fondamentaux de Java jusqu'aux sujets avances, incluant les principes orientes objet, la gestion des exceptions, le framework de collections, le multithreading et le developpement d'interfaces graphiques. Nous avons utilise des IDE professionnels comme Eclipse et IntelliJ IDEA pour le developpement et pratique les principes du developpement dirige par les tests (TDD).
Ma fonction
Dans ce cours, j'etais responsable de :
- Comprendre la syntaxe Java et les concepts orientes objet
- Implementer des classes, interfaces et hierarchies d'heritage
- Utiliser efficacement le Java Collections Framework
- Developper des applications multithreadees
- Creer des interfaces graphiques avec Swing/JavaFX
- Gerer les exceptions et les ressources
- Ecrire des tests unitaires avec JUnit
- Travailler avec les API d'E/S et de reseau Java
PARTIE C : PARTIE TECHNIQUE
Cette section explore les aspects techniques de la programmation Java et du developpement oriente objet.
Concepts techniques appris
1. Fondamentaux Java et bases de la POO
Structure de classe :
public class BankAccount {
// Variables d'instance (private pour l'encapsulation)
private String accountNumber;
private double balance;
private String owner;
// Constructeur
public BankAccount(String accountNumber, String owner) {
this.accountNumber = accountNumber;
this.owner = owner;
this.balance = 0.0;
}
// Methodes
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("Deposited: " + amount);
}
}
public boolean withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
return true;
}
return false;
}
// Getters
public double getBalance() {
return balance;
}
public String getAccountNumber() {
return accountNumber;
}
}
Principes cles de la POO :
- Encapsulation : Masquage des donnees avec des champs prives et des methodes publiques
- Heritage : Reutilisation du code par des hierarchies de classes
- Polymorphisme : Dispatch dynamique de methodes
- Abstraction : Masquage des details d'implementation
2. Heritage et interfaces
Exemple d'heritage :
public abstract class Animal {
protected String name;
protected int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
// Methode abstraite (doit etre implementee par les sous-classes)
public abstract void makeSound();
// Methode concrete
public void sleep() {
System.out.println(name + " is sleeping");
}
}
public class Dog extends Animal {
private String breed;
public Dog(String name, int age, String breed) {
super(name, age); // Appel au constructeur parent
this.breed = breed;
}
@Override
public void makeSound() {
System.out.println("Woof! Woof!");
}
public void fetch() {
System.out.println(name + " is fetching");
}
}
Interfaces :
public interface Drawable {
void draw();
default void display() { // Methode par defaut (Java 8+)
System.out.println("Displaying drawable object");
}
}
public interface Resizable {
void resize(double factor);
}
public class Circle implements Drawable, Resizable {
private double radius;
@Override
public void draw() {
System.out.println("Drawing a circle");
}
@Override
public void resize(double factor) {
radius *= factor;
}
}
Interface vs Classe abstraite :
- Interfaces : Heritage multiple, definition de contrat
- Classes abstraites : Implementation partielle, etat partage
3. Gestion des exceptions
Gestion robuste des erreurs en Java :
public class FileProcessor {
public String readFile(String filename) throws IOException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(filename));
StringBuilder content = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
content.append(line).append("\n");
}
return content.toString();
} catch (FileNotFoundException e) {
System.err.println("File not found: " + filename);
throw e;
} catch (IOException e) {
System.err.println("Error reading file: " + e.getMessage());
throw e;
} finally {
// Toujours execute, meme si une exception survient
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
System.err.println("Error closing file");
}
}
}
}
// Try-with-resources (Java 7+)
public String readFileModern(String filename) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
StringBuilder content = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
content.append(line).append("\n");
}
return content.toString();
}
// reader.close() appele automatiquement
}
}
// Exception personnalisee
public class InsufficientFundsException extends Exception {
private double amount;
public InsufficientFundsException(double amount) {
super("Insufficient funds: " + amount);
this.amount = amount;
}
public double getAmount() {
return amount;
}
}
4. Framework de collections
Structures de donnees et algorithmes puissants :
import java.util.*;
public class CollectionsDemo {
public void demonstrateCollections() {
// List (ordonnee, autorise les doublons)
List<String> arrayList = new ArrayList<>();
arrayList.add("Apple");
arrayList.add("Banana");
arrayList.add("Apple"); // Doublon autorise
List<String> linkedList = new LinkedList<>();
// Set (pas de doublons)
Set<String> hashSet = new HashSet<>();
hashSet.add("Apple");
hashSet.add("Banana");
hashSet.add("Apple"); // Ignore
// La taille sera 2
Set<String> treeSet = new TreeSet<>(); // Trie
// Map (paires cle-valeur)
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("Alice", 25);
hashMap.put("Bob", 30);
hashMap.put("Charlie", 28);
// Iteration
for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// Queue (file d'attente)
Queue<String> queue = new LinkedList<>();
queue.offer("First");
queue.offer("Second");
String first = queue.poll(); // Retire et retourne "First"
// File de priorite
PriorityQueue<Integer> pq = new PriorityQueue<>();
pq.offer(5);
pq.offer(2);
pq.offer(8);
System.out.println(pq.poll()); // Retourne 2 (le plus petit)
}
}
Comparateurs et tri :
public class Student {
private String name;
private double gpa;
// Constructeur, getters, setters...
}
// Tri avec Comparator
List<Student> students = new ArrayList<>();
// Ajouter des etudiants...
// Trier par GPA (decroissant)
students.sort((s1, s2) -> Double.compare(s2.getGpa(), s1.getGpa()));
// Ou en utilisant Comparator
students.sort(Comparator.comparingDouble(Student::getGpa).reversed());
5. Generiques
Programmation type-safe :
public class Box<T> {
private T content;
public void set(T content) {
this.content = content;
}
public T get() {
return content;
}
}
// Utilisation
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String value = stringBox.get(); // Pas de cast necessaire
// Methode generique
public <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
// Parametres de type bornes
public <T extends Comparable<T>> T findMax(T[] array) {
T max = array[0];
for (T element : array) {
if (element.compareTo(max) > 0) {
max = element;
}
}
return max;
}
6. Multithreading
Programmation concurrente en Java :
// Extension de la classe Thread
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// Implementation de l'interface Runnable
public class MyRunnable implements Runnable {
@Override
public void run() {
// Code de la tache
}
}
// Utilisation d'ExecutorService
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executor.submit(new MyRunnable());
}
executor.shutdown();
Synchronisation :
public class Counter {
private int count = 0;
// Methode synchronisee
public synchronized void increment() {
count++;
}
// Bloc synchronise
public void incrementBlock() {
synchronized(this) {
count++;
}
}
public int getCount() {
return count;
}
}
7. Expressions lambda et Streams (Java 8+)
Fonctionnalites de programmation fonctionnelle :
// Expressions lambda
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
// Ancienne methode
for (String name : names) {
System.out.println(name);
}
// Avec lambda
names.forEach(name -> System.out.println(name));
// Ou reference de methode
names.forEach(System.out::println);
// Streams
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// Filtrer, transformer et collecter
List<Integer> evenSquares = numbers.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.collect(Collectors.toList());
// Resultat : [4, 16, 36, 64, 100]
// Somme avec reduce
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
// Grouper par
Map<Integer, List<String>> groupedByLength = names.stream()
.collect(Collectors.groupingBy(String::length));
8. E/S de fichiers et serialisation
Travail avec les fichiers et la persistance des donnees :
import java.io.*;
import java.nio.file.*;
// Lecture depuis un fichier
public List<String> readLines(String filename) throws IOException {
return Files.readAllLines(Paths.get(filename));
}
// Ecriture dans un fichier
public void writeLines(String filename, List<String> lines) throws IOException {
Files.write(Paths.get(filename), lines);
}
// Serialisation
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
// Constructeur, getters, setters...
}
// Sauvegarder un objet
public void saveObject(Person person, String filename) throws IOException {
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(filename))) {
oos.writeObject(person);
}
}
// Charger un objet
public Person loadObject(String filename) throws IOException, ClassNotFoundException {
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(filename))) {
return (Person) ois.readObject();
}
}
9. Developpement d'interfaces graphiques avec Swing
Creation d'interfaces utilisateur graphiques :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SimpleCalculator extends JFrame {
private JTextField display;
private double result = 0;
private String operator = "=";
private boolean startNewNumber = true;
public SimpleCalculator() {
setTitle("Calculator");
setSize(300, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Creer l'affichage
display = new JTextField("0");
display.setEditable(false);
display.setHorizontalAlignment(JTextField.RIGHT);
add(display, BorderLayout.NORTH);
// Creer le panneau de boutons
JPanel buttonPanel = new JPanel(new GridLayout(4, 4));
String[] buttons = {
"7", "8", "9", "/",
"4", "5", "6", "*",
"1", "2", "3", "-",
"0", ".", "=", "+"
};
for (String text : buttons) {
JButton button = new JButton(text);
button.addActionListener(new ButtonClickListener());
buttonPanel.add(button);
}
add(buttonPanel, BorderLayout.CENTER);
}
private class ButtonClickListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
// Logique de gestion du clic...
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
SimpleCalculator calc = new SimpleCalculator();
calc.setVisible(true);
});
}
}
10. Tests unitaires avec JUnit
Developpement dirige par les tests :
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
public class CalculatorTest {
private Calculator calculator;
@BeforeEach
public void setUp() {
calculator = new Calculator();
}
@Test
public void testAddition() {
assertEquals(5, calculator.add(2, 3));
assertEquals(-1, calculator.add(2, -3));
}
@Test
public void testDivision() {
assertEquals(2.0, calculator.divide(6, 3), 0.001);
}
@Test
public void testDivisionByZero() {
assertThrows(ArithmeticException.class, () -> {
calculator.divide(5, 0);
});
}
@AfterEach
public void tearDown() {
calculator = null;
}
}
PARTIE D : PARTIE ANALYTIQUE
Connaissances et competences mobilisees
- Comprehension de la syntaxe Java et des principes de la POO
- Implementation de hierarchies de classes et d'interfaces
- Utilisation efficace du Collections Framework
- Ecriture de code resistant aux exceptions
- Developpement d'applications multithreadees
- Creation d'interfaces utilisateur graphiques
- Application de la programmation fonctionnelle avec les lambdas et les streams
- Ecriture de tests unitaires
- Travail avec les E/S de fichiers et la serialisation
- Utilisation des outils de developpement Java (IDE, debogueur, profileur)
Auto-evaluation
Apprendre Java apres le C et le C++ s'est fait relativement en douceur, car de nombreux concepts etaient familiers. Cependant, la gestion automatique de la memoire de Java (ramasse-miettes) constituait un changement de paradigme significatif. Ne pas avoir a gerer manuellement la memoire etait liberateur mais impliquait aussi moins de controle sur les performances.
Le Collections Framework est l'une des fonctionnalites les plus puissantes de Java. Apprendre quand utiliser ArrayList vs LinkedList, HashMap vs TreeMap, etc., necessitait de comprendre les compromis de complexite temporelle. L'API Stream et les expressions lambda ont rendu le code plus concis et lisible.
Le multithreading en Java etait un defi. Comprendre la synchronisation des threads, les interblocages et les conditions de concurrence necessitait une reflexion approfondie. Le package java.util.concurrent fournissait des outils puissants mais avait une courbe d'apprentissage abrupte.
Le developpement d'interfaces graphiques avec Swing etait interessant mais semblait quelque peu date compare aux frameworks UI modernes. La programmation evenementielle necessitait un etat d'esprit different. Construire des interfaces reactives tout en evitant de bloquer le thread principal etait une lecon precieuse.
Mon avis
Java est un excellent langage pour apprendre la POO et construire des applications d'entreprise. Sa philosophie "ecrire une fois, executer partout" est puissante, bien qu'en pratique, les differences de plateforme puissent encore causer des problemes. La bibliotheque standard etendue et l'ecosysteme de bibliotheques tierces rendent Java tres productif.
Le cours a fourni des bases solides en developpement Java. Ce que j'ai particulierement apprecie :
- Systeme de types fort empechant de nombreuses erreurs d'execution
- Documentation complete et grande communaute
- Excellent outillage (IDE, profileurs, debogueurs)
- Independance de plateforme
Axes d'amelioration :
- Plus de couverture des fonctionnalites modernes de Java (Java 11+)
- Patrons de conception et principes architecturaux
- Outils de build (Maven, Gradle)
- Introduction au Spring Framework
- Bases du developpement Android
La verbosite de Java comparee aux langages modernes peut etre fastidieuse (beaucoup de code boilerplate), mais cela s'ameliore avec les nouvelles versions de Java. Dans l'ensemble, Java reste pertinent et precieux pour le developpement logiciel professionnel, en particulier dans le developpement d'entreprise et Android.
Object-Oriented Programming Java
PART A: GENERALITIES
Presentation
The "Programmation Orientee Objets Java" course provided comprehensive training in object-oriented programming using Java. As one of the most popular programming languages for enterprise applications, web services, and Android development, Java's platform independence and extensive ecosystem make it essential for modern software development.
Academic Year: 2023-2024
Semester: 7
Category: Programming
PART B: DESCRIPTIVE PART
Experience Details
Environment and Context
The course covered Java fundamentals through advanced topics including object-oriented principles, exception handling, collections framework, multithreading, and GUI development. We used industry-standard IDEs like Eclipse and IntelliJ IDEA for development and practiced Test-Driven Development (TDD) principles.
My Function
In this course, I was responsible for:
- Understanding Java syntax and object-oriented concepts
- Implementing classes, interfaces, and inheritance hierarchies
- Using Java Collections Framework effectively
- Developing multithreaded applications
- Creating graphical user interfaces with Swing/JavaFX
- Handling exceptions and managing resources
- Writing unit tests with JUnit
- Working with Java I/O and networking APIs
PART C: TECHNICAL PART
This section explores the technical aspects of Java programming and object-oriented development.
Technical Concepts Learned
1. Java Fundamentals and OOP Basics
Class Structure:
public class BankAccount {
// Instance variables (private for encapsulation)
private String accountNumber;
private double balance;
private String owner;
// Constructor
public BankAccount(String accountNumber, String owner) {
this.accountNumber = accountNumber;
this.owner = owner;
this.balance = 0.0;
}
// Methods
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("Deposited: " + amount);
}
}
public boolean withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
return true;
}
return false;
}
// Getters
public double getBalance() {
return balance;
}
public String getAccountNumber() {
return accountNumber;
}
}
Key OOP Principles:
- Encapsulation: Data hiding using private fields and public methods
- Inheritance: Code reuse through class hierarchies
- Polymorphism: Dynamic method dispatch
- Abstraction: Hiding implementation details
2. Inheritance and Interfaces
Inheritance Example:
public abstract class Animal {
protected String name;
protected int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
// Abstract method (must be implemented by subclasses)
public abstract void makeSound();
// Concrete method
public void sleep() {
System.out.println(name + " is sleeping");
}
}
public class Dog extends Animal {
private String breed;
public Dog(String name, int age, String breed) {
super(name, age); // Call parent constructor
this.breed = breed;
}
@Override
public void makeSound() {
System.out.println("Woof! Woof!");
}
public void fetch() {
System.out.println(name + " is fetching");
}
}
Interfaces:
public interface Drawable {
void draw();
default void display() { // Default method (Java 8+)
System.out.println("Displaying drawable object");
}
}
public interface Resizable {
void resize(double factor);
}
public class Circle implements Drawable, Resizable {
private double radius;
@Override
public void draw() {
System.out.println("Drawing a circle");
}
@Override
public void resize(double factor) {
radius *= factor;
}
}
Interface vs Abstract Class:
- Interfaces: Multiple inheritance, contract definition
- Abstract classes: Partial implementation, shared state
3. Exception Handling
Robust error management in Java:
public class FileProcessor {
public String readFile(String filename) throws IOException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(filename));
StringBuilder content = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
content.append(line).append("\n");
}
return content.toString();
} catch (FileNotFoundException e) {
System.err.println("File not found: " + filename);
throw e;
} catch (IOException e) {
System.err.println("Error reading file: " + e.getMessage());
throw e;
} finally {
// Always executed, even if exception occurs
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
System.err.println("Error closing file");
}
}
}
}
// Try-with-resources (Java 7+)
public String readFileModern(String filename) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
StringBuilder content = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
content.append(line).append("\n");
}
return content.toString();
}
// reader.close() called automatically
}
}
// Custom exception
public class InsufficientFundsException extends Exception {
private double amount;
public InsufficientFundsException(double amount) {
super("Insufficient funds: " + amount);
this.amount = amount;
}
public double getAmount() {
return amount;
}
}
4. Collections Framework
Powerful data structures and algorithms:
import java.util.*;
public class CollectionsDemo {
public void demonstrateCollections() {
// List (ordered, allows duplicates)
List<String> arrayList = new ArrayList<>();
arrayList.add("Apple");
arrayList.add("Banana");
arrayList.add("Apple"); // Duplicate allowed
List<String> linkedList = new LinkedList<>();
// Set (no duplicates)
Set<String> hashSet = new HashSet<>();
hashSet.add("Apple");
hashSet.add("Banana");
hashSet.add("Apple"); // Ignored
// Size will be 2
Set<String> treeSet = new TreeSet<>(); // Sorted
// Map (key-value pairs)
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("Alice", 25);
hashMap.put("Bob", 30);
hashMap.put("Charlie", 28);
// Iteration
for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// Queue
Queue<String> queue = new LinkedList<>();
queue.offer("First");
queue.offer("Second");
String first = queue.poll(); // Removes and returns "First"
// Priority Queue
PriorityQueue<Integer> pq = new PriorityQueue<>();
pq.offer(5);
pq.offer(2);
pq.offer(8);
System.out.println(pq.poll()); // Returns 2 (smallest)
}
}
Comparators and Sorting:
public class Student {
private String name;
private double gpa;
// Constructor, getters, setters...
}
// Sorting with Comparator
List<Student> students = new ArrayList<>();
// Add students...
// Sort by GPA (descending)
students.sort((s1, s2) -> Double.compare(s2.getGpa(), s1.getGpa()));
// Or using Comparator
students.sort(Comparator.comparingDouble(Student::getGpa).reversed());
5. Generics
Type-safe programming:
public class Box<T> {
private T content;
public void set(T content) {
this.content = content;
}
public T get() {
return content;
}
}
// Usage
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String value = stringBox.get(); // No casting needed
// Generic method
public <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
// Bounded type parameters
public <T extends Comparable<T>> T findMax(T[] array) {
T max = array[0];
for (T element : array) {
if (element.compareTo(max) > 0) {
max = element;
}
}
return max;
}
6. Multithreading
Concurrent programming in Java:
// Extending Thread class
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
// Implementing Runnable interface
public class MyRunnable implements Runnable {
@Override
public void run() {
// Task code
}
}
// Using ExecutorService
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executor.submit(new MyRunnable());
}
executor.shutdown();
Synchronization:
public class Counter {
private int count = 0;
// Synchronized method
public synchronized void increment() {
count++;
}
// Synchronized block
public void incrementBlock() {
synchronized(this) {
count++;
}
}
public int getCount() {
return count;
}
}
7. Lambda Expressions and Streams (Java 8+)
Functional programming features:
// Lambda expressions
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
// Old way
for (String name : names) {
System.out.println(name);
}
// With lambda
names.forEach(name -> System.out.println(name));
// Or method reference
names.forEach(System.out::println);
// Streams
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// Filter, map, and collect
List<Integer> evenSquares = numbers.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.collect(Collectors.toList());
// Result: [4, 16, 36, 64, 100]
// Sum with reduce
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
// Group by
Map<Integer, List<String>> groupedByLength = names.stream()
.collect(Collectors.groupingBy(String::length));
8. File I/O and Serialization
Working with files and data persistence:
import java.io.*;
import java.nio.file.*;
// Reading from file
public List<String> readLines(String filename) throws IOException {
return Files.readAllLines(Paths.get(filename));
}
// Writing to file
public void writeLines(String filename, List<String> lines) throws IOException {
Files.write(Paths.get(filename), lines);
}
// Serialization
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
// Constructor, getters, setters...
}
// Save object
public void saveObject(Person person, String filename) throws IOException {
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(filename))) {
oos.writeObject(person);
}
}
// Load object
public Person loadObject(String filename) throws IOException, ClassNotFoundException {
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(filename))) {
return (Person) ois.readObject();
}
}
9. GUI Development with Swing
Creating graphical user interfaces:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SimpleCalculator extends JFrame {
private JTextField display;
private double result = 0;
private String operator = "=";
private boolean startNewNumber = true;
public SimpleCalculator() {
setTitle("Calculator");
setSize(300, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create display
display = new JTextField("0");
display.setEditable(false);
display.setHorizontalAlignment(JTextField.RIGHT);
add(display, BorderLayout.NORTH);
// Create button panel
JPanel buttonPanel = new JPanel(new GridLayout(4, 4));
String[] buttons = {
"7", "8", "9", "/",
"4", "5", "6", "*",
"1", "2", "3", "-",
"0", ".", "=", "+"
};
for (String text : buttons) {
JButton button = new JButton(text);
button.addActionListener(new ButtonClickListener());
buttonPanel.add(button);
}
add(buttonPanel, BorderLayout.CENTER);
}
private class ButtonClickListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
// Handle button click logic...
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
SimpleCalculator calc = new SimpleCalculator();
calc.setVisible(true);
});
}
}
10. Unit Testing with JUnit
Test-driven development:
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
public class CalculatorTest {
private Calculator calculator;
@BeforeEach
public void setUp() {
calculator = new Calculator();
}
@Test
public void testAddition() {
assertEquals(5, calculator.add(2, 3));
assertEquals(-1, calculator.add(2, -3));
}
@Test
public void testDivision() {
assertEquals(2.0, calculator.divide(6, 3), 0.001);
}
@Test
public void testDivisionByZero() {
assertThrows(ArithmeticException.class, () -> {
calculator.divide(5, 0);
});
}
@AfterEach
public void tearDown() {
calculator = null;
}
}
PART D: ANALYTICAL PART
Knowledge and Skills Mobilized
- Understanding Java syntax and OOP principles
- Implementing class hierarchies and interfaces
- Using Collections Framework effectively
- Writing exception-safe code
- Developing multithreaded applications
- Creating graphical user interfaces
- Applying functional programming with lambdas and streams
- Writing unit tests
- Working with file I/O and serialization
- Using Java development tools (IDE, debugger, profiler)
Self Evaluation
Learning Java after C and C++ was relatively smooth, as many concepts were familiar. However, Java's automatic memory management (garbage collection) was a significant paradigm shift. Not having to manually manage memory was liberating but also meant less control over performance.
The Collections Framework is one of Java's strongest features. Learning when to use ArrayList vs LinkedList, HashMap vs TreeMap, etc., required understanding time complexity trade-offs. The Stream API and lambda expressions made code more concise and readable.
Multithreading in Java was challenging. Understanding thread synchronization, deadlocks, and race conditions required careful thinking. The java.util.concurrent package provided powerful tools but had a steep learning curve.
GUI development with Swing was interesting but felt somewhat dated compared to modern UI frameworks. Event-driven programming required a different mindset. Building responsive UIs while avoiding freezing the main thread was a valuable lesson.
My Opinion
Java is an excellent language for learning OOP and building enterprise applications. Its "write once, run anywhere" philosophy is powerful, though in practice, platform differences can still cause issues. The extensive standard library and ecosystem of third-party libraries make Java very productive.
The course provided solid foundations in Java development. What I particularly appreciated:
- Strong type system preventing many runtime errors
- Comprehensive documentation and large community
- Excellent tooling (IDEs, profilers, debuggers)
- Platform independence
Areas for improvement:
- More coverage of modern Java features (Java 11+)
- Design patterns and architectural principles
- Build tools (Maven, Gradle)
- Spring Framework introduction
- Android development basics
Java's verbosity compared to modern languages can be tedious (lots of boilerplate), but this is improving with newer Java versions. Overall, Java remains relevant and valuable for professional software development, particularly in enterprise and Android development.