Java中内部类和静态嵌套类的主要区别是什么?设计/实现是否在选择其中一个方面发挥作用?


当前回答

针对Java和/或嵌套类新手的学习者

嵌套类可以是:1.静态嵌套类。2.非静态嵌套类。(也称为内部类)=>请记住这一点

1.内部类例子:

class OuterClass  {
/*  some code here...*/
     class InnerClass  {  }
/*  some code here...*/
}

内部类是嵌套类的子集:

内部类是特定类型的嵌套类内部类是嵌套类的子集可以说内部类也是嵌套类,但不能说嵌套类也是内部类。

内层专业:

内部类的实例可以访问外部类的所有成员,即使是标记为“private”的成员

2.静态嵌套类:例子:

class EnclosingClass {
  static class Nested {
    void someMethod() { System.out.println("hello SO"); }
  }
}

案例1:从非封闭类实例化静态嵌套类

class NonEnclosingClass {

  public static void main(String[] args) {
    /*instantiate the Nested class that is a static
      member of the EnclosingClass class:
    */

    EnclosingClass.Nested n = new EnclosingClass.Nested(); 
    n.someMethod();  //prints out "hello"
  }
}

案例2:从封闭类实例化静态嵌套类

class EnclosingClass {

  static class Nested {
    void anotherMethod() { System.out.println("hi again"); } 
  }

  public static void main(String[] args) {
    //access enclosed class:

    Nested n = new Nested(); 
    n.anotherMethod();  //prints out "hi again"
  }

}

静态类专业:

静态内部类只能访问外部类的静态成员,不能访问非静态成员。

结论:问:Java中内部类和静态嵌套类的主要区别是什么?答:只需仔细阅读上面提到的每门课的细节。

其他回答

嵌套类的另一个用例,除了已经提到的那些用例之外,是当嵌套类具有只能从外部类访问的方法时。这是可能的,因为外部类可以访问嵌套类的私有构造函数、字段和方法。

在下面的示例中,银行可以发行具有私有构造函数的Bank.CreditCard,并可以使用Bank.credit card的私有setLimit(…)实例方法根据当前银行策略更改信用卡的限额。从任何其他类只能访问Bank.CreditCard的公共方法。

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;
        }
    }
}

嗯……内部类是嵌套类……您是指匿名类和内部类吗?

编辑:如果您实际上是指内部v.s.匿名:内部类只是在类中定义的类,例如:

public class A {
    public class B {
    }
}

…而匿名类是匿名定义的类的扩展,因此没有定义实际的“类”,如:

public class A {
}

A anon = new A() { /* You could change behavior of A here */ };

进一步编辑:

维基百科声称Java存在差异,但我已经用Java工作了八年,这是我第一次听到这样的区别——更不用说那里没有引用来支持这一说法……总之,内部类是在类中定义的类(静态或非静态),嵌套只是另一个意思相同的术语。

静态和非静态嵌套类之间有一个微妙的区别……基本上,非静态内部类可以隐式访问封闭类的实例字段和方法(因此它们不能在静态上下文中构造,这将是编译器错误)。另一方面,静态嵌套类不具有对实例字段和方法的隐式访问,并且可以在静态上下文中构造。

这些术语可以互换使用。如果你真的想变得迂腐,那么你可以定义“嵌套类”来引用一个静态的内部类,这个类没有封闭的实例。在代码中,您可能有如下内容:

public class Outer {
    public class Inner {}

    public static class Nested {}
}

但这并不是一个被广泛接受的定义。

Java中的内部类和嵌套静态类都是在另一个类中声明的类,在Java中称为顶级类。在Java术语中,如果您将嵌套类声明为静态的,则在Java中将其称为嵌套静态类,而非静态嵌套类则简称为内部类。

什么是Java中的内部类?

任何不是顶级或在另一个类中声明的类都称为嵌套类,在这些嵌套类中,声明为非静态的类在Java中称为内部类。Java中有三种内部类:

1) 本地内部类-在代码块或方法中声明。2) 匿名内部类-是一个没有名称可引用的类,并在创建它的同一位置初始化。3) 成员内部类-声明为外部类的非静态成员。

public class InnerClassTest {
    public static void main(String args[]) {      
        //creating local inner class inside method i.e. main() 
        class Local {
            public void name() {
                System.out.println("Example of Local class in Java");

            }
        }      
        //creating instance of local inner class
        Local local = new Local();
        local.name(); //calling method from local inner class

        //Creating anonymous inner class in Java for implementing thread
        Thread anonymous = new Thread(){
            @Override
            public void run(){
                System.out.println("Anonymous class example in java");
            }
        };
        anonymous.start();

        //example of creating instance of inner class
        InnerClassTest test = new InnerClassTest();
        InnerClassTest.Inner inner = test.new Inner();
        inner.name(); //calling method of inner class
    }

     //Creating Inner class in Java
    private class Inner{
        public void name(){
            System.out.println("Inner class example in java");
        }
    }
}

什么是Java中的嵌套静态类?

嵌套静态类是另一个在类内部声明为成员并使其成为静态的类。嵌套的静态类也被声明为外部类的成员,并且可以像任何其他成员一样成为私有的、公共的或受保护的。嵌套静态类相对于内部类的主要优点之一是嵌套静态类的实例不附加到外部类的任何封闭实例。您也不需要任何外部类的实例来在Java中创建嵌套静态类的实例。

1) 它可以访问外部类(包括private)的静态数据成员。2) 静态嵌套类无法访问非静态(实例)数据成员或方法。

public class NestedStaticExample {
    public static void main(String args[]){  
        StaticNested nested = new StaticNested();
        nested.name();
    }  
    //static nested class in java
    private static class StaticNested{
        public void name(){
            System.out.println("static nested class example in java");
        }
    }
}

参考:Java中的内部类和嵌套静态类及其示例

简单来说,我们需要嵌套类,主要是因为Java不提供闭包。

嵌套类是在另一个封闭类的主体内定义的类。它们有两种类型——静态和非静态。

它们被视为封闭类的成员,因此您可以指定四个访问说明符中的任意一个-私有、包、受保护和公共。对于顶级类,我们没有这种奢侈,它只能声明为public或packageprivate。

内部类(也称为非堆栈类)可以访问顶级类的其他成员,即使它们被声明为私有,而静态嵌套类不能访问顶级类中的其他成员。

public class OuterClass {
    public static class Inner1 {
    }
    public class Inner2 {
    }
}

Inner1是我们的静态内部类,Inner2是我们的非静态内部类。它们之间的关键区别是,如果没有Outer,就无法创建Inner2实例,因为您可以独立创建Inner1对象。

你什么时候使用内部类?

想象一下这样一种情况:a类和B类是相关的,B类需要访问a类成员,而B类只与a类相关。

为了创建内部类的实例,需要创建外部类的实例。

OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();

or

OuterClass.Inner2 inner = new OuterClass().new Inner2();

什么时候使用静态内部类?

当您知道静态内部类与封闭类/顶层类的实例没有任何关系时,可以定义它。如果您的内部类不使用外部类的方法或字段,这只是浪费空间,所以请将其设置为静态。

例如,要为静态嵌套类创建对象,请使用以下语法:

OuterClass.Inner1 nestedObject = new OuterClass.Inner1();

静态嵌套类的优点是它不需要包含类/顶级类的对象来工作。这可以帮助您减少应用程序在运行时创建的对象数量。