Java Academy · Lektion

Best practices for Optional

Anvend orElse, orElseGet og orElseThrow, og undgå almindelige anti-mønstre med Optional.

Lektion 4 af 413 trin

Best practices for Optional er en gratis Java Academy-lektion på CoddyKit. Dette er lektion 4 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Java Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Java Academy-kurset indeholder 4 lektioner i alt.

Bedste fremgangsmåder for Optional

Optional er et effektivt værktøj, når det bruges korrekt. Denne lektion gennemgår, hvad du bør og ikke bør gøre, med konkrete eksempler fra virkelige kodebaser.

Gør: Brug Optional som returtype

Den primære anvendelse af Optional er som returtype fra metoder, der måske ikke finder eller opretter en værdi.

import java.util.Optional;

// Good: signals to caller that result might be absent
public Optional<User> findByUsername(String username) { ... }
public Optional<Config> getConfig(String key) { ... }
public Optional<String> getHeader(String name) { ... }

// These are all cases where absence is a normal outcome,
// not an exceptional condition

Undgå: Optional som felt

Optional-felter medfører ekstra objektomkostninger og gør serialisering mere kompliceret. Brug null eller en markørværdi til valgfrie felter i klasser.

// BAD
class User {
    private Optional<String> middleName; // wrong
}

// GOOD: use null for absent optional field
class User {
    private final String middleName; // null = absent
    public Optional<String> middleName() {
        return Optional.ofNullable(middleName); // expose as Optional in getter
    }
}
User u = new User(null); // null field
System.out.println(u.middleName().isPresent()); // false

Undgå: Optional som metodeparameter

Optional-parametre tvinger kaldende kode til at pakke værdier ind i Optional uden grund. Brug overloadning eller @Nullable i stedet.

// BAD
void sendNotification(String message, Optional<String> subject) { ... }
// caller must write: sendNotification("Hello", Optional.of("News"))

// GOOD: overloading
void sendNotification(String message) { sendNotification(message, null); }
void sendNotification(String message, String subject) {
    // subject may be null
}
// caller writes: sendNotification("Hello", "News") — clean

Undgå: Optional i samlinger

Anbring aldrig Optional-værdier i en List, Set eller som en Map-værdi. Tomme Optional-værdier i samlinger er meningsløse — udelad blot posten.

// BAD: List of Optionals
List<Optional<User>> results = ...; // meaningless empty Optionals

// GOOD: List of present values only
List<User> presentUsers = maybeUsers.stream()
    .flatMap(Optional::stream)
    .collect(Collectors.toList());

// BAD: Map with Optional values
Map<String, Optional<String>> config = ...;

// GOOD: just use null or omit the key for absent values
Map<String, String> config2 = ...;
String value = config2.getOrDefault("key", "default");

Gør: Brug orElseGet til dyre standardværdier

Når standardværdien kræver beregning (databaseforespørgsel, netværkskald), skal du altid bruge orElseGet — leverandøren kaldes kun, når det er nødvendigt.

import java.util.Optional;

// BAD: buildDefault() always called, even when value is present!
String config = getConfig("timeout").orElse(buildDefault());

// GOOD: supplier called lazily only when empty
String config2 = getConfig("timeout").orElseGet(() -> buildDefault());

// Or with method reference:
String config3 = getConfig("timeout").orElseGet(this::buildDefault);

// For cheap literals, orElse is fine
String name = getConfig("name").orElse("default");

Gør: Brug orElseThrow til nødvendige værdier

Når en manglende værdi er en programmeringsfejl eller en overtrædelse af en invariant, skal du bruge orElseThrow med en beskrivende undtagelse.

import java.util.Optional;

// Good: throw when absence is an error
User user = userRepository.findById(userId)
    .orElseThrow(() -> new UserNotFoundException("User not found: " + userId));

// Good: in validation code
String apiKey = Optional.ofNullable(System.getenv("API_KEY"))
    .orElseThrow(() -> new IllegalStateException(
        "API_KEY environment variable is required"));

System.out.println("Key found: " + apiKey.length() + " chars");

Antimønster: isPresent + get()

Undgå antimønstret, hvor du kontrollerer isPresent() og derefter kalder get(). Det er ikke bedre end en null-kontrol og modarbejder formålet med Optional.

import java.util.Optional;

Optional<String> opt = findValue();

// BAD: isPresent() + get() — no improvement over null check
if (opt.isPresent()) {
    String val = opt.get();
    process(val);
}

// GOOD: use the functional API
opt.ifPresent(this::process);

// GOOD: transform and return
return opt.map(this::process).orElse(null);

// GOOD: provide a default
String result = opt.orElse("default");

Bedste fremgangsmåde ved kædning

Opbyg en ren kæde: find → filter → transformér → reserveværdi. Hvert trin forklarer sig selv.

import java.util.Optional;

record User(long id, String plan, boolean active) {}

static Optional<User> findUser(long id) { return Optional.empty(); }

String result = findUser(42L)
    .filter(User::active)           // keep only active users
    .filter(u -> "PRO".equals(u.plan())) // keep only PRO users
    .map(u -> "Welcome, Pro user #" + u.id()) // transform
    .orElse("Upgrade to Pro!");     // fallback

System.out.println(result); // Upgrade to Pro!

Optional i servicelaget

Et realistisk eksempel på servicelaget, der følger de bedste fremgangsmåder.

import java.util.Optional;

class OrderService {
    public Optional<OrderSummary> getOrderSummary(long orderId) {
        return orderRepo.findById(orderId)
            .filter(o -> !o.isCancelled())
            .map(this::toSummary);
    }

    public OrderSummary requireOrderSummary(long orderId) {
        return getOrderSummary(orderId)
            .orElseThrow(() -> new OrderNotFoundException(orderId));
    }

    private OrderSummary toSummary(Order o) { return new OrderSummary(o); }
}
// API callers choose: Optional (handle absence) or require (exception)

Optional og værktøjer til null-sikkerhed

Optional supplerer @Nullable- og @NonNull-annotations samt værktøjer som SpotBugs og NullAway for at give fuldstændig dækning af null-sikkerhed.

// Annotation-based: declares intent for in-class nulls
import org.jetbrains.annotations.*;

class ProductService {
    @Nullable  // may return null — for framework/bean use
    public String getCachedName(String id) { return cache.get(id); }

    // Optional — for service API that handles absence
    public Optional<Product> findProduct(String id) {
        return repo.findById(id);
    }
}
// Use @Nullable for fields/parameters; Optional for return types

Hurtig kontrol

Hvad er der galt med følgende kode?

if (opt.isPresent()) {
    process(opt.get());
}

Opsummering: Bedste fremgangsmåder for Optional

Vigtigste pointer:

  • Brug kun Optional som returtype — aldrig som felt eller metodeparameter
  • Foretræk orElseGet frem for orElse, når standardværdien er dyr at beregne
  • Brug orElseThrow, når en manglende værdi repræsenterer en programmeringsfejl
  • Undgå isPresent() + get() — brug ifPresent, map eller orElse i stedet
  • Anbring aldrig Optional i samlinger — filtrér streams i stedet
  • Opbyg læsbare kæder: filter → map → orElse for et tydeligt dataflow
Gratis at komme i gang

Lær Java med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
104
Lektioner
374

Ofte stillede spørgsmål

Er lektionen “Best practices for Optional” gratis?

Ja — hele teksten til “Best practices for Optional” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Java Academy-kurset, skal du opgradere til CoddyKit PRO. Java Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Best practices for Optional”?

Anvend orElse, orElseGet og orElseThrow, og undgå almindelige anti-mønstre med Optional. Du øver dig i Java Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Java Academy?

Der kræves ingen tidligere erfaring. Java Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 4 af 4.

Hvor lang tid tager lektionen “Best practices for Optional”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Java Academy-lektion?

Ja. Alle Java Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Hvorfor findes Optional?
  2. Oprettelse og inspektion af Optionals
  3. Transformation af Optionals: map og flatMap
  4. Best practices for Optional
← Tilbage til Java Academy