public class Container {public class Item{Object data;public Container getContainer(){return Container.this;}public Item(Object data) {super();this.data = data;}
}
public static Item create(Object data){// does not compile since no instance of Container is availablereturn new Item(data);}public Item createSubItem(Object data){// compiles, since 'this' Container is availablereturn new Item(data);}}
public class C0 {
static C0 instance = null;
// Uncomment the following line and a null pointer exception will be// generated before anything gets printed.//public static final String outerItem = instance.makeString(98.6);
public C0() {instance = this;}
public String makeString(int i) {return ((new Integer(i)).toString());}
public String makeString(double d) {return ((new Double(d)).toString());}
public static final class nested {public static final String innerItem = instance.makeString(42);}
static public void main(String[] argv) {System.out.println("start");// Comment out this line and a null pointer exception will be// generated after "start" prints and before the following// try/catch block even gets entered.new C0();try {System.out.println("retrieve item: " + nested.innerItem);}catch (Exception e) {System.out.println("failed to retrieve item: " + e.toString());}System.out.println("finish");}}
public static class A {} //ERROR
public class A {public class B {public static class C {} //ERROR}}
public class A {public static class B {} //COMPILE !!!
}
class A{class B{// static int x; not allowed here…..}static class C{static int x; // allowed here}}
class Test{public static void main(String… str){A o=new A();A.B obj1 =o.new B();//need of inclosing instance
A.C obj2 =new A.C();
// not need of reference of object of outer class….}}
class OuterClass {/* some code here...*/class InnerClass { }/* some code here...*/}
内部类是嵌套类的子集:
内部类是一种特定类型的嵌套类
内部类是嵌套类的子集
你可以说一个内部类也是一个嵌套类,但是你可以Not说嵌套类也是一个内部类。
内部类的特长:
内部类的实例有获得所有个外部类的成员,即使是那些标记为“私有”的成员
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 staticmember 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"}
}
public class Outer {
public class Inner {
}
public Inner inner(){return new Inner();}
@Overrideprotected void finalize() throws Throwable {// as you know finalize is called by the garbage collector due to destroying an object instanceSystem.out.println("I am destroyed !");}}
public static void main(String arg[]) {
Outer outer = new Outer();Outer.Inner inner = outer.new Inner();
// out instance is no more used and should be garbage collected !!!// However this will not happen as inner instance is still alive i.e used, not null !// and outer will be kept in memory until inner is destroyedouter = null;
//// inner = null;
//kick out garbage collectorSystem.gc();
}
如果删除// inner = null;上的注释,程序将输出"我被毁灭了!",但保留此注释不会。 原因是白色的内部实例仍然被引用GC无法收集它,因为它引用(有一个指针指向)外部实例,它也不会被收集。与静态内部类相比,它不持有指向内部类实例的点,因为它不是实例相关的,而是类相关的。上面的程序可以打印“我被毁灭了!”,如果你使内部类静态并用Outer.Inner i = new Outer.Inner();实例化
Cannot access outer class instance methods or fields
Not associated with any instance of enclosing class So to instantiate it:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
Similarities
Both Inner classes can access even private fields and methods of outer class
Also the Outer class have access to private fields and methods of inner classes
Both classes can have private, protected or public access modifier
Why Use Nested Classes?
According to Oracle documentation there're several reasons (full documentation):
It is a way of logically grouping classes that are only used in one place: If a class is useful to only one other class, then it is logical to embed it in that class and keep the two together. Nesting such "helper classes" makes their package more streamlined.
It increases encapsulation: Consider two top-level classes, A and B, where B needs access to members of A that would otherwise be declared private. By hiding class B within class A, A's members can be declared private and B can access them. In addition, B itself can be hidden from the outside world.
It can lead to more readable and maintainable code: Nesting small classes within top-level classes places the code closer to where it is used.
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());}}
当我们在类内声明非静态成员类时,它被称为内部类。内部类可以演示如下:
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);}}}
public class OuterClass {private String someVariable = "Non Static";
private static String anotherStaticVariable = "Static";
OuterClass(){
}
//Nested classes are staticstatic class StaticNestedClass{private static String privateStaticNestedClassVariable = "Private Static Nested Class Variable";
//can access private variables declared in the outer classpublic static void getPrivateVariableofOuterClass(){System.out.println(anotherStaticVariable);}}
//non staticclass InnerClass{
//can access private variables of outer classpublic String getPrivateNonStaticVariableOfOuterClass(){return someVariable;}}
public static void accessStaticClass(){//can access any variable declared inside the Static Nested Class//even if it privateString var = OuterClass.StaticNestedClass.privateStaticNestedClassVariable;System.out.println(var);}
}
外部测试:
public class OuterClassTest {public static void main(String[] args) {
//access the Static Nested ClassOuterClass.StaticNestedClass.getPrivateVariableofOuterClass();
//test the private variable declared inside the static nested classOuterClass.accessStaticClass();/** Inner Class Test* */
//Declaration
//first instantiate the outer classOuterClass outerClass = new OuterClass();
//then instantiate the inner classOuterClass.InnerClass innerClassExample = outerClass. new InnerClass();
//test the non static private variableSystem.out.println(innerClassExample.getPrivateNonStaticVariableOfOuterClass());
}
}
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 classLocal local = new Local();local.name(); //calling method from local inner class
//Creating anonymous inner class in Java for implementing threadThread anonymous = new Thread(){@Overridepublic void run(){System.out.println("Anonymous class example in java");}};anonymous.start();
//example of creating instance of inner classInnerClassTest test = new InnerClassTest();InnerClassTest.Inner inner = test.new Inner();inner.name(); //calling method of inner class}
//Creating Inner class in Javaprivate class Inner{public void name(){System.out.println("Inner class example in java");}}}
public class NestedStaticExample {public static void main(String args[]){StaticNested nested = new StaticNested();nested.name();}//static nested class in javaprivate static class StaticNested{public void name(){System.out.println("static nested class example in java");}}}
public class BankAccount {
private long accountNumber;private String owner;...
public static class Builder {
private long accountNumber;private String owner;...
static public Builder(long accountNumber) {this.accountNumber = accountNumber;}
public Builder withOwner(String owner){this.owner = owner;return this;}
...public BankAccount build(){BankAccount account = new BankAccount();account.accountNumber = this.accountNumber;account.owner = this.owner;...return account;}}}
public class MyClass extends Applet {...someObject.addMouseListener(new MyAdapter());...class MyAdapter extends MouseAdapter {public void mouseClicked(MouseEvent e) {...// Event listener implementation goes here......// change some outer class instance property depend on the event}}}
public class Bank {
// maximum limit as per current bank policy// is subject to changeprivate 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 limitcreditCard.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 classprivate 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 falsepublic 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;}}}