Weeks
JavaWeek 2 · Datatypes, Control Flow, Classes and I/O
Week 2 Notes

Java,
Week 2

Programming Concepts using Java, Week 2: the first real Java. Hello, world taken apart, the eight primitive types, strings and arrays, control flow, defining classes and objects, and basic input and output. Every Java example in these notes was really compiled and run.

7 chapters21 worked examples~55 min read
main()PrimitivesStringswitchConstructorsScannerInterview prep

Chapters

  1. 01A First Taste of JavaLecture 1
  2. 02Basic Datatypes in JavaLecture 2
  3. 03Control Flow in JavaLecture 3
  4. 04Defining Classes and ObjectsLecture 4
  5. 05Basic Input and OutputLecture 5
  6. 06Interview Question BankInterview
  7. 07Week 2 Summary SheetAll lectures
01
Lecture 1

A First Taste of Java

Hello, world in Python, C and Java, why Java's syntax is heavy, and how a program is compiled and run.

1.1Getting started: hello, world

The first program in any language prints hello, world. Compare how much each language needs to do that one thing.

main.py
print('hello, world')
Output
hello, world
hello.c
#include <stdio.h>
main() {
    printf("hello, world\n");
}
helloworld.java
public class helloworld {
    public static void main(String[] args) {
        System.out.println("hello, world");
    }
}
Output
hello, world
Naming convention (extra). The lecture calls the class helloworld. Java programmers capitalise class names (HelloWorld), and the examples in these notes follow the lecture's spelling only where it matters. The file name must match the public class exactly, capitals included.

1.2Why so complicated?

Python needs one line, Java needs five. None of the extra words is decoration: each one is a decision the language made. Read the figure, then the table.

public class helloworld { public static void main(String[] args) { System.out.println("hello, world"); }}publicvisible from outsideclass helloworldall code lives in a classstaticbelongs to the class, no object neededvoidreturns nothingmain(String[] args)start point + command line wordsSystem.out.printlnprints, then a new line{ } ;blocks and statements end here
Figure 1. The pieces of Hello World
PieceWhat it meansWhy Java needs it
classAll code lies within a class. There are no free-floating functions, unlike Python.Java is object oriented: everything belongs to some type.
publicVisibility modifier: who may use it.main must be reachable from outside the class, since the JVM starts it.
staticThe method belongs to the class, not to an object.No object exists yet when the program starts.
voidReturn type: nothing is returned.Java wants every method's output type declared.
mainThe agreed name where execution starts (a convention from C).The JVM must know which method to call by default.
String[] argsInput: an array of strings, the command line arguments.Input types must be declared too.
System.out.printlnSystem is a public class; out is a stream object in it (like a file handle); println prints and adds \n.out must also be static so it exists without an object.
{ } ;Punctuation delimits blocks and statements, instead of layout and indentation.Indentation is only for humans in Java.

static: the chicken-and-egg problem

Functions defined inside a class are normally attached to objects. But to create an object the program must already be running. So how can it start? static methods belong to the class itself and exist before any object is made, which is why main is static.

The input of main: command line arguments

Greet.java
public class Greet {
    public static void main(String[] args) {
        System.out.println("words typed after the program name: " + args.length);
        for (String a : args) {
            System.out.println("hello, " + a);
        }
    }
}
Terminal
$ javac Greet.java
$ java Greet Asha Ravi
words typed after the program name: 2
hello, Asha
hello, Ravi

What happens if you get the signature wrong

The JVM looks for exactly public static void main(String[] args). Remove static and the program compiles fine, then refuses to start:

Main.java
public class Main {
    public void main(String[] args) {      // static is missing
        System.out.println("hi");
    }
}
Error
Error: Main method is not static in class Main, please define the main method as:
   public static void main(String[] args)

1.3Compiling and running Java code

  • A Java program is a collection of classes. Each class lives in its own file, named after the class, with the extension .java: class helloworld in helloworld.java.
  • javac compiles it to JVM bytecode: javac helloworld.java creates helloworld.class.
  • java helloworld interprets and runs the bytecode on the Java Virtual Machine.
  • The JVM gives a uniform execution environment across operating systems. Java's semantics are defined in terms of the JVM, so they are OS independent: "Write once, run anywhere".
helloworld.javasource you writehelloworld.classJVM bytecodeoutputhello, worldjavacjavacompilesJVM interpretsjavac helloworld.javajavac needs the .java extensionjava helloworld.classwrong: give the class name onlyOne class per file; the file is named after the public class
Figure 2. javac makes the bytecode, java runs it
Terminal
$ javac helloworld.java
$ ls
helloworld.class helloworld.java
$ java helloworld
hello, world
Two rules about extensions
  • javac requires the file extension: javac helloworld.java.
  • java must not be given .class: give the class name only. Otherwise:
Terminal
$ java helloworld.class
Error: Could not find or load main class helloworld.class
Caused by: java.lang.ClassNotFoundException: helloworld.class

The file name must match the public class

Terminal
$ javac Hello.java
Hello.java:1: error: class helloworld is public, should be declared in a file named helloworld.java
public class helloworld {
       ^
1 error

javac follows dependencies

If Main uses another class Greeter, it is enough to compile Main.java. javac finds Greeter.java in the same directory and compiles it too.

Greeter.java
public class Greeter {
    public String hi(String name) {
        return "hello, " + name;
    }
}
Main.java
public class Main {
    public static void main(String[] args) {
        Greeter g = new Greeter();
        System.out.println(g.hi("Asha"));
    }
}
Terminal
$ javac Main.java
$ ls *.class
Greeter.class Main.class
$ java Main
hello, Asha
More than one class in a file (extra). A file may hold several classes, but only one can be public and it names the file. Each class still compiles to its own .class file.

1.4What to carry forward

PythonJava
Where code livesanywhere, functions on their owninside classes
Blocksindentationbraces and semicolons
Typesfrom values, not declareddeclared in advance
Run a programpython hello.pyjavac Hello.java, then java Hello
Portabilityneeds an interpreterbytecode runs on any JVM
  • The syntax of Java is comparatively heavy. Many modifiers are the unavoidable overhead of object-oriented design.
  • Visibility: public and private. Availability: all functions live inside objects, so static definitions are needed.
  • Functions and variable types have to be declared in advance. We will meet more modifiers as we go.

1.5Exam tips and common mistakes

Exam tips
  • Be able to explain each word of public static void main(String[] args). It is the most-asked line in Java.
  • Commands: javac Name.java (with extension), java Name (without).
  • Remember where the checks happen: wrong file name or types fail in javac; a missing main fails in java.
Common mistakes
  • Writing java Name.class or javac Name.
  • A file name that differs from the public class (even in capitals).
  • Forgetting static or misspelling String[] args, so the JVM cannot find main.
  • Forgetting the semicolon at the end of a statement.

1.6Interview corner: what they may ask

Likely questionChanceCrisp answer
Why is main public static void?Very likelypublic: the JVM calls it from outside. static: it must run before any object exists. void: it returns nothing to the JVM.
What is String[] args?LikelyThe command line arguments, passed as an array of strings: java Greet Asha Ravi gives args.length == 2.
Difference between javac and java?Very likelyjavac is the compiler: .java to .class bytecode. java starts the JVM, which runs the bytecode.
Must the file name match the class name?Very likelyFor a public class, yes, exactly. Other classes in the file may have any name; each gets its own .class.
What is System.out.println?LikelySystem is a class, out a static PrintStream object in it, println a method that prints and adds a newline.
Why is Java called platform independent?Very likelyjavac produces bytecode, which any JVM can run, so the same .class works on every OS.
Next · Lecture 2Basic Datatypes in Java
02
Lecture 2

Basic Datatypes in Java

The eight primitive types, declarations and constants, operators and casting, and the two built-in objects you use all the time: strings and arrays.

2.1Scalar types: the eight primitives

In a purely object-oriented language all data would be objects. That is cumbersome for numbers, and we like to compute with numbers the way conventional languages do. So Java also has eight primitive datatypes that are not objects:

GroupTypes
whole numbersint, long, short, byte
decimalsfloat, double
characterschar
truth valuesboolean

The size of each type is fixed by the JVM and does not depend on the native architecture of your machine. That is part of why Java code behaves the same everywhere.

Size in bytes (fixed by the JVM, not by your machine)byte1short2char2int4float4long8double8boolean1whole numbersdecimalscharacterstrue / falsechar is 2 bytes because it holds a Unicode (UTF-16) code unit
Figure 3. Size of each primitive type in bytes
Main.java
public class Main {
    public static void main(String[] args) {
        System.out.println("byte    " + Byte.MIN_VALUE + " to " + Byte.MAX_VALUE);
        System.out.println("short   " + Short.MIN_VALUE + " to " + Short.MAX_VALUE);
        System.out.println("int     " + Integer.MIN_VALUE + " to " + Integer.MAX_VALUE);
        System.out.println("long    " + Long.MIN_VALUE + " to " + Long.MAX_VALUE);
        System.out.println("char    " + (int) Character.MIN_VALUE + " to " + (int) Character.MAX_VALUE);
    }
}
Output
byte    -128 to 127
short   -32768 to 32767
int     -2147483648 to 2147483647
long    -9223372036854775808 to 9223372036854775807
char    0 to 65535
  • char is 2 bytes because it holds a Unicode character, so '\u03C0' (Greek pi) is a perfectly good char.
  • boolean has only true and false. The lecture lists it as 1 byte; the JVM does not strictly fix its size, 1 byte is what it usually takes.
  • int is the everyday whole-number type: about ±2.1 billion. Use long when you need more.

2.2Declarations and assignment

We declare variables before we use them, with the type first. The assignment statement then works as usual.

Main.java
public class Main {
    public static void main(String[] args) {
        int x, y;
        float f;
        char c;
        boolean b1;

        x = 5;
        y = 7;
        c = 'x';
        char d = '\u03C0';        // Greek pi, a Unicode character
        b1 = false;
        boolean b2 = true;

        System.out.println(x + y);
        System.out.println(c);
        System.out.println(d);
        System.out.println(b1 + " " + b2);
    }
}
Output
12
x
π
false true
  • Characters are written with single quotes only. Double quotes make a String. They are different types:
Main.java
public class Main {
    public static void main(String[] args) {
        char c = "x";
    }
}
Error
Main.java:3: error: incompatible types: String cannot be converted to char
        char c = "x";
                 ^
1 error
  • Boolean constants are true and false, in lower case. (Python's True and False do not work.)
  • A local variable must be given a value before it is read. Java refuses to guess:
Main.java
public class Main {
    public static void main(String[] args) {
        int x;
        System.out.println(x);
    }
}
Error
Main.java:4: error: variable x might not have been initialized
        System.out.println(x);
                           ^
1 error

2.3Initialization and constants

  • Declarations can come anywhere, not only at the top. Use this judiciously, to keep the code readable.
  • Best of all, initialise at the time of declaration: int x = 10;.
  • The modifier final marks a constant: it can be assigned only once.
Main.java
public class Main {
    public static void main(String[] args) {
        final float pi = 3.1415927f;
        pi = 22/7;          // flagged as an error
    }
}
Error
Main.java:4: error: cannot assign a value to final variable pi
        pi = 22/7;          // flagged as an error
        ^
1 error
Correction (extra). The lecture writes float y = 5.7;. That line does not compile: a decimal literal like 5.7 is a double, and squeezing a double into a float loses precision. Write 5.7f (as the pi example does) or declare double y = 5.7;.
Main.java
public class Main {
    public static void main(String[] args) {
        float y = 5.7;
    }
}
Error
Main.java:3: error: incompatible types: possible lossy conversion from double to float
        float y = 5.7;
                  ^
1 error
Main.java
public class Main {
    public static void main(String[] args) {
        float y = 5.7f;
        double z = 5.7;
        System.out.println(y + " " + z);
    }
}
Output
5.7 5.7

Default values

Fields of an object and the cells of an array start with a default value: 0 for numbers, false for boolean, null for objects. Local variables get none, which is why the compiler complains above.

Main.java
public class Main {
    static int count;
    static boolean done;
    static double ratio;
    static String name;

    public static void main(String[] args) {
        System.out.println(count + " " + done + " " + ratio + " " + name);
        int[] marks = new int[3];
        System.out.println(marks[0] + " " + marks[1] + " " + marks[2]);
    }
}
Output
0 false 0.0 null
0 0 0

2.4Operators, shortcuts and type casting

The arithmetic operators are the usual ones: + - * / %. Three differences from Python matter:

  • No separate integer-division operator. When both operands are integers, / is integer division, and it truncates towards zero.
  • No exponentiation operator. Use Math.pow(a, n), which returns ana^n as a double.
  • Increment and decrement operators exist: a++, b--, and shortcuts like a += 7, b *= 12.
Main.java
public class Main {
    public static void main(String[] args) {
        float f = 22/7;                       // integer division first, then widened
        System.out.println(f);
        System.out.println(22 / 7);
        System.out.println(22 / 7.0);
        System.out.println(-7 / 2);              // truncates towards zero (Python gives -4)
        System.out.println(-7 % 3);              // remainder takes the sign of the left operand
        System.out.println(Math.pow(2, 10));     // a double
        System.out.println((int) Math.pow(2, 10));

        int a = 0, b = 10;
        a++;                                     // same as a = a + 1
        b--;                                     // same as b = b - 1
        a += 7;                                  // same as a = a + 7
        b *= 12;                                 // same as b = b * 12
        System.out.println(a + " " + b);
    }
}
Output
3.0
3
3.142857142857143
-3
-1
1024.0
1024
8 108
Typo in the lecture (extra). It writes b—;. The decrement operator is two plain minus signs: b--;.

a++ versus ++a

Main.java
public class Main {
    public static void main(String[] args) {
        int i = 5;
        System.out.println(i++);       // uses 5, then increases i
        System.out.println(i);
        System.out.println(++i);       // increases i first, then uses 7
        System.out.println(i);
    }
}
Output
5
6
7
7

Type casting

Moving a value to a wider type is automatic (int to float, as in float f = 22/7). Moving to a narrower type can lose information, so Java makes you say so with a cast.

byteshortintlongfloatdoublecharautomatic, safe (widening) -><- needs a cast: (int) 3.9float f = 22 / 7;ok: int widens to float, f = 3.0int i = 3.9;error: lossy conversion double to intint i = (int) 3.9;ok: you asked for it, i = 3 (truncates)
Figure 4. Widening is automatic, narrowing needs a cast
Main.java
public class Main {
    public static void main(String[] args) {
        System.out.println((int) 3.9);          // truncates, does not round
        System.out.println((int) -3.9);
        System.out.println((byte) 200);         // wraps around: 200 - 256
        int big = Integer.MAX_VALUE;
        System.out.println(big + 1);            // overflow wraps to the most negative int
        System.out.println((long) big + 1);     // widen first, no overflow
        byte small = 10;
        small += 5;                             // compound assignment casts for you
        System.out.println(small);
        System.out.println('A' + 1);            // char arithmetic gives an int
        System.out.println((char) ('A' + 1));
    }
}
Output
3
-3
-56
-2147483648
2147483648
15
66
B
Main.java
public class Main {
    public static void main(String[] args) {
        byte small = 10;
        small = small + 5;
    }
}
Error
Main.java:4: error: incompatible types: possible lossy conversion from int to byte
        small = small + 5;
                      ^
1 error
  • small = small + 5 is an int expression, which will not fit back in a byte without a cast, but small += 5 inserts that cast itself.
  • Overflow is silent: Integer.MAX_VALUE + 1 becomes -2147483648. There is no error, unlike Python which grows its integers.
Main.java
public class Main {
    public static void main(String[] args) {
        System.out.println(0.1 + 0.2);          // decimals are binary fractions
        System.out.println(5.0 / 0);            // floating point: Infinity, no exception
        System.out.println(5 / 0);              // integer: ArithmeticException
    }
}
Error
0.30000000000000004
Infinity
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at Main.main(Main.java:5)

2.5Strings

  • String is a built-in class, not a primitive. Constants are in double quotes.
  • + is overloaded for concatenation.
  • Strings are not arrays of characters: s[3] = 'p' is not allowed. Call a method such as substring instead.
Main.java
public class Main {
    public static void main(String[] args) {
        String s = "Hello", t = "world";
        String u = s + " " + t;
        System.out.println(u);

        s = s.substring(0, 3) + "p!";            // s now points at a NEW String
        System.out.println(s);
        System.out.println(s.length());          // a method, so it has brackets
        System.out.println(s.charAt(1));
        System.out.println("Hello".toUpperCase());
    }
}
Output
Hello world
Help!
5
e
HELLO
Main.java
public class Main {
    public static void main(String[] args) {
        String s = "Hello";
        s[3] = 'p';
    }
}
Error
Main.java:4: error: array required, but String found
        s[3] = 'p';
         ^
1 error
BeforeAfter s = s.substring(0, 3) + "p!"s"Hello"s"Help!""Hello"old object: nobody points to it-> garbage collector frees itStrings are immutable:no s[3] = 'p'. Instead build a new Stringand make s point to it."Hello" + "p!" cuts the first 3 characters: "Hel" + "p!" = "Help!"
Figure 5. Updating a String makes a new one
  • Strings are immutable. If we "change" a String we really get a new object, and s points to it.
  • The old "Hello" is now unreachable, and Java's automatic garbage collection frees it (Week 1, Lecture 3).

== versus equals (a favourite trap)

Main.java
public class Main {
    public static void main(String[] args) {
        String a = "hi";
        String b = "hi";
        String c = new String("hi");
        System.out.println(a == b);          // same object? (literals are shared)
        System.out.println(a == c);          // c is a different object
        System.out.println(a.equals(c));     // same characters?
        System.out.println("1" + 2 + 3);     // left to right: "12", then "123"
        System.out.println(1 + 2 + "3");     // 3, then "33"
    }
}
Output
true
false
true
123
33
Remember
  • == compares references (are they the same object?). equals compares contents. For strings, always use equals.

2.6Arrays

  • Arrays are objects. Declare the reference, then create the array with new: int[] a; a = new int[100]; or both in one line.
  • a.length gives the size. For a String it is a method: s.length().
  • Indices run from 0 to a.length - 1.
  • The size can be a variable, chosen at run time. Array constants {v1, v2, v3} are allowed.
int[] a = new int[5];abint[] b = a;array object (on the heap) length = 50[0]0[1]0[2]0[3]0[4]b[0] = 99; then a[0] is also 99one array, two names: assigning arrays copies the REFERENCE, not the dataa.length is a field (no brackets); s.length() on a String is a method
Figure 6. One array object, two names
Main.java
public class Main {
    public static void main(String[] args) {
        int[] a = new int[5];
        System.out.println(a.length + " " + a[0]);       // cells start at 0

        int n = 10;
        a = new int[n];                                  // a new array; the old one is garbage
        System.out.println(a.length);
        n = 20;
        a = new int[n];
        System.out.println(a.length);

        int[] c = {2, 3, 5, 7, 11};                      // an array constant, in a declaration
        System.out.println(c[c.length - 1]);

        int[] d = c;                                     // copies the REFERENCE
        d[0] = 99;
        System.out.println(c[0]);
        System.out.println(java.util.Arrays.toString(java.util.Arrays.copyOf(c, 3)));   // a real copy
    }
}
Output
5 0
10
20
11
99
[99, 3, 5]
Correction (extra). The lecture ends with a = {2, 3, 5, 7, 11}; as a plain assignment. That is not legal: the {...} constant is allowed only in a declaration. After the declaration use new int[] {2, 3, 5, 7, 11}.
Main.java
public class Main {
    public static void main(String[] args) {
        int[] a;
        a = {2, 3, 5, 7, 11};
    }
}
Error
Main.java:4: error: illegal start of expression
        a = {2, 3, 5, 7, 11};
            ^
Main.java:4: error: not a statement
        a = {2, 3, 5, 7, 11};
             ^
Main.java:4: error: ';' expected
        a = {2, 3, 5, 7, 11};
              ^
3 errors
Main.java
public class Main {
    public static void main(String[] args) {
        int[] a;
        a = new int[] {2, 3, 5, 7, 11};
        System.out.println(a.length);
    }
}
Output
5

Going outside the valid indices is a run-time error, not a compile-time one:

Main.java
public class Main {
    public static void main(String[] args) {
        int[] a = new int[5];
        System.out.println(a[5]);
    }
}
Error
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
	at Main.main(Main.java:4)

2.7Exam tips and common mistakes

Exam tips
  • Integer division: if both operands are integers the result is an integer. One double operand is enough to get a decimal result.
  • A cast to int truncates (3.9 becomes 3, -3.9 becomes -3). It does not round.
  • Single quotes for a char, double quotes for a String.
  • Array of size n has valid indices 0 to n-1; a.length without brackets, s.length() with.
Common mistakes
  • Writing float x = 3.14; (a double literal): add f.
  • Comparing strings with == instead of equals.
  • Expecting 7 / 2 to be 3.5. It is 3.
  • Assuming an assigned array is a copy: int[] d = c; shares one array.
  • Modifying a final variable, or reading an uninitialised local.

2.8Interview corner: what they may ask

Likely questionChanceCrisp answer
Primitive types vs objects? Name the eight.Very likelyPrimitives (byte short int long float double char boolean) hold the value directly and are not objects; String and arrays are objects reached through references.
Why are Strings immutable? What does that cost?Very likelyAn immutable object is safe to share and can be cached (the string pool). Every "change" builds a new object, so heavy concatenation in a loop is slow: use StringBuilder.
== vs equals() for strings?Very likely== asks whether two references point to the same object; equals asks whether the characters match. Use equals.
What does 7 / 2 give? And (double) 7 / 2?Very likely3, because both are integers. 3.5, because the cast to double happens first and widens the other operand.
What happens on integer overflow?LikelyIt wraps around silently: Integer.MAX_VALUE + 1 is -2147483648. Use long, or Math.addExact to get an exception.
How is an array different from a String or from Python's list?LikelyAn array is an object of fixed size and one element type, with length as a field. A Python list grows and can mix types.
What does final do?LikelyA final variable can be assigned only once, so it is a constant. (On classes and methods it also forbids extending or overriding.)
Next · Lecture 3Control Flow in Java
03
Lecture 3

Control Flow in Java

Program layout, if and else, while and do-while, the two kinds of for, and switch with its fall-through.

3.1Program layout and the constructs

  • Statements end with a semicolon ;.
  • Blocks of statements are delimited by braces { }.
PurposeJavaPython equivalent
Conditional executionif (c) { ... } else { ... }if / elif / else
Conditional loopwhile (c) { ... }, do { ... } while (c);while c:
Iterationtwo kinds of forfor x in l:, range
Multiway branchingswitchif / elif chain

3.2Conditional execution: if and else

  • else is optional. The condition must be in parentheses.
  • If the body is a single statement, braces are not needed.
  • There is no elif. Write else if: a nested if is one statement, so it needs no extra braces. Indentation is not enforced; just align the else if by habit.
  • Aside: there is no def for a function. A method is written with its modifiers and types: public static int sign(int v).
MyClass.java
public class MyClass {
    public static int sign(int v) {
        if (v < 0)
            return(-1);
        else if (v > 0)
            return(1);
        else
            return(0);
    }

    public static void main(String[] args) {
        System.out.println(sign(-5) + " " + sign(0) + " " + sign(7));
    }
}
Output
-1 0 1

Why indentation can mislead you (the dangling else)

Python uses indentation to decide what belongs to what. Java uses only braces, so an else belongs to the nearest if, whatever the layout suggests.

Main.java
public class Main {
    public static void main(String[] args) {
        int x = 5, y = 0;
        if (x > 3)
            if (y > 3)
                System.out.println("both");
        else
            System.out.println("else belongs to the inner if");
        System.out.println("done");
    }
}
Output
else belongs to the inner if
done
Safe habit. Always write braces, even for a single statement. Then the layout and the meaning cannot disagree.

3.3Conditional loops: while and do-while

  • while (c) { ... }: the condition is checked before every iteration, so the body may run zero times.
  • do { ... } while (c);: the condition is checked at the end, so the body runs at least once, even if the condition is false. Useful for interactive input: read, then test.
while (c) { body }do { body } while (c);c ?bodyyesno: leavebody may run 0 timesbodyc ?yes: againnobody runs at least onceUse do-while when you must act first and test later,for example "read the input, ask again if it is invalid".int i = 10; while (i < 5) {...} -> 0 times; do {...} while (i < 5); -> 1 time
Figure 7. while tests first, do-while runs the body first
MyClass.java
public class MyClass {
    public static int sumupto(int n) {
        int sum = 0;
        while (n > 0) {
            sum += n;
            n--;
        }
        return(sum);
    }

    public static int sumupto2(int n) {
        int sum = 0;
        int i = 0;
        do {
            sum += i;
            i++;
        } while (i <= n);
        return(sum);
    }

    public static void main(String[] args) {
        System.out.println(sumupto(10) + " " + sumupto2(10));
        System.out.println(sumupto(0) + " " + sumupto2(0));
    }
}
Output
55 55
0 0

Same answer for 10, but look at 0: sumupto2(0) still ran its body once (adding 0), which happens to be harmless here. With a condition that is false from the start the difference is visible:

Main.java
public class Main {
    public static void main(String[] args) {
        int i = 10;
        while (i < 5) {
            System.out.println("while body");
        }
        do {
            System.out.println("do body runs once, i = " + i);
        } while (i < 5);
    }
}
Output
do body runs once, i = 10

3.4Iteration: the two kinds of for

The classic for, inherited from C

Main.java
for (int i = 0; i < n; ++i) {
    // body
}

// is exactly the same as
int i = 0;
while (i < n) {
    // body
    ++i;
}
for (int i = 0; i < n; i++) { body }1 initint i = 02 condi < n ?3 body{ ... }4 updatei++trueback to the testfalse: leave the loopinit runs once. Then repeat: test, body, update.i is local to the loop: it cannot be used after the closing brace.
Figure 8. init once; then test, body, update, test...

for (init; cond; upd) { ... } is completely equivalent to init; while (cond) { ...; upd; }. The usual use is for (i = 0; i < n; ++i). It is poor style to use for where a plain while reads better.

Main.java
public class Main {
    public static void main(String[] args) {
        int s1 = 0;
        for (int i = 0; i < 5; ++i) {
            s1 += i;
        }
        int s2 = 0;
        int j = 0;
        while (j < 5) {
            s2 += j;
            j++;
        }
        System.out.println(s1 + " " + s2);
    }
}
Output
10 10

The loop variable can be declared inside the for. Its scope is local to the loop, an instance of the more general local scoping Java allows. Using it afterwards is an error:

Main.java
public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
        }
        System.out.println(i);
    }
}
Error
Main.java:5: error: cannot find symbol
        System.out.println(i);
                           ^
  symbol:   variable i
  location: class Main
1 error
MyClass.java
public class MyClass {
    public static int sumarray(int[] a) {
        int sum = 0;
        int n = a.length;
        int i;

        for (i = 0; i < n; ++i) {
            sum += a[i];
        }

        return(sum);
    }

    public static void main(String[] args) {
        int[] a = {2, 3, 5, 7, 11};
        System.out.println(sumarray(a));
    }
}
Output
28

Iterating over elements directly (the Python-style for)

Java later added a for in the style of Python's for x in l. Same keyword, different syntax: for (type x : a). The loop variable must be declared right there.

MyClass.java
public class MyClass {
    public static int sumarray(int[] a) {
        int sum = 0;

        for (int v : a) {
            sum += v;
        }

        return(sum);
    }

    public static void main(String[] args) {
        int[] a = {2, 3, 5, 7, 11};
        System.out.println(sumarray(a));
    }
}
Output
28

One catch: v is a copy of each element, so assigning to it does not change the array.

Main.java
public class Main {
    public static void main(String[] args) {
        int[] a = {1, 2, 3};
        for (int v : a) {
            v = v * 10;                   // changes only the copy
        }
        System.out.println(a[0] + " " + a[1] + " " + a[2]);
        for (int i = 0; i < a.length; i++) {
            a[i] = a[i] * 10;             // changes the array
        }
        System.out.println(a[0] + " " + a[1] + " " + a[2]);
    }
}
Output
1 2 3
10 20 30
UseWhen
for (int v : a)you only need to read every element
for (int i = 0; i < n; i++)you need the index, or must change elements
whileyou do not know in advance how many times

3.5Multiway branching: switch

  • switch selects between different options. The options (case labels) have to be constants: no conditional expressions.
  • The default behaviour is to fall through from one case to the next. You must break out explicitly. (break also works in loops.)
with breakwithout break (fall through)switch (x) x = 2case 1:print "one"case 2:print "two"case 3:print "three"break;endswitch (x) x = 2case 1:print "one"case 2:print "two"case 3:print "three"endleft prints: two right prints: two, three
Figure 9. With and without break
MyClass.java
public class MyClass {
    public static void printsign(int v) {
        switch(v) {
            case -1: {
                System.out.println("Negative");
                break;
            }
            case 1: {
                System.out.println("Positive");
                break;
            }
            case 0: {
                System.out.println("Zero");
                break;
            }
        }
    }

    public static void main(String[] args) {
        printsign(-1);
        printsign(1);
        printsign(0);
        printsign(5);              // no case matches: nothing is printed
        System.out.println("end");
    }
}
Output
Negative
Positive
Zero
end

Aside: the return type here is void. A non-void return type needs a matching return value. Now remove the breaks and watch it fall through:

Main.java
public class Main {
    public static void main(String[] args) {
        int x = 2;
        switch (x) {
            case 1: System.out.println("one");
            case 2: System.out.println("two");
            case 3: System.out.println("three"); break;
            case 4: System.out.println("four");
            default: System.out.println("default");
        }
    }
}
Output
two
three

A case label must be a constant, not a variable:

Main.java
public class Main {
    public static void main(String[] args) {
        int k = 2;
        int x = 1;
        switch (x) {
            case k: break;
        }
    }
}
Error
Main.java:6: error: constant expression required
            case k: break;
                 ^
1 error

Handy extras (not in the lecture)

Main.java
public class Main {
    public static void main(String[] args) {
        String d = "sat";
        switch (d) {                              // strings and chars work too
            case "sat":
            case "sun": System.out.println("weekend"); break;   // two labels, one body
            default: System.out.println("weekday");
        }
        int day = 3;
        String name = switch (day) {              // Java 14+: arrows never fall through
            case 1 -> "Mon";
            case 2 -> "Tue";
            case 3 -> "Wed";
            default -> "?";
        };
        System.out.println(name);
        for (int i = 1; i <= 6; i++) {
            if (i == 2) continue;                 // skip this round
            if (i == 5) break;                    // leave the loop
            System.out.print(i + " ");
        }
        System.out.println();
        int v = -4;
        System.out.println((v < 0) ? "neg" : "non-neg");   // the ?: shortcut for a small if
    }
}
Output
weekend
Wed
1 3 4 
neg

3.6Exam tips and common mistakes

Exam tips
  • Trace a switch without break by writing down every line from the matching case downwards.
  • while can run 0 times, do-while at least once.
  • A for variable declared in the header does not exist after the loop.
  • For an if without braces only the next one statement belongs to it.
Common mistakes
  • Writing elif, or an if condition without parentheses.
  • Forgetting break in a switch.
  • Writing = where == is meant. In an if with ints the compiler rejects it, but boolean variables can slip through.
  • Adding a semicolon right after if (c) or for (...), which makes the body empty.
  • Trusting indentation to show which if an else belongs to.

3.7Interview corner: what they may ask

Likely questionChanceCrisp answer
Difference between while and do-while?Very likelywhile tests first and may never run; do-while runs the body first, so at least once.
What is fall-through in switch? How do you stop it?Very likelyWithout break execution continues into the next case. Add break, or use the arrow form (case 1 -> ...) in Java 14+.
What can a switch switch on?LikelyIntegral types, char, enums and String; case labels must be constants.
Plain for vs enhanced for?Very likelyEnhanced for (T x : a) gives each element as a copy, with no index. Use the plain form when you need the index or must modify elements.
Scope of a variable declared in a for header?LikelyOnly the loop itself. After the closing brace the name no longer exists.
Does Java have elif?SometimesNo. You write else if: an if nested in the else.
Next · Lecture 4Defining Classes and Objects in Java
04
Lecture 4

Defining Classes and Objects in Java

A class as a type, private instance variables with accessors and mutators, new, constructors and overloading, this, default and copy constructors, shallow and deep copy.

4.1Defining a class

  • A definition block with class and the class name. The modifier public says it is visible everywhere.
  • Java lets you omit public. The default visibility is public to the package: packages are administrative units of code, and all classes defined in the same directory belong to the same package.
  • Instance variables: each concrete object of type Date has its own local copies of day, month, year. They are marked private. A public instance variable is possible, but it breaks encapsulation.
Date.java
public class Date {
    private int day, month, year;
}
class Dateprivate int day;private int month;private int year;the templatevariables (stack)objects (heap)d1d2day = 13month = 8year = 2015day = 1month = 1year = 2000Date d1 = new Date(13, 8, 2015);Date d2 = new Date(1, 1, 2000);The variable holds a reference; new creates the object.d1.setDate(...) changes only d1's object, never d2's.
Figure 10. A class is the template; each object keeps its own values
Python (Week 1)Java (this week)
class Date:public class Date { ... }
self.daythis.day
instance variables created in __init__declared in the class body, with a type and private
anyone can read d.dayd.day outside the class is a compile error

4.2Creating objects, methods that set and get

  • Declare the variable with the class name as its type, and new creates the object: Date d; d = new Date();.
  • How do we set the instance variables? Add methods. Inside them this is a reference to the current object; it can be omitted when there is no ambiguity.
  • How do we check the values? Methods that read and report them. These are accessor (get) and mutator (set) methods.
Date.java
public class Date {
    private int day, month, year;

    public void setDate(int d, int m, int y) {
        this.day = d;
        this.month = m;
        this.year = y;
    }

    public int getDay() {
        return(day);
    }

    public int getMonth() {
        return(month);
    }

    public int getYear() {
        return(year);
    }
}
Main.java
public class Main {
    public static void main(String[] args) {
        Date d;
        d = new Date();                 // no constructor written: every field starts at 0
        System.out.println(d.getDay() + "/" + d.getMonth() + "/" + d.getYear());
        d.setDate(13, 8, 2015);
        System.out.println(d.getDay() + "/" + d.getMonth() + "/" + d.getYear());
    }
}
Output
0/0/0
13/8/2015

Because day is private, code outside the class has to go through the methods. This is encapsulation:

Main.java
public class Main {
    public static void main(String[] args) {
        Date d = new Date();
        System.out.println(d.day);
    }
}
Error
Main.java:4: error: day has private access in Date
        System.out.println(d.day);
                            ^
1 error

A classic bug: the parameter hides the field

If a parameter has the same name as a field, the bare name means the parameter. Without this. the assignment copies the parameter onto itself and the field stays unchanged:

Main.java
public class Main {
    static class P {
        private int day;
        void setWrong(int day) { day = day; }          // parameter = parameter
        void setRight(int day) { this.day = day; }     // field = parameter
        int getDay() { return day; }
    }

    public static void main(String[] args) {
        P p = new P();
        p.setWrong(9);
        System.out.println(p.getDay());
        p.setRight(9);
        System.out.println(p.getDay());
    }
}
Output
0
9

A variable is not an object

Main.java
public class Main {
    public static void main(String[] args) {
        Date d;
        System.out.println(d.getDay());
    }
}
Error
Main.java:4: error: variable d might not have been initialized
        System.out.println(d.getDay());
                           ^
1 error
Main.java
public class Main {
    public static void main(String[] args) {
        Date d = null;
        System.out.println(d.getDay());
    }
}
Error
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Date.getDay()" because "d" is null
	at Main.main(Main.java:4)
  • The first is stopped by the compiler: a local reference must be assigned before use.
  • The second compiles. A reference that points at null points at no object, so calling a method through it throws NullPointerException at run time.

4.3Constructors

  • We would like to set an object up when we create it: combine new Date() and setDate(). A constructor is a special function called when an object is created.
  • It has the same name as the class and no return type: d = new Date(13, 8, 2015);.
  • Constructors with different signatures: d = new Date(13, 8); sets the year to 2021. Java allows function overloading: the same name with different signatures. (Python has default arguments and no overloading.)
Date.java
public class Date {
    private int day, month, year;

    public Date(int d, int m, int y) {
        day = d;
        month = m;
        year = y;
    }

    public Date(int d, int m) {
        day = d;
        month = m;
        year = 2021;
    }
}

One constructor can call another with this

A later constructor can reuse an earlier one using this(...). It must be the first statement. This avoids repeating the assignments.

new Date(13, 8)1 you callDate(int d, int m) {this(d, m, 2021);2 the short constructor hands overDate(int d, int m, int y) {day = d; month = m; year = y;3 the full constructor sets the fieldsyear defaults to 2021this(...) must be the FIRST line
Figure 11. The two-argument constructor hands over to the three-argument one
Main.java
public class Main {
    static class D {
        int day, month, year;

        D(int d, int m, int y) {
            System.out.println("3-argument constructor");
            day = d;
            month = m;
            year = y;
        }

        D(int d, int m) {
            this(d, m, 2021);
            System.out.println("2-argument constructor finished");
        }
    }

    public static void main(String[] args) {
        D x = new D(13, 8);
        System.out.println(x.year);
    }
}
Output
3-argument constructor
2-argument constructor finished
2021

The default constructor, and when it disappears

  • If you define no constructor, Java provides a default constructor with no arguments, so new Date() works. It sets instance variables to sensible defaults (int to 0).
  • This is true only if no constructor is defined. As soon as you write one, you need an explicit no-argument constructor if you still want new Date():
Main.java
public class Main {
    public static void main(String[] args) {
        Date d = new Date();
    }
}
Error
Main.java:3: error: constructor Date in class Date cannot be applied to given types;
        Date d = new Date();
                 ^
  required: int
  found:    no arguments
  reason: actual and formal argument lists differ in length
1 error

4.4Copy constructors, shallow and deep copy

  • A copy constructor creates a new object from an existing one. It takes an object of the same type as its argument and copies the instance variables.
  • Use the object name to say which instance variables you mean: this.day = d.day. Note that the private variables of the argument are visible, because both are the same class.
Main.java
public class Main {
    public static void main(String[] args) {
        Date d1 = new Date(12, 4, 1954);
        Date d2 = new Date(d1);          // copy constructor
        d1.setDate(1, 1, 2000);
        System.out.println(d1.getYear() + " " + d2.getYear());     // d2 is independent
    }
}
Output
2000 1954

Shallow copy versus deep copy

We want the new object to be disjoint from the old one. That is easy when every instance variable is a plain number. If an instance variable is itself an object, copying it just copies the reference, and we end up aliasing instead of copying.

Student.java
public class Student {
    String name;
    Date dob;                                   // an object inside an object

    Student(String name, Date dob) { this.name = name; this.dob = dob; }

    Student(Student s) {                        // DEEP copy: duplicates the Date too
        this.name = s.name;
        this.dob = new Date(s.dob);
    }

    static Student shallowCopy(Student s) {     // SHALLOW copy: shares the Date
        return new Student(s.name, s.dob);
    }
}
originalshallow copydeep copyStudentdob ->Studentdob ->Studentdob ->Date 1/2/2000Date 1/2/2000same Dateits own copychange it through one student andthe other one sees the changenew Date(s.dob)
Figure 12. Shallow copy shares the inner Date, deep copy duplicates it
Main.java
public class Main {
    public static void main(String[] args) {
        Student s1 = new Student("Asha", new Date(1, 2, 2000));
        Student shallow = Student.shallowCopy(s1);
        Student deep = new Student(s1);

        s1.dob.setDate(9, 9, 1999);                // change the original's date

        System.out.println("original: " + s1.dob.getDay());
        System.out.println("shallow : " + shallow.dob.getDay());
        System.out.println("deep    : " + deep.dob.getDay());
    }
}
Output
original: 9
shallow : 9
deep    : 1
Why this matters. The shallow copy changed behind our back. Whenever a class holds other objects (or arrays), ask: "does my copy constructor copy them too?"

4.5Putting the Date class together

Date.java
public class Date {
    private int day, month, year;

    public Date(int d, int m, int y) {
        day = d;
        month = m;
        year = y;
    }

    public Date(int d, int m) {
        this(d, m, 2021);
    }

    public Date(Date d) {
        this.day = d.day;
        this.month = d.month;
        this.year = d.year;
    }

    public void setDate(int d, int m, int y) {
        this.day = d;
        this.month = m;
        this.year = y;
    }

    public int getDay() { return(day); }
    public int getMonth() { return(month); }
    public int getYear() { return(year); }
}
Main.java
public class Main {
    public static void main(String[] args) {
        Date d = new Date(13, 8, 2015);
        Date e = new Date(13, 8);
        Date c = new Date(d);
        System.out.println(d.getDay() + "/" + d.getMonth() + "/" + d.getYear());
        System.out.println(e.getYear());
        System.out.println(c.getYear());
    }
}
Output
13/8/2015
2021
2015
PieceWhat it does
private fieldshide the representation
getters and setDatethe public interface
3-argument constructorthe one that really sets things up
2-argument constructoroverload that reuses it with this(...)
copy constructora new, independent Date

4.6Exam tips and common mistakes

Exam tips
  • Constructor = same name as the class, no return type. Adding void turns it into an ordinary method.
  • The default constructor exists only if you write no constructor.
  • this(...) calls another constructor of the same class and must be the first line.
  • Say "shallow" when objects inside are shared, "deep" when they are duplicated too.
Common mistakes
  • Writing day = day; in a setter and wondering why nothing changes: use this.day = day;.
  • Using a declared-but-never-newed variable: a compile error, or a NullPointerException if it was set to null.
  • Making instance variables public, which breaks encapsulation.
  • Thinking a copy constructor copies everything: it copies what you tell it to.

4.7Interview corner: what they may ask

Likely questionChanceCrisp answer
What is a constructor? Can it be overloaded? Does it return anything?Very likelySpecial code run when an object is created, named like the class, with no return type. It can be overloaded with different parameter lists.
What is the default constructor?Very likelyA no-argument constructor the compiler adds only when you write none. Writing any constructor removes it.
What does this mean? What is this(...)?Very likelythis is a reference to the current object. this(args) as the first line of a constructor calls another constructor of the same class.
Shallow copy vs deep copy?Very likelyShallow copies the references, so the copy shares inner objects with the original. Deep copies the inner objects too, so the two are independent.
Why make fields private and add getters and setters?Very likelyTo hide the representation, so it can change without breaking callers, and to validate values in one place.
Constructor overloading vs Python's default arguments?LikelyJava has no default arguments; you write several constructors, often one chaining to another with this(...).
What is a NullPointerException?Very likelyUsing a reference that points at null (no object), for example calling a method through it. It happens at run time.
Next · Lecture 5Basic Input and Output in Java
05
Lecture 5

Basic Input and Output in Java

Reading with Console and Scanner, and writing with println, print and printf.

5.1Interacting with a Java program

We have already seen how to print data with System.out.println("Hello, world");. The new question is how to read data. Java has two tools for that, Console and Scanner; output has three methods, println, print and printf.

KeyboardScanneryour programSystem.outScreenSystem.innextLine() nextInt()println() printf()Console (System.console()) is the other way in: readLine, readPassword.Scanner works everywhere (files, pipes, IDEs); Console needs a real terminal.
Figure 13. Data flows in through System.in and out through System.out

5.2Reading input with Console

  • The simplest to use is the Console class, quite similar to Python's input(). You get one from System.console().
  • Two methods: readLine returns a String (like input()); readPassword returns an array of char and does not echo the characters on the screen.
Main.java
Console cons = System.console();
String username = cons.readLine("Username: ");
char[] password = cons.readPassword("Password: ");
Why a char array for a password? A String is immutable and may stay in memory until garbage collection. A char[] can be overwritten with zeros as soon as you are done with it.

A gotcha the lecture does not mention. System.console() returns null when the program is not attached to a real terminal (many IDEs, input redirected from a file or pipe). Then cons.readLine throws a NullPointerException. Here is the same code run with its input piped in:

Main.java
public class Main {
    public static void main(String[] args) {
        java.io.Console cons = System.console();
        String username = cons.readLine("Username: ");
        System.out.println(username);
    }
}
Error
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.io.Console.readLine(String, Object[])" because "cons" is null
	at Main.main(Main.java:4)
So in practice
  • Console is fine in a real terminal, and the only choice for passwords. For everything else, and in IDEs or online judges, use Scanner.

5.3Scanner: reading line by line or token by token

  • The more general Scanner class allows more granular reading: a full line, or an integer, and so on.
  • Create it on the input stream: new Scanner(System.in). Then call nextLine(), nextInt(), nextDouble(), next() (one word).
  • Scanner lives in java.util, so you need import java.util.Scanner; at the top.
Main.java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String name = in.nextLine();
        int age = in.nextInt();
        System.out.println(name + " is " + age);
    }
}
Terminal
$ java Main
Asha Rao
17
Asha Rao is 17

The first two lines under the command are what the user typed; the last line is the program's output.

The nextInt() then nextLine() trap

nextInt() reads the number but leaves the Enter key (the end of that line) unread. A following nextLine() then returns the rest of the current line, which is empty, instead of the next line you typed:

Main.java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int age = in.nextInt();
        String name = in.nextLine();         // the rest of the "17" line: empty
        System.out.println("age=" + age + " name=[" + name + "]");
        String real = in.nextLine();         // now the line "Asha Rao"
        System.out.println("next line=[" + real + "]");
    }
}
Output
age=17 name=[]
next line=[Asha Rao]
The fix
  • Call in.nextLine() once to throw away the rest of the number's line, or read everything with nextLine() and convert with Integer.parseInt(...).

Wrong kind of input, and reading until the input ends

Main.java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int age = in.nextInt();             // the input is "abc"
        System.out.println(age);
    }
}
Error
Exception in thread "main" java.util.InputMismatchException
	at java.base/java.util.Scanner.throwFor(Scanner.java:947)
Main.java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int sum = 0;
        while (in.hasNextInt()) {           // is there another integer?
            sum += in.nextInt();
        }
        System.out.println(sum);
    }
}
Output
15
PythonJava Scanner
a lineinput()in.nextLine()
an integerint(input())in.nextInt()
a decimalfloat(input())in.nextDouble()
bad inputValueErrorInputMismatchException

5.4Generating output

MethodWhat it does
System.out.println(arg)prints arg and goes to a new line; implicitly converts the argument to a string
System.out.print(arg)similar, but does not advance to a new line
System.out.printf(format, args...)formatted output, with the same conventions as printf in C
Main.java
public class Main {
    public static void main(String[] args) {
        System.out.print("a");
        System.out.print("b");
        System.out.println();                           // just a newline
        System.out.println(1 + 2 + "x" + 1 + 2);        // left to right: 3, then text

        System.out.printf("%d|%5d|%-5d|%05d%n", 42, 42, 42, 42);
        System.out.printf("%f|%.2f|%8.3f%n", 3.14159, 3.14159, 3.14159);
        System.out.printf("%s is %d, grade %c, passed: %b%n", "Asha", 17, 'A', true);
        System.out.printf("%,d|%x|%e|%%%n", 1234567, 255, 12345.678);
    }
}
Output
ab
3x12
42|   42|42   |00042
3.141590|3.14|   3.142
Asha is 17, grade A, passed: true
1,234,567|ff|1.234568e+04|%
CodePrintsMeaning
%dan integerdecimal integer; %5d width 5, %-5d left aligned, %05d zero padded
%f %.2fa decimal%.2f keeps 2 digits after the point
%s %c %bstring, char, booleanthe value as text
%na newlineportable line break (prefer it to \n in printf)
%%%a literal percent sign

The type must fit the code. %d with a decimal is a run-time error:

Main.java
public class Main {
    public static void main(String[] args) {
        System.out.printf("%d%n", 3.5);
    }
}
Error
Exception in thread "main" java.util.IllegalFormatConversionException: d != java.lang.Double
	at java.base/java.util.Formatter$FormatSpecifier.failConversion(Formatter.java:4515)
Main.java
public class Main {
    public static void main(String[] args) {
        String s = String.format("%.1f", 2.25);    // format without printing
        System.out.println(s);
        char[] cs = {'h', 'i'};
        System.out.println(cs);                       // a char array prints as text
        System.out.println(100.0 / 3);                // println shows the full double
    }
}
Output
2.3
hi
33.333333333333336

5.5Putting it together

Main.java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("Name: ");
        String name = in.nextLine();
        System.out.print("Age: ");
        int age = in.nextInt();
        System.out.printf("%s will be %d next year.%n", name, age + 1);
    }
}
Terminal
$ java Main
Name: Asha Rao
Age: 17
Asha Rao will be 18 next year.
  • print keeps the cursor on the same line, so the typed answer appears right after the prompt.
  • nextLine() for the name (it has a space), nextInt() for the age.
  • printf builds the sentence in one go, like a Python f-string.

5.6Exam tips and common mistakes

Exam tips
  • readLine gives a String; readPassword gives char[] and does not echo.
  • println adds a newline, print does not, printf formats.
  • After nextInt() or nextDouble() the line break is still in the input.
Common mistakes
  • Forgetting import java.util.Scanner;.
  • Calling nextLine() right after nextInt() and getting an empty string.
  • Using Console inside an IDE and meeting a NullPointerException.
  • A printf code that does not match the argument type (%d with a double).

5.7Interview corner: what they may ask

Likely questionChanceCrisp answer
Scanner vs Console?Very likelyScanner parses tokens and lines from any input and works everywhere. Console needs a real terminal but can read passwords without echo.
Why does readPassword return char[]?LikelyStrings are immutable and linger in memory; a char[] can be wiped right after use.
Why does nextLine() after nextInt() return an empty string?Very likelynextInt() stops before the line break, so nextLine() reads the (empty) rest of that same line. Consume it with an extra nextLine().
print, println and printf?Very likelyprint no newline; println adds one; printf uses a format string (%d %s %.2f %n).
What is System.in?LikelyThe standard input stream (keyboard by default), the counterpart of System.out. Scanner wraps it.
How do you read until the input ends?LikelyLoop on in.hasNext(), hasNextInt() or hasNextLine().
Next · InterviewInterview Question Bank
06
Interview

Interview Question Bank

What is likely to be asked from Week 2, with 30-second answers, deeper explanations, a lecture-or-extra tag on each question, and code-reading practice.

Week 2 is the first week with real Java, so interviewers can ask both concepts and what does this print. Every answer starts with a 30-second version. Each question is tagged From the lecture or Extra, so you know which answers go beyond what the lecture said.

1Definition

One clear sentence: what it is.

2Tiny example

Three or four lines of code.

3The failure it prevents

What goes wrong without it.

6.1Interview heat-map: what is most likely

Very likely9 topics
String immutability, == vs equals"Why are Strings immutable? Compare two Strings."Notes 2.5
public static void main word by word"Why is main static?"Notes 1.2
Constructors: default, overloading, this(...)"When does Java give a default constructor?"Notes 4.3
Shallow vs deep copy, copy constructor"Difference between shallow and deep copy?"Notes 4.4
Primitive types vs objects"Why does Java have primitives?"Notes 2.1
Integer division, casting, overflow"What does 7 / 2 give?"Notes 2.4
switch fall-through"What happens without break?"Notes 3.5
Scanner: nextInt then nextLine"Why do I get an empty line?"Notes 5.3
Compile and run, file name rules"Can the file name differ from the class?"Notes 1.3
Likely5 topics
NullPointerException"When do you get one?"Notes 4.2
this and parameter shadowing"What does this.day = day do?"Notes 4.2
while vs do-while, for vs enhanced for"When do you use each?"Notes 3.3, 3.4
final, array defaults, length vs length()"What is in a new int[3]?"Notes 2.3, 2.6
Console vs Scanner, password as char[]"Why char[] for a password?"Notes 5.2
Sometimes3 topics
print vs println vs printf"Format a number to 2 decimals."Notes 5.4
char is 2 bytes (Unicode)"Can a char hold a Greek letter?"Notes 2.1
Command line arguments"What is args?"Notes 1.2

6.2Getting started and compiling

Interview 1Explain public static void main(String[] args) word by word.
Lecture 1Very likelyNotes 1.2From the lecture

The most asked line in Java.

Answer
Say this first (30 seconds)

public: the JVM can call it from outside. static: it belongs to the class, so it runs before any object exists. void: it returns nothing. main: the agreed starting name. String[] args: the command line arguments.

Go deeper
  • static solves a chicken-and-egg problem: methods normally belong to objects, but we cannot create an object before the program starts.
  • Remove static and it compiles, but the JVM answers "Main method is not static in class Main".
Follow-up they may askCan main be overloaded? Can a class have no main?
Interview 2Must the file name match the class name? How do you compile and run?
Lecture 1Very likelyNotes 1.3From the lecture

Give the exact commands and one thing that goes wrong.

Answer
Say this first (30 seconds)

A public class must live in a file with exactly its name. Compile with javac Name.java (extension needed); run with java Name (no .class).

Go deeper
  • javac makes Name.class bytecode; java starts the JVM, which interprets it.
  • javac follows dependencies, so compiling the class with main compiles the classes it uses.
  • A file may hold other, non-public classes; each still gets its own .class.
Follow-up they may askWhat is the difference between javac and java?

6.3Datatypes, strings and arrays

Interview 3Why does Java have primitive types when it is object oriented?
Lecture 2Very likelyNotes 2.1From the lecture

Name the eight and what separates them from objects.

Answer
Say this first (30 seconds)

Wrapping every number in an object would be cumbersome and slow, so Java keeps eight primitives (byte short int long float double char boolean) that hold the value directly, with sizes fixed by the JVM.

Go deeper
  • Primitives live in the variable itself and cannot be null; objects (String, arrays) are reached through references.
  • Each primitive has an object wrapper (Integer, Double, ...) for collections and null; the compiler converts automatically (boxing). Wrappers are an extra beyond this lecture.
Follow-up they may askWhat are the default values of fields and array cells?
Interview 4Why are Strings immutable, and what does it cost?
Lecture 2Very likelyNotes 2.5From the lecture

The lecture says "if we change a String we get a new object". Say why that is a feature.

Answer
Say this first (30 seconds)

An immutable object can never change under you, so it is safe to share, cache and use as a key. The cost is that every "change" builds a new object.

Go deeper
  • s = s.substring(0, 3) + "p!" makes a new String; the old one becomes garbage and the garbage collector frees it.
  • Concatenating in a long loop builds many throw-away objects. Use StringBuilder (extra) for that.
Follow-up they may askIs a final String the same thing as an immutable String?
Interview 5== versus equals() on Strings.
Lecture 2 + extraVery likelyNotes 2.5Extra: often asked

Predict the output of the snippet, then explain.

Main.java
String a = "hi";
String b = "hi";
String c = new String("hi");
System.out.println(a == b);
System.out.println(a == c);
System.out.println(a.equals(c));
Prints
true
false
true
Answer
Say this first (30 seconds)

== asks whether two references point to the same object; equals asks whether the characters match. For Strings always use equals.

Go deeper
  • Two identical string literals share one object (the string pool), so a == b is true; new String("hi") makes a separate object, so a == c is false.
Follow-up they may askWhat does intern() do?
Interview 6What does 7 / 2 give, and how do you get 3.5? What is overflow?
Lecture 2Very likelyNotes 2.4From the lecture

Integer division, casting and silent overflow in one question.

Answer
Say this first (30 seconds)

7 / 2 is 3 because both are integers. Make one operand a double (7 / 2.0 or (double) 7 / 2) to get 3.5. An int that goes past its range wraps around silently.

Go deeper
  • Widening (int to double) is automatic; narrowing ((int) 3.9) needs a cast and truncates to 3.
  • Integer.MAX_VALUE + 1 is -2147483648. Python never does this because its integers grow.
Follow-up they may askHow would you detect overflow instead of ignoring it?
Interview 7Arrays in Java: defaults, length, and what int[] d = c; does.
Lecture 2LikelyNotes 2.6From the lecture

Compare with a Python list.

Answer
Say this first (30 seconds)

An array is an object with a fixed size and one element type. Its cells start at 0 / false / null, a.length is a field, and assigning an array to another variable copies the reference, not the data.

Go deeper
  • Going outside 0..length-1 throws ArrayIndexOutOfBoundsException at run time.
  • To copy the data use Arrays.copyOf or clone(). To grow, make a bigger array (or use ArrayList, an extra).

6.4Control flow

Interview 8How does switch work? What is fall-through?
Lecture 3Very likelyNotes 3.5From the lecture

What prints for x = 2?

Main.java
int x = 2;
switch (x) {
    case 1: System.out.println("one");
    case 2: System.out.println("two");
    case 3: System.out.println("three"); break;
    case 4: System.out.println("four");
}
Prints
two
three
Answer
Say this first (30 seconds)

switch jumps to the matching case and then keeps running the following cases until a break. That is fall-through. Case labels must be constants.

Go deeper
  • Forgetting break is the classic bug; sometimes it is used on purpose to give several labels one body.
  • Java 14+ has case 1 -> ... arrows that never fall through (extra).
Follow-up they may askWhich types can you switch on?
Interview 9while vs do-while, and plain for vs enhanced for.
Lecture 3LikelyNotes 3.3, 3.4From the lecture

Say when you would pick each.

Answer
Say this first (30 seconds)

while tests first and may run zero times; do-while runs the body first, at least once. Plain for gives you the index; enhanced for (T x : a) gives each element as a copy.

Go deeper
  • Use do-while for "read, then validate". Use plain for when you need i or must change elements.

6.5Classes, objects and constructors

Interview 10What is a constructor? When does Java give you a default one?
Lecture 4Very likelyNotes 4.3From the lecture

A very common question; the trap is the second half.

Answer
Say this first (30 seconds)

A constructor runs when an object is created; it has the class name and no return type. Java supplies a no-argument default constructor only if you wrote no constructor at all.

Go deeper
  • Write any constructor and new Date() stops compiling, unless you add a no-argument one yourself.
  • Constructors can be overloaded, and one can call another with this(...), which must be the first statement.
Follow-up they may askDoes a constructor have a return type? Can it be private?
Interview 11Shallow copy versus deep copy.
Lecture 4Very likelyNotes 4.4From the lecture

Use the Student that holds a Date.

Answer
Say this first (30 seconds)

A shallow copy copies the references, so the copy and the original share the same inner objects. A deep copy duplicates the inner objects too, so the two are independent.

Go deeper
  • Changing the original's inner Date changes the shallow copy's too: aliasing.
  • A copy constructor takes an object of the same class and copies each field, calling new for inner objects to get a deep copy. Java also has clone(), which is shallow by default (extra).
Follow-up they may askIs an array copy made with = shallow or deep?
Interview 12What does this do? Why does day = day; not work in a setter?
Lecture 4LikelyNotes 4.2From the lecture

Parameter shadowing, the classic beginner bug.

Answer
Say this first (30 seconds)

this is a reference to the current object. When a parameter has the same name as a field, the bare name means the parameter, so day = day assigns the parameter to itself. this.day = day sets the field.

Go deeper
  • The program compiles and runs, and the field silently stays at 0.
Interview 13What is a NullPointerException and how do you avoid it?
Lecture 4 + extraVery likelyNotes 4.2Extra: often asked

The most common run-time error in Java.

Answer
Say this first (30 seconds)

It is thrown when you use a reference that points to null (no object), for example calling a method through it. Make sure the variable was given an object with new, and check for null where it can legitimately be empty.

Go deeper
  • A local variable that was never assigned is stopped earlier, by the compiler (might not have been initialized).
  • The message names the variable that was null, which tells you where to look.
Interview 14Why make instance variables private and use getters and setters?
Lecture 4Very likelyNotes 4.1From the lecture

Connect it to Week 1's abstraction.

Answer
Say this first (30 seconds)

A public instance variable breaks encapsulation: outside code depends on how the data is stored. With private fields and methods, the class can change its representation, or validate values, without breaking callers.

Go deeper
  • The compiler enforces it: d.day from outside gives day has private access in Date.

6.6Input and output

Interview 15Why does nextLine() after nextInt() return an empty string?
Lecture 5 + extraVery likelyNotes 5.3Extra: often asked

The classic Scanner trap.

Answer
Say this first (30 seconds)

nextInt() reads only the digits and stops before the line break, so the next nextLine() reads what is left of that same line: nothing. Call nextLine() once to consume it, or read everything with nextLine() and parse it.

Go deeper
  • next(), nextInt() and nextDouble() skip leading whitespace; nextLine() does not.
Interview 16Console vs Scanner; why does readPassword return char[]?
Lecture 5LikelyNotes 5.2From the lecture

Two small facts that often come together.

Answer
Say this first (30 seconds)

Scanner parses tokens and lines from any input and works everywhere. Console needs a real terminal but can read a password without echo. The password is a char[] because an array can be wiped after use, while an immutable String lingers in memory.

Go deeper
  • Without a terminal (IDEs, redirected input) System.console() returns null.
Interview 17print, println, printf: how do you print 3.14159 as 3.14?
Lecture 5LikelyNotes 5.4From the lecture

Name the format codes you know.

Answer
Say this first (30 seconds)

System.out.printf("%.2f%n", 3.14159). print adds no newline, println adds one, and printf formats with C-style codes.

Go deeper
  • %d integer, %f decimal, %s string, %c char, %b boolean, %n newline.
  • A wrong code for the type, like %d with a double, throws IllegalFormatConversionException.

6.7Code-reading questions to expect

All outputs below come from really compiling and running the code. Try each before opening the answer.

Trace ADivision and casts
Code readingVery likelyNotes 2.4
Main.java
System.out.println(7 / 2 + " " + 7 / 2.0 + " " + (double) 7 / 2 + " " + (double) (7 / 2));
Answer
Prints
3 3.5 3.5 3.0
  • 7 / 2 is integer division: 3. 7 / 2.0: 3.5.
  • (double) 7 / 2 casts the 7 first: 3.5. (double) (7 / 2) divides first, then converts 3: 3.0.
Trace BChar arithmetic and concatenation
Code readingLikelyNotes 2.1, 2.5
Main.java
System.out.println('a' + 1 + "b" + 'c');
System.out.println("b" + 'c' + 1);
System.out.println((char) ('a' + 1));
Answer
Prints
98bc
bc1
b
  • 'a' + 1 is arithmetic on the char's number (97 + 1 = 98); only after a String appears does + concatenate.
  • A cast turns the number back into a char.
Trace CConstructor chaining
Code readingVery likelyNotes 4.3
Main.java
public class Main {
    static class D {
        int day, month, year;

        D(int d, int m, int y) {
            System.out.println("3-argument constructor");
            day = d;
            month = m;
            year = y;
        }

        D(int d, int m) {
            this(d, m, 2021);
            System.out.println("2-argument constructor finished");
        }
    }

    public static void main(String[] args) {
        D x = new D(13, 8);
        System.out.println(x.year);
    }
}
Answer
Prints
3-argument constructor
2-argument constructor finished
2021
  • new D(13, 8) enters the 2-argument constructor, whose first line this(d, m, 2021) runs the 3-argument one first. Only then does the rest of the 2-argument body run.
Trace DLoop variable is a copy
Code readingVery likelyNotes 3.4, 2.6
Main.java
int[] a = {1, 2, 3};
for (int v : a) {
    v = v * 10;
}
int[] b = a;
b[0] = 99;
System.out.println(a[0] + " " + a[1] + " " + a[2]);
Answer
Prints
99 2 3
  • v is a copy, so the first loop changes nothing.
  • b = a shares the array, so b[0] = 99 shows through a.
Next · SummaryWeek 2 Summary Sheet
07
Summary

Week 2 Summary Sheet

Week 2 on one page: a lecture-by-lecture glance, key terms, the pairs to tell apart, the errors you can now read, a checklist and corrections to the source notes.

7.1Week 2 at a glance

L1A first taste of Java

All code lives in classes; main starts the program; javac makes bytecode and java runs it on the JVM.

L2Basic datatypes

Eight primitives; integer division and casts; Strings are immutable objects; arrays are objects.

L3Control flow

if, while, do-while, two kinds of for, and switch that falls through without break.

L4Classes and objects

Private fields with getters and setters, constructors and overloading, this, copy constructors, shallow vs deep copy.

L5Input and output

Console and Scanner read; println, print and printf write.

7.2Key terms, lecture by lecture

L1 · A first taste of Java
public
Visible from outside the class.
static
Belongs to the class; needs no object.
void
The method returns nothing.
main
Where the JVM starts the program.
String[] args
Command line arguments.
javac / java
Compile to bytecode / run it on the JVM.
L2 · Basic datatypes
Primitive
A scalar value that is not an object.
char
A 2-byte Unicode character, in single quotes.
final
A constant: assigned once.
Cast
An explicit conversion: (int) 3.9.
String
An immutable object; text in double quotes.
Array
An object of fixed size and one element type.
L3 · Control flow
do-while
Tests at the end: runs at least once.
Enhanced for
for (T x : a): each element, as a copy.
switch
Multiway branch on constants.
Fall-through
Running on into the next case without break.
break
Leaves a switch or a loop.
L4 · Classes and objects
Instance variable
Data each object keeps its own copy of.
Accessor / mutator
A getter / a setter method.
this
The current object; this(...) calls another constructor.
Constructor
Class-named code that sets an object up.
Default constructor
Supplied only if none is written.
Copy constructor
Builds a new object from an existing one.
Shallow / deep copy
Shares inner objects / duplicates them.
L5 · Input and output
Scanner
Reads tokens and lines from System.in.
Console
Terminal input; readLine, readPassword.
println / print
Print with / without a newline.
printf
Formatted output: %d %s %.2f %n.

7.3The pairs you must tell apart

==same object?
VS
equals()same characters?
'x' (char)one character, single quotes
VS
"x" (String)an object, double quotes
Wideningautomatic, safe
VS
Narrowingneeds a cast, may lose data
a.lengtharray field, no brackets
VS
s.length()String method, with brackets
whiletests first, may run 0 times
VS
do-whileruns first, at least once
Plain forhas the index
VS
Enhanced foreach element, as a copy
breakleaves the switch
VS
No breakfalls through to the next case
Overloadingsame name, different parameters (Java)
VS
Default argumentsone function, optional parameters (Python)
Default constructorgiven only if you write none
VS
Explicit constructoryou write it; removes the default
Shallow copyshares inner objects
VS
Deep copyduplicates them too
printno newline
VS
printlnadds a newline
Consoleneeds a real terminal
VS
Scannerworks everywhere
Primitiveholds the value, never null
VS
Objectreached by reference, can be null

7.4Messages and errors you can now read

What went wrongWhat you will seeWhen
double literal into a float (float y = 5.7;)error: incompatible types: possible lossy conversion from double to floatcompile time
narrowing without a cast (b = b + 5 for a byte)error: incompatible types: possible lossy conversion from int to bytecompile time
assigning a final variable twiceerror: cannot assign a value to final variable picompile time
reading a local that was never seterror: variable x might not have been initializedcompile time
"x" where a char is needederror: incompatible types: String cannot be converted to charcompile time
indexing a String like an arrayerror: array required, but String foundcompile time
array constant outside a declarationerror: illegal start of expressioncompile time
a variable as a case labelerror: constant expression requiredcompile time
loop variable used after the looperror: cannot find symbolcompile time
outside code touching a private fielderror: day has private access in Datecompile time
no constructor matches the argumentserror: constructor Date in class Date cannot be applied to given types;compile time
public class in a file with another nameerror: class helloworld is public, should be declared in a file named helloworld.javacompile time
main without staticError: Main method is not static in class Mainrun time
java Name.classError: Could not find or load main class helloworld.classrun time
integer divided by zerojava.lang.ArithmeticException: / by zerorun time
index outside the arrayjava.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5run time
method call on nulljava.lang.NullPointerExceptionrun time
nextInt() on textjava.util.InputMismatchExceptionrun time
%d with a decimaljava.util.IllegalFormatConversionException: d != java.lang.Doublerun time

7.5Last-minute checklist

L1 · A first taste of Java
  • Every word of public static void main(String[] args)
  • javac Name.java, java Name
  • File name = public class name
  • Bytecode, JVM, write once run anywhere
L2 · Basic datatypes
  • The eight primitives and their sizes
  • Declare, initialise, final
  • Integer division, Math.pow, ++, +=
  • Casting and overflow
  • Strings immutable; equals not ==
  • Arrays: new, length, indices
L3 · Control flow
  • if / else if, no elif
  • while vs do-while
  • Both kinds of for
  • switch, break, fall-through
L4 · Classes and objects
  • Private fields, getters and setters
  • new, this
  • Constructors, overloading, this(...)
  • Default and copy constructors
  • Shallow vs deep copy
L5 · Input and output
  • Console: readLine, readPassword
  • Scanner and its next... methods
  • println, print, printf

7.6Corrections made to the source notes

WhereThe source saysCorrect
Lecture 2, initializationfloat y = 5.7;does not compile: use 5.7f or double (checked by running)
Lecture 2, decrementb—;b--;
Lecture 2, arraysa = {2, 3, 5, 7, 11};illegal: use a = new int[] {2, 3, 5, 7, 11}; (checked by running)
Lecture 2, characterscurly quotes ‘x’ in the PDFJava needs straight quotes 'x'
Lecture 2, Math.pow"returns an"returns it as a double, e.g. 1024.0
Lecture 2, boolean size1 bytethe JVM does not strictly fix it; 1 byte is typical
Lecture 1, class namehelloworldworks, but Java convention is HelloWorld
Revision overview
First tasteclass + main
javac, java
bytecode, JVM
Datatypes8 primitives
casts, / and %
String, array objects
Control flowif, while, do-while
for, for (x : a)
switch + break
Week 2Java basics
Classesprivate fields
constructors, this(...)
shallow vs deep copy
Input / outputConsole, Scanner
println, print
printf
Traps== vs equals
7 / 2 is 3
nextInt then nextLine
Revision: all of Week 2 on one page
Back to top