Java
Expressions
Precedence (highest to lowest):
- Postfix:
i++,i-- - Unary:
(int) a,!b,++i,--i - Multiplicative:
*,/,% - Additive:
+,- - Relational:
>,>=,<=,<,instanceof - Equality:
==,!= - And:
&& - Or:
|| - Assignment:
=,+=,-=,*=,/=,%=
== vs .equals()**
==: two primitives (int, boolean, etc.) have the same value OR two variables point to the same object in memory.
.equals(): Checks if two objects have the same contents if they implement the equals() method, otherwise still reference.
Watch out that methods like .toLowerCase() create a new object in memory!
Weird Java quirk: When calling .equals() on two arrays, it still compares references, not contents!
Inheritance
Static type: the type of the variable reference Dynamic type: the type of the actual object
| Field | Type |
|---|---|
| Static method | Static type |
| Regular method | Dynamic type |
| Fields (Attributes) | Static type |
Error: If only the dynamic type has a static method or attribute and not the static type, we cannot access it. Trying causes a compile error.
Casting only changes the static type, not the dynamic type.
Example
class Animal {
int energy = 10;
}
class Dog extends Animal {
int energy = 50; // hides Animal.energy
void eat() {
energy += 5; // modifies Dog.energy
}
}
Animal a = new Dog();
Dog d = (Dog) a;
d.eat();
System.out.println(a.energy); // 10
System.out.println(d.energy); // 55In this example, we have the following memory layout:
Reference a (Animal) ---> Dog object:
-------------------------------
| Animal.energy = 10 | <-- a.energy
| Dog.energy = 55 | <-- modified by Dog.eat()
-------------------------------
Reference d (Dog) ---> same object
Explanation:
- If a class inherits from another class, its objects contain both the fields of the actual type and of all the parents, even if they have the same names.
- Inside a method, field access resolves to the nearest field in that class. Here,
Dog.energyis the nearest. IfDogdidn’t have an energy field, then it would resolve toAnimal.energy. - The static type hides the fields that don’t belong to it. It acts as a filter. The other fields are still there and can be modified by methods belonging to the same class.
- Casting changes which fields are hidden and which ones aren’t. It changes the filter
Errors
Compile Errors
- Syntax errors (missing semicolons, type definitions)
- Incompatible types (assigning a boolean to an int, dividing a string)
- Undefined variables or methods, including because they belong to the dynamic type and not the static one
- Casting a variable where the static type has no inheritance relationship to the type to cast.
- The compiler can already know for sure that this cannot work.
- You can cast upwards and downwards the inheritance chain, but never sideways
- Important: This compiles fine because
Integerinherits fromObject:Object o = "hello"; Integer i = (Integer) o;It would not compile if we exchangeObjectforString.
Runtime Exceptions
- Division by zero
- Null reference / null pointer access
- Array or index out of bounds
- Casting a variable where the dynamic type has no inheritance relationship
Tips
a % 0throws an ArithmeticException- Pay close attention to whether a method is truly overridden (same signature) or merely overloaded (different parameters)
- If an exam shows a call
obj.calculate(5), and5is anint, Java will look for a version specifically forintbefore trying to “widen” it to adouble.
- If an exam shows a call
- Assignment are expressions that returns the assigned value
finalclasses cannot be inherited from;abstractclasses cannot be initialized.abstractclasses define behavior and state (via fields); interfaces define only behavior (and constants). For that reason, we can implement multiple interfaces but only one class.- If we implement two interfaces that have the same default methods, we must overwrite them
- Only possible to increment on variables, not values