Lecture from: 01.11.2024 | Video: Videos ETHZ
Working with null
In Java, reference type variables (variables that hold objects, arrays, or strings) can have a special value called null
. Understanding null
is crucial for avoiding common errors and writing robust code.
What is null
?
null
represents the absence of a value. It indicates that a reference variable does not currently point to any valid object, array, or string in memory.
- Not an Object:
null
itself is not an object. It’s a special keyword. - Default Value: Reference type variables are automatically initialized to
null
if you don’t explicitly assign them a value.
null
vs. null
The expression null == null
evaluates to true
. You can compare a reference variable to null
to check if it currently refers to an object.
The NullPointerException
The dreaded NullPointerException
occurs when you try to access a member (attribute or method) of a variable that is currently null
. This is because null
doesn’t point to an object, so there are no members to access.
Example:
Preventing NullPointerExceptions
If you try to access an attribute or method of a null
reference, you get a NullPointerException
.
1. Check for null
before dereferencing: This is the most common and effective way to prevent NullPointerExceptions
.
2. Use the Optional class (Advanced): (Beyond EProg scope currently.) The Optional
class provides a more structured way to handle situations where a value might be absent.
3. Careful Initialization: Initialize variables to non-null values whenever possible. This can sometimes eliminate the need for null checks. However, it’s not always feasible or appropriate.
4. Assertions (For Debugging): In development, use assertions to check for unexpected null values. Assertions are checked at runtime and will throw an error if the assertion fails, helping you identify potential problems early.
5. Handle Potential null
Returns from Methods: Be aware that methods can return null
. Always check for null
on return values if the method documentation indicates it’s a possibility.
Null Checks and Conditional Logic
Be mindful of how null checks interact with conditional logic, especially with &&
(AND) and ||
(OR).
- Short-Circuiting: Java uses short-circuit evaluation. With
&&
, if the left side isfalse
, the right side is not evaluated. With||
, if the left side istrue
, the right side is not evaluated.
Methods
Methods define the behavior of a class. They are functions that operate on the object’s state (its attributes).
Defining Methods
Methods are declared inside the class body, similar to functions in procedural programming.
Syntax:
Object Methods vs. Static Methods (Preview – More Detail Later)
- Object Methods (Instance Methods): Operate on a specific object’s state. They have access to the object’s attributes via the
this
reference. - Static Methods (Class Methods): Not associated with a specific object. They cannot access instance attributes or use the
this
keyword. We’ll discuss static methods in more detail later.
The toString()
Method
Every Java class inherits a toString()
method from the Object
class. This method is called implicitly when you try to print an object or concatenate it with a string. The default implementation of toString()
returns a string representation of the object’s memory address, which is often not very helpful.
Example:
Overriding toString()
To provide a more meaningful string representation, you can override the toString()
method in your class.
Example:
Important: The overriding toString()
method must have the exact signature public String toString()
.
Nested Structures and toString()
If you have nested objects (e.g., an array of Point
objects), calling toString()
on the outer object will implicitly call toString()
on each of the inner objects.
Example:
Constructors
Constructors are special methods used to initialize the state of an object when it’s created. They have the same name as the class and no return type (not even void
).
Defining Constructors
Constructor Execution
A constructor is automatically called when an object is created using the new
operator.
Example: Point
Constructors
Default Constructor
If you don’t define any constructors for a class, Java automatically provides a default constructor with no parameters. This default constructor initializes all instance variables to their default values (0, false
, or null
). However, if you define any constructor yourself, the default constructor is not automatically provided.
Delegating Constructors
Constructors can call other constructors within the same class using this(parameters)
. This is called constructor delegation and can help reduce redundant code. The delegating call must be the first statement in the constructor.
Example:
Common Constructor Errors
-
Shadowing: Accidentally declaring local variables with the same name as attributes inside the constructor, effectively hiding the attributes. Use
this.attributeName
to refer to attributes unambiguously. -
Return Type: Declaring a return type (even
void
) for a constructor. Constructors don’t have return types. -
Missing Default Constructor: Trying to use a no-argument constructor after defining a constructor with parameters, without also explicitly defining a no-argument constructor.
Continue here: 13 Visibility Modifiers, Object Invariants, Static Methods, Final and Attributes