⌘ Thema: Objektorientierung in Java
Objektorientierte Programmierung in Java: Klassen, Interfaces und gutes Design
Von Guido Zeuner · Softwareentwickler und Autor von tiny-tool.de
Objektorientierung ist mehr als Klassen, Vererbung und Getter. Sie hilft dir, fachliche Regeln in klar abgegrenzten Typen abzubilden, Zustände zu schützen und austauschbare Komponenten über stabile Verträge zusammenarbeiten zu lassen.
Das Wichtigste vorab
Kurzfassung: ca. 1 Minute · vollständiger Artikel: ca. 13 Minuten
- Eine Klasse beschreibt Struktur und Verhalten; ein Objekt ist eine konkrete Instanz dieser Klasse.
- Kapselung schützt Regeln und gültige Zustände – sie bedeutet nicht, jedes Feld per Setter veränderbar zu machen.
- Interfaces definieren Verträge. Dadurch kann aufrufender Code mit unterschiedlichen Implementierungen arbeiten.
- Vererbung passt zu einer stabilen Ist-ein-Beziehung; Komposition verbindet Objekte flexibler über eine Hat-ein-Beziehung.
final, Records und Sealed Types drücken Entwurfsentscheidungen direkt im Typsystem aus.- Die oft genannten „vier Säulen“ sind ein Lernmodell. In der Praxis zählen verständliche Verantwortlichkeiten, geringe Kopplung und geschützte Invarianten.

In Java modellierst du Objekte mit Zustand und Verhalten. Gutes objektorientiertes Design beginnt jedoch nicht mit möglichst vielen Klassen, sondern mit einer einfachen Frage: Welche Verantwortung gehört wohin? Dieser Guide führt von Klassen und Objekten über Kapselung, Interfaces und Polymorphie bis zu Komposition, Records und Sealed Types – mit praxisnahen Beispielen und einem kompakten Kotlin-Vergleich.
Was objektorientierte Programmierung wirklich bedeutet
Ein Objekt bündelt zusammengehörigen Zustand und das dazu passende Verhalten. Statt Daten durch viele unverbundene Funktionen zu reichen, erhält ein Typ die Verantwortung für seine eigenen Regeln. Ein Konto kennt beispielsweise seinen Kontostand und entscheidet selbst, ob eine Auszahlung zulässig ist.
Die bekannte Einteilung in Kapselung, Abstraktion, Vererbung und Polymorphie ist als Einstieg nützlich. Sie ist aber keine Checkliste, nach der jede Anwendung möglichst viel Vererbung oder besonders viele Abstraktionen enthalten sollte. Entscheidend ist, ob das Modell verständlich bleibt und ungültige Zustände erschwert.
| Grundidee | Praktische Bedeutung | Typisches Java-Mittel |
|---|---|---|
| Kapselung | Interne Daten schützen und Änderungen nur über kontrollierte Operationen erlauben. | private, Konstruktoren, fachliche Methoden |
| Abstraktion | Das Wesentliche eines Konzepts zeigen und unnötige Details verbergen. | Interfaces, abstrakte Klassen, kleine öffentliche APIs |
| Vererbung | Einen bestehenden Typ spezialisieren, wenn tatsächlich eine stabile Ist-ein-Beziehung besteht. | extends, abstract, protected |
| Polymorphie | Verschiedene Implementierungen über denselben Vertrag verwenden. | interface, implements, Überschreiben |
Objektorientierter Code ist nicht automatisch guter Code. Eine Klasse mit zwanzig öffentlichen Settern kapselt ihre Daten technisch, schützt aber kaum fachliche Regeln.
Klassen und Objekte: Bauplan und konkrete Instanz
Eine Klasse deklariert Felder, Konstruktoren und Methoden. Mit new entsteht daraus ein Objekt. Jede Instanz besitzt ihren eigenen Zustand, während der Code der Methoden durch die Klasse festgelegt wird.
import java.math.BigDecimal;
import java.util.Objects;
public final class BankAccount {
private final String iban;
private BigDecimal balance;
public BankAccount(String iban, BigDecimal openingBalance) {
this.iban = Objects.requireNonNull(iban, "iban");
this.balance = requireNonNegative(openingBalance);
}
public String iban() {
return iban;
}
public BigDecimal balance() {
return balance;
}
public void deposit(BigDecimal amount) {
balance = balance.add(requirePositive(amount));
}
public void withdraw(BigDecimal amount) {
BigDecimal checkedAmount = requirePositive(amount);
if (balance.compareTo(checkedAmount) < 0) {
throw new IllegalStateException("Kontostand reicht nicht aus");
}
balance = balance.subtract(checkedAmount);
}
private static BigDecimal requirePositive(BigDecimal amount) {
Objects.requireNonNull(amount, "amount");
if (amount.signum() <= 0) {
throw new IllegalArgumentException("Betrag muss positiv sein");
}
return amount;
}
private static BigDecimal requireNonNegative(BigDecimal amount) {
Objects.requireNonNull(amount, "openingBalance");
if (amount.signum() < 0) {
throw new IllegalArgumentException("Startguthaben darf nicht negativ sein");
}
return amount;
}
}
Die Klasse ist bewusst final: Ohne konkreten Erweiterungspunkt gibt es keinen Grund, beliebige Unterklassen zuzulassen. Die IBAN wird nach dem Erzeugen nicht mehr ausgetauscht, der Kontostand darf sich dagegen über kontrollierte Methoden verändern.
BankAccount checking = new BankAccount(
"DE02120300000000202051", new BigDecimal("250.00"));
BankAccount savings = new BankAccount(
"DE02120300000000202052", new BigDecimal("1000.00"));
checking.withdraw(new BigDecimal("49.90"));
savings.deposit(new BigDecimal("100.00"));
checking und savings verweisen auf unterschiedliche Instanzen. Eine Änderung am einen Konto verändert das andere nicht. Die Variablen enthalten Referenzen auf die Objekte – nicht die Objekte selbst.
Kapselung: gültige Zustände statt Setter-Sammlung
Die stärkste Eigenschaft von BankAccount ist nicht das Schlüsselwort private, sondern die Kontrolle über Zustandsänderungen. Es gibt keinen setBalance(...)-Aufruf, der den Kontostand ohne Prüfung auf einen beliebigen Wert setzt. Stattdessen drücken deposit(...) und withdraw(...) fachliche Absichten aus.
Eine Regel, die für jedes gültige Objekt gelten muss, heißt Invariante. Im Beispiel sind Einzahlungen positiv, das Startguthaben ist nicht negativ und eine Auszahlung kann das Konto nicht unter null drücken. Konstruktor und Methoden bewahren diese Regeln gemeinsam.
| Modifikator | Sichtbarkeit | Typischer Einsatz |
|---|---|---|
public |
Überall, sofern der umgebende Typ erreichbar ist | Bewusst angebotene öffentliche API |
protected |
Im Paket und in Unterklassen unter den Java-Zugriffsregeln | Gezielte Erweiterungspunkte für Vererbung |
| kein Modifikator | Nur im selben Paket | Zusammenarbeit innerhalb eines Moduls oder Pakets |
private |
Nur innerhalb des umgebenden Top-Level-Typs beziehungsweise seiner Nestmates | Implementierungsdetails und veränderlicher Zustand |
Wähle die kleinste sinnvolle Sichtbarkeit. Was heute öffentlich ist, wird schnell zu einem Vertrag, den anderer Code erwartet und den du später nur schwer ändern kannst.
Interfaces und Polymorphie: gegen Verträge programmieren
Ein Interface beschreibt, was ein Typ anbietet, ohne eine bestimmte Implementierung vorzuschreiben. Unabhängige Klassen können dasselbe Interface implementieren. Eine Variable des Interface-Typs kann anschließend auf jede passende Implementierung verweisen.
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;
public interface DiscountPolicy {
BigDecimal applyTo(BigDecimal subtotal);
}
final class NoDiscount implements DiscountPolicy {
@Override
public BigDecimal applyTo(BigDecimal subtotal) {
return requireNonNegative(subtotal);
}
private static BigDecimal requireNonNegative(BigDecimal value) {
Objects.requireNonNull(value, "subtotal");
if (value.signum() < 0) {
throw new IllegalArgumentException("Zwischensumme darf nicht negativ sein");
}
return value;
}
}
final class PercentageDiscount implements DiscountPolicy {
private final BigDecimal rate;
public PercentageDiscount(BigDecimal rate) {
Objects.requireNonNull(rate, "rate");
if (rate.signum() < 0 || rate.compareTo(BigDecimal.ONE) > 0) {
throw new IllegalArgumentException("Rabatt muss zwischen 0 und 1 liegen");
}
this.rate = rate;
}
@Override
public BigDecimal applyTo(BigDecimal subtotal) {
Objects.requireNonNull(subtotal, "subtotal");
if (subtotal.signum() < 0) {
throw new IllegalArgumentException("Zwischensumme darf nicht negativ sein");
}
return subtotal.multiply(BigDecimal.ONE.subtract(rate))
.setScale(2, RoundingMode.HALF_UP);
}
}
Aufrufender Code muss nicht wissen, welche konkrete Rabattregel aktiv ist. Die Auswahl kann beim Start, anhand einer Konfiguration oder durch Dependency Injection erfolgen:
DiscountPolicy policy = new PercentageDiscount(new BigDecimal("0.10"));
BigDecimal total = policy.applyTo(new BigDecimal("89.90"));
System.out.println(total); // 80.91
Welche Methode ausgeführt wird, entscheidet Java zur Laufzeit anhand des tatsächlichen Objekts. Das ist dynamische Polymorphie. Neue Implementierungen lassen sich ergänzen, ohne den verwendenden Code mit einer wachsenden if– oder switch-Kette zu belasten.
Überladen ist nicht dasselbe wie Überschreiben
Beim Überladen tragen mehrere Methoden denselben Namen, haben aber unterschiedliche Parameterlisten; die Auswahl erfolgt anhand der zur Compile-Zeit bekannten Typen. Beim Überschreiben liefert eine Unterklasse oder Implementierung eine neue Ausführung derselben Methodensignatur. Für austauschbare Objekte ist vor allem das Überschreiben relevant.
Vererbung oder Komposition?
Java erlaubt einer Klasse genau eine direkte Oberklasse, aber mehrere implementierte Interfaces. Vererbung kann gemeinsamen Code und einen gemeinsamen Typ bereitstellen. Gleichzeitig koppelt sie eine Unterklasse eng an Aufbau und Verhalten ihrer Oberklasse.
Prüfe deshalb zuerst die Beziehung:
- Ist-ein: Ein
Circleist eineShapeund kann überall verwendet werden, wo eineShapeerwartet wird. - Hat-ein: Ein
CheckoutServicehat eineDiscountPolicy. Er ist keine Rabattregel.
Die Preisregel aus dem vorherigen Abschnitt lässt sich per Komposition in einen Service einsetzen:
import java.math.BigDecimal;
import java.util.Objects;
public final class CheckoutService {
private final DiscountPolicy discountPolicy;
public CheckoutService(DiscountPolicy discountPolicy) {
this.discountPolicy = Objects.requireNonNull(
discountPolicy, "discountPolicy");
}
public BigDecimal calculateTotal(BigDecimal subtotal) {
return discountPolicy.applyTo(subtotal);
}
}
Der Service ist nicht an PercentageDiscount gebunden, sondern nur an den kleinen Vertrag DiscountPolicy. In einem Test kannst du eine einfache Testimplementierung einsetzen. Im Produktivbetrieb kann eine andere Regel verwendet werden, ohne CheckoutService zu verändern.
| Frage | Vererbung | Komposition |
|---|---|---|
| Beziehung | Ist-ein | Hat-ein oder nutzt-ein |
| Austauschbarkeit | Durch die feste Typhierarchie begrenzt | Abhängigkeit kann eingesetzt oder ausgetauscht werden |
| Kopplung | Oft enger an die Oberklasse | Bei kleinen Interfaces meist geringer |
| Guter Einsatz | Stabile Spezialisierung mit echtem Substitutionsverhältnis | Variierendes Verhalten und Zusammenarbeit mehrerer Rollen |
abstract, final und sealed: Erweiterbarkeit ausdrücken
Eine API sollte nicht zufällig erweiterbar sein. Java bietet mehrere Möglichkeiten, die beabsichtigte Form einer Hierarchie sichtbar zu machen:
| Schlüsselwort | Aussage | Geeignet für |
|---|---|---|
abstract |
Der Typ ist unvollständig und nicht direkt instanziierbar. | Gemeinsame Basis mit geteiltem Zustand oder Verhalten |
final |
Von der Klasse kann nicht geerbt werden; eine Methode kann nicht überschrieben werden. | Abgeschlossene Implementierungen und geschützte Invarianten |
sealed |
Nur ausdrücklich erlaubte Typen dürfen direkt erweitern oder implementieren. | Geschlossene, kontrollierte Varianten eines Fachkonzepts |
non-sealed |
Öffnet einen erlaubten Zweig einer Sealed-Hierarchie wieder. | Gezielt offene Teilhierarchien |
Sealed Types sind besonders nützlich, wenn alle zulässigen Varianten bekannt sind. Ein switch kann dadurch vollständig und ohne pauschalen default-Zweig formuliert werden:
public sealed interface PaymentResult permits Approved, Rejected {}
record Approved(String transactionId) implements PaymentResult {}
record Rejected(String reason) implements PaymentResult {}
final class PaymentMessages {
private PaymentMessages() {}
static String messageFor(PaymentResult result) {
return switch (result) {
case Approved approved ->
"Zahlung bestätigt: " + approved.transactionId();
case Rejected rejected ->
"Zahlung abgelehnt: " + rejected.reason();
};
}
}
Fügst du später eine weitere erlaubte Variante hinzu, weist der Compiler auf nicht mehr vollständige switch-Ausdrücke hin. Das ist ein Vorteil gegenüber einer offenen Hierarchie, in der zur Laufzeit unerwartete Untertypen auftreten können.
Records: kompakte Datenträger und Wertobjekte
Records eignen sich für Daten, deren Bedeutung hauptsächlich durch ihre Komponenten bestimmt wird. Der Compiler erzeugt unter anderem Zugriffsmethoden, equals(), hashCode() und toString(). Records sind implizit final.
import java.math.BigDecimal;
import java.util.Currency;
import java.util.Objects;
public record Price(BigDecimal amount, Currency currency) {
public Price {
Objects.requireNonNull(amount, "amount");
Objects.requireNonNull(currency, "currency");
if (amount.signum() < 0) {
throw new IllegalArgumentException("Preis darf nicht negativ sein");
}
}
public Price add(Price other) {
Objects.requireNonNull(other, "other");
if (!currency.equals(other.currency)) {
throw new IllegalArgumentException("Währungen stimmen nicht überein");
}
return new Price(amount.add(other.amount), currency);
}
}
Ein Record ist nicht automatisch tief unveränderlich. Seine Komponenten können nach der Konstruktion nicht neu zugewiesen werden, doch ein darin referenziertes veränderliches Objekt kann weiterhin verändert werden. BigDecimal und Currency sind für dieses Beispiel geeignete unveränderliche Bausteine.
Record oder normale Klasse?
Ein Record passt gut zu transparenten Werten wie Koordinaten, Zeiträumen oder Preisen. Eine Entität mit eigener Identität, komplexem Lebenszyklus und verborgenem veränderlichem Zustand bleibt meist als normale Klasse verständlicher – wie das Konto aus dem ersten Beispiel.
Identität und Gleichheit: ==, equals() und hashCode()
Bei Referenztypen prüft ==, ob zwei Variablen auf dasselbe Objekt verweisen. equals() beantwortet dagegen die fachliche Frage, ob zwei Objekte als gleich gelten. Die von Object geerbte Standardimplementierung verwendet ebenfalls Identität, solange eine Klasse sie nicht überschreibt.
Currency eur = Currency.getInstance("EUR");
Price first = new Price(new BigDecimal("19.90"), eur);
Price second = new Price(new BigDecimal("19.90"), eur);
System.out.println(first == second); // false
System.out.println(first.equals(second)); // true
Überschreibst du equals() in einer normalen Klasse, musst du dazu ein konsistentes hashCode() bereitstellen. Das ist besonders für HashMap und HashSet wichtig. Records erzeugen beide Methoden komponentenbasiert und gemeinsam.
Java und Kotlin: Objektorientierung auf derselben JVM
Java und Kotlin arbeiten auf der JVM problemlos zusammen und teilen viele objektorientierte Grundlagen. Kotlin setzt jedoch andere Standardeinstellungen und bietet kompaktere Sprachmittel. Das verändert nicht das Ziel guten Designs, wohl aber dessen Schreibweise.
| Aspekt | Java | Kotlin |
|---|---|---|
| Vererbung | Klassen sind offen, sofern sie nicht final oder sealed sind. |
Klassen und überschreibbare Member sind standardmäßig final; Öffnung mit open. |
| Properties | Feld und Methoden werden separat deklariert; Records bieten Komponenten-Accessors. | val und var bilden Properties mit Zugriffsfunktionen direkt ab. |
| Datenträger | record ist final und komponentenbasiert. |
data class erzeugt zusätzlich unter anderem copy() und componentN(). |
| Null-Sicherheit | Referenztypen sind ohne Zusatzwerkzeuge grundsätzlich nullable. | Nullable Typen werden mit ? ausdrücklich markiert. |
| Typprüfung | instanceof unterstützt Pattern Matching. |
is ermöglicht häufig einen automatischen Smart Cast. |
| Geschlossene Hierarchie | sealed class oder sealed interface |
sealed class oder sealed interface |
Das Java-Record-Beispiel lässt sich in Kotlin als Data Class ausdrücken:
import java.math.BigDecimal
import java.util.Currency
data class Price(
val amount: BigDecimal,
val currency: Currency
) {
init {
require(amount.signum() >= 0) {
"Preis darf nicht negativ sein"
}
}
operator fun plus(other: Price): Price {
require(currency == other.currency) {
"Währungen stimmen nicht überein"
}
return copy(amount = amount + other.amount)
}
}
val verhindert, dass die Property auf einen anderen Wert gesetzt wird. Wie bei Java bedeutet das keine automatische tiefe Unveränderlichkeit: Ein mit val referenziertes veränderliches Objekt kann weiterhin seinen internen Zustand ändern.
Data Classes und Records sind verwandt, aber nicht identisch. Eine Kotlin Data Class kann beispielsweise Properties mit var besitzen und erzeugt copy(). Ein Java Record hat eine fest definierte Record-Struktur und kann von Kotlin über seine Komponenten verwendet werden; Kotlin unterstützt umgekehrt auf der JVM auch die Deklaration echter Java Records mit @JvmRecord.
Best Practices und typische Anti-Patterns
Gute Leitlinien
- Gib jeder Klasse eine klar erkennbare Verantwortung.
- Schütze Invarianten im Konstruktor und in fachlichen Methoden.
- Halte öffentliche APIs klein und benenne sie nach Absichten.
- Nutze Interfaces an Stellen, an denen Implementierungen wirklich variieren.
- Bevorzuge Komposition für austauschbares Verhalten.
- Deklariere Klassen
final, wenn keine Vererbung vorgesehen ist. - Verwende Records für transparente, wertbasierte Datenträger.
Warnsignale
- Eine Klasse ändert sich aus vielen unabhängigen Gründen.
- Jedes Feld besitzt ungeprüfte Getter und Setter.
- Unterklassen überschreiben Methoden nur, um Verhalten zu deaktivieren.
- Typprüfungen und Casts ersetzen einen klaren Vertrag.
- Eine tiefe Hierarchie dient lediglich der Codewiederverwendung.
- Domänenobjekte enthalten nur Daten, während alle Regeln in einem riesigen Service liegen.
- Für jeden einzelnen Typ wird vorsorglich ein Interface angelegt.
1. Tell, don’t ask – aber ohne Dogma
Statt den Zustand eines Objekts auszulesen, extern zu verändern und zurückzuschreiben, rufst du besser eine fachliche Operation auf. account.withdraw(amount) lässt das Konto seine Regeln selbst schützen. Reine Abfragen bleiben selbstverständlich sinnvoll, wenn anderer Code Informationen tatsächlich anzeigen oder auswerten muss.
2. Kleine Verträge statt vorsorglicher Abstraktionen
Ein Interface ist wertvoll, wenn mehrere Implementierungen existieren, eine Systemgrenze entkoppelt oder eine Rolle ausdrücklich beschrieben werden soll. Ein Interface nur für eine triviale Klasse anzulegen, macht das Modell nicht automatisch flexibler.
3. Untertypen müssen den Vertrag erfüllen
Wenn Code einen Obertyp erwartet, muss jede Unterklasse dessen Zusagen einhalten. Eine Unterklasse, die erlaubte Eingaben plötzlich ablehnt oder nach einer geerbten Methode in einem unerwarteten Zustand endet, ist kein sauberer Ersatz. Das ist der praktische Kern des Liskovschen Substitutionsprinzips.
4. Unveränderlichkeit reduziert Zustandsfehler
Unveränderliche Objekte sind leichter zu teilen, zu testen und nachzuvollziehen. Nutze final-Felder und Records, wenn Änderungen nicht zur Identität des Konzepts gehören. Veränderlicher Zustand ist nicht grundsätzlich falsch – er sollte nur eng gekapselt und über klare Operationen verändert werden.
Glossar
- Klasse
- Deklaration eines Referenztyps mit Feldern, Konstruktoren und Methoden.
- Objekt
- Zur Laufzeit erzeugte Instanz einer Klasse mit eigener Identität und eigenem Zustand.
- Invariante
- Regel, die für jeden gültigen Zustand eines Objekts erfüllt sein muss.
- Interface
- Typvertrag, den eine oder mehrere Klassen implementieren können.
- Polymorphie
- Verwendung unterschiedlicher konkreter Objekte über einen gemeinsamen Obertyp oder ein Interface.
- Komposition
- Aufbau eines Objekts aus anderen Objekten, deren Fähigkeiten es verwendet.
- Vererbung
- Spezialisierung einer Klasse über
extends; Java unterstützt dabei genau eine direkte Oberklasse. - Record
- Kompakte, implizit finale Java-Klasse für transparente, komponentenbasierte Daten.
- Sealed Type
- Klasse oder Interface mit einer kontrollierten Menge direkt erlaubter Untertypen.
Fazit: Gute OOP schützt Regeln und hält Änderungen lokal
Objektorientierung in Java entfaltet ihren Nutzen nicht durch möglichst viele Klassen oder tiefe Vererbungshierarchien. Sie funktioniert dann gut, wenn Typen klare Verantwortlichkeiten besitzen, ihre gültigen Zustände selbst bewahren und über kleine Verträge zusammenarbeiten.
Beginne mit einfachen Klassen und aussagekräftigen Methoden. Setze Interfaces dort ein, wo Verhalten austauschbar sein soll, bevorzuge Komposition für Zusammenarbeit und beschränke Vererbung bewusst. Records und Sealed Types ergänzen dieses Modell um präzise Werkzeuge für Werte und geschlossene Varianten.
Offizielle Quellen und weiterführende Informationen
- Dev.java: Objects, Classes, Interfaces and Inheritance
- Dev.java: Classes and Objects
- Java Language Specification: Classes
- Java Language Specification: Interfaces
- Oracle Java Documentation: Record Classes
- Kotlin Documentation: Classes
- Kotlin Documentation: Inheritance
- Kotlin Documentation: Data Classes
- Kotlin Documentation: Java Records
Transparenzhinweis
Die Inhalte auf tiny-tool.de werden sorgfältig recherchiert, redaktionell geprüft und regelmäßig aktualisiert. Quellen und Zitate werden möglichst nachvollziehbar angegeben. Dennoch übernehmen wir keine Garantie für Richtigkeit, Vollständigkeit oder Aktualität der bereitgestellten Informationen. Irrtümer sind nicht ausgeschlossen.
Redaktion und Einsatz von KI: Bei der Erstellung von Inhalten können digitale Werkzeuge – darunter auch KI-basierte Assistenzsysteme – unterstützend eingesetzt werden, etwa bei Recherche, Strukturierung, sprachlicher Überarbeitung, Übersetzung, Codeanalyse oder visueller Gestaltung. Veröffentlichte Inhalte werden redaktionell geprüft, bearbeitet und von Guido Zeuner freigegeben. Auswahl, Einordnung und Veröffentlichung liegen beim Menschen. KI-Ausgaben gelten nicht als eigenständige Quellen. KI-Systeme sind keine verantwortlichen Autoren oder Redakteure. Weitere Informationen zu Texten, Bildern, Videos und digitalen Personas findest du auf unserer Seite Transparenz beim Einsatz von Künstlicher Intelligenz.
Reichweitenmessung (VG WORT / METIS): Zur Ermittlung der Reichweite einzelner Texte können Zählmarken der VG WORT eingesetzt werden. Im Rahmen der METIS-Zugriffszählung kann eine Client-ID gebildet und ein sogenanntes „METIS Session Cookie“ gesetzt werden. Die Messung dient der statistischen Ermittlung von Textzugriffen und als Grundlage für mögliche Ausschüttungen der VG WORT. Nach Angaben der VG WORT werden dabei keine personenbezogenen Nutzungsprofile erstellt; die Messung dient nicht der Werbung oder dem Marketing-Tracking. Weitere Informationen findest du in unseren Datenschutzhinweisen.
Bitte beachte: Die Inhalte dienen ausschließlich der allgemeinen Information und stellen keine fachliche Beratung dar, insbesondere keine rechtliche, steuerliche, medizinische, technische oder finanzielle Beratung. Die Nutzung der Inhalte erfolgt auf eigene Verantwortung.
Werbung und Affiliate-Links: Einige Beiträge können werbliche Hinweise oder sogenannte Affiliate-Links enthalten. Diese werden entsprechend gekennzeichnet. Beim Klick entstehen dir keine zusätzlichen Kosten; wir erhalten gegebenenfalls eine kleine Provision.
Markenrechtlicher Hinweis: Alle Markennamen, Logos und Produktbezeichnungen sind Eigentum der jeweiligen Rechteinhaber und werden ausschließlich zur Identifikation und Beschreibung verwendet. Eine Verbindung zu den genannten Unternehmen besteht nur, wenn dies ausdrücklich angegeben wird.
Externe Links: Diese Website enthält Verweise auf externe Websites Dritter. Trotz sorgfältiger Prüfung übernehmen wir keine Verantwortung für deren Inhalte. Bei Bekanntwerden rechtswidriger Inhalte werden entsprechende Links geprüft und gegebenenfalls entfernt.



tiny-tool.de
tiny-tool.de