Skip to content

TD1 — VSCodium, Maven & First Java Classes

← Part 1 Overview

S7 Inf A3 — Java for Graphical and Mobile Programming
Stéphane Derrode — Centrale Lyon
Part 1 — Java Fundamentals
Duration: 2h · Pair or individual work


Objectives

By the end of this session you will be able to:

  • Create and run a Maven project in VSCodium
  • Write Java classes with private fields, constructors, getters and setters
  • Instantiate objects, call methods, and use toString()
  • Understand the difference between == and .equals()
  • Work with arrays of objects

Part 0 — Environment Setup

This part should already be done before the session.
Follow the VSCodium & Maven Setup Tutorial available on the course website. It walks you through installing JDK 17, Maven, VSCodium, and the Java Extension Pack step by step.

If you have any problem with installation, come 10 minutes early and we will sort it out.

Quick check — open a terminal inside VSCodium and verify:

java -version     # openjdk 17.x.x
mvn -version      # Apache Maven 3.x.x

Part 1 — Create the Maven Project (10 min)

1.1 Create the project

In VSCodium, press Ctrl+Shift+P → type Maven: Create Maven Project → select:

  • Archetype: maven-archetype-quickstart, version 1.5
  • Group Id: com.s7infa3
  • Artifact Id: td1

Then File ▸ Open Folder… and select the td1/ folder that was just created.

1.2 Configure Java 17

Replace the content of pom.xml with:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.s7infa3</groupId>
  <artifactId>td1</artifactId>
  <version>1.0</version>
  <properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
</project>

Save (Ctrl+S). Then open src/main/java/com/s7infa3/App.java, click ▶ Run above main() — you should see Hello World!.


Part 2 — Class Car (45 min)

This Car class is the running example for the whole of Part 1 — it grows in TD2 (collections, file I/O) and TD3 (inheritance).

2.1 UML specification

┌────────────────────────────────────────────┐
│                    Car                      │
├────────────────────────────────────────────┤
│ - model   : String                          │
│ - power   : int                             │
│ - started : boolean                         │
│ - speed   : double                          │
├────────────────────────────────────────────┤
│ + Car(String model, int power)              │
│ + Car(String model)                         │
│ + getModel()  : String                      │
│ + getPower()  : int                         │
│ + getSpeed()  : double                      │
│ + isStarted() : boolean                     │
│ + maxSpeed()  : int                         │
│ + start()  : void                           │
│ + stop()   : void                           │
│ + accelerate(double delta) : void           │
│ + brake(double delta)      : void           │
│ + equals(Object obj) : boolean              │
│ + hashCode() : int                          │
│ + toString() : String                       │
└────────────────────────────────────────────┘

2.2 Behaviour rules

Method Behaviour
Car(String model, int power) Stores model. If power > 0, power = power; otherwise power = 70. Always: started = false, speed = 0.0
Car(String model) Delegate to Car(model, 70) using this(model, 70)
maxSpeed() Returns 80 + power (top speed grows with engine power)
start() Sets started = true
stop() Sets started = false and speed = 0.0
accelerate(double delta) Only if started and delta > 0: speed = min(speed + delta, maxSpeed())
brake(double delta) Only if delta > 0: speed = max(0.0, speed - delta)
equals(Object obj) Two Car are equal if they have the same model and same power
toString() Returns "Car[Clio, 90hp, on, 60 km/h]"

2.3 Skeleton to complete

Create src/main/java/com/s7infa3/Car.java:

package com.s7infa3;

import java.util.Objects;

public class Car {

    // TODO: declare the 4 private fields (model is final)

    public Car(String model, int power) {
        // TODO
    }

    public Car(String model) {
        this(model, 70); // delegates to Car(String, int)
    }

    public String  getModel()  { /* TODO */ return ""; }
    public int     getPower()  { /* TODO */ return 0; }
    public double  getSpeed()  { /* TODO */ return 0; }
    public boolean isStarted() { /* TODO */ return false; }
    public int     maxSpeed()  { /* TODO: 80 + power */ return 0; }

    public void start() { /* TODO */ }
    public void stop()  { /* TODO */ }

    public void accelerate(double delta) {
        // TODO: only if started && delta > 0, capped at maxSpeed()
    }

    public void brake(double delta) {
        // TODO: never below 0
    }

    @Override
    public boolean equals(Object obj) {
        // TODO: true if obj is a Car with same model and power
        return false;
    }

    @Override
    public int hashCode() {
        return Objects.hash(model, power);
    }

    @Override
    public String toString() {
        // TODO: "Car[Clio, 90hp, on, 60 km/h]"
        return "";
    }
}

2.4 Test in App.java

Replace App.java with the following and verify every printed value:

package com.s7infa3;

public class App {
    public static void main(String[] args) {

        // Basic usage
        Car clio = new Car("Clio", 90);
        clio.start();
        clio.accelerate(50);
        clio.accelerate(30);
        System.out.println(clio);
        // Car[Clio, 90hp, on, 80 km/h]

        // brake() never goes below 0
        clio.brake(20);
        System.out.println(clio);
        // Car[Clio, 90hp, on, 60 km/h]

        // top speed is capped at maxSpeed() = 80 + 90 = 170
        clio.accelerate(500);
        System.out.println(clio.getSpeed());   // 170.0

        // accelerate() has no effect if not started
        Car polo = new Car("Polo", 110);
        polo.accelerate(50);
        System.out.println(polo.getSpeed());   // 0.0

        // stop() resets the speed
        clio.stop();
        System.out.println(clio);
        // Car[Clio, 90hp, off, 0 km/h]

        // Invalid power → defaults to 70
        Car mystery = new Car("Mystery", -10);
        System.out.println(mystery.getPower()); // 70

        // One-argument constructor (delegates with this(...))
        Car twingo = new Car("Twingo");
        System.out.println(twingo.getPower());  // 70

        // == vs equals()
        Car clio2 = new Car("Clio", 90);
        System.out.println(clio == clio2);       // false (different objects)
        System.out.println(clio.equals(clio2));  // true  (same model + power)
    }
}

Part 3 — Array of Objects: class Garage (25 min)

A Garage manages a fixed-size fleet of Car objects using a plain array (not ArrayList — that is CM2).

3.1 Specification

Create src/main/java/com/s7infa3/Garage.java:

Member Description
Garage(int capacity) Creates an array of capacity slots (all null initially)
add(Car c) Adds c to the next free slot; silently ignores if full
size() Returns the number of cars currently stored
getAt(int i) Returns the car at index i; throws IllegalArgumentException if out of range
startAll() Calls start() on every stored car
toString() Returns one car per line

3.2 Skeleton

package com.s7infa3;

public class Garage {
    private Car[] cars;
    private int count;

    public Garage(int capacity) {
        // TODO
    }

    public void add(Car c) {
        // TODO: add only if count < cars.length
    }

    public int size() { /* TODO */ return 0; }

    public Car getAt(int i) {
        // TODO: throw IllegalArgumentException if i < 0 or i >= count
        return null;
    }

    public void startAll() {
        // TODO: loop over the count stored cars
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        // TODO: append each car + newline
        return sb.toString();
    }
}

3.3 Test

Add to the end of main():

System.out.println("\n--- Garage ---");
Garage garage = new Garage(5);
garage.add(new Car("Clio", 90));
garage.add(new Car("Polo", 110));
garage.add(new Car("Ferrari", 280));

System.out.println("Size: " + garage.size());  // 3
garage.startAll();
System.out.println(garage.getAt(0));
// Car[Clio, 90hp, on, 0 km/h]
System.out.println(garage);

try {
    garage.getAt(10);
} catch (IllegalArgumentException e) {
    System.out.println("Caught: " + e.getMessage());
}

Part 4 — Exploration (remaining time)

4.1 Add a private static int carsCreated = 0 counter to Car, incremented in every constructor. Add public static int getCarsCreated(). Test that after creating 5 cars the counter returns 5.

4.2 Add a cruiseAt(double v) method: set the speed directly to v, but only if the car is started and 0 <= v <= maxSpeed(). If v < 0, throw IllegalArgumentException.

4.3 You already override both equals() and hashCode(). Why is it important to override them together? (Hint: think of HashMap<Car, String> — what happens if two equal cars return different hash codes?)


Deliverable

No formal submission for TD1. Verify all outputs match the expected values before leaving.
Keep this project — it will be extended in TD2.


Common Errors

Error Cause Fix
cannot find symbol Typo or missing import Check spelling; Ctrl+. in VSCodium to auto-fix
incompatible types Wrong type assigned Check declared type matches the value
NullPointerException Array slot is null Make sure count tracks filled slots correctly
ArrayIndexOutOfBoundsException Index out of range Guard with i >= 0 && i < count in getAt()
accelerate() has no visible effect Car not started Call start() before accelerate()
Speed never exceeds a ceiling That is maxSpeed() doing its job Expected — accelerate() is capped at 80 + power