Was ist der Hauptunterschied zwischen einer inneren Klasse und einer statischen verschachtelten Klasse in Java? Spielt der Entwurf/die Implementierung eine Rolle bei der Wahl einer dieser beiden Klassen?
Antworten
Zu viele Anzeigen?Wenn wir eine statische Mitgliedsklasse innerhalb einer Klasse deklarieren, wird sie als verschachtelte Klasse der obersten Ebene oder als statische verschachtelte Klasse bezeichnet. Dies kann wie folgt demonstriert werden:
class Test{
private static int x = 1;
static class A{
private static int y = 2;
public static int getZ(){
return B.z+x;
}
}
static class B{
private static int z = 3;
public static int getY(){
return A.y;
}
}
}
class TestDemo{
public static void main(String[] args){
Test t = new Test();
System.out.println(Test.A.getZ());
System.out.println(Test.B.getY());
}
}
Wenn wir eine nicht-statische Mitgliedsklasse innerhalb einer Klasse deklarieren, wird sie als innere Klasse bezeichnet. Die innere Klasse kann wie folgt dargestellt werden:
class Test{
private int i = 10;
class A{
private int i =20;
void display(){
int i = 30;
System.out.println(i);
System.out.println(this.i);
System.out.println(Test.this.i);
}
}
}
Im Folgenden ein Beispiel für static nested class
y inner class
:
OuterClass.java
public class OuterClass {
private String someVariable = "Non Static";
private static String anotherStaticVariable = "Static";
OuterClass(){
}
//Nested classes are static
static class StaticNestedClass{
private static String privateStaticNestedClassVariable = "Private Static Nested Class Variable";
//can access private variables declared in the outer class
public static void getPrivateVariableofOuterClass(){
System.out.println(anotherStaticVariable);
}
}
//non static
class InnerClass{
//can access private variables of outer class
public String getPrivateNonStaticVariableOfOuterClass(){
return someVariable;
}
}
public static void accessStaticClass(){
//can access any variable declared inside the Static Nested Class
//even if it private
String var = OuterClass.StaticNestedClass.privateStaticNestedClassVariable;
System.out.println(var);
}
}
OuterClassTest:
public class OuterClassTest {
public static void main(String[] args) {
//access the Static Nested Class
OuterClass.StaticNestedClass.getPrivateVariableofOuterClass();
//test the private variable declared inside the static nested class
OuterClass.accessStaticClass();
/*
* Inner Class Test
* */
//Declaration
//first instantiate the outer class
OuterClass outerClass = new OuterClass();
//then instantiate the inner class
OuterClass.InnerClass innerClassExample = outerClass. new InnerClass();
//test the non static private variable
System.out.println(innerClassExample.getPrivateNonStaticVariableOfOuterClass());
}
}
Die Programmiersprache Java ermöglicht es Ihnen, eine Klasse innerhalb einer anderen Klasse zu definieren. Eine solche Klasse wird als verschachtelte Klasse bezeichnet und ist hier abgebildet:
class OuterClass {
...
class NestedClass {
...
}
}
Verschachtelte Klassen werden in zwei Kategorien unterteilt: statische und nicht-statische. Verschachtelte Klassen, die als statisch deklariert sind, werden statische verschachtelte Klassen genannt. Nicht-statische verschachtelte Klassen werden als innere Klassen bezeichnet. Dabei ist zu beachten, dass nicht-statische verschachtelte Klassen (innere Klassen) Zugriff auf andere Mitglieder der umschließenden Klasse haben, auch wenn sie als privat deklariert sind. Statische verschachtelte Klassen haben nur Zugriff auf andere Mitglieder der umschließenden Klasse, wenn diese statisch sind. Auf nicht statische Mitglieder der äußeren Klasse kann sie nicht zugreifen. Wie bei Klassenmethoden und -variablen ist eine statische verschachtelte Klasse mit ihrer äußeren Klasse verbunden. Um zum Beispiel ein Objekt für die statische verschachtelte Klasse zu erstellen, verwenden Sie diese Syntax:
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
Um eine innere Klasse zu instanziieren, müssen Sie zunächst die äußere Klasse instanziieren. Dann erstellen Sie das innere Objekt innerhalb des äußeren Objekts mit dieser Syntax:
OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();
Warum wir verschachtelte Klassen verwenden
- Auf diese Weise lassen sich Klassen, die nur an einem Ort verwendet werden, logisch gruppieren.
- Sie erhöht die Verkapselung.
- Dies kann zu besser lesbarem und wartbarem Code führen.
Zunächst einmal gibt es keine solche Klasse namens Static class.The Static Modifikator Verwendung mit inneren Klasse (als Nested Class genannt) sagt, dass es ein statisches Mitglied der äußeren Klasse ist, was bedeutet, wir können es wie mit anderen statischen Mitgliedern zugreifen und ohne eine Instanz der äußeren Klasse. (Das ist der ursprüngliche Vorteil von static.)
Der Unterschied zwischen der Verwendung einer verschachtelten Klasse und einer normalen inneren Klasse ist:
OuterClass.InnerClass inner = new OuterClass().new InnerClass();
Zuerst können wir Outerclass instanziieren, dann können wir auf Inner zugreifen.
Aber wenn die Klasse verschachtelt ist, dann ist es die Syntax:
OuterClass.InnerClass inner = new OuterClass.InnerClass();
Dabei wird die statische Syntax als normale Implementierung des Schlüsselworts static verwendet.
Ein weiterer Anwendungsfall für verschachtelte Klassen, zusätzlich zu den bereits erwähnten, ist, wenn die verschachtelte Klasse Methoden hat, die nur von der äußeren Klasse aus zugänglich sein sollen. Dies ist möglich, weil die äußere Klasse Zugriff auf die privaten Konstruktoren, Felder und Methoden der verschachtelten Klasse hat.
Im folgenden Beispiel wird die Bank
kann eine Bank.CreditCard
die einen privaten Konstruktor hat, und kann das Limit einer Kreditkarte entsprechend der aktuellen Bankpolitik mit Hilfe des privaten setLimit(...)
Fallmethode von Bank.CreditCard
. (Ein direkter Feldzugriff auf die Instanzvariable limit
würde auch in diesem Fall funktionieren). Von jeder anderen Klasse werden nur die öffentlichen Methoden von Bank.CreditCard
zugänglich sind.
public class Bank {
// maximum limit as per current bank policy
// is subject to change
private int maxLimit = 7000;
// ------- PUBLIC METHODS ---------
public CreditCard issueCard(
final String firstName,
final String lastName
) {
final String number = this.generateNumber();
final int expiryDate = this.generateExpiryDate();
final int CVV = this.generateCVV();
return new CreditCard(firstName, lastName, number, expiryDate, CVV);
}
public boolean setLimit(
final CreditCard creditCard,
final int limit
) {
if (limit <= this.maxLimit) { // check against current bank policy limit
creditCard.setLimit(limit); // access private method Bank.CreditCard.setLimit(int)
return true;
}
return false;
}
// ------- PRIVATE METHODS ---------
private String generateNumber() {
return "1234-5678-9101-1123"; // the numbers should be unique for each card
}
private int generateExpiryDate() {
return 202405; // date is YYYY=2024, MM=05
}
private int generateCVV() {
return 123; // is in real-life less predictable
}
// ------- PUBLIC STATIC NESTED CLASS ---------
public static final class CreditCard {
private final String firstName;
private final String lastName;
private final String number;
private final int expiryDate;
private final int CVV;
private int balance;
private int limit = 100; // default limit
// the constructor is final but is accessible from outer class
private CreditCard(
final String firstName,
final String lastName,
final String number,
final int expiryDate,
final int CVV
) {
this.firstName = firstName;
this.lastName = lastName;
this.number = number;
this.expiryDate = expiryDate;
this.CVV = CVV;
}
// ------- PUBLIC METHODS ---------
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
public String getNumber() {
return this.number;
}
public int getExpiryDate() {
return this.expiryDate;
}
// returns true if financial transaction is successful
// otherwise false
public boolean charge(final int amount) {
final int newBalance = this.balance - amount;
if (newBalance < -this.limit) {
return false;
}
this.balance = newBalance;
return true;
}
// ------- PRIVATE METHODS ---------
private int getCVV() {
return this.CVV;
}
private int getBalance() {
return this.balance;
}
private void setBalance(final int balance) {
this.balance = balance;
}
private int getLimit() {
return limit;
}
private void setLimit(final int limit) {
this.limit = limit;
}
}
}
99 Stimmen
Die Antwort von Joshua Bloch ist in Leistungsfähiges Java lesen
item 22 : Favor static member classes over non static
24 Stimmen
Für das Protokoll, es ist Punkt 24 in der 3. Auflage des gleichen Buches.