Skip to content
Kittycat.tech logo

Java Study Notes

Contributor:
Pretty Image
Erica Madebeykin, MBA
🇬🇧MBA Merit
🇬🇧MSc Comp Sci student
Creation Date:
8th of August, 2026
❤️ Reference Acknowledgments: A heartfelt gratitude to Professor Christos Chrysoulas for delivering such an amazing and inspiring Java programming course! A big and sincere thank you as well to Dr. Abrar Ullah for directing this master’s degree programme❤️

I would like to give a special thank you to Teacher Tess Watt for her wonderful academic support, dedication, and commitment to helping us succeed. ❤️

I would also like to express my sincere appreciation to the amazing administrative team, especially Miss Debbie Ross and Richard Knight, for their outstanding assistance and continuous support throughout our studies in this Master’s degree program. Your guidance and encouragement have made a meaningful difference in our academic journey. ❤️

Thank you all for your dedication, encouragement, and unwavering commitment to supporting us throughout our studies! 🙏🎓

This review reflects my personal learning experience and thoughts based on the materials covered so far in the MSc Computer Science online degree provided by the Heriot-Watt University based in Edinburgh, United Kingdom, delivered on the Coursera platform.

Sharing My Notes: Java Tips and Tricks

I’ve listed the parts of Java syntax that I found most confusing as I learned them throughout my master’s journey. I also included some practical tips that I discovered while solving math problems involving the modulo operator (%) and understanding the Java exception hierarchy.

I hope these study notes can also help you better understand Java (just as they helped me), write more reliable programs, and pass your exams.

Update: This reviewer helped me almost perfect my exam. I got a 98%! 🎉

F91PD Erica Tablan Madebeykin's grade

1.1 Modulo Operations using Formula

Solving for the remainder is quite easy when dealing with positive integers. For example:

16 ÷ 5 = 3 with a remainder of 1.

Therefore:

16 % 5 = 1

My Discovery: Formula for solving Remainders

However, as a student, I initially found it challenging when problems involved negative integers, cases where the dividend is smaller than the divisor, or situations where I needed to understand how Java handles the % operator (for example, what is 1 % 10?).

I found it helpful to use this golden formula:

Remainder = Dividend − (Divisor × Integer Quotient)

For example:

1 % 10

The integer quotient is 0, so:

1 − (10 × 0) = 1

Therefore:

1 % 10 = 1

Important: In Java, the % operator calculates the remainder. When integer operands are negative, the remainder has the same sign as the dividend (or is zero). For example:

-16 % 5 = -1

This is because Java's integer division drops the decimal part and rounds the result toward zero:

-16 / 5 = -3

Therefore:

-16 − (5 × -3) = -1

This approach has been a lifesaver for me, especially during exams where programming questions involving loops use the % operator. Understanding how the % operator works is very useful in programming, particularly when working with loops.

1.2 Difference between the == Equals Operator and the .equals() Method

As a student, I easily got confused between the equals operator (==) and the .equals() method. So, let’s break down the difference:

In Java, == and .equals() are used for comparison, but they work differently:

== operator: For objects, it compares whether two references point to the same object in memory. For primitive types, it compares their actual values.

.equals() method: Compares the content or logical value of two objects, depending on how the method is implemented.

For example:

java
String a = new String("Hello");
String b = new String("Hello");

System.out.println(a == b);       // false
System.out.println(a.equals(b));  // true

Here, a and b contain the same text but refer to different String objects. Therefore, == returns false, while .equals() returns true.

In short: Use == to compare primitive values or object references, and .equals() to compare the contents of objects.

Cases when the == Operator returns True
  1. With primitives
java
int a = 10;
int b = 10;

System.out.println(a == b); // true

For primitives, == compares the actual values.

  1. With objects of same reference
java
String a = "Hello";
String b = a;

System.out.println(a == b); // true

Here, b = a means both variables refer to the same String object, so the == operator returns true.

1.3 throws Clause vs. Multiple Exceptions in a Single catch Clause

A common Java syntax difference to remember is the separator used between the exception types. I listed it here because it’s easy to accidentally use a comma instead of a pipe (|) when specifying multiple exceptions inside catch().

1. throws clause → use comma ,

With a throws clause, multiple exception types are separated by commas:

java
void readFile() throws IOException, SQLException {
    // ...
}

The comma separates the exception types in a list of exceptions that the method may throw.

This is similar to how commas separate method parameters:

java
void foo(int x, String y) {
    // ...
}

2. Multiple exceptions in a single catch clause → use pipe bar |

When handling multiple exception types in a single catch clause, the exception types are separated by a pipe bar |:

java
try {
    // ...
} catch (IOException | SQLException e) {
    // Handle either exception
}

Here, IOException | SQLException represents alternative exception types that can be handled by the single catch block.

In other words, the same catch block handles either an IOException or a SQLException.

The catch parameter e represents the exception caught from either alternative.


Why are the separators different?

They represent different grammatical constructs in Java:

SyntaxSeparatorMeaning
throws IOException, SQLException,A list of exception types the method may throw
catch (IOException | SQLException e)|Multiple alternative exception types handled by one catch block

So a useful trick is:

, = list
| = multiple alternative exceptions

The Java Language Specification defines these separately: a throws clause contains a comma-separated list of exception types, while a multi-catch parameter uses | between alternative exception types.

Easy way to remember

java
throws IOException, SQLException
       //     "and/or list"

catch (IOException | SQLException e)
                  // "or"

So:

throws → use comma ,

multiple exceptions in single-catch → use pipe |

For more info, see: Oracle Documentation

1.4 Java Exception Hierarchy

JavaScript-ConditionalsPhoto source: Module 10 of the MSc Computer Science course at Heriot-Watt University.

This is the Java Exceptions hierarchy as we learn it in Module 10 of the Java Programming course, which is the first subject of the MSc Computer Science programme.
We can see that Throwableis the superclass of both Exception and Error. Under these two categories, there are numerous subclasses.

Key Takeaway:

Important: I learned that it is very important to be specific when writing exception handlers. For example, if you need to catch only IOException and SQLException, you can use the pipe (|) format we discussed in Section 1.3.


I understood that using Throwable might catch more than you expect because Throwable is the superclass of both Exception and Error. As a result, it can catch errors and exceptions that you may not intend to handle.


So I learned that it is generally better to catch only the specific exceptions that you expect and know how to handle. This makes your code more predictable, easier to understand, and less likely to hide unexpected problems.

1.5 Distinction between void and Return Methods

A common point of confusion when learning Java is the difference between a method that uses void and a method that returns a value.

Key Difference

void method: Performs an action but does not return a value.

Return method: Returns a value using the return keyword.

For example, a getter returns a value, while a setter does not:

java
class Student {

    private String name;

    // Getter
    String getName() {
        return name;
    }

    // Setter
    void setName(String name) {
        this.name = name;
    }
}

Here:

  • getName() uses return because it gives the value of name back.
  • setName() uses void because it changes the value but does not return anything.

So, an easy way to remember it is:

Getter → return a value

Setter → void

Return method:

Performs an action and returns a value using the return statement. The method's return type specifies what type of value it returns.

For example, a method can return:

Return TypeSizeDescriptionDefault Value
byte8 bitsSmall integer (-128 to 127)0
short16 bitsInteger (-32,768 to 32,767)0
int32 bitsInteger (-2,147,483,648 to 2,147,483,647)0
long64 bitsVery large integers (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)0L
float32 bitsDecimal number0.0f
double64 bitsMore precise decimal number0.0d
char16 bitsSingle Unicode character'\u0000'
boolean1 bittrue or falsefalse
StringNot fixedSequence of charactersnull
Object/reference typeNot fixedReference to an objectnull

Table Source: Module 2 of HWU's Online MSc Computer Science program


Code examples of methods returning value:
java
int add(int a, int b) {
    return a + b;
}

double calculateAverage() {
    return 85.5;
}

boolean isAdult(int age) {
    return age >= 18;
}

String getName() {
    return "John";
}

char getGrade() {
    return 'A';
}

The return value can then be stored in a variable or used directly:

java
int result = add(2, 3);
boolean adult = isAdult(20);
String name = getName();

1.6 Ellipsis in Varargs

Another Java syntax feature I found tricky is the ellipsis (...) used with variable-length arguments, commonly called varargs.

Key Difference

The ... indicates that a method can accept a variable number of arguments of the same type.

For example:

java
void printNames(String... names) {
    for (String name : names) {
        System.out.println(name);
    }
}

The method can then be called with different numbers of arguments:

java
printNames("John");
printNames("John", "Mary");
printNames("John", "Mary", "David", "Sarah");

The same method can therefore accept one, several, or even zero arguments:

java
printNames();

Inside the method, names is treated as an array of String values.

Easy way to remember

... → variable number of arguments

java
String... names

can be thought of as:

java
String[] names

when used inside the method.

Important: A method can have only one varargs parameter, and it must be the last parameter in the method declaration.

For example:

java
void printStudentInfo(String course, String... students) {
    // ...
}

Here, course is a regular parameter, while students can contain a variable number of String arguments.

1.7 Loops: break vs. continue

When working with loops in Java, break and continue are both used to change the normal flow of a loop, but they do different things.

Key Difference

break → stops the loop completely.

continue → skips the current iteration and moves to the next iteration.

1. break, Stop the loop

When Java encounters break, the loop terminates immediately.

java
for (int i = 1; i <= 5; i++) {

    if (i == 3) {
        break;
    }

    System.out.println(i);
}

Output:

text
1
2

When i becomes 3, break stops the entire loop. The values 3, 4, and 5 are therefore not processed.

2. continue, Skip the current iteration

When Java encounters continue, it skips the remaining code in the current iteration and moves to the next iteration.

java
for (int i = 1; i <= 5; i++) {

    if (i == 3) {
        continue;
    }

    System.out.println(i);
}

Output:

text
1
2
4
5

When i becomes 3, continue skips System.out.println(i) for that iteration. The loop then continues with i = 4.

Easy way to remember

break → break out of the loop

continue → continue with the next iteration

StatementWhat it doesLoop continues?
breakTerminates the loop completelyNo
continueSkips the current iterationYes

Quick tip: Think of break as "stop" and continue as "skip."

1.8 Pre-increment ++x vs. Post-increment x++

The increment operator ++ increases a variable's value by 1. However, ++x and x++ behave differently depending on when the value is increased.

Key Difference

Pre-increment ++x → increments the value first, then uses the new value.

Post-increment x++ → uses the current value first, then increments it.

1. Pre-increment ++x

The variable is increased before its value is used.

java
int x = 5;

int result = ++x;

System.out.println(result); // 6
System.out.println(x);      // 6

Here, x is first increased from 5 to 6, and then 6 is assigned to result.

2. Post-increment x++

The variable's current value is used before it is increased.

java
int x = 5;

int result = x++;

System.out.println(result); // 5
System.out.println(x);      // 6

Here, the current value 5 is first assigned to result. After that, x is increased to 6.

Easy way to remember

++x → increment first, use later

x++ → use first, increment later

OperatorWhat happens first?Example result
++xIncrement, then use the valueIf x = 5, ++x produces 6
x++Use the value, then incrementIf x = 5, x++ produces 5 then increment it later to 6

Quick tip: When ++ is used by itself, both forms ultimately increase the variable by 1. The difference matters when the value is used as part of a larger expression.

1.9 Heap vs. Stack: Which Gets Stored Where?

Understanding the difference between the stack and the heap is important when learning how Java manages memory.

Key Difference

Stack → stores method calls, local variables, and references to objects.

Heap → stores objects and arrays.

For example:

java
public class Student {

    String name;

    public static void main(String[] args) {

        int age = 25;
        Student student = new Student();

        student.name = "John";
    }
}

In this example:

  • age is a local primitive variable associated with the stack frame of main().
  • student is a reference variable associated with the stack frame.
  • new Student() creates a Student object on the heap.
  • name is an instance variable belonging to the Student object on the heap.
  • The String object represented by "John" is stored on the heap.

Easy way to remember

Stack → method calls, local variables, and references

Heap → objects and arrays

Memory AreaCommonly StoresExample
StackMethod calls, local variables, object referencesint age = 25;
HeapObjects and arraysnew Student()

Important: The reference and the object are different. In:

java
Student student = new Student();

student is the reference, while new Student() creates the object.

1.10 Numeric Promotion

Also, I found it important to understan the numeric promotion in Java. When arithmetic operations are performed using different numeric types, Java may automatically convert or promote values to a type that can be used for the operation.

It is important to note that Java does not simply promote numeric types according to one straightforward hierarchy such as:

byte → short → int → long → float → double

Instead, Java has specific rules for numeric promotion, particularly when performing arithmetic operations.

Numeric Promotion in Arithmetic

When arithmetic operations are performed, values of type byte, short, and char are generally promoted to int.

For example:

java
byte a = 10;
byte b = 20;

int result = a + b;

Even though both a and b are byte, the result of a + b is an int.

Similarly:

java
short a = 10;
short b = 20;

int result = a + b;

The short values are promoted to int before the addition.

The same applies to char:

java
char a = 'A';
char b = 'B';

int result = a + b;

Here, both char values are promoted to int before the addition.

Common Numeric Promotion Rules

For arithmetic operations, a useful way to remember the common rules is:

Operand types involvedResult type
byte, short, charint
int and longlong
int/long and floatfloat
Any operand is doubledouble

For example:

java
int a = 10;
long b = 20;

long result = a + b;

The int value is promoted to long, so the result is a long.

Similarly:

java
long a = 10;
double b = 20.5;

double result = a + b;

The long value is promoted to double, so the result is a double.

Another example:

java
int a = 10;
float b = 20.5f;

float result = a + b;

The int value is promoted to float, so the result is a float.

Important: byte, short, and char

One of the most common mistakes is assuming that two small integer types produce another small integer type.

For example, this does not compile:

java
byte a = 10;
byte b = 20;

byte result = a + b; // Compile-time error

The reason is that a and b are promoted to int before the addition, so the expression a + b has type int.

You would need an explicit cast if you wanted to store the result in a byte:

java
byte result = (byte) (a + b);

However, casting can cause information to be lost if the result is outside the range of byte.

What about String?

String is not part of numeric promotion.

However, Java uses the + operator for String concatenation when a String is involved.

For example:

java
int age = 25;

String result = "Age: " + age;

System.out.println(result);

Output:

text
Age: 25

Here, the int value is converted to its string representation and concatenated with "Age: ".

This can produce different results depending on where the String appears:

java
System.out.println(10 + 20);        // 30
System.out.println("10" + 20);      // 1020
System.out.println(10 + 20 + "");    // 30
System.out.println("" + 10 + 20);    // 1020

The operations are evaluated from left to right.

In:

java
10 + 20 + ""

Java first calculates:

text
10 + 20 = 30

and then concatenates 30 with the empty string:

text
30 + "" = "30"

But in:

java
"" + 10 + 20

the first operation involves a String, so string concatenation is used:

text
"" + 10 = "10"
"10" + 20 = "1020"

Easy way to remember

For arithmetic expressions, remember:

byte, short, charint

Then, depending on the other operands:

int + longlong

int/long + floatfloat

Anything + doubledouble

And remember:

String is not part of numeric promotion.

When + is used with a String, Java performs String concatenation instead.

1.11 Closing Resources: Scanner and File Readers

Lastly, I found it important to understand why we should close resources such as Scanner and file readers when we are finished using them.

When a program opens a resource, such as a file, that resource uses system resources. If we leave it open, it can cause problems such as resource leaks and unnecessary memory usage.

I encountered the following resource leaks while programming:

JavaScript-Conditionals

For example, when using a Scanner:

java
Scanner scanner = new Scanner(System.in);

System.out.print("Enter your name: ");
String name = scanner.nextLine();

scanner.close();

After we are finished using the Scanner, we call:

java
scanner.close();

This releases the resources used by the scanner.

Similarly, when working with a file reader, we should close it after we are finished reading the file:

java
FileReader reader = new FileReader("example.txt");

int data = reader.read();

reader.close();

If the reader is not closed, the underlying file resource may remain open longer than necessary.

Why Should We Close Resources?

Resources such as Scanner, FileReader, BufferedReader, and other input/output classes may use system resources that should be released when they are no longer needed.

For example:

java
FileReader reader = new FileReader("example.txt");

// Read from the file...

reader.close();

The call:

java
reader.close();

tells Java that we are finished using the reader.

Failing to close resources can eventually lead to resource leaks, especially when a program opens many files or other resources.

This is particularly important in programs that run for a long time or repeatedly open resources.

What if an Exception Occurs?

There is an important problem with manually calling close().

Consider:

java
FileReader reader = new FileReader("example.txt");

int data = reader.read(); // Something goes wrong here

reader.close();

If an exception occurs before reader.close() is reached, the reader may never be closed.

For example, if this line throws an exception:

java
int data = reader.read();

the program may leave the resource open.

This is why Java provides try-with-resources.

Try-with-Resources

A better way to work with resources is to use a try-with-resources statement.

For example:

java
try (FileReader reader = new FileReader("example.txt")) {

    int data = reader.read();

}

Here, Java automatically closes the FileReader when the try block finishes.

This happens even if an exception is thrown while working with the resource.

Because of this, we do not need to manually write:

java
reader.close();

The resource is closed automatically.

The same approach can be used with many classes that implement AutoCloseable, including Scanner:

java
try (Scanner scanner = new Scanner(System.in)) {

    System.out.print("Enter your name: ");
    String name = scanner.nextLine();

}

When the try block finishes, Java automatically closes the Scanner.

That’s a wrap on my study notes on Java tips and tricks! I hope they’ve helped you as much as they’ve helped me.

Sharing is caring! ❤️

✅Summarized reviews based on Kittycat's insights from the best online courses at top universities