Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add nullability concept #2584

Merged
merged 6 commits into from
Nov 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions concepts/nullability/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"blurb": "In Java, the null literal is used to denote the absence of a value.",
"authors": [
"smcg468"
],
"contributors": []
}
53 changes: 53 additions & 0 deletions concepts/nullability/about.md
sanderploegsma marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# About

In Java, the [`null` literal][null-keyword] is used to denote the absence of a value.
sanderploegsma marked this conversation as resolved.
Show resolved Hide resolved

[Primitive variables][primitive-data-types] in java all have a default value and therefore can never be `null`.
By convention, they start with a lowercase letter e.g `int`

[Reference variables][reference-data-types] contain the memory address of an object and can have a value of null.
These variables usually start with an uppercase e.g `String`

Attempting to assign a primitive variable a value of `null` will result in a compile time error as the variable always holds
a default value of the type assigned.

```java
//Throws compile time error stating the required type is int, but null was provided
int number = null;
```

Assigning a reference variable a `null` value will not result in a compile time error as reference variables are nullable.

```java
//No error will occur as the String variable str is nullable
String str = null;
```

Whilst accessing a reference variable which has a value of `null` will compile fine, it will result in a `NullPointerException` being thrown at runtime.

```java
int[] arr = null;

// Throws NullPointerException at runtime
arr.Length;
```

A [`NullPointerException` is thrown][null-pointer-exception] when trying to access a reference variable which is null but requires an object.

To safely work with nullable values, one should check if they are `null` before working with them which can be done using [equality operators][equality-operators] such as `==` or `!=`:

```java
int[] arr = null;

if(arr != null) {
System.out.println(arr.length);
} else {
//Perform an alternate action when arr is null
}
```

[null-keyword]: https://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.7
[primitive-data-types]: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
[reference-data-types]: https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.3
[null-pointer-exception]: https://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
[equality-operators]: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html
24 changes: 24 additions & 0 deletions concepts/nullability/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Introduction

In Java, the `null` literal is used to denote the absence of a value.

Primitive data types in java all have a default value and therefore can never be `null`.
By convention, they start with a lowercase letter e.g `int`

Reference types contain the memory address of an object can have a value of null.
These variables usually start with an uppercase e.g `String`

Attempting to assign a primitive variable a value of `null` will result in a compile time error as the variable always holds
a primitive value of the type assigned.

```java
//Throws compile time error stating the required type is int, but null was provided
int number = null;
```

Assigning a reference variable a `null` value will not result in a compile time error as reference variables are nullable.

```java
//No error will occur as the String variable str is nullable
String str = null;
```
22 changes: 22 additions & 0 deletions concepts/nullability/links.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[
{
"url": "https://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.7",
"description": "null-keyword"
},
{
"url": "https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html",
"description": "primitive-data-types"
},
{
"url": "https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.3",
"description": "reference-data-types"
},
{
"url": "https://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html",
"description": "null-pointer-exception"
},
{
"url": "https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html",
"description": "equality-operators"
}
]
17 changes: 17 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,18 @@
"switch-statement",
"constructors"
]
},
{
"slug": "tim-from-marketing",
"name": "Tim from Marketing",
"uuid": "28bd20c5-4fdd-4660-9225-54f24aae24e4",
"concepts": [
"nullability"
],
"prerequisites": [
"if-else-statements",
"strings"
]
}
],
"practice": [
Expand Down Expand Up @@ -2098,6 +2110,11 @@
"slug": "lists",
"name": "Lists"
},
{
"uuid": "0718bff1-25ad-42bb-860d-1b0834beb9fc",
"slug": "nullability",
"name": "Nullability"
},
{
"uuid": "58529dab-0ef2-4943-ac12-a98ca79b922b",
"slug": "numbers",
Expand Down
20 changes: 20 additions & 0 deletions exercises/concept/tim-from-marketing/.docs/hints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Hints

## 1. Print a badge for an employee

- [String interpolation][string-interpolation] can be used to create description strings.
- There is a [built-in method to convert a string to uppercase][to-upper-case].

## 2. Print a badge for a new employee

- You should check if the ID is `null` before using it.
- You can use the [equality operators][equality-operators] to compare the value to `null`

## 3. Print a badge for the owner

- You should check if the department is `null` before using it.
- You can use the [equality operators][equality-operators] to compare the value to `null`

[string-interpolation]: https://www.baeldung.com/java-string-interpolation
[to-upper-case]:https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#toUpperCase--
[equality-operators]: https://docs.oracle.com/cd/E21764_01/apirefs.1111/e17787/com/sigmadynamics/util/Null.html#isNull_java_lang_String_
47 changes: 47 additions & 0 deletions exercises/concept/tim-from-marketing/.docs/instructions.md
sanderploegsma marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Instructions

In this exercise you'll be writing code to print name badges for factory employees.

## 1. Print a badge for an employee

Employees have an ID, name and department name. Employee badge labels are formatted as follows: `"[id] - name - DEPARTMENT"`.
Implement the `Badge.print()` method to return an employee's badge label:

```java
Badge badge = new Badge();
badge.print(734, "Ernest Johnny Payne", "Strategic Communication");
// => "[734] - Ernest Johnny Payne - STRATEGIC COMMUNICATION"
```

Note that the department should be uppercased on the label.

## 2. Print a badge for a new employee

Due to a quirk in the computer system, new employees occasionally don't yet have an ID when they start working at the factory.
As badges are required, they will receive a temporary badge without the ID prefix. Modify the `Badge.print()` method to support new employees that don't yet have an ID:

```java
Badge badge = new Badge();
Badge.print(null, "Jane Johnson", "Procurement");
// => "Jane Johnson - PROCUREMENT"
```

## 3. Print a badge for the owner

Even the factory's owner has to wear a badge at all times.
However, an owner does not have a department. In this case, the label should print `"OWNER"` instead of the department name.
Modify the `Badge.print()` method to print a label for the owner:

```java
Badge badge = new Badge();
badge.print(254, "Charlotte Hale", null);
// => "[254] - Charlotte Hale - OWNER"
```

Note that it is possible for the owner to also be a new employee:

```java
Badge badge = new Badge();
badge.print(null, "Charlotte Hale", null);
// => "Charlotte Hale - OWNER"
```
26 changes: 26 additions & 0 deletions exercises/concept/tim-from-marketing/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Introduction

## Nullability

In Java, the `null` literal is used to denote the absence of a value.

Primitive data types in java all have a default value and therefore can never be `null`.
By convention, they start with a lowercase letter e.g `int`

Reference types contain the memory address of an object can
have a value of null. These variables usually start with an uppercase e.g `String`

Attempting to assign a primitive variable a value of `null` will result in a compile time error as the variable always holds
a primitive value of the type assigned.

```java
//Throws compile time error stating the required type is int, but null was provided
int number = null;
```

Assigning a reference variable a `null` value will not result in a compile time error as reference variables are nullable.

```java
//No error will occur as the String variable str is nullable
String str = null;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Introduction

## Nullability

%{concept:nullability}
23 changes: 23 additions & 0 deletions exercises/concept/tim-from-marketing/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"authors": [
"smcg468"
],
"files": {
"solution": [
"src/main/java/Badge.java"
],
"test": [
"src/test/java/BadgeTest.java"
],
"exemplar": [
".meta/src/reference/java/Badge.java"
],
"invalidator": [
"build.gradle"
]
},
"forked_from": [
"csharp/tim-from-marketing"
],
"blurb": "Learn about the null literal and nullable variables in java by printing name badges."
}
20 changes: 20 additions & 0 deletions exercises/concept/tim-from-marketing/.meta/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Design

## Learning objectives

- Know of the existence of the `null` literal.
- Know what a `NullPointerException` is and when it is thrown.
- Know how to compare a value to `null`.

## Out of scope

- `java.util.Optional`

## Concepts

- `nullability`

## Prerequisites

- `strings`: strings will be compared to null and basic methods from strings will be called.
- `if-else-statements`: using a conditional statement.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
public class Badge {

public String print(Integer id, String name, String department) {

String worksAt;

if (department == null) {
worksAt = "OWNER";
} else {
worksAt = department.toUpperCase();
}

if (id == null) {
return name + " - " + worksAt;
}

return "[" + id + "] - " + name + " - " + worksAt;
}

}
23 changes: 23 additions & 0 deletions exercises/concept/tim-from-marketing/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
plugins {
id "java"
}

repositories {
mavenCentral()
}

dependencies {
testImplementation platform("org.junit:junit-bom:5.10.0")
testImplementation "org.junit.jupiter:junit-jupiter"
testImplementation "org.assertj:assertj-core:3.15.0"
}

test {
useJUnitPlatform()

testLogging {
exceptionFormat = "full"
showStandardStreams = true
events = ["passed", "failed", "skipped"]
}
}
5 changes: 5 additions & 0 deletions exercises/concept/tim-from-marketing/src/main/java/Badge.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Badge {
public String print(Integer id, String name, String department) {
throw new UnsupportedOperationException("Please implement the (static) Badge.print() method");
}
}
40 changes: 40 additions & 0 deletions exercises/concept/tim-from-marketing/src/test/java/BadgeTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;

public class BadgeTest {

@Test
@Tag("task:1")
@DisplayName("Printing a badge for an employee")
public void labelForEmployee() {
Badge badge = new Badge();
assertThat(badge.print(17, "Ryder Herbert", "Marketing"))
.isEqualTo("[17] - Ryder Herbert - MARKETING");
}

@Test
@Tag("task:2")
@DisplayName("Printing a badge for a new employee")
public void labelForNewEmployee() {
Badge badge = new Badge();
assertThat(badge.print(null, "Bogdan Rosario", "Marketing")).isEqualTo("Bogdan Rosario - MARKETING");
}

@Test
@Tag("task:3")
@DisplayName("Printing a badge for the owner")
public void labelForOwner() {
Badge badge = new Badge();
assertThat(badge.print(59, "Julie Sokato", null)).isEqualTo("[59] - Julie Sokato - OWNER");
}

@Test
@Tag("task:3")
@DisplayName("Printing a badge for the owner who is a new employee")
public void labelForNewOwner() {
Badge badge = new Badge();
assertThat(badge.print(null, "Amare Osei", null)).isEqualTo("Amare Osei - OWNER");
}
}
2 changes: 2 additions & 0 deletions exercises/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ include 'concept:football-match-reports'
include 'concept:wizards-and-warriors'
include 'concept:calculator-conundrum'
include 'concept:logs-logs-logs'
include 'concept:tim-from-marketing'

// practice exercises
include 'practice:accumulate'
Expand Down Expand Up @@ -150,3 +151,4 @@ include 'practice:wordy'
include 'practice:yacht'
include 'practice:zebra-puzzle'
include 'practice:zipper'