Insel-Update für Java 25: Modul-Import

In größeren Java-Programmen sammeln sich naturgemäß zahlreiche Import-Deklarationen an. Zwar lassen sich diese in modernen Entwicklungsumgebungen bequem einklappen, doch sie bleiben Teil des Quellcodes und können schnell unübersichtlich werden.

Java bietet einige Möglichkeiten, die Imports zu vereinfachen. Eine Option ist der Einsatz von Wildcards – etwa import java.awt.*, um sämtliche Typen eines Pakets auf einmal zu importieren. Außerdem wird das Paket java.lang automatisch importiert, sodass dort Typen wie String, Math oder Comparable ganz ohne explizite Import-Deklaration verwendet werden können.

In Java 25 wurden Modul-Importe eingeführt, die alle öffentlichen Typen der exportierten Pakete eines Moduls sowie die Typen der indirekt referenzierten Module einbinden.

Erklärung

Ein Paket ist eine Sammlung thematisch zusammengehöriger Typen – wie Klassen und Schnittstellen –, die gemeinsam eine bestimmte Funktionalität bereitstellen. Ein Modul ist eine übergeordnete Einheit, die mehrere Pakete logisch zusammenfasst. Module dienen der besseren Strukturierung größerer Anwendungen und ermöglichen es, explizit festzulegen, welche Teile eines Moduls für andere Module zugänglich sind und von welchen Modulen es selbst abhängt. Die Java-Standardbibliothek ist vollständig modularisiert. Eigene Module spielen in der Praxis eine untergeordnete Rolle.

Die Syntax eines Modul-Imports lautet wie folgt:

import module Modulname;

Ein typisches Beispiel ist der Import des Basismoduls der Java-Standardbibliothek:

import module java.base;

Das Modul java.base ist das zentrale Kernmodul und umfasst essenzielle Pakete wie java.io, java.net, java.util und weitere. Die Javadoc zeigt alle Module und ihre enthaltenen Pakete auf.

Namenskonflikte durch Mehrfachimporte

Beim Einsatz von Wildcards in mehreren Paketimporten kann es zu Namenskonflikten kommen, wenn gleichnamige Typen in unterschiedlichen Paketen vorhanden sind. Dasselbe Problem kann auch bei Modul-Importen auftreten, da ein Modul in der Regel viele Pakete mit potenziell gleichnamigen Typen enthält. Ein klassisches Beispiel sind die Typen Date und List, die in mehreren Paketen existieren: Es gibt Date in java.util (Modul java.base) und in java.sql (Modul java.sql) und List in java.util (Modul java.base) und in java.awt (Modul java.desktop).

Nehmen wir folgenden Modul-Import an:

import module java.base;    // Enthält java.util.Date und java.util.List

import module java.sql;     // Enthält java.sql.Date

import module java.desktop; // Enthält java.awt.List

Dann meldet der Compiler einen Fehler, wenn Date oder List im Programm verwendet werden, da Date entweder java.util.Date oder java.sql.Date bedeuten könnte und List entweder java.util.List oder java.awt.List. Der Konflikt tritt also auf, weil die Modul-Importe mehrere Pakete einbinden, die Typen mit denselben einfachen Namen exportieren.

Es gibt unterschiedliche Lösungsansätze für das Problem.

Lösung 1: Eine gezielte Import-Deklaration für den gewünschten Typ verwenden:

import module java.base;

import module java.sql;

import module java.desktop;

import java.sql.Date;       // Eindeutig – nutzt Date aus java.sql und

import java.util.List;      // List aus dem Paket java.util

Lösung 2: Ein Wildcard-Import für die Priorisierung eines Pakets:

import module java.base;

import module java.sql;

import module java.desktop;

import java.util.*;  // Priorisiert Typen aus java.util gegenüber Modul-Importen

import java.sql.*;   // Priorisiert Typen aus java.sql gegenüber Modul-Importen

Die Mehrdeutigkeit für Date bleibt bestehen, da die Wildcard-Importe import java.util.* und import java.sql.* gleichrangig sind. Um Date eindeutig zu machen, ist ein gezielter Klassen-Import wie import java.sql.Date erforderlich. Der Typ List wird durch import java.util.* auf java.util.List festgelegt, da dieser Wildcard-Import den Modul-Import java.desktop überlagert.

Lösung 3: Vollständige Qualifikation von Typen:

import module java.base;

import module java.sql;

import module java.desktop;

Und dann zum Beispiel:

java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis());

Um es zusammenzufassen: Die Regel der Spezifität hilft bei der Auflösung solcher Namenskonflikte:

·       Einzelne Typ-Importe (import java.sql.Date) haben Vorrang vor

·       Paket-Importen mit Wildcard (import java.util.*), die wiederum Vorrang haben vor

·       Modul-Importen (import module java.base).

Strukturierung

Zur besseren Lesbarkeit des Codes empfiehlt es sich, Import-Deklarationen logisch zu gruppieren, in folgender Reihenfolge:

// Modul-Importe

import module java.base;

import module java.sql;

 

// Paket-Importe

import java.util.*;

import javax.sql.*;

 

// Einzelne Typ-Importe

import java.sql.Date;

 

class Application { }

Ähnliche Beiträge

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert