1 Punkte von GN⁺ 2024-08-04 | 1 Kommentare | Auf WhatsApp teilen

Null-Restricted and Nullable Types (Preview)

Zusammenfassung

Eine Preview-Sprachfunktion, die Nullness-Marker unterstützt, um bei Java-Typen null zuzulassen oder abzulehnen.

Ziele

  • Verbesserung der Java-Referenztypen, damit Programmierer ausdrücken können, ob sie null-Referenzen erwarten
  • Unterstützung von Konvertierungen zwischen Typen mit unterschiedlichen Nullness-Eigenschaften sowie Warnungen bei fehlerhaft behandelten null-Werten
  • Kompatibilität mit bestehendem Java-Code und Unterstützung einer schrittweisen Einführung der neuen Funktion
  • Sicherstellen, dass Variablen von null-beschränkten Typen vor dem ersten Lesen initialisiert werden
  • Laufzeitdurchsetzung von null-beschränkten Typen auch in separat kompilierten Klassen
  • Bereitstellung der für Laufzeitoptimierungen erforderlichen Metadaten und Integritätsgarantien

Nicht-Ziele

  • Bestehenden Code nicht automatisch neu interpretieren
  • Nicht verlangen, dass alle null-Werte explizit behandelt werden
  • Keine Änderungen an primitiven Typen einschließen
  • Sprachverbesserungen nicht auf die Standardbibliothek anwenden

Motivation

  • In Java-Programmen kann eine Variable vom Typ String eine Referenz auf ein String-Objekt oder den Wert null haben
  • Es lässt sich nicht eindeutig ausdrücken, ob eine Variable null zulassen soll, was zu Verwirrung und Bugs führt
  • Es werden Werkzeuge benötigt, mit denen Entwickler als Teil des Typs festlegen können, ob null unterstützt oder erwartet wird

Beschreibung

Nullness-Eigenschaften und Marker

  • Referenztypen können Nullness optional ausdrücken
  • Foo! ist ein null-beschränkter Typ, der null nicht enthält
  • Foo? ist ein nullable Typ, der null enthalten kann
  • Standardmäßig ist die Nullness von Foo nicht festgelegt

Initialisierung von Feldern und Arrays

  • Null-beschränkte Felder oder Arrays müssen vor der Verwendung initialisiert werden
  • Wird ein nicht initialisiertes null-beschränktes Feld gelesen, tritt eine Ausnahme auf

Ausdrucks-Nullness und Konvertierungen

  • Der Java-Compiler bestimmt die Nullness aller Ausdrücke
  • Über Nullness-Konvertierungen können Ausdrücke mit unterschiedlicher Nullness verarbeitet werden
  • Eine Narrowing-Nullness-Konvertierung kann zur Laufzeit eine NullPointerException auslösen

Laufzeit-Nullprüfungen

  • Tritt eine Narrowing-Nullness-Konvertierung auf, wird eine NullPointerException ausgelöst

Nullness von Typparametern

  • Auch Typparameter können Nullness ausdrücken
  • Null-beschränkte und nullable Typparameter behaupten in generischem Code eine bestimmte Nullness

Typargumente und Grenzen

  • Typargumente können Nullness ausdrücken, was sich auf die Nullness einer API auswirkt
  • Typargumente mit nicht übereinstimmender Nullness können Warnungen auslösen

Methodenüberschreibung und Typinferenz für Typargumente

  • Nullness wird ignoriert, wenn bestimmt wird, ob Methodensignaturen identisch sind
  • Der Rückgabetyp einer überschreibenden Methode kann über Nullness-Konvertierungen umgewandelt werden

Compiler-Warnungen

  • Das Erstellen eines null-beschränkten Typs kann neue Compile-Time-Fehler verursachen
  • Narrowing-Nullness-Konvertierungen, die Verwendung eines ?-Typs in null-feindlichen Operationen usw. können Warnungen auslösen

Kompilierung und Darstellung in Class-Dateien

  • Die meisten Null-Marker werden aus Class-Dateien entfernt
  • Das neue Attribut NullRestricted zeigt an, dass ein Feld keine null-Werte zulässt

Core Reflection

  • Literale wie Foo!.class oder Foo?.class existieren nicht
  • Die neue RuntimeType-API beschreibt zur Laufzeit null-beschränkte Varianten

Ergänzende Änderungen

  • Die traditionelle Serialisierung ist nicht mit null-beschränkten Feldern und Arrays kompatibel
  • javadoc enthält Nullness-Marker
  • Die APIs java.lang.reflect.Type und javax.lang.model kodieren Nullness

Alternativen

  • Verschiedene Entwicklungswerkzeuge im Java-Ökosystem implementieren eigenes Null-Tracking
  • Andere Programmiersprachen verfolgen Nullness im Typsystem
  • Laufzeitdurchsetzung von Nullness kann über explizite Prüfungen oder Aufrufe von Objects.requireNonNull umgesetzt werden

Abhängigkeiten

  • Flexible Constructor Bodies (Second Preview) erforderlich
  • Zukünftige Arbeiten wie Null-Restricted Value Class Types (Preview) und JEP 402: Enhanced Primitive Boxing (Preview)

Zusammenfassung von GN⁺

  • Dieses JEP stellt Werkzeuge bereit, um null-Werte in Java klarer zu behandeln, und erhöht damit Stabilität und Lesbarkeit des Codes
  • Durch die Einführung von null-beschränkten und nullable Typen lassen sich Bugs durch null-Referenzen reduzieren
  • Die Funktion ist mit bestehendem Code kompatibel und kann schrittweise eingeführt werden, was Entwicklern Flexibilität bietet
  • Im Vergleich mit anderen Sprachen kann sie Javas Fähigkeiten im Umgang mit null stärken
  • Ein Werkzeug mit ähnlicher Funktionalität ist etwa die Null-Safety von Kotlin

1 Kommentare

 
GN⁺ 2024-08-04
Hacker-News-Kommentare
  • Vergleich der Null-Behandlung in C# und Kotlin

    • In C# werden, wenn im Projekt Nullability aktiviert wird, alle Variablen standardmäßig als non-null deklariert
    • Kotlin ist ähnlich, benötigt aber keine Backwards Compatibility
    • Kotlin bietet mit der Deklaration lateinit var die Möglichkeit, nicht initialisierte non-nullable Variablen später zu initialisieren
  • Meinungen zum neuen Vorschlag

    • Bestehende Variablen werden in nullable, explizit nullable und explizit non-nullable unterschieden
    • Der Ansatz von C# wirkt besser, vor allem weil man Nullability-Probleme in Legacy-Codebasen nicht lösen muss
    • Allerdings hebt der C#-Ansatz Nullability-Probleme in der Codebasis sofort hervor
  • Bedenken zur automatischen Umwandlung durch nullness narrowing

    • Automatische Umwandlung vermittelt ein falsches Gefühl
    • In manchen Fällen sollte ein Compiler-Fehler ausgelöst werden
    • Eine explizite Umwandlung ist sicherer
  • Notwendigkeit einer Methode, alle Variablen standardmäßig als non-null zu markieren

    • Es braucht eine Möglichkeit, auf Paket- oder Dateiebene alle Variablen als non-null zu markieren
    • Andernfalls müsste man die Syntax T! bei fast allen Variablen verwenden, was den Code komplex macht
  • Bedarf an einer expliziten Optionality-Funktion auf Sprachebene in Java

    • Basierend auf Erfahrungen mit Kotlin und Typescript ist Unterstützung auf Sprachebene besser
    • Tools wie NullAway in Java sind umständlich
  • Kritik an der Entscheidung, Sprachverbesserungen nicht auf die Standardbibliothek anzuwenden

    • Aus der Erfahrung mit PHP ist die Interaktion mit der Standardbibliothek umständlich
    • Es ist nötig, diese Ausdrucksstärke zur Standardbibliothek hinzuzufügen
  • Bedarf an einer einfachen Möglichkeit, Compile-Time-Warnungen zu Fehlern hochzustufen

    • Java ist überwiegend eine statisch typisierte Sprache, daher ist es nicht gut, dynamisches Verhalten einzuführen
  • Notwendigkeit, standardmäßig non-nullable, immutable und eng eingegrenzt zu setzen

    • Bei neuen Designentscheidungen wird der sichere Weg oft zugunsten unmittelbarer Bequemlichkeit aufgegeben
    • In vielen Sprachen und Technologien verursacht dieses Problem viele Fehler
  • Erfahrungen mit der Null-Behandlung in der Sprache Hack

    • Nullness ist ein wichtiger Teil des Typsystems von Hack
    • Frage zu nullable Arrays
    • In Java wird das zum Problem, weil aller Legacy-Code von Nullability ausgeht
  • Frage, ob sich diese Funktion auf das Java SDK anwenden lässt

    • Unklar ist, wie sie sich auf Legacy-Code anwenden ließe
  • Relevante Links