Java: strongly typed language

String: reference type, immutable
Array length: immutable

Jagged array: multidimensional array in which the inner arrays can have different lengths

// define 1D array
int[] arr = new int[3]; // arr: {0, 0, 0}; all primitives have default value
Integer[] arr = new Integer[3]; // arr: {null, null, null}
int[] arr = new int[]{1, 2, 3};
// int[] arr = new int[]; will cause syntax error
 
// define 2D array
int[][] arr = new int[3][3];
// define 2D jagged array
int[][] arr = new int[3][]; // arr: {null, null, null}
arr[1] = new int[]{1, 2}; // arr: {null, {1, 2}, null}
arr[0] = new int[]{3}; // arr: {{3}, {1, 2}, null}

NOTE: unlike C++, Java allows an array’s length to be determined at runtime using a variable

Compact array: from 0 to n-1 with all initialized values
Oversize array must be compact
Oversize array size don’t have to equal to arr.length

Capacity: the maximum slots (arr.length)
Size: use an additional variable to determine

If sentinal in one continuous group, then the array is compact otherwise the array is not compact

NOTE: varaibles should be delcared in top row of the method, except for loop counters (i, j, k)

Sparse array: not every element initialized (not meaningful since sentinal value)
Oversize array: meaningful on size

Border case: atypical case
Edge case: subset of border case, even more atypical

Hexdecimal: 0xffffffff

NOTE: wrapped values are immutable

The stack: primitive
The heap: objects, classes

Primitive data types cannot be null
Null only for reference type

==: true if same location in memory; false otherwise
.equals(): true if the two have the same content; false otherwise

Inheritance:
Rumtime exception: uncheck exception
Compiler will check checked exception

NOTE: main method can declare throws keyword

Method stub: a short and simple placeholder for an incomplete method

Exceptions are all about communication!
Try-catch stops the exception
Throws keyword throws the exception out

NOTE: in this class, if the copied array and the original array are stored at different memory locations, they are considered a deep copy, even though the objects within the arrays still reference the same objects


Java Basics

  • Java: strongly typed language
  • String: reference type, immutable
  • Array length: immutable
  • Wrapper objects: immutable
  • Primitive data types: cannot be null
  • null: only forreference types

Arrays

Jagged array: a multidimensional array in which the inner arrays can have different lengths

// Define 1D array
int[] arr = new int[3];          // {0, 0, 0}; primitives have default values
Integer[] arr = new Integer[3];  // {null, null, null}
int[] arr = new int[]{1, 2, 3};
 
// int[] arr = new int[]; // Syntax error
 
// Define 2D array
int[][] arr = new int[3][3];
 
// Define 2D jagged array
int[][] arr = new int[3][];      // {null, null, null}
 
// int[] arr = new int[][3]; // Syntax error
 
arr[1] = new int[]{1, 2};        // {null, {1, 2}, null}
arr[0] = new int[]{3};           // {{3}, {1, 2}, null}

NOTE: unlike C++, Java allows an array’s length to be determined at runtime using a variable.

Compact array

  • Valid/initialized elements occupy indices 0 to n - 1.
  • If sentinels appear in one continuous group at the end, the array is compact.
  • Otherwise, the array is not compact.

Oversize array

  • Must be compact.
  • size does not have to equal arr.length.
  • Capacity = maximum number of slots (arr.length)
  • Size = number of meaningful elements, tracked using an additional variable.

Sparse array

  • Not every element is meaningful/initialized.
  • Sentinel values can represent unused elements.

Memory & Comparison

  • Stack: primitives
  • Heap: objects / classes

==: for reference types: checks whether two references point to the same object/location.
.equals(): usually checks whether two objects have the same content, depending on how the class implements it

NOTE: in this class, if the copied array and original array are stored at different memory locations, they are considered a deep copy, even if the objects inside the arrays still reference the same objects.

Exceptions

  • Runtime exception: unchecked exception
  • Checked exception: compiler checks whether it is handled or declared.
  • try-catch: handles/stops the exception from propagating.
  • throws: passes responsibility for the exception to the caller.
  • The main method can declare throws.

Exceptions are all about communication!

Other Notes

  • Border case: atypical case.
  • Edge case: a more extreme subset of a border case.
  • Hexadecimal example: 0xffffffff
  • Method stub: a short and simple placeholder for an incomplete method.
  • Inheritance: allows a class to inherit fields/methods from another class.
  • Variables should be declared at the top of the method, except loop counters (i, j, k)

Class method = static method

// Even if the method doesn't throw the declared exception, if the exception is checked, the caller still has to handle or declare it.
public static void bark() throws Exception {  
   return;  
}
// Need to use try-catch
try {
	bark();
} catch (Exception) {
    // This will never happen
}
 
// A method can declare an unchecked exception, but even if it is declared, the caller doesn't have to handle it.  
public static void bark() throws RuntimeException {  
   return;  
}
// Don't need to use try-catch  
bark();

toString() returns the class name and hashcode of the instance unless overriden


Slides:

Arrays:
OVERSIZE ARRAY: size <= length (capacity) AND has size variable AND compact (0 to size - 1, may or may not include sentinal values). To iterate: for (int i = 0; i < size; i++) {...}

PERFECT SIZE ARRAY: size = length AND no need sentinal value or size variable. To iterate: for (int i = 0; i < arr.length; i++) {...}

COMPACT ARRAY: all elements stored at the start of array (all sentinal values only appear after all meaning values: monotonicity). To iterate: for (int i = 0; i < arr.length && arr[i] != sent; i++) {...}

SPARSE ARRAY: meaningful elements and sentinal values can be found anywhere. To iterate: for (int i = 0; i < arr.length; i++) if (arr[i] != sent) {...}


Writing tests: check normal case, atypical case, invalid case, border case

Static methods: get information from arguments.
Instance methods: get information from the object (and possibly arguments).

An ArrayList must use a reference type


Wrapper classes:
AUTOBOXING: Integer num = 1;
UNBOXING: int value = num;
NOTE: immutable

Memory regions:
CODE: instructions for the computer
STATIC MEMORY: any static (class) variables, outside of any method
THE STACK: local variables, primitive values and references to the heap
THE HEAP: object memory

Shallow and deep copy:
Shallow: copy = original
Deep: copy = Arrays.copyOf(original);

NullPointerException: thrown when attempt to use a reference that is null or uninitialized

GC: deletes objects automatically when reference count hits 0


Exceptions:
Used when you don’t WANT to or CANNOT handle something effectively. Since a method must return its declared type, exceptions communicate that something went wrong
Throw using the throw keyword

Uncheck: inhertite or is the RuntimeException (handle or not handle)
Checked: anything else must handle

throws: used in method delcareation that the method throws specific exception if not handled using try-catch
throw: throw the exception

finally: always happen

try-with-resources: try (Scanner in = new Scanner(System.in))