Skip to content

02 - First Real Program

What this session is

About 45 minutes. You'll learn variables, Java's primitive types, strings, and how Java handles text-with-values (text blocks and String.format/printf). By the end you'll have written a program that uses all three.

A small program with variables

Create a file Greet.java. Type:

public class Greet {
    public static void main(String[] args) {
        String name = "Alice";
        int age = 30;
        System.out.println(name + " is " + age + " years old");
    }
}

Compile and run:

javac Greet.java
java Greet

Output:

Alice is 30 years old

What's new

Two lines:

String name = "Alice";
int age = 30;
  • String name = "Alice"; - create a variable. String is the type; name is the name; = assigns; "Alice" is the value. Semicolon ends the statement.
  • int age = 30; - same for an integer.

The print line:

System.out.println(name + " is " + age + " years old");

+ between strings glues them together (called concatenation). When + sees a string on one side and a number on the other, it converts the number to a string and glues. Convenient - and also a source of bugs, as we'll see.

Java's type system: primitives vs everything else

Java has two kinds of types:

  1. Primitives. Built-in lowercase types that hold a single value directly. There are eight: byte, short, int, long, float, double, char, boolean.
  2. Reference types. Everything else - String, arrays, classes you define. Variables hold a reference to an object, not the object itself.

You'll meet references properly in page 05. For now, focus on the eight primitives.

The four primitives you'll actually use

Type Holds Example
int 32-bit whole number, ±2.1 billion range 42, -7, 1000
long 64-bit whole number, much larger range 42L, 1000000000000L
double 64-bit floating-point number 3.14, -0.5, 1.0
boolean true or false true, false

The other four (byte, short, float, char) exist for specific reasons; you'll meet them rarely. Use int for whole numbers, double for decimals, boolean for true/false. Use long if you need numbers bigger than 2.1 billion (timestamps, file sizes).

The L suffix on long literals: 42L means "the literal 42, treated as long." Otherwise 42 is an int and you get a compiler complaint when assigning to long.

Strings

String is a reference type, not a primitive - but it's so common that Java has special syntax for it. You write "hello" as a literal, and Java creates a String object.

String greeting = "hello";
String name = "world";
String message = greeting + ", " + name;
System.out.println(message);    // hello, world

Strings are immutable - once created, you can't change one. Operations that "modify" a string actually create a new one. (For long-running construction, use StringBuilder - we'll meet it when it matters.)

Type inference with var

Modern Java (10+) lets you skip the type when it's obvious:

var name = "Alice";    // Java infers String
var age = 30;          // Java infers int
var price = 19.99;     // Java infers double

var only works on local variables (inside methods). You can't use it on fields, parameters, or return types - those still need explicit types. The Java team's reasoning: var is convenient for locals but explicit types make APIs self-documenting.

Use var when the type is obvious from the right-hand side. Use the explicit type when it isn't.

Arithmetic

int x = 10;
int y = 3;
System.out.println(x + y);    // 13
System.out.println(x - y);    // 7
System.out.println(x * y);    // 30
System.out.println(x / y);    // 3   - integer division, drops remainder
System.out.println(x % y);    // 1   - modulo (remainder)

The // ... part is a comment - anything from // to end-of-line is ignored.

Integer division drops the remainder. 10 / 3 is 3, not 3.333.... To get the decimal, at least one operand must be a double:

double q = 10.0 / 3;
System.out.println(q);        // 3.3333333333333335

You can also explicitly cast an int to a double:

int a = 10, b = 3;
double q = (double) a / b;
System.out.println(q);        // 3.3333333333333335

The (double) is a cast - "treat a as a double for this expression." Without it you'd get integer division before the assignment.

Building strings: three ways

Way 1 - concatenation with +:

String name = "Alice";
int age = 30;
System.out.println(name + " is " + age + " years old");

Works for quick stuff. Gets unreadable past 3-4 pieces.

Way 2 - String.format and printf:

String msg = String.format("%s is %d years old", name, age);
System.out.println(msg);

// Or print directly:
System.out.printf("%s is %d years old%n", name, age);

The format codes: %s for any value (as string), %d for integers, %f for floats, %n for a line break.

Way 3 - text blocks (modern Java, 15+):

For multi-line text, use triple-quoted text blocks:

String poem = """
        Roses are red,
        Violets are blue,
        Java has text blocks
        Since version 15.
        """;
System.out.println(poem);

Indentation is stripped intelligently. Useful for SQL, JSON, HTML - anything multi-line you'd otherwise build with concatenation.

What you cannot do

int n = 5;
String s = "items: " + n;          // works - Java converts n to string
String s2 = "items: " + n + 3;     // probably surprising - see below

That second line gives "items: 53", not "items: 8". Why? + is left-associative, so it evaluates as ("items: " + n) + 3. The first + sees a string + an int → string "items: 5". The second + sees a string + an int → string "items: 53".

If you want "items: 8":

String s2 = "items: " + (n + 3);   // parens force int math first

This is a classic Java gotcha. Always parenthesize arithmetic when concatenating.

Reading input from the user (briefly)

To prompt the user for input:

import java.util.Scanner;

public class Echo {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("What's your name? ");
        String name = in.nextLine();
        System.out.println("Hello, " + name);
    }
}

New things: - import java.util.Scanner; - bring the Scanner class into scope (it lives in the java.util package). - Scanner in = new Scanner(System.in); - create a Scanner that reads from standard input. - in.nextLine() - read one line of input.

You'll meet import and new properly soon. For now, use the pattern as-is.

Exercise

In a new file Me.java:

Write a program that:

  1. Has variables for your name (String), favorite number (int), and a boolean for whether it's morning.
  2. Prints a line like: Hi, I'm Victor, my favorite number is 7, and yes (true) it's morning.

Try it three ways: - With concatenation: "Hi, I'm " + name + ", ...". - With String.format and %s/%d/%b placeholders. - With System.out.printf.

Don't skip. The act of typing is the learning.

What you might wonder

"Why no f-strings like Python?" Java doesn't have them yet. There's a proposal (JEP 430, "String Templates") that's been through a few rounds. For now, use String.format or printf.

"Why String (capital) vs int (lowercase)?" Primitives are lowercase. Reference types (classes) are CapitalCase. The distinction is built into the language. Every class follows this - Integer, Double, Boolean (capital) are the boxed wrapper classes for primitives, used when you need a primitive value to live in a collection (page 06).

"What if I never use a variable?" The compiler warns but doesn't fail. Linters like SpotBugs or IntelliJ's inspector flag unused variables more loudly. Clean them up.

"What's the difference between = and ==?" = assigns. == compares. We'll meet == in page 03. They're easy to mix up; reading Java aloud as "is set to" (=) vs "equals" (==) helps.

Done

You can now: - Make variables with explicit types (String, int, double, boolean) or with var. - Recognize the eight primitives and know the four you'll actually use. - Do arithmetic with proper attention to integer vs float division. - Build strings three ways: concatenation, format/printf, text blocks. - Read a line of input with Scanner.

Next page: making your program decide and repeat.

Next: Decisions and loops →

Comments