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.
Chapters
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.
print('hello, world')hello, world#include <stdio.h>
main() {
printf("hello, world\n");
}public class helloworld {
public static void main(String[] args) {
System.out.println("hello, world");
}
}hello, worldhelloworld. 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.
| Piece | What it means | Why Java needs it |
|---|---|---|
class | All code lies within a class. There are no free-floating functions, unlike Python. | Java is object oriented: everything belongs to some type. |
public | Visibility modifier: who may use it. | main must be reachable from outside the class, since the JVM starts it. |
static | The method belongs to the class, not to an object. | No object exists yet when the program starts. |
void | Return type: nothing is returned. | Java wants every method's output type declared. |
main | The agreed name where execution starts (a convention from C). | The JVM must know which method to call by default. |
String[] args | Input: an array of strings, the command line arguments. | Input types must be declared too. |
System.out.println | System 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
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);
}
}
}$ javac Greet.java
$ java Greet Asha Ravi
words typed after the program name: 2
hello, Asha
hello, RaviWhat 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:
public class Main {
public void main(String[] args) { // static is missing
System.out.println("hi");
}
}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: classhelloworldinhelloworld.java. javaccompiles it to JVM bytecode:javac helloworld.javacreateshelloworld.class.java helloworldinterprets 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".
$ javac helloworld.java
$ ls
helloworld.class helloworld.java
$ java helloworld
hello, worldjavacrequires the file extension:javac helloworld.java.javamust not be given.class: give the class name only. Otherwise:
$ java helloworld.class
Error: Could not find or load main class helloworld.class
Caused by: java.lang.ClassNotFoundException: helloworld.classThe file name must match the public class
$ javac Hello.java
Hello.java:1: error: class helloworld is public, should be declared in a file named helloworld.java
public class helloworld {
^
1 errorjavac 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.
public class Greeter {
public String hi(String name) {
return "hello, " + name;
}
}public class Main {
public static void main(String[] args) {
Greeter g = new Greeter();
System.out.println(g.hi("Asha"));
}
}$ javac Main.java
$ ls *.class
Greeter.class Main.class
$ java Main
hello, Ashapublic and it names the file. Each class still compiles to its own .class file.1.4What to carry forward
| Python | Java | |
|---|---|---|
| Where code lives | anywhere, functions on their own | inside classes |
| Blocks | indentation | braces and semicolons |
| Types | from values, not declared | declared in advance |
| Run a program | python hello.py | javac Hello.java, then java Hello |
| Portability | needs an interpreter | bytecode runs on any JVM |
- The syntax of Java is comparatively heavy. Many modifiers are the unavoidable overhead of object-oriented design.
- Visibility:
publicandprivate. Availability: all functions live inside objects, sostaticdefinitions 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
- 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 missingmainfails injava.
- Writing
java Name.classorjavac Name. - A file name that differs from the public class (even in capitals).
- Forgetting
staticor misspellingString[] args, so the JVM cannot findmain. - Forgetting the semicolon at the end of a statement.
1.6Interview corner: what they may ask
| Likely question | Chance | Crisp answer |
|---|---|---|
Why is main public static void? | Very likely | public: 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? | Likely | The command line arguments, passed as an array of strings: java Greet Asha Ravi gives args.length == 2. |
Difference between javac and java? | Very likely | javac is the compiler: .java to .class bytecode. java starts the JVM, which runs the bytecode. |
| Must the file name match the class name? | Very likely | For a public class, yes, exactly. Other classes in the file may have any name; each gets its own .class. |
What is System.out.println? | Likely | System 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 likely | javac produces bytecode, which any JVM can run, so the same .class works on every OS. |
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:
| Group | Types |
|---|---|
| whole numbers | int, long, short, byte |
| decimals | float, double |
| characters | char |
| truth values | boolean |
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.
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);
}
}byte -128 to 127
short -32768 to 32767
int -2147483648 to 2147483647
long -9223372036854775808 to 9223372036854775807
char 0 to 65535charis 2 bytes because it holds a Unicode character, so'\u03C0'(Greek pi) is a perfectly goodchar.booleanhas onlytrueandfalse. The lecture lists it as 1 byte; the JVM does not strictly fix its size, 1 byte is what it usually takes.intis the everyday whole-number type: about ±2.1 billion. Uselongwhen 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.
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);
}
}12
x
π
false true- Characters are written with single quotes only. Double quotes make a
String. They are different types:
public class Main {
public static void main(String[] args) {
char c = "x";
}
}Main.java:3: error: incompatible types: String cannot be converted to char
char c = "x";
^
1 error- Boolean constants are
trueandfalse, in lower case. (Python'sTrueandFalsedo not work.) - A local variable must be given a value before it is read. Java refuses to guess:
public class Main {
public static void main(String[] args) {
int x;
System.out.println(x);
}
}Main.java:4: error: variable x might not have been initialized
System.out.println(x);
^
1 error2.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
finalmarks a constant: it can be assigned only once.
public class Main {
public static void main(String[] args) {
final float pi = 3.1415927f;
pi = 22/7; // flagged as an error
}
}Main.java:4: error: cannot assign a value to final variable pi
pi = 22/7; // flagged as an error
^
1 errorfloat 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;.public class Main {
public static void main(String[] args) {
float y = 5.7;
}
}Main.java:3: error: incompatible types: possible lossy conversion from double to float
float y = 5.7;
^
1 errorpublic class Main {
public static void main(String[] args) {
float y = 5.7f;
double z = 5.7;
System.out.println(y + " " + z);
}
}5.7 5.7Default 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.
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]);
}
}0 false 0.0 null
0 0 02.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 as adouble. - Increment and decrement operators exist:
a++,b--, and shortcuts likea += 7,b *= 12.
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);
}
}3.0
3
3.142857142857143
-3
-1
1024.0
1024
8 108b—;. The decrement operator is two plain minus signs: b--;.a++ versus ++a
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);
}
}5
6
7
7Type 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.
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));
}
}3
-3
-56
-2147483648
2147483648
15
66
Bpublic class Main {
public static void main(String[] args) {
byte small = 10;
small = small + 5;
}
}Main.java:4: error: incompatible types: possible lossy conversion from int to byte
small = small + 5;
^
1 errorsmall = small + 5is anintexpression, which will not fit back in abytewithout a cast, butsmall += 5inserts that cast itself.- Overflow is silent:
Integer.MAX_VALUE + 1becomes-2147483648. There is no error, unlike Python which grows its integers.
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
}
}0.30000000000000004
Infinity
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.main(Main.java:5)2.5Strings
Stringis 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 assubstringinstead.
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());
}
}Hello world
Help!
5
e
HELLOpublic class Main {
public static void main(String[] args) {
String s = "Hello";
s[3] = 'p';
}
}Main.java:4: error: array required, but String found
s[3] = 'p';
^
1 error- Strings are immutable. If we "change" a
Stringwe really get a new object, andspoints 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)
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"
}
}true
false
true
123
33==compares references (are they the same object?).equalscompares contents. For strings, always useequals.
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.lengthgives the size. For aStringit is a method:s.length().- Indices run from
0toa.length - 1. - The size can be a variable, chosen at run time. Array constants
{v1, v2, v3}are allowed.
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
}
}5 0
10
20
11
99
[99, 3, 5]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}.public class Main {
public static void main(String[] args) {
int[] a;
a = {2, 3, 5, 7, 11};
}
}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 errorspublic class Main {
public static void main(String[] args) {
int[] a;
a = new int[] {2, 3, 5, 7, 11};
System.out.println(a.length);
}
}5Going outside the valid indices is a run-time error, not a compile-time one:
public class Main {
public static void main(String[] args) {
int[] a = new int[5];
System.out.println(a[5]);
}
}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
- Integer division: if both operands are integers the result is an integer. One
doubleoperand is enough to get a decimal result. - A cast to
inttruncates (3.9 becomes 3, -3.9 becomes -3). It does not round. - Single quotes for a
char, double quotes for aString. - Array of size
nhas valid indices0ton-1;a.lengthwithout brackets,s.length()with.
- Writing
float x = 3.14;(adoubleliteral): addf. - Comparing strings with
==instead ofequals. - Expecting
7 / 2to be3.5. It is3. - Assuming an assigned array is a copy:
int[] d = c;shares one array. - Modifying a
finalvariable, or reading an uninitialised local.
2.8Interview corner: what they may ask
| Likely question | Chance | Crisp answer |
|---|---|---|
| Primitive types vs objects? Name the eight. | Very likely | Primitives (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 likely | An 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 likely | 3, because both are integers. 3.5, because the cast to double happens first and widens the other operand. |
| What happens on integer overflow? | Likely | It 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? | Likely | An 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? | Likely | A final variable can be assigned only once, so it is a constant. (On classes and methods it also forbids extending or overriding.) |
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
{ }.
| Purpose | Java | Python equivalent |
|---|---|---|
| Conditional execution | if (c) { ... } else { ... } | if / elif / else |
| Conditional loop | while (c) { ... }, do { ... } while (c); | while c: |
| Iteration | two kinds of for | for x in l:, range |
| Multiway branching | switch | if / elif chain |
3.2Conditional execution: if and else
elseis optional. The condition must be in parentheses.- If the body is a single statement, braces are not needed.
- There is no
elif. Writeelse if: a nestedifis one statement, so it needs no extra braces. Indentation is not enforced; just align theelse ifby habit. - Aside: there is no
deffor a function. A method is written with its modifiers and types:public static int sign(int v).
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));
}
}-1 0 1Why 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.
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");
}
}else belongs to the inner if
done3.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.
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));
}
}55 55
0 0Same 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:
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);
}
}do body runs once, i = 103.4Iteration: the two kinds of for
The classic for, inherited from C
for (int i = 0; i < n; ++i) {
// body
}
// is exactly the same as
int i = 0;
while (i < n) {
// body
++i;
}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.
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);
}
}10 10The 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:
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
}
System.out.println(i);
}
}Main.java:5: error: cannot find symbol
System.out.println(i);
^
symbol: variable i
location: class Main
1 errorpublic 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));
}
}28Iterating 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.
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));
}
}28One catch: v is a copy of each element, so assigning to it does not change the array.
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]);
}
}1 2 3
10 20 30| Use | When |
|---|---|
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 |
while | you do not know in advance how many times |
3.5Multiway branching: switch
switchselects between different options. The options (caselabels) have to be constants: no conditional expressions.- The default behaviour is to fall through from one case to the next. You must
breakout explicitly. (breakalso works in loops.)
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");
}
}Negative
Positive
Zero
endAside: 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:
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");
}
}
}two
threeA case label must be a constant, not a variable:
public class Main {
public static void main(String[] args) {
int k = 2;
int x = 1;
switch (x) {
case k: break;
}
}
}Main.java:6: error: constant expression required
case k: break;
^
1 errorHandy extras (not in the lecture)
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
}
}weekend
Wed
1 3 4
neg3.6Exam tips and common mistakes
- Trace a
switchwithoutbreakby writing down every line from the matching case downwards. whilecan run 0 times,do-whileat least once.- A
forvariable declared in the header does not exist after the loop. - For an
ifwithout braces only the next one statement belongs to it.
- Writing
elif, or anifcondition without parentheses. - Forgetting
breakin aswitch. - Writing
=where==is meant. In anifwith ints the compiler rejects it, butbooleanvariables can slip through. - Adding a semicolon right after
if (c)orfor (...), which makes the body empty. - Trusting indentation to show which
ifanelsebelongs to.
3.7Interview corner: what they may ask
| Likely question | Chance | Crisp answer |
|---|---|---|
Difference between while and do-while? | Very likely | while 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 likely | Without 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? | Likely | Integral types, char, enums and String; case labels must be constants. |
Plain for vs enhanced for? | Very likely | Enhanced 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? | Likely | Only the loop itself. After the closing brace the name no longer exists. |
Does Java have elif? | Sometimes | No. You write else if: an if nested in the else. |
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
classand the class name. The modifierpublicsays 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
Datehas its own local copies ofday,month,year. They are markedprivate. Apublicinstance variable is possible, but it breaks encapsulation.
public class Date {
private int day, month, year;
}| Python (Week 1) | Java (this week) |
|---|---|
class Date: | public class Date { ... } |
self.day | this.day |
instance variables created in __init__ | declared in the class body, with a type and private |
anyone can read d.day | d.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
newcreates the object:Date d; d = new Date();. - How do we set the instance variables? Add methods. Inside them
thisis 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.
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);
}
}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());
}
}0/0/0
13/8/2015Because day is private, code outside the class has to go through the methods. This is encapsulation:
public class Main {
public static void main(String[] args) {
Date d = new Date();
System.out.println(d.day);
}
}Main.java:4: error: day has private access in Date
System.out.println(d.day);
^
1 errorA 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:
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());
}
}0
9A variable is not an object
public class Main {
public static void main(String[] args) {
Date d;
System.out.println(d.getDay());
}
}Main.java:4: error: variable d might not have been initialized
System.out.println(d.getDay());
^
1 errorpublic class Main {
public static void main(String[] args) {
Date d = null;
System.out.println(d.getDay());
}
}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
nullpoints at no object, so calling a method through it throwsNullPointerExceptionat run time.
4.3Constructors
- We would like to set an object up when we create it: combine
new Date()andsetDate(). 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.)
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.
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);
}
}3-argument constructor
2-argument constructor finished
2021The 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 (intto 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():
public class Main {
public static void main(String[] args) {
Date d = new Date();
}
}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 error4.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 theprivatevariables of the argument are visible, because both are the same class.
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
}
}2000 1954Shallow 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.
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);
}
}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());
}
}original: 9
shallow : 9
deep : 14.5Putting the Date class together
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); }
}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());
}
}13/8/2015
2021
2015| Piece | What it does |
|---|---|
private fields | hide the representation |
getters and setDate | the public interface |
| 3-argument constructor | the one that really sets things up |
| 2-argument constructor | overload that reuses it with this(...) |
| copy constructor | a new, independent Date |
4.6Exam tips and common mistakes
- Constructor = same name as the class, no return type. Adding
voidturns 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.
- Writing
day = day;in a setter and wondering why nothing changes: usethis.day = day;. - Using a declared-but-never-
newed variable: a compile error, or aNullPointerExceptionif it was set tonull. - 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 question | Chance | Crisp answer |
|---|---|---|
| What is a constructor? Can it be overloaded? Does it return anything? | Very likely | Special 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 likely | A no-argument constructor the compiler adds only when you write none. Writing any constructor removes it. |
What does this mean? What is this(...)? | Very likely | this 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 likely | Shallow 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 likely | To hide the representation, so it can change without breaking callers, and to validate values in one place. |
| Constructor overloading vs Python's default arguments? | Likely | Java has no default arguments; you write several constructors, often one chaining to another with this(...). |
What is a NullPointerException? | Very likely | Using a reference that points at null (no object), for example calling a method through it. It happens at run time. |
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.
5.2Reading input with Console
- The simplest to use is the
Consoleclass, quite similar to Python'sinput(). You get one fromSystem.console(). - Two methods:
readLinereturns aString(likeinput());readPasswordreturns an array ofcharand does not echo the characters on the screen.
Console cons = System.console();
String username = cons.readLine("Username: ");
char[] password = cons.readPassword("Password: ");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:
public class Main {
public static void main(String[] args) {
java.io.Console cons = System.console();
String username = cons.readLine("Username: ");
System.out.println(username);
}
}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)Consoleis fine in a real terminal, and the only choice for passwords. For everything else, and in IDEs or online judges, useScanner.
5.3Scanner: reading line by line or token by token
- The more general
Scannerclass allows more granular reading: a full line, or an integer, and so on. - Create it on the input stream:
new Scanner(System.in). Then callnextLine(),nextInt(),nextDouble(),next()(one word). Scannerlives injava.util, so you needimport java.util.Scanner;at the top.
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);
}
}$ java Main
Asha Rao
17
Asha Rao is 17The 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:
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 + "]");
}
}age=17 name=[]
next line=[Asha Rao]- Call
in.nextLine()once to throw away the rest of the number's line, or read everything withnextLine()and convert withInteger.parseInt(...).
Wrong kind of input, and reading until the input ends
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);
}
}Exception in thread "main" java.util.InputMismatchException
at java.base/java.util.Scanner.throwFor(Scanner.java:947)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);
}
}15| Python | Java Scanner | |
|---|---|---|
| a line | input() | in.nextLine() |
| an integer | int(input()) | in.nextInt() |
| a decimal | float(input()) | in.nextDouble() |
| bad input | ValueError | InputMismatchException |
5.4Generating output
| Method | What 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 |
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);
}
}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|%| Code | Prints | Meaning |
|---|---|---|
%d | an integer | decimal integer; %5d width 5, %-5d left aligned, %05d zero padded |
%f %.2f | a decimal | %.2f keeps 2 digits after the point |
%s %c %b | string, char, boolean | the value as text |
%n | a newline | portable 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:
public class Main {
public static void main(String[] args) {
System.out.printf("%d%n", 3.5);
}
}Exception in thread "main" java.util.IllegalFormatConversionException: d != java.lang.Double
at java.base/java.util.Formatter$FormatSpecifier.failConversion(Formatter.java:4515)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
}
}2.3
hi
33.3333333333333365.5Putting it together
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);
}
}$ java Main
Name: Asha Rao
Age: 17
Asha Rao will be 18 next year.printkeeps 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.printfbuilds the sentence in one go, like a Python f-string.
5.6Exam tips and common mistakes
readLinegives aString;readPasswordgiveschar[]and does not echo.printlnadds a newline,printdoes not,printfformats.- After
nextInt()ornextDouble()the line break is still in the input.
- Forgetting
import java.util.Scanner;. - Calling
nextLine()right afternextInt()and getting an empty string. - Using
Consoleinside an IDE and meeting aNullPointerException. - A
printfcode that does not match the argument type (%dwith a double).
5.7Interview corner: what they may ask
| Likely question | Chance | Crisp answer |
|---|---|---|
Scanner vs Console? | Very likely | Scanner 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[]? | Likely | Strings are immutable and linger in memory; a char[] can be wiped right after use. |
Why does nextLine() after nextInt() return an empty string? | Very likely | nextInt() 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 likely | print no newline; println adds one; printf uses a format string (%d %s %.2f %n). |
What is System.in? | Likely | The standard input stream (keyboard by default), the counterpart of System.out. Scanner wraps it. |
| How do you read until the input ends? | Likely | Loop on in.hasNext(), hasNextInt() or hasNextLine(). |
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.
One clear sentence: what it is.
Three or four lines of code.
What goes wrong without it.
6.1Interview heat-map: what is most likely
== vs equals"Why are Strings immutable? Compare two Strings."Notes 2.5public static void main word by word"Why is main static?"Notes 1.2this(...)"When does Java give a default constructor?"Notes 4.37 / 2 give?"Notes 2.4switch fall-through"What happens without break?"Notes 3.5Scanner: nextInt then nextLine"Why do I get an empty line?"Notes 5.3NullPointerException"When do you get one?"Notes 4.2this and parameter shadowing"What does this.day = day do?"Notes 4.2while vs do-while, for vs enhanced for"When do you use each?"Notes 3.3, 3.4final, array defaults, length vs length()"What is in a new int[3]?"Notes 2.3, 2.6Console vs Scanner, password as char[]"Why char[] for a password?"Notes 5.2print vs println vs printf"Format a number to 2 decimals."Notes 5.4char is 2 bytes (Unicode)"Can a char hold a Greek letter?"Notes 2.1args?"Notes 1.26.2Getting started and compiling
public static void main(String[] args) word by word.The most asked line in Java.
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
staticsolves a chicken-and-egg problem: methods normally belong to objects, but we cannot create an object before the program starts.- Remove
staticand it compiles, but the JVM answers "Main method is not static in class Main".
main be overloaded? Can a class have no main?Give the exact commands and one thing that goes wrong.
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
javacmakesName.classbytecode;javastarts the JVM, which interprets it.javacfollows dependencies, so compiling the class withmaincompiles the classes it uses.- A file may hold other, non-public classes; each still gets its own
.class.
javac and java?6.3Datatypes, strings and arrays
Name the eight and what separates them from objects.
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 andnull; the compiler converts automatically (boxing). Wrappers are an extra beyond this lecture.
The lecture says "if we change a String we get a new object". Say why that is a feature.
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.
final String the same thing as an immutable String?== versus equals() on Strings.Predict the output of the snippet, then explain.
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));true
false
true== 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 == bistrue;new String("hi")makes a separate object, soa == cisfalse.
intern() do?7 / 2 give, and how do you get 3.5? What is overflow?Integer division, casting and silent overflow in one question.
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 (
inttodouble) is automatic; narrowing ((int) 3.9) needs a cast and truncates to3. Integer.MAX_VALUE + 1is-2147483648. Python never does this because its integers grow.
int[] d = c; does.Compare with a Python list.
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-1throwsArrayIndexOutOfBoundsExceptionat run time. - To copy the data use
Arrays.copyOforclone(). To grow, make a bigger array (or useArrayList, an extra).
6.4Control flow
switch work? What is fall-through?What prints for x = 2?
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");
}two
threeswitch 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
breakis 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).
while vs do-while, and plain for vs enhanced for.Say when you would pick each.
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-whilefor "read, then validate". Use plainforwhen you needior must change elements.
6.5Classes, objects and constructors
A very common question; the trap is the second half.
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.
private?Use the Student that holds a Date.
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
Datechanges the shallow copy's too: aliasing. - A copy constructor takes an object of the same class and copies each field, calling
newfor inner objects to get a deep copy. Java also hasclone(), which is shallow by default (extra).
= shallow or deep?this do? Why does day = day; not work in a setter?Parameter shadowing, the classic beginner bug.
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.
NullPointerException and how do you avoid it?The most common run-time error in Java.
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.
private and use getters and setters?Connect it to Week 1's abstraction.
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.dayfrom outside gives day has private access in Date.
6.6Input and output
nextLine() after nextInt() return an empty string?The classic Scanner trap.
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()andnextDouble()skip leading whitespace;nextLine()does not.
Console vs Scanner; why does readPassword return char[]?Two small facts that often come together.
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()returnsnull.
print, println, printf: how do you print 3.14159 as 3.14?Name the format codes you know.
System.out.printf("%.2f%n", 3.14159). print adds no newline, println adds one, and printf formats with C-style codes.
Go deeper
%dinteger,%fdecimal,%sstring,%cchar,%bboolean,%nnewline.- A wrong code for the type, like
%dwith a double, throwsIllegalFormatConversionException.
6.7Code-reading questions to expect
All outputs below come from really compiling and running the code. Try each before opening the answer.
System.out.println(7 / 2 + " " + 7 / 2.0 + " " + (double) 7 / 2 + " " + (double) (7 / 2));3 3.5 3.5 3.07 / 2is integer division:3.7 / 2.0:3.5.(double) 7 / 2casts the7first:3.5.(double) (7 / 2)divides first, then converts3:3.0.
System.out.println('a' + 1 + "b" + 'c');
System.out.println("b" + 'c' + 1);
System.out.println((char) ('a' + 1));98bc
bc1
b'a' + 1is arithmetic on the char's number (97 + 1 =98); only after aStringappears does+concatenate.- A cast turns the number back into a
char.
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);
}
}3-argument constructor
2-argument constructor finished
2021new D(13, 8)enters the 2-argument constructor, whose first linethis(d, m, 2021)runs the 3-argument one first. Only then does the rest of the 2-argument body run.
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]);99 2 3vis a copy, so the first loop changes nothing.b = ashares the array, sob[0] = 99shows througha.
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
All code lives in classes; main starts the program; javac makes bytecode and java runs it on the JVM.
Eight primitives; integer division and casts; Strings are immutable objects; arrays are objects.
if, while, do-while, two kinds of for, and switch that falls through without break.
Private fields with getters and setters, constructors and overloading, this, copy constructors, shallow vs deep copy.
Console and Scanner read; println, print and printf write.
7.2Key terms, lecture by lecture
- 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.
- 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.
- 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
switchor a loop.
- 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.
- 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
7.4Messages and errors you can now read
| What went wrong | What you will see | When |
|---|---|---|
double literal into a float (float y = 5.7;) | error: incompatible types: possible lossy conversion from double to float | compile time |
narrowing without a cast (b = b + 5 for a byte) | error: incompatible types: possible lossy conversion from int to byte | compile time |
assigning a final variable twice | error: cannot assign a value to final variable pi | compile time |
| reading a local that was never set | error: variable x might not have been initialized | compile time |
"x" where a char is needed | error: incompatible types: String cannot be converted to char | compile time |
| indexing a String like an array | error: array required, but String found | compile time |
| array constant outside a declaration | error: illegal start of expression | compile time |
a variable as a case label | error: constant expression required | compile time |
| loop variable used after the loop | error: cannot find symbol | compile time |
| outside code touching a private field | error: day has private access in Date | compile time |
| no constructor matches the arguments | error: constructor Date in class Date cannot be applied to given types; | compile time |
| public class in a file with another name | error: class helloworld is public, should be declared in a file named helloworld.java | compile time |
main without static | Error: Main method is not static in class Main | run time |
java Name.class | Error: Could not find or load main class helloworld.class | run time |
| integer divided by zero | java.lang.ArithmeticException: / by zero | run time |
| index outside the array | java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5 | run time |
method call on null | java.lang.NullPointerException | run time |
nextInt() on text | java.util.InputMismatchException | run time |
%d with a decimal | java.util.IllegalFormatConversionException: d != java.lang.Double | run time |
7.5Last-minute checklist
- 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
- The eight primitives and their sizes
- Declare, initialise,
final - Integer division,
Math.pow,++,+= - Casting and overflow
- Strings immutable;
equalsnot== - Arrays:
new,length, indices
if/else if, noelifwhilevsdo-while- Both kinds of
for switch,break, fall-through
- Private fields, getters and setters
new,this- Constructors, overloading,
this(...) - Default and copy constructors
- Shallow vs deep copy
Console:readLine,readPasswordScannerand itsnext...methodsprintln,print,printf
7.6Corrections made to the source notes
| Where | The source says | Correct |
|---|---|---|
| Lecture 2, initialization | float y = 5.7; | does not compile: use 5.7f or double (checked by running) |
| Lecture 2, decrement | b—; | b--; |
| Lecture 2, arrays | a = {2, 3, 5, 7, 11}; | illegal: use a = new int[] {2, 3, 5, 7, 11}; (checked by running) |
| Lecture 2, characters | curly quotes ‘x’ in the PDF | Java needs straight quotes 'x' |
| Lecture 2, Math.pow | "returns an" | returns it as a double, e.g. 1024.0 |
| Lecture 2, boolean size | 1 byte | the JVM does not strictly fix it; 1 byte is typical |
| Lecture 1, class name | helloworld | works, but Java convention is HelloWorld |
javac, java
bytecode, JVM
casts, / and %
String, array objects
for, for (x : a)
switch + break
constructors, this(...)
shallow vs deep copy
println, print
printf
7 / 2 is 3
nextInt then nextLine