Java Fundamentals

Java Syntax and IDE Setup

Lecture 3

IntelliJ IDEA, Java syntax, types, operators, and encapsulation

Main.java public class Main { public static void main( String[] args) { System.out.println( " Hello, World! "); } }

Recap: What We've Learned

In the previous lectures, we covered:

  • Lecture 1: OOP concepts, classes, objects, and UML class diagrams
  • Lecture 2: Behavioral diagrams (Use Case, Activity, Sequence)
Today: We write our first Java code! Setting up IntelliJ and learning Java syntax.

Quick Review: Class Relationships

classDiagram
    direction TB
    A -- B : Association
    C o-- D : Aggregation
    E *-- F : Composition
    G <|-- H : Inheritance
            
Association (--) "uses" or "knows about"
Aggregation (o--) "has" - parts can exist independently
Composition (*--) "owns" - parts cannot exist alone
Inheritance (<|--) "is a" - child extends parent

Our Development Tool: IntelliJ IDEA

IntelliJ IDEA is one of the most popular Java IDEs (Integrated Development Environment):

  • Intelligent code completion - suggests methods and properties as you type
  • Real-time error detection - catches mistakes before you run
  • Powerful refactoring - safely rename and restructure code
  • Built-in debugger - step through code line by line
  • Version control - integrated Git support
Download: IntelliJ IDEA Community Edition (free) at jetbrains.com/idea

IntelliJ IDEA Interface

  • Project View (left): Shows your project structure and files
  • Editor (center): Where you write code with intelligent completion
  • Tool Windows (bottom/right): Terminal, Run, Debug, Version Control

Key shortcuts:

Shift + ShiftSearch anything
Ctrl + SpaceCode completion
Alt + EnterQuick fixes and suggestions
Ctrl + /Comment/uncomment line
Shift + F10Run current program

Creating Your First Project

  1. Open IntelliJ IDEA
  2. Click New Project
  3. Select Java (left panel)
  4. Choose your JDK (Java 17+ recommended)
    • If no JDK listed, click "Download JDK" and select a version
  5. Name your project: JavaExercises
  6. Click Create
IntelliJ automatically creates a src folder for your source code.

Creating a Java Class

  1. Right-click on the src folder
  2. Select New → Java Class
  3. Enter: fr.wayup.exercises.HelloWorld
    • This creates a package fr.wayup.exercises and class HelloWorld
  4. Press Enter
package fr.wayup.exercises;

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

Click the green play button or press Shift+F10 to run!

Anatomy of a Java Class

package fr.wayup.exercises; 1

public class JavaSyntaxDemo { 2
    private String demoVersion = "1.0"; 3

    public JavaSyntaxDemo() { 4
        // Initialization code
    }

    public String getDemoVersion() { 5
        return this.demoVersion;
    }
}
1 Package - Namespace to organize classes
2 Class declaration - Blueprint for objects
3 Field - Property/attribute of the class
4 Constructor - Same name as class, no return type
5 Method - Behavior with return type

Basic Code Elements

  • Comments:
    // Single-line comment
    
    /* Multi-line comment
       spanning multiple lines */
    
    /** Javadoc comment - generates documentation */
  • Statements: End with semicolon ;
    int x = 10;  // Statement ends with semicolon
  • Blocks: Grouped with curly braces { }
    if (x > 5) {
        System.out.println("x is greater than 5");
    }

Packages and Imports

Packages organize your classes and prevent naming conflicts:

package fr.wayup.banking;  // This class belongs to this package

import java.util.ArrayList;  // Import a specific class
import java.time.*;          // Import all classes from a package

public class Account {
    private ArrayList transactions;
    private LocalDate openDate;
}
  • Package names follow reverse domain convention: com.company.project
  • Package structure matches folder structure on disk
  • java.lang is imported automatically (String, System, etc.)

Two Kinds of Types in Java

Primitive Types Reference Types (Objects)
Built into the language Created from classes
Stored directly in memory Stored as references (pointers)
Lowercase names: int, double Uppercase names: String, ArrayList
Have default values (0, false) Default to null
Cannot be null Can be null
int count = 10;              // Primitive
String message = "Hello";    // Reference (Object)

Primitive Types: Integers

Type Size Range Example
byte 1 byte -128 to 127 byte b = 100;
short 2 bytes -32,768 to 32,767 short s = 1000;
int 4 bytes ±2.1 billion int i = 100000;
long 8 bytes ±9.2 quintillion long l = 100000L;
Most common: Use int for most integer values. Use long with L suffix for large numbers.

Primitive Types: Floating Point

Type Size Precision Example
float 4 bytes ~7 decimal digits float f = 3.14f;
double 8 bytes ~15 decimal digits double d = 3.14159;
float price = 19.99f;      // Note the 'f' suffix
double pi = 3.14159265359; // Default for decimals
double scientific = 1.5e10; // Scientific notation: 1.5 × 10^10
Most common: Use double for decimal numbers (it's the default).

Primitive Types: Boolean and Char

Type Size Values Example
boolean 1 bit* true or false boolean active = true;
char 2 bytes Unicode character char grade = 'A';
boolean isLoggedIn = false;
boolean hasPermission = true;

char firstLetter = 'A';       // Single quotes for char
char unicode = '\u0041';      // Unicode: also 'A'
char newline = '\n';          // Escape character
Note: char uses single quotes 'A', while String uses double quotes "Hello"

The String Type

String is a reference type (object), but it's used so often it has special syntax:

// String creation
String greeting = "Hello, World!";  // String literal
String name = new String("Alice");  // Using constructor (rarely needed)

// String operations
String fullName = "John" + " " + "Doe";  // Concatenation
int length = greeting.length();          // 13
String upper = greeting.toUpperCase();   // "HELLO, WORLD!"
boolean starts = greeting.startsWith("Hello"); // true
String sub = greeting.substring(0, 5);   // "Hello"
Important: Strings are immutable - methods return new strings, they don't modify the original.

Local Variable Type Inference: var

Since Java 10, you can use var to let the compiler infer the type:

// Traditional declarations
String message = "Hello";
ArrayList<String> names = new ArrayList<String>();
Map<String, List<Integer>> data = new HashMap<String, List<Integer>>();

// With var - compiler infers the type
var message = "Hello";                    // Inferred as String
var names = new ArrayList<String>();      // Inferred as ArrayList<String>
var data = new HashMap<String, List<Integer>>();  // Much cleaner!
Note: var only works for local variables with initializers. Not for fields, parameters, or return types.

When to Use var

Good Uses

// Type is obvious from right side
var count = 0;
var name = "Alice";
var list = new ArrayList<String>();

// Long generic types
var map = new HashMap<String, List<Integer>>();

// With streams
var filtered = names.stream()
    .filter(n -> n.startsWith("A"))
    .toList();

Avoid

// Type not clear
var result = getResult();  // What type?
var x = calculate();       // Unclear

// Numeric literals
var num = 3.14;  // double or float?
var id = 100;    // int or long?

// Diamond with var (fails)
var list = new ArrayList<>();  // Error!

var Best Practices

RuleExample
Use meaningful variable names var customerList = getCustomers(); (type clear from name)
Use when type is on the right side var scanner = new Scanner(System.in);
Avoid with primitive literals Use int count = 0; not var count = 0;
Great for loop variables for (var item : collection) { ... }
Remember: var is about reducing verbosity, not hiding types. If the type isn't obvious, use explicit declaration.

Arithmetic Operators

OperatorDescriptionExampleResult
+Addition5 + 38
-Subtraction5 - 32
*Multiplication5 * 315
/Division5 / 31 (integer!)
%Modulo (remainder)5 % 32
int a = 10, b = 3;
System.out.println(a / b);    // 3 (integer division!)
System.out.println(a % b);    // 1 (remainder)
System.out.println(10.0 / 3); // 3.333... (double division)

Increment and Compound Operators

int i = 10;

// Increment / Decrement
i++;      // i is now 11 (post-increment)
++i;      // i is now 12 (pre-increment)
i--;      // i is now 11

// Compound assignment operators
i += 5;   // Same as: i = i + 5  → i is 16
i -= 3;   // Same as: i = i - 3  → i is 13
i *= 2;   // Same as: i = i * 2  → i is 26
i /= 2;   // Same as: i = i / 2  → i is 13

// Pre vs Post increment
int a = 5;
int b = a++;  // b = 5, a = 6 (use then increment)
int c = ++a;  // c = 7, a = 7 (increment then use)

Comparison Operators

OperatorDescriptionExampleResult
==Equal to5 == 5true
!=Not equal to5 != 3true
>Greater than5 > 3true
<Less than5 < 3false
>=Greater or equal5 >= 5true
<=Less or equal5 <= 3false
For Strings: Use .equals() instead of ==!
String a = "hello";
a.equals("hello")  // true - correct way
a == "hello"       // may be false - compares references!

Logical Operators

OperatorDescriptionExampleResult
&&ANDtrue && falsefalse
||ORtrue || falsetrue
!NOT!truefalse
int age = 25;
boolean hasLicense = true;

// Combining conditions
boolean canDrive = age >= 18 && hasLicense;  // true
boolean isMinorOrNoLicense = age < 18 || !hasLicense; // false

// Short-circuit evaluation
if (name != null && name.length() > 0) {
    // Safe: second part only evaluated if first is true
}

Access Modifiers

Access modifiers control who can see and use your classes, fields, and methods:

Modifier Class Package Subclass World
public
protected
(default)
private
Best practice: Start with private, then widen access only when needed.

Access Modifiers: Example

public class BankAccount {
    public String accountNumber;    // Accessible from anywhere
    protected double balance;       // Package + subclasses
    String bankName;                // Default: package only
    private String pin;             // Only within this class

    public void deposit(double amount) {  // Public method
        if (amount > 0) {
            this.balance += amount;
            logTransaction("Deposit: " + amount);
        }
    }

    private void logTransaction(String msg) {  // Private helper
        System.out.println(msg);
    }
}

Encapsulation: Protecting Your Data

Encapsulation = hiding internal details and providing controlled access.

classDiagram
    class BankAccount {
        -double balance
        -String pin
        +getBalance() double
        +deposit(amount) void
        +withdraw(amount) boolean
    }
                

- = private, + = public

  • Problem: Public fields can be set to invalid values
  • Solution: Make fields private, provide getters/setters

Getters and Setters

public class BankAccount {
    private double balance;  // Private field

    // Getter - read access
    public double getBalance() {
        return this.balance;
    }

    // Setter - controlled write access
    public void setBalance(double balance) {
        if (balance >= 0) {  // Validation!
            this.balance = balance;
        } else {
            throw new IllegalArgumentException("Balance cannot be negative");
        }
    }
}
  • Getter: getFieldName() - returns the value
  • Setter: setFieldName(value) - sets with validation

Complete Encapsulation Example

public class Customer {
    private String name;
    private String email;

    public Customer(String name, String email) {
        setName(name);   // Use setters for validation
        setEmail(email);
    }

    public String getName() { return name; }
    public void setName(String name) {
        if (name != null && !name.isEmpty()) {
            this.name = name;
        }
    }

    public String getEmail() { return email; }
    public void setEmail(String email) {
        if (email != null && email.contains("@")) {
            this.email = email;
        }
    }
}

Type Casting

Converting values from one type to another:

  • Widening (automatic): smaller → larger type, no data loss
    int myInt = 100;
    double myDouble = myInt;  // Automatic: 100.0
  • Narrowing (manual): larger → smaller type, possible data loss
    double myDouble = 9.78;
    int myInt = (int) myDouble;  // Cast required: 9
Widening order: byte → short → int → long → float → double

Type Casting Examples

// Widening - automatic, safe
byte b = 10;
int i = b;       // OK
long l = i;      // OK
double d = l;    // OK

// Narrowing - requires cast, may lose data
double price = 19.99;
int roundedPrice = (int) price;  // 19 (decimal lost)

long bigNumber = 10_000_000_000L;
int smaller = (int) bigNumber;   // OVERFLOW! Wrong value

// String conversions
int age = Integer.parseInt("25");
double salary = Double.parseDouble("50000.50");
String ageStr = String.valueOf(age);  // "25"
String concat = "" + age;             // "25" (quick way)

Exercise 1: Create the Bank Classes

Create Java classes based on this class diagram:

classDiagram
    direction LR
    class Customer {
        -String name
        -String address
    }
    class Account {
        -String accountNumber
        -double balance
    }
    class SavingsAccount {
        -double interestRate
    }
    class InvestmentAccount

    Customer "1" -- "0..*" Account
    Account <|-- SavingsAccount
    Account <|-- InvestmentAccount
            

Exercise 1: Tasks

For each class in the diagram, implement:

  1. Private fields as shown in the diagram
  2. Constructor to initialize all fields
  3. Getters and setters for each field with validation
Hints:
  • SavingsAccount and InvestmentAccount extend Account
  • A Customer can have multiple accounts (0 or more)
  • Use ArrayList<Account> in Customer to store accounts

Exercise 2: Add Behavior

Add the following methods to your SavingsAccount class:

  1. deposit(double amount)
    • Add amount to balance (must be positive)
  2. withdraw(double amount)
    • Subtract amount from balance (cannot go below 0)
  3. computeInterest()
    • Return: balance × interestRate
  4. applyInterest()
    • Add computed interest to balance
Remember: Validate inputs in your setters and methods!

Key Takeaways

  • IntelliJ IDEA is our development environment
    • Projects contain packages, packages contain classes
  • Two type kinds: primitives (int, double) and objects (String)
  • Operators: arithmetic, comparison, logical, assignment
  • Access modifiers: private → default → protectedpublic
  • Encapsulation: private fields + public getters/setters
  • Type casting: widening (auto) vs narrowing (manual)
Next lecture: JVM, compilation process, and control flow (if/switch)

Slide Overview