Chapter 1 (intro to OOP, getting started with Java, numerical data), Chapter 2 (programmer-defined classes, this, overloading) and Chapter 3 (selection statements: if, switch, enum). Every slide is covered, including the ones that were only pictures and diagrams.
✎ Select any text to add your own highlights. They're saved and only you can see them.
how we got to OOP
anatomy of an object
the cookie-cutter picture
one class (cutter) can stamp out many objects (cookies) → "an object is an instance of a class"
<Object Name> : <Class Name>, shows which class the object is an instance of, e.g. SV198 : BankAccount.the three icons
three message diagrams from the slides
① message deposit with argument 250.00 is sent to object SV198 (instance method, nothing comes back)
② ask for the current balance of this particular account → SV198 sends its balance back to the sender
③ class method: sent to the class itself (not underlined), returns the max possible speed for all MobileRobot objects back to the sender
sample class & instance data values
the dashed lines = instance-of relationship · one shared copy of minimum balance in the class · all 3 objects have the same instance data value (current balance) but different amounts
no class icon drawn?
sample inheritance
inheritance hierarchy
the 5 stages, in order
mnemonic: A D C T O → "A Dog Can Take Orders"
| # | Advantage | Why |
|---|---|---|
| 1 | Improved software-development productivity | modular (separation of duties), extensible (objects extended with new attributes & behaviours), reused within and across applications |
| 2 | Improved software maintainability | easier to maintain; modular design means part of the system can be updated without large-scale changes |
| 3 | Faster development | reuse → faster development; rich libraries of objects; project code reusable in future projects |
| 4 | Lower cost of development | reuse lowers cost; more effort goes into OO analysis & design, which lowers the overall cost |
| 5 | Higher-quality software | faster + cheaper → more time & resources for verification (quality still depends on team experience) |
| VALID | INVALID | why invalid |
|---|---|---|
MyFirstApplication | 45678 | starts with a digit |
FunTime | Sample Program | contains a space |
DEFAULT_VALUE | hello,there | comma not allowed |
standard naming convention
Robotclass name → Capital firstrobotobject name → small firstmultiple words → capitalise the first letter of every word, except the first word if it's an object name
MyMainWindowclassmyMainWindowobject (NOT mymainwindow)Customer customer; // 1. declaration customer = new Customer( ); // 2. creation
what happens in memory
Student john = new Student(); instead of Student john; + john = new Student();name vs objects: calling new twice
Customer customer; customer = new Customer( ); // first object customer = new Customer( ); // second object
the second new makes customer point to the new object → reference to the first Customer object is lost
<object>.<method>(<arguments>); e.g. account.deposit(200.0); · student.setName("john"); · car1.startEngine();/* The program is
expected to print Java */ // comment
public class Main{ // class
String attribute;
public void display() { // method
System.out.println(attribute);}
public static void main(String[] args) {
Main obj = new Main();
// obj.attribute = "Hello"; This line is commented
obj.attribute = "Java";
obj.display();
}
}| Type | Markers | Use |
|---|---|---|
| Multiline | /* … */ | comment across several lines |
| Single line | // … | everything after // on that line |
| javadoc | /** … */ | documentation comment, e.g. describing a class ("This class provides basic clock functions…") |
/* /* /* This is a comment */ */ <-- Error!
Comments do not nest. The first */ closes the comment, so the inner /* markers are just part of the comment text.
The leftover */ gives "Error: No matching beginning marker."
import syntax
importkeyword<package name>package that contains the class. <class name>class to import (* = all); e.g. dorm.Resident; · import javax.swing.JFrame; · import java.util.*; · import com.drcaffeine.simplegui.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
String S;
Scanner in = new Scanner(System.in);
System.out.println("Enter a string");
S = in.nextLine();
System.out.println("You enter a string " + S);
}}| Standard class | Package | Used for |
|---|---|---|
Scanner | java.util | keyboard input |
String | java.lang | text (auto-imported) |
Date | java.util | current date & time |
SimpleDateFormat | java.text | formatting dates |
System.out is an instance of the PrintStream class, a simple way to show results on the console window (its look depends on the Java tool you use).System.out.print("How do you do? ");
System.out.print("My name is ");
System.out.print("Jon Java. ");System.out.println("How do you do? ");
System.out.println("My name is ");
System.out.println("Jon Java. ");String is an object
String name; // 1
name = new String("Jon Java"); // 21 = identifier name declared, space allocated · 2 = String object created, name refers to it
Indexing: the position (index) of the first character is 0.
charAt(index)
String a = "Expresso"; → a.charAt(3) gives r · a.length() gives 8 (last index = length − 1)
| Method | Returns | Examples |
|---|---|---|
str.length() | number of characters in str | "programming" → 11 · str1 = "Hello" → 5 · str2 = "Java" → 4 · str3 = "" (empty string) → 0 · str4 = " " (one space) → 1 |
str.indexOf(substr) | first position where substr occurs; −1 if not found; case-sensitive | "programming".indexOf("gram") → 3 |
+ (concatenation) | joins strings | see below |
str = "I Love Java and Java loves me.";
str.indexOf("J") | 7 | first J |
str.indexOf("love") | 21 | lowercase "love" is inside "loves", not "Love" |
str.indexOf("ove") | 3 | "ove" is found in "Love" |
str.indexOf("Me") | −1 | "Me" not found (case-sensitive, text has "me") |
| str1 = "Jon"; str2 = "Java"; | Result |
|---|---|
str1 + str2 | "JonJava" (no space added!) |
str1 + " " + str2 | "Jon Java" |
str2 + ", " + str1 | "Java, Jon" |
"Are you " + str1 + "?" | "Are you Jon?" |
import java.util.*;
//import java.util.Date;
//import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Date today;
today = new Date( );
System.out.println(today);
}
}import java.util.Date;
import java.text.SimpleDateFormat;
...
Date today = new Date( );
SimpleDateFormat sdf1, sdf2;
sdf1 = new SimpleDateFormat("MM/dd/yy");
sdf2 = new SimpleDateFormat("MMMM dd, yyyy");
String a = sdf1.format(today);
String b = sdf2.format(today);
System.out.println(a + "\n" + b);java.util.* imports all classes in java.util (so both Date and Scanner).MM = month number · MMMM = full month name · dd = day · yy / yyyy = 2- / 4-digit year.sdf1.format(today)) and it returns the date as a String.System.in (the keyboard).input flow
import java.util.Scanner;Scanner in = new Scanner(System.in);name = in.nextLine();import java.util.Scanner;
public class Main {
public static void main(String args[]) {
String name;
Scanner in = new Scanner(System.in);
name = in.nextLine();
System.out.println("Hello there, " + name);
System.out.println("Welcome to Java");
}
}x + y we must declare their data type: int x, y; or int x; int y;int i, j, k; · float numberOne, numberTwo; · long bigInteger; · double bigNumber;int count = 10, height = 34;| Type | Content | Default | Minimum | Maximum |
|---|---|---|---|---|
byte | Integer | 0 | −128 | 127 |
short | Integer | 0 | −32768 | 32767 |
int | Integer | 0 | −2147483648 | 2147483647 |
long | Integer | 0 | −9223372036854775808 | 9223372036854775807 |
float | Real | 0.0 | −3.40282347E+38 | 3.40282347E+38 |
double | Real | 0.0 | −1.79769313486231570E+308 | 1.79769313486231570E+308 |
precision ladder (low → high)
long a = 323456789098765L; System.out.println(a);
E+38 means × 1038. So 3.40282347E+38 = 340,282,347 followed by 30 zeros.
A big whole number literal needs L at the end to be a long.
<variable> = <expression>; e.g. sum = firstNumber + secondNumber; · avg = (one + two + three) / 3.0;| Operation | Operator | Example | Value (x = 10, y = 7, z = 2.5) |
|---|---|---|---|
| Addition | + | x + y | 17 |
| Subtraction | - | x - y | 3 |
| Multiplication | * | x * y | 70 |
| Division | / | x / yx / z | 1 (not 1.429!) 4.0 |
| Modulo (remainder) | % | x % y | 3 |
int / int is integer division: the fractional part is truncated (10 / 7 = 1). If one operand is real (x / z) you get a real answer (4.0). Use a DecimalFormat object to format numerical output.The modulo operator returns the remainder of a division. It works with real numbers too, but is mostly used with integers.
| Modulo | Result |
|---|---|
23 % 5 | 3 |
23 % 25 | 23 |
16 % 2 | 0 |
x + 3 * y → x is added to 3*y (multiply first).evaluation order: high → low
( )innermost first · same level → left to right- +unary minus / plus* / %left to right+ -evaluated last · left to rightx is float and y is int, x * y is a float.casting decision flow
double x = 3 + 5; → 8.0int x = 3.5;(float) x / 3 · (int) (x / y * 3.0)Implicit: double x = 3 + 5; → 3 + 5 is int 8, promoted to 8.0 (double) before being assigned.
int x = 3.5; → error: a higher precision value cannot be assigned to a lower precision variable.
Explicit: prefix the operand with the type, syntax ( <data type> ) <expression>
(float) x / 3 → cast x to float, then divide by 3(int) (x / y * 3.0) → cast the result of the whole expression to intint x = 10; float y; y = (float) x / 3; System.out.println(y);
final declares a constant: final double PI = 3.14159; · final int MONTH_IN_YEAR = 12;final int x = 10; x = 20; // not allowed int y; y = x / 5; System.out.println(y);
int x = 10; x = 20; // fine int y; y = x / 5; System.out.println(y);
int num = 15;
System.out.print(num); //print a variable
System.out.print(" "); //print a string
System.out.print(10); //print a constantimport java.text.DecimalFormat;) to format numerical output.new DecimalFormat("0.000") → three decimal places (rounded).String.format("%.3f", num)double num = 123.45789345;
DecimalFormat df = new DecimalFormat("0.000");
System.out.println(num);
System.out.print(df.format(num));double num = 123.45789345;
String formatted = String.format("%.3f", num);
System.out.println(formatted);sample program Ch3Circle → Ch3Circle3
final double PI = 3.14159;
double radius, area, circumference;
radius = 2.35;
area = PI * radius * radius;
circumference = 2.0 * PI * radius;
System.out.println("Given Radius: " + radius);
System.out.println("Area: " + area);
System.out.println("Circumference: " + circumference);import java.text.*;
final double PI = 3.14159;
final String TAB = "\t";
final String NEWLINE = "\n";
DecimalFormat df = new DecimalFormat("0.000");
radius = 2.35;
...
System.out.println(
"Given Radius: " + TAB + df.format(radius) + NEWLINE +
"Area: " + TAB + df.format(area) + NEWLINE +
"Circumference: " + TAB + df.format(circumference));shows: radius value set · usage of constants (PI, TAB, NEWLINE) · usage of control characters \t (tab) and \n (new line) · formatted to 3 d.p.
Scanner scanner = new Scanner(System.in);
int age;
System.out.print("Enter your age: ");
age = scanner.nextInt();| Method | Example |
|---|---|
nextByte() | byte b = scanner.nextByte(); |
nextDouble() | double d = scanner.nextDouble(); |
nextFloat() | float f = scanner.nextFloat(); |
nextInt() | int i = scanner.nextInt(); |
nextLong() | long l = scanner.nextLong(); |
nextShort() | short s = scanner.nextShort(); |
nextLine() | String str = scanner.nextLine(); |
Math.method().(1.0 / 2.0) * Math.sin( x - Math.PI / Math.sqrt(y) )| Method | Description |
|---|---|
exp(a) | natural number e raised to the power of a |
log(a) | natural logarithm (base e) of a |
floor(a) | largest whole number ≤ a |
max(a,b) | the larger of a and b |
pow(a,b) | a raised to the power of b |
sqrt(a) | square root of a |
sin(a) | sine of a (all trig functions use radians) |
Math.sin (a trig function) together with Math.PI and Math.sqrt. The Math class covers trig functions like sin, but also powers, roots, logs, rounding down and max.Math.random also works but is harder to use.)nextInt method.import java.util.Random;
public class Main {
public static void main(String[] args) {
Random ran = new Random();
int num = ran.nextInt(6);
System.out.println(num);
}
}random.nextInt() → any int.
ran.nextInt(6) → 0 to 5 (not 6!).
For a die use ran.nextInt(6) + 1 → 1 to 6. General: nextInt(MAX − MIN + 1) + MIN.
class BicycleRegistration {
public static void main(String[] args) {
Bicycle bike1, bike2;
String owner1, owner2;
bike1 = new Bicycle( );
bike1.setOwnerName("Adam Smith");
bike2 = new Bicycle( );
bike2.setOwnerName("Ben Jones");
owner1 = bike1.getOwnerName( );
owner2 = bike2.getOwnerName( );
System.out.println(owner1 + " owns a bicycle.");
System.out.println(owner2 + " also owns a bicycle.");
}
}class Bicycle {
// Data Member
private String ownerName;
//Constructor: Initialises the data member
public void Bicycle( ) {
ownerName = "Unknown";
}
//Returns the name of this bicycle's owner
public String getOwnerName( ) {
return ownerName;
}
//Assigns the name of this bicycle's owner
public void setOwnerName(String name) {
ownerName = name;
}
}public void Bicycle( ) as the constructor, but a real constructor has NO return type. With void it becomes an ordinary method that never runs automatically (see Kitty example 2 in topic 6 below). The correct form is public Bicycle( ) { … }.Once the Bicycle class is defined, we can create multiple instances; each has its own copy of ownerName.
A a = new A();
for (int i = 0; i < 10; i++) {
String keyedinname = scanner.nextLine();
a.setname(keyedinname);
}1 object created → its name is overwritten 10 times on the SAME object
for (int i = 0; i < 10; i++) {
A a = new A();
String keyedinname = scanner.nextLine();
a.setname(keyedinname);
}a NEW object every iteration → 10 objects in total
class diagram for Bicycle
method listing: list the name and the data type of any argument passed to the method
template for a class definition
class Class Name {}data member declaration
privatemodifiersStringdata typeownerNamename; <modifiers> <data type> <name>; · only one modifier in this example
method declaration
publicmodifiervoidreturn typesetOwnerNamemethod name( String name )parameter{ ownerName = name; }statements<modifier> <return type> <method name> ( <parameters> ) { <statements> }
void → a method that does not return a value (e.g. setOwnerName).getOwnerName() returns the value of instance variable ownerName, which was declared as String, so its return type is String.return <expression>;int, you can return int, short or byte.public <class name> ( <parameters> ) { <statements> }. <class name> = the class this constructor belongs to.constructor anatomy
publicmodifierBicycleclass name( )parameter{ ownerName = "Unassigned"; }statementsexample 1: who makes the constructor?
public class Kitty{
public static void main(String []args){
Kitty myKitty = new Kitty( );}
}public class Kitty{
public Kitty(){
//no need this constructor
}
public static void main(String []args){
Kitty myKitty = new Kitty( ); }
}example 2: constructor vs method with the same name
public class Kitty{
public Kitty(String name){
System.out.println("Passed Name is :" + name);
}
public static void main(String []args){
Kitty myKitty = new Kitty("molly");
}
}public class Kitty{
String name;
public void Kitty(){
System.out.println("Passed Name is :" + name);
}
public static void main(String []args){
Kitty myKitty = new Kitty( );
myKitty.name = "molly";
myKitty.Kitty();
}
}void and Kitty() stops being a constructor. It's a normal method that you must call yourself (myKitty.Kitty()).class SecondMain {
public static void main(String[] args) {
Bicycle bike;
Account acct;
String myName = "Jon Java";
bike = new Bicycle( );
bike.setOwnerName(myName);
acct = new Account( );
acct.setOwnerName(myName);
acct.setInitialBalance(250.00);
acct.add(25.00);
acct.deduct(50);
System.out.println(bike.getOwnerName() + " owns a bicycle and");
System.out.println("has $ " + acct.getCurrentBalance() +
" left in the bank");
}
}class Account {
private String ownerName;
private double balance;
public Account( ) {
ownerName = "Unassigned";
balance = 0.0;
}
public void add(double amt) {
balance = balance + amt; }
public void deduct(double amt) {
balance = balance - amt; }
public double getCurrentBalance( ) {
return balance; }
public String getOwnerName( ) {
return ownerName; }
public void setInitialBalance(double bal) {
balance = bal; }
public void setOwnerName(String name) {
ownerName = name; }
}250.00 + 25.00 − 50 = 225.0
class Demo {
public void compute(int i, int j, double x) {
double result = i + j + x;
System.out.println("Computation result: " + result);
}
}
class Account {
private double balance = 0.0;
public void add(double amt) {
balance = balance + amt;
System.out.println("Current Balance: " + balance);
}
}
public class Main {
public static void main(String[] args) {
Account acct = new Account();
acct.add(400);
Demo demo = new Demo();
int i = 5;
int k = 14;
demo.compute(i, k, 20);
}
}main is public, and the file is named after it (Main.java). Passing int 400 to a double parameter prints 400.0, and 5 + 14 + 20.0 = 39.0.acct.add(400); → 400 is the argument.add(double amt) → amt is the parameter.matching them up
i (5)k (14)20int iint jdouble xdemo.compute(i, k, 20) → compute(int i, int j, double x) · 3 arguments ↔ 3 parameters
① The number of arguments and parameters must be the same.
② They are paired left to right.
③ Each pair must be assignment-compatible. You can't pass a double argument to an int parameter.
public and private set the accessibility of data members and methods.accessibility example: client → service
Service obj = new Service(); obj.memberOne = 10; // ✓ public obj.memberTwo = 20; // ✗ private obj.doOne(); // ✓ public obj.doTwo(); // ✗ private
class Service {
public int memberOne;
private int memberTwo;
public void doOne() { … }
private void doTwo() { … }
}Exception: constants can (should) be public if outside methods are meant to use them directly.
UML visibility: + public − private
static, final, abstract.from most open to most closed
import java.util.Scanner;
class Carpeting {
//Attribute (default access)
int length;
int width;
float price;
//Method
public void calculatePrice() {
System.out.println("The carpet price is :RM"
+ length * width * price);
}
// Main Method
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Carpeting carpet = new Carpeting();
System.out.println("Enter the room length (ft.):");
carpet.length = in.nextInt();
System.out.println("Enter the room width (ft.) :");
carpet.width = in.nextInt();
System.out.println("Enter the carpet price per sq. ft. :");
carpet.price = in.nextFloat();
carpet.calculatePrice();
}
}import java.util.Scanner;
class Carpeting {
int length;
int width;
float price;
public void calculatePrice() {
System.out.println("The carpet price is :RM"
+ length * width * price);
}
}
public class A {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Carpeting carpet = new Carpeting();
...same input lines...
carpet.calculatePrice();
}
}import java.util.Random;
class Die {
private static final int MAX_NUMBER = 6;
private static final int MIN_NUMBER = 1;
private static final int NO_NUMBER = 0;
private int number;
private Random random;
public Dice( ) { // should be Die( )
random = new Random();
number = NO_NUMBER;
}
//Rolls the dice
public void roll( ) {
number = random.nextInt(MAX_NUMBER - MIN_NUMBER + 1) + MIN_NUMBER;
}
//Returns the number on this dice
public int getNumber( ) {
return number;
}
}static final → one shared copy (class constant) whose value can't change.nextInt(6 − 1 + 1) + 1 = nextInt(6) + 1 → 1 to 6.main) creates a Die and calls roll() / getNumber().class MusicCD {
private String artist;
private String title;
private String id;
public MusicCD(String name1, String name2) {
String ident;
artist = name1;
title = name2;
ident = artist.substring(0,2) + "-" +
title.substring(0,9);
id = ident;
}
...
}where each variable lives
artist · title · idname1 · name2identflow: name1 → artist, name2 → title, then artist + title build ident, then ident → id (saved in the object)
// You cannot do: Shape s = new Shape(); // ERROR!
abstract class Shape {
String color;
public void setColor(String color) {
this.color = color;
}
public static void main(String[] args) {
System.out.println("Look at the abstract conceptual");
}
}new.calling methods
dot notation is necessary when calling a method of another object
dot notation is optional when calling a method of the same object
main method.class Bicycle {
//definition of the class as shown before comes here
public static void main(String[] args) {
Bicycle myBike;
myBike = new Bicycle( );
myBike.setOwnerName("Jon Java");
System.out.println(myBike.getOwnerName() + "owns a bicycle");
}
}this Keyword & Overloadingthis is usedthisthis in any method or constructor to refer to the current object, the one that called the method or invoked the constructor.this.variable → refers to the current class instance variablethis() → invokes the current class constructorpublic class Circle {
double radius; // member variable
public Circle(double radius) { // argument
this.radius = radius;
System.out.println(radius);
}
public static void main(String [] args){
Circle circle = new Circle(789);
}
}public Circle(double radius) {
this.radius = 500;
System.out.println(radius);
System.out.println(this.radius);
}
...
Circle circle = new Circle(789);which "radius" is which?
this.radiusthis instance's member variableradiusthe constructor's argument (parameter)new Circle(789) · only exists inside the constructorRad_radius = radius;), but radius is more meaningful, so Java gives us this to resolve the conflict.class Student10{
int id;
String name;
Student10(int id, String name){
id = id; //supposed to be this.id
name = name; //supposed to be this.name
}
void display(){System.out.println(id+" "+name);}
public static void main(String args[]){
Student10 s1 = new Student10(111,"Karan");
Student10 s2 = new Student10(321,"Aryan");
s1.display();
s2.display();
}
}Student10(int id, String name){
this.id = id;
this.name = name;
}this, id = id assigns the parameter to itself. The fields keep their defaults: 0 for int and null for String.class Student12{
int id;
String name;
Student12(int i, String n){
id = i;
name = n;
}
void display(){System.out.println(id+" "+name);}
...
Student12 e1 = new Student12(111,"karan");
Student12 e2 = new Student12(222,"Aryan");
}i, n) are different from the field names (id, name), so this isn't needed.public class TestMethodOverloading {
public int average(int n1, int n2) { // A
return (n1 + n2) / 2;
}
public double average(double n1, double n2) { // B
return (n1 + n2) / 2;
}
public int average(int n1, int n2, int n3) { // C
return (n1 + n2 + n3) / 3;
}
public static void main(String[] args) {
TestMethodOverloading tester = new TestMethodOverloading();
System.out.println(tester.average(1, 2)); // Use A
System.out.println(tester.average(1.0, 2.0)); // Use B
System.out.println(tester.average(1, 2, 3)); // Use C
System.out.println(tester.average(1.0, 2)); // Use B
// System.out.println(tester.average(1, 2, 3, 4)); // Compilation Error
}
}which version gets called?
| Call | Version | Result | Why |
|---|---|---|---|
average(1, 2) | A (int, int) | 1 | 3 / 2 → integer division |
average(1.0, 2.0) | B (double, double) | 1.5 | exact type match |
average(1, 2, 3) | C (int, int, int) | 2 | 3 arguments |
average(1.0, 2) | B | 1.5 | int 2 implicitly cast to 2.0 |
average(1, 2, 3, 4) | none | compile error | no matching method |
package Overload; as the first line puts the class into the package Overload. That's how classes are organised into a package.package Overload;
public class StudentData {
private int stuID;
private String stuName;
private int stuAge;
StudentData() { // default constructor
stuID = 100;
stuName = "New Student";
stuAge = 18;
}
StudentData(int num1, String str, int num2) { // parameterized
stuID = num1;
stuName = str;
stuAge = num2;
}
//Getter and setter methods
public int getStuID() { return stuID; }
public void setStuID(int stuID) { this.stuID = stuID; }
public String getStuName() { return stuName; }
public void setStuName(String stuName) { this.stuName = stuName; }
public int getStuAge() { return stuAge; }
public void setStuAge(int stuAge) { this.stuAge = stuAge; }
}
class TestOverloading {
public static void main(String args[]) {
StudentData myobj = new StudentData(); // default
...print name, age, ID...
StudentData myobj2 = new StudentData(555, "Chaitanya", 25); // parameterized
...print name, age, ID...
}
}two objects, two constructors
via StudentData()
via StudentData(int, String, int)
public Circle() { // 1st Constructor
radius = 1.0;
color = "red";
}
public Circle(double r) { // 2nd Constructor
radius = r;
color = "red";
}
public Circle(double r, String c) { // 3rd Constructor
radius = r;
color = c;
}this.stuID = stuID because the parameter has the same name as the field, which is exactly the case from topic 1 above.if statements and switch statementsif statement inside another if statementif statement (if-else)int testScore;
testScore = //get test score input
if (testScore < 70)
System.out.println("You did not pass"); // runs if testScore is less than 70
else
System.out.println("You did pass"); // runs if testScore is 70 or highersyntax
if ( testScore < 70boolean expression) System.out.println("You did not pass");then blockelse System.out.println("You did pass");else blockif ( <boolean expression> ) <then block> else <else block>
control flow
A boolean expression gives true or false. Relational operators compare two values:
| Operator | Meaning |
|---|---|
< | less than |
<= | less than or equal to |
== | equal to (two = signs; one = is assignment) |
!= | not equal to |
> | greater than |
>= | greater than or equal to |
Examples from the slide: testScore < 80 · testScore * 2 >= 350 · 30 < w / (h * h) · x + y != 2 * (a + b) · 2 * Math.PI * radius <= 359.99
{ } if the then or else block has more than one statement. A block in braces is a compound statement.if (testScore < 70)
{
System.out.println("You did not pass"); // then block
System.out.println("Try harder next time");
}
else
{
System.out.println("You did pass"); // else block
System.out.println("Keep up the good work");
}if / else belongs to that block.if ( <boolean expression> ) {
…
} else {
…
}if ( <boolean expression> )
{
…
}
else
{
…
}Both styles do the same thing. They only differ in where the braces go; pick one and use it consistently.
if ( <boolean expression> ) <then block>. There is no else block.if (testScore >= 95) // boolean expression
System.out.println("You are an honor student"); // then blockcontrol flow of if-then
if statements.if (testScore >= 70) {
if (studentAge < 10) {
System.out.println("You did a great job");
} else {
System.out.println("You did pass"); //test score >= 70
} //and age >= 10
} else { //test score < 70
System.out.println("You did not pass");
}control flow of nested-if
| testScore | studentAge | Output |
|---|---|---|
| ≥ 70 | < 10 | You did a great job |
| ≥ 70 | ≥ 10 | You did pass |
| < 70 | (not checked) | You did not pass |
if (score >= 90)
System.out.print("Your grade is A");
else if (score >= 80)
System.out.print("Your grade is B");
else if (score >= 70)
System.out.print("Your grade is C");
else if (score >= 60)
System.out.print("Your grade is D");
else
System.out.print("Your grade is F");| Test score | Grade |
|---|---|
| 90 ≤ score | A |
| 80 ≤ score < 90 | B |
| 70 ≤ score < 80 | C |
| 60 ≤ score < 70 | D |
| score < 60 | F |
checked from the top, stops at the first true
else if (score >= 80) doesn't need score < 90, because it's only reached when score >= 90 was already false. A score of 95 prints only "A".&& · or || · not !if (temperature >= 65 && distanceToDestination < 2) {
System.out.println("Let's walk");
} else {
System.out.println("Let's drive");
}Walk only when it's warm (≥ 65) and close (< 2). If either part is false, drive.
| a | b | a && b | a || b | !a |
|---|---|---|---|---|
| true | true | true | true | false |
| true | false | false | true | false |
| false | true | false | true | true |
| false | false | false | false | true |
truth table: extra, not on the slides. && needs both true · || needs at least one true · ! flips the value
Reversing a condition: reverse the relational operator and switch the if and else blocks to get equivalent code.
three ways to write the same check
if (age < 0) {
println("Invalid age is entered");
} else {
println("Valid age is entered");
}if ( !(age < 0) ) {
println("Valid age is entered");
} else {
println("Invalid age is entered");
}if (age >= 0) {
println("Valid age is entered");
} else {
println("Invalid age is entered");
}!(age < 0) means the same as age >= 0 · println is short for System.out.println here
Testing a range (slide title "Boolean variables"): in maths we write 80 ≤ x < 90. In Java, to test that x is within the specified lower and upper bounds:
80 <= x && x < 90Two separate comparisons joined with &&.
80 <= x < 90Java works out 80 <= x first, which gives true/false, then tries true < 90, which is a compile error.
== vs equals==equals| Sample | Code | Output | Why |
|---|---|---|---|
1 · == | str1 = new String("Java");str2 = new String("Java");if (str1 == str2) | They are not equal | str1 and str2 point to different String objects |
2 · == | str1 = new String("Java");str2 = str1;if (str1 == str2) | They are equal | str1 and str2 point to the same object |
3 · equals | str1 = new String("Java");str2 = new String("Java");if (str1.equals(str2)) | They are equal | same sequence of characters |
== on objects compares the references (which object each variable points to), not the text "Java".equals compares the characters.the semantics of ==
Case A: two variables refer to two different objects
str1 == str2 → falseCase B: two variables refer to the same object
str1 == str2 → trueCase A code: str1 = new String("Java"); str2 = new String("Java"); · Case B code: str1 = new String("Java"); str2 = str1;
in creating String objects
| Code | Objects made | word1 == word2 |
|---|---|---|
word1 = new String("Java");word2 = new String("Java"); | 2: whenever the new operator is used, there will be a new object | false |
word1 = "Java";word2 = "Java"; | 1: a literal string constant such as "Java" always refers to one object | true |
str1.equals(str2). == happens to give true for two identical literals (they share one object), but gives false for two new String(...) objects with the same text.switch statementScanner scanner = new Scanner(System.in);
System.out.println("Grade (Frosh-1,Soph-2,...):");
int gradeLevel = scanner.nextInt();
switch (gradeLevel) {
case 1: System.out.print("Go to the Gymnasium"); // runs if gradeLevel is 1
break;
case 2: System.out.print("Go to the Science Auditorium");
break;
case 3: System.out.print("Go to Harris Hall Rm A3");
break;
case 4: System.out.print("Go to Bolt Hall Rm 101"); // runs if gradeLevel is 4
break;
}syntax
switch ( gradeLevelarithmetic expression) { case 1:case labelSystem.out.print("Go to the Gymnasium"); break;case body… } switch ( <arithmetic expression> ) { <case label 1> : <case body 1> … <case label n> : <case body n> }
how a switch runs
gradeLevelcase labelbreak;leave the switchWithout break, Java keeps running into the next case body ("fall through").
If no case matches (e.g. gradeLevel = 7) nothing runs, unless you add a default: case.
enum)final). Another type of constant in Java is the enumerated constant.enum.compare both structures
class Student {
public static final int FRESHMAN = 0;
public static final int SOPHOMORE = 1;
public static final int JUNIOR = 2;
public static final int SENIOR = 3;
}class Student {
public static enum GradeLevel
{FRESHMAN, SOPHOMORE, JUNIOR, SENIOR}
}The enum version is shorter, and a GradeLevel can only hold one of those 4 values. An int could hold any number, like 7.
enum <enumerated type> { <constants> }enum Month {JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER}enum Gender {MALE, FEMALE}enum SkillLevel {NOVICE, INTERMEDIATE, ADVANCED, EXPERT}enum Fruit {APPLE, ORANGE, BANANA}
Fruit f1, f2, f3;
f1 = Fruit.APPLE;
f2 = f1;
System.out.println("Favorite Fruit is " + f2);
Fruit favoriteFruit = …;
switch (favoriteFruit) {
case Fruit.APPLE: …
break;
case Fruit.ORANGE: …
break;
case Fruit.BANANA: …
break;
}case Fruit.APPLE:. Before Java 21 that's a compile error: inside a switch on an enum you write just case APPLE:. Use the short form to be safe.Accessing an enum from outside: if the enum type in a class is declared public, other classes can use it as ClassName.EnumName.
class Faculty {
public static enum Rank {LECTURER, ASSISTANT, ASSOCIATE, FULL}
. . .
}
class SampleMain {
. . .
Faculty.Rank rank = Faculty.Rank.ASSISTANT;
. . .
}Faculty and SampleMain are two separate classes. "Outside" means SampleMain is outside Faculty. Because Rank is public, SampleMain can reach it through the class name: Faculty.Rank.Semangatttt Sayangggg · Good Luckkkk