Packages, package Modifier,
und das import Keyword

Video

Mit dem Laden des Videos akzeptierst du die Datenschutzerklärung von YouTube. Wenn du die Menge an Daten reduzieren möchtest, die YouTube von dir sammelt, solltest du dich vorher aus deinem YouTube-Account ausloggen, das Speichern von Cookies für das Google-Ads-Programm deaktivieren und/oder Cookies im Browser blockieren.

YouTube immer automatisch laden
Inhaltsverzeichnis
Als Text lesen

Jetzt wo du mit einer richtigen IDE programmierst, hast du genug Platz um mehr als nur eine Klasse zu erstellen. In Java sollte nämlich (bis auf wenige Ausnahmen) jede Klasse in einer eigenen .java Datei liegen. Diese muss genauso heißen wie die Klasse selbst, also z.B. Calculator.java für die Klasse Calculator.

Ich denke du glaubst mir wenn ich dir sage, dass es bei großen Softwareprojekten seeehr viele Klassen und damit ebenso viele Dateien geben kann. Was aber, wenn mehrere dieser Klassen einen identischen Namen haben?

Um dieses Problem zu lösen, und um dem Projekt eine gute Struktur zu geben, gibt es Packages.

Packages sind Ordner, in denen .java Dateien liegen, und werden verwendet um zusammengehörende Klassen zu gruppieren. Wenn eine Klasse in einem anderen Package liegt als dem default Package, muss dies mit dem package Keyword explizit deklariert werden:

package game.util; // Die Datei Calculator.java liegt im Ordner src/game/util/
public class Calculator {
// ...
}
 
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

In IntelliJ kannst du ein neues Package über Rechtsklick auf src Ordner > New > Package erstellen.

Wenn nun in einer Klasse ein Objekt einer anderen Klasse verwendet wird, muss dem Compiler zuerst mitgeteilt werden, in welcher Datei sich diese Klasse befindet. Hierfür gibt es das import Keyword:

package game; // Game.java befindet sich in src/game/
/*
* Calculator muss importiert werden, weil es nicht im
* gleichen Package liegt wie Game
*/
import game.util.Calculator;
public class Game {
// ...
public static void main(String[] args) {
// ...
new Calculator();
// ...
}
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Noch eine Sache

Du kennst schon die Access modifier private und public. Was aber, wenn du (wie zu Beginn dieses Kurses) gar keinen Access Modifier vor Attributen bzw. Methoden verwendest?

Der package private Modifier (oder auch default Modifier) wird implizit immer dann verwendet, wenn kein konkreter Access Modifier angegeben wurde.

Attribute und Methoden, die package private sind, sind nur innerhalb des eigenen Packages sichtbar. Für Klassen innerhalb des Packages verhält sich dieser also wie public, für Klassen außerhalb wie private.

Modifier private package (kein Modifier) public
Zugriff aus eigener Klasse
Zugriff aus eigenem Package
Zugriff aus anderen Packages

Du solltest in den allermeisten Fällen jedoch explizit private oder public als Modifier angeben.

Tic-Tac-Toe

Diese Übung wird ein bisschen größer als sonst. Dafür wirst du am Ende ein funktionierendes Tic-Tac-Toe Spiel für zwei Spieler programmiert haben.

Teil 1: Nutzereingabe

Bisher hast du immer nur Ausgaben auf der Konsole angezeigt. Wir wollen aber auch Nutzereingaben über diese entgegennehmen. Hierfür gibt es in der Java-Bibliothek die Klasse Scanner des Packages java.util. Du kannst beispielsweise mit der folgenden Methode readInt(String inputText) eine Ganzzahl einlesen:

public class UserInput {
private Scanner scanner;
public UserInput() {
scanner = new Scanner(System.in); /* System.in ist wie System.out,
nur in die andere Richtung */
}
/**
* Gibt eine Zahl zurück, die der Nutzer über die Konsole eingibt.
* inputText ist ein Text, der links neben der Nutzereingabe angezeigt wird, z.B.
*
* Dein Name: [Eingabe]
*/
public int readInt(String inputText) {
System.out.print(inputText);
return scanner.nextInt();
}
}
 
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Aufgaben

  • Erstelle ein neues Java Projekt
  • Erstelle eine neue Klasse UserInput im Package tictactoe.input und füge den Code von oben ein
  • Importiere Scanner aus dem Package java.util

Teil 2: Spielfeld

Wir benötigen ein Spielfeld. Bei Tic-Tac-Toe ist das ein 3 x 3 Gitter aus einzelnen Feldern, die entweder leer (' ') sind oder von einem Spieler gesetzt wurden ('X' / 'O'). Wir modellieren dieses Spielfeld mit einer neuen Klasse, die ein 9-elementiges char Array enthält.

Erstelle eine Klasse GameGrid im Package tictactoe.grid und implementiere die folgenden Programmteile:

  • Ein Objektattribut content, das ein char Array ist und später speichert, welche Felder von welchem Spieler belegt sind. Index 0 soll hierbei die obere linke Ecke sein, Index 8 die untere rechte.
  • Ein Konstruktor, der content mit 9 Leerzeichen initialisiert
  • Eine Methode void set(int position, char value), die das Feld an Position position mit dem Wert value füllt (Du kannst davon ausgehen, dass position ein valider Index ist)
  • Eine Methode boolean freePosition(int position), die genau dann true zurückgibt, wenn position ein gültiger Index für content ist, und das Feld an diesem Index leer ist
  • Eine Methode boolean full(), die genau dann true zurückgibt, wenn alle Felder durch einen Spieler gesetzt wurden, also keines mehr leer ist
  • Eine Methode void printToConsole(), die zuerst eine Leerzeile auf der Konsole ausgibt, und anschließend das Spielfeld in folgender Form (Beispiel):

     O |   |
    ---|---|---
     O | X |
    ---|---|---
       |   | X
  • Eine Methode boolean won(), die genau dann true zurückgibt, wenn ein Spieler gewonnen hat (egal welcher). Das ist der Fall, wenn eine Zeile, eine Spalte, oder eine Diagonale nur noch aus 'X' bzw. 'O' besteht.

Teil 3: Das Eigentliche Spiel

Lass uns nun das eigentliche Spiel zusammenbauen:

  • Erstelle eine Klasse TicTacToe im Package tictactoe
  • Erstelle die Objektattribute GameGrid gameGrid und UserInput userInput, die in einem parameterlosen Konstruktor instanziiert werden
  • Erstelle eine Methode int readValidPosition(char currentPlayer), die eine vom Nutzer eingegebene Spielfeld-Position zurückgibt. Falls diese jedoch kein gültiger Index ist oder das Feld bereits belegt ist, soll der Vorgang wiederholt werden, bis eine korrekte Eingabe vorliegt
  • Erstelle eine Methode void gameLoop(), die vom Konstruktor aufgerufen wird und den Spielablauf steuert. Dieser ist folgendermaßen:

    • Das Spielfeld wird vor jedem Zug auf der Konsole ausgegeben
    • Spieler X beginnt
    • Nach jedem Zug ist der jeweils andere Spieler an der Reihe
    • Hat ein Spieler gewonnen, so ist das Spiel beendet. Es soll ausgegeben werden, wer der Gewinner ist
    • Sind alle 9 Felder belegt und kein Spieler hat gewonnen, ist das Spiel unentschieden und endet
  • Erstelle eine main Funktion, die den Konstruktor aufruft

Denk daran, dass du die Methoden der anderen Klassen nicht zum Spaß implementiert hast!

Fertig!

Teste dein Spiel, ob alles so funktioniert wie erwartet. Vermutlich musst du noch einige Fehler suchen und beheben.

Häufige Fehlerquellen
  • Missing package statement: Du musst in jeder Klasse angeben, in welchem Package diese sich befindet
  • Cannot resolve symbol 'Xyz': Der Import für Xyz fehlt
  • Es passiert nichts: Ruft main den Konstruktor auf? Ruft der Konstruktor gameLoop() auf?
  • Das Spiel endet sofort nach dem ersten Zug: Gibt deine won() Methode nur true zurück, wenn die Felder nicht leer sind?
  • 'xyz()' has private access in 'Abc' Methoden in Abc sind nicht public
Lösungsvorschlag UserInput.java
package tictactoe.input; // UserInput.java befindet sich in src/tictactoe/input
import java.util.Scanner;
public class UserInput {
private Scanner scanner; // Scanner ist Teil der Java-Bibliothek und ermöglicht Nutzereingaben
public UserInput() {
scanner = new Scanner(System.in);
}
/**
* Gibt eine Zahl zurück, die der Nutzer über die Konsole eingibt.
*/
public int readInt(String inputText) {
System.out.print(inputText);
return scanner.nextInt();
}
}
 
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Lösungsvorschlag GameGrid.java
package tictactoe.grid; // GameGrid.java befindet sich in src/tictactoe/grid
public class GameGrid {
private char[] content;
public GameGrid() {
content = new char[9]; // 3 x 3 Gitter hat insgesamt 9 Felder
for (int i = 0; i < content.length; i++) {
content[i] = ' '; // Jedes Feld ist leer
}
}
public void set(int position, char value) {
content[position] = value;
}
public boolean freePosition(int position) {
return position >= 0 && position < 9 && content[position] == ' ';
}
public boolean full() {
for (int i = 0; i < 9; i++) {
if (content[i] == ' ') {
return false;
}
}
return true;
}
public void printToConsole() {
System.out.println(); // Leerzeile
System.out.println(" " + content[0] + " | " + content[1] + " | " + content[2]); // Zeile 1
System.out.println("---|---|---");
System.out.println(" " + content[3] + " | " + content[4] + " | " + content[5]); // Zeile 2
System.out.println("---|---|---");
System.out.println(" " + content[6] + " | " + content[7] + " | " + content[8]); // Zeile 3
}
public boolean won() {
// Zeilen
for (int y = 0; y < 3; y++) {
if (content[y * 3] != ' ' && content[y * 3] == content[y * 3 + 1]
&& content[y * 3] == content[y * 3 + 2]) {
return true;
}
}
// Spalten
for (int x = 0; x < 3; x++) {
if (content[x] != ' ' && content[x] == content[x + 3]
&& content[x] == content[x + 6]) {
 
 
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Lösungsvorschlag TicTacToe.java
package tictactoe; // TicTacToe.java befindet sich in src/tictactoe
import tictactoe.grid.GameGrid;
import tictactoe.input.UserInput;
public class TicTacToe {
private GameGrid gameGrid;
private UserInput userInput;
public TicTacToe() {
gameGrid = new GameGrid();
userInput = new UserInput();
gameLoop(); // Spiel starten
}
public void gameLoop() {
char currentPlayer = 'X';
while (!gameGrid.full()) { // Solange nicht alle 9 Felder belegt sind
gameGrid.printToConsole();
// Feld setzen
int pos = readValidPosition(currentPlayer);
gameGrid.set(pos, currentPlayer);
// Prüfen, ob jemand gewonnen hat
if (gameGrid.won()) {
gameGrid.printToConsole();
System.out.println("Spieler " + currentPlayer + " hat gewonnen!");
return; // Methode abbrechen
}
// Anderer Spieler ist am Zug
if (currentPlayer == 'X') {
currentPlayer = 'O';
} else {
currentPlayer = 'X';
}
}
gameGrid.printToConsole();
System.out.println("Unentschieden!");
}
private int readValidPosition(char currentPlayer) {
int pos;
do {
pos = userInput.readInt("Spieler " + currentPlayer + ": ");
} while (!gameGrid.freePosition(pos));
return pos;
 
 
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Dir gefällt meine Arbeit?

Unterstütze Mich
AllgemeinSocialRechtliches
HomeInstagramDatenschutz
ÜberYouTubeImpressum
TikTok
Ko-fi

Made with love by a former noob.

© 2022-2024 Timo Friedl