Java/Class/Inner Class

Материал из Java эксперт
Перейти к: навигация, поиск

Accessing its enclosing instance from an inner class

   <source lang="java">

public class Main {

 private int number = 12;
 public Main() {
   InnerClass inner = new InnerClass();
   inner.printNumber();
 }
 class InnerClass {
   public void printNumber() {
     System.out.println(Main.this.number);
   }
 }
 public static void main(String[] args) {
   new Main();
 }

}

 </source>
   
  
 
  



A named inner class is used to

   <source lang="java">

/** Demonstrate inner-inner class. A named inner class

* is used to show that it can access non-local variables
* in the enclosing object.
*/

public class InnerClass3 {

 static String msg = "Hello";
 public static void main(String[] av) {
   class Inner {
     public void doTheWork() {
       // print member of enclosing class
       System.out.println(msg);
     }
   }
   Inner p = new Inner();
   p.doTheWork();
 }

}


 </source>
   
  
 
  



An inner class cannot be overriden like a method

   <source lang="java">

// : c08:BigEgg.java // An inner class cannot be overriden like a method. // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt. class Egg {

 private Yolk y;
 protected class Yolk {
   public Yolk() {
     System.out.println("Egg.Yolk()");
   }
 }
 public Egg() {
   System.out.println("New Egg()");
   y = new Yolk();
 }

} public class BigEgg extends Egg {

 public class Yolk {
   public Yolk() {
     System.out.println("BigEgg.Yolk()");
   }
 }
 public static void main(String[] args) {
   new BigEgg();
 }

} ///:~


 </source>
   
  
 
  



Compiler will generate a synthetic constructor since SyntheticConstructor() is private

   <source lang="java">

/*

* Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   - Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*
*   - Redistributions in binary form must reproduce the above copyright
*     notice, this list of conditions and the following disclaimer in the
*     documentation and/or other materials provided with the distribution.
*
*   - Neither the name of Sun Microsystems nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

public class SyntheticConstructor {

 private SyntheticConstructor() {
 }
 class Inner {
   // Compiler will generate a synthetic constructor since
   // SyntheticConstructor() is private.
   Inner() {
     new SyntheticConstructor();
   }
 }

}

 </source>
   
  
 
  



Creating a constructor for an anonymous inner class

   <source lang="java">

// : c08:AnonymousConstructor.java // Creating a constructor for an anonymous inner class. // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt. abstract class Base {

 public Base(int i) {
   System.out.println("Base constructor, i = " + i);
 }
 public abstract void f();

} public class AnonymousConstructor {

 public static Base getBase(int i) {
   return new Base(i) {
     {
       System.out.println("Inside instance initializer");
     }
     public void f() {
       System.out.println("In anonymous f()");
     }
   };
 }
 public static void main(String[] args) {
   Base base = getBase(47);
   base.f();
 }

} ///:~


 </source>
   
  
 
  



Creating inner classes

   <source lang="java">

// : c08:Parcel1.java // Creating inner classes. // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt. public class Parcel1 {

 class Contents {
   private int i = 11;
   public int value() {
     return i;
   }
 }
 class Destination {
   private String label;
   Destination(String whereTo) {
     label = whereTo;
   }
   String readLabel() {
     return label;
   }
 }
 // Using inner classes looks just like
 // using any other class, within Parcel1:
 public void ship(String dest) {
   Contents c = new Contents();
   Destination d = new Destination(dest);
   System.out.println(d.readLabel());
 }
 public static void main(String[] args) {
   Parcel1 p = new Parcel1();
   p.ship("Tanzania");
 }

} ///:~


 </source>
   
  
 
  



Creating instances of inner classes

   <source lang="java">

// : c08:Parcel11.java // Creating instances of inner classes. // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt. public class Parcel11 {

 class Contents {
   private int i = 11;
   public int value() {
     return i;
   }
 }
 class Destination {
   private String label;
   Destination(String whereTo) {
     label = whereTo;
   }
   String readLabel() {
     return label;
   }
 }
 public static void main(String[] args) {
   Parcel11 p = new Parcel11();
   // Must use instance of outer class
   // to create an instances of the inner class:
   Parcel11.Contents c = p.new Contents();
   Parcel11.Destination d = p.new Destination("Tanzania");
 }

} ///:~


 </source>
   
  
 
  



Demonstrate an Inner Child class

   <source lang="java">

/*

* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java 
* language and environment is gratefully acknowledged.
* 
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/

/**

* Demonstrate an Inner Child class
* @author Ian F. Darwin, http://www.darwinsys.ru/
* @version $Id: InnerChild.java,v 1.3 2004/02/09 03:33:53 ian Exp $
*/

public class InnerChild {

 public class InnerInnerChild extends InnerChild {
 }
 public static void main(String[] argv) {
   // System.out.println(new InnerChild.InnerInnerChild()); // NOT how!
   InnerChild x = new InnerChild();
   System.out.println(x.new InnerInnerChild());
 }

}


 </source>
   
  
 
  



Demonstrate simple inner class

   <source lang="java">

/** Demonstrate simple inner class. A named inner class

* is used to show that it can access non-local variables
* in the enclosing object.
*/

public class InnerClass1 {

 String msg = "Hello";
 void doWork() {
   Inner i = new Inner();
   i.doTheWork();
   msg = "Goodbye";
   i.doTheWork();
 }
 public static void main(String[] av) {
   InnerClass1 p = new InnerClass1();
   p.doWork();
 }
 class Inner {
   public void doTheWork() {
     // print member of enclosing class
     System.out.println(msg);
   }
 }

}


 </source>
   
  
 
  



Holds a sequence of Objects

   <source lang="java">

// : c08:LocalInnerClass.java // Holds a sequence of Objects. // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt. interface Counter {

 int next();

} public class LocalInnerClass {

 private int count = 0;
 Counter getCounter(final String name) {
   // A local inner class:
   class LocalCounter implements Counter {
     public LocalCounter() {
       // Local inner class can have a constructor
       System.out.println("LocalCounter()");
     }
     public int next() {
       System.out.print(name); // Access local final
       return count++;
     }
   }
   return new LocalCounter();
 }
 // The same thing with an anonymous inner class:
 Counter getCounter2(final String name) {
   return new Counter() {
     // Anonymous inner class cannot have a named
     // constructor, only an instance initializer:
     {
       System.out.println("Counter()");
     }
     public int next() {
       System.out.print(name); // Access local final
       return count++;
     }
   };
 }
 public static void main(String[] args) {
   LocalInnerClass lic = new LocalInnerClass();
   Counter c1 = lic.getCounter("Local inner "), c2 = lic
       .getCounter2("Anonymous inner ");
   for (int i = 0; i < 5; i++)
     System.out.println(c1.next());
   for (int i = 0; i < 5; i++)
     System.out.println(c2.next());
 }

} ///:~


 </source>
   
  
 
  



Inheriting an inner class

   <source lang="java">

// : c08:InheritInner.java // Inheriting an inner class. // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt. class WithInner {

 class Inner {
 }

} public class InheritInner extends WithInner.Inner {

 //! InheritInner() {} // Won"t compile
 InheritInner(WithInner wi) {
   wi.super();
 }
 public static void main(String[] args) {
   WithInner wi = new WithInner();
   InheritInner ii = new InheritInner(wi);
 }

} ///:~


 </source>
   
  
 
  



Just to show that there is no such thing as inner methods in Java

   <source lang="java">

/** Just to show that there is no such thing as inner methods in Java */ public class InnerMethods {

 public static void main(String[] args) {
   new InnerMethods().work();
 }
 public void work() {  // EXPECT COMPILE ERROR
   void inner() {
     System.out.println("Hey, there is such a thing as Inner Methods");
     System.out.println("in Java. Better tell James Gosling and Sun!");
   }
   inner();
 }

}


 </source>
   
  
 
  



Nested classes can access all members of all levels of the classes they are nested within

   <source lang="java">

// : c08:MultiNestingAccess.java // Nested classes can access all members of all levels of the classes they are nested within. // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt.

public class MultiNestingAccess {

 public static void main(String[] args) {
   MNA mna = new MNA();
   MNA.A mnaa = mna.new A();
   MNA.A.B mnaab = mnaa.new B();
   mnaab.h();
 }

} ///:~ class MNA {

 private void f() {
 }
 class A {
   private void g() {
   }
   public class B {
     void h() {
       g();
       f();
     }
   }
 }

}


 </source>
   
  
 
  



Nested Class Static

   <source lang="java">

public class NestedClassStatic {

 /** Just show that Nested Classes may be static */
 static class V {
 }
 public static void main(String[] args) {
   V v = new V();
   System.out.println(v);
   v = new V();
   System.out.println(v);
 }

}


 </source>
   
  
 
  



Nesting a class within a scope

   <source lang="java">

// : c08:Parcel5.java // Nesting a class within a scope. // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt. public class Parcel5 {

 private void internalTracking(boolean b) {
   if (b) {
     class TrackingSlip {
       private String id;
       TrackingSlip(String s) {
         id = s;
       }
       String getSlip() {
         return id;
       }
     }
     TrackingSlip ts = new TrackingSlip("slip");
     String s = ts.getSlip();
   }
   // Can"t use it here! Out of scope:
   //! TrackingSlip ts = new TrackingSlip("x");
 }
 public void track() {
   internalTracking(true);
 }
 public static void main(String[] args) {
   Parcel5 p = new Parcel5();
   p.track();
 }

} ///:~


 </source>
   
  
 
  



Proper inheritance of an inner class

   <source lang="java">

// : c08:BigEgg2.java // Proper inheritance of an inner class. // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt. class Egg2 {

 protected class Yolk {
   public Yolk() {
     System.out.println("Egg2.Yolk()");
   }
   public void f() {
     System.out.println("Egg2.Yolk.f()");
   }
 }
 private Yolk y = new Yolk();
 public Egg2() {
   System.out.println("New Egg2()");
 }
 public void insertYolk(Yolk yy) {
   y = yy;
 }
 public void g() {
   y.f();
 }

} public class BigEgg2 extends Egg2 {

 public class Yolk extends Egg2.Yolk {
   public Yolk() {
     System.out.println("BigEgg2.Yolk()");
   }
   public void f() {
     System.out.println("BigEgg2.Yolk.f()");
   }
 }
 public BigEgg2() {
   insertYolk(new Yolk());
 }
 public static void main(String[] args) {
   Egg2 e2 = new BigEgg2();
   e2.g();
 }

} ///:~


 </source>
   
  
 
  



Putting test code in a nested class

   <source lang="java">

// : c08:TestBed.java // Putting test code in a nested class. // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt. public class TestBed {

 public TestBed() {
 }
 public void f() {
   System.out.println("f()");
 }
 public static class Tester {
   public static void main(String[] args) {
     TestBed t = new TestBed();
     t.f();
   }
 }

} ///:~


 </source>
   
  
 
  



Returning a reference to an inner class

   <source lang="java">

// : c08:Parcel2.java // Returning a reference to an inner class. // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt. public class Parcel2 {

 class Contents {
   private int i = 11;
   public int value() {
     return i;
   }
 }
 class Destination {
   private String label;
   Destination(String whereTo) {
     label = whereTo;
   }
   String readLabel() {
     return label;
   }
 }
 public Destination to(String s) {
   return new Destination(s);
 }
 public Contents cont() {
   return new Contents();
 }
 public void ship(String dest) {
   Contents c = cont();
   Destination d = to(dest);
   System.out.println(d.readLabel());
 }
 public static void main(String[] args) {
   Parcel2 p = new Parcel2();
   p.ship("Tanzania");
   Parcel2 q = new Parcel2();
   // Defining references to inner classes:
   Parcel2.Contents c = q.cont();
   Parcel2.Destination d = q.to("Borneo");
 }

} ///:~


 </source>
   
  
 
  



This file is to show what happens if you try to access an inner class created in another class

   <source lang="java">

/*

* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java 
* language and environment is gratefully acknowledged.
* 
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/

import java.awt.event.*; // This file is to show what happens if you try to access an inner class // created in another class. Here we try to steal ButtonDemo2.java"s // inner class named MyActionListener. You will find that you can"t, // since it has no visible constructor! class ButtonDemo2 {

 // Create an inner class which may be named ButtonDemo2$1
 Object o = new ActionListener() {
     public void actionPerformed(ActionEvent evt) {
     }
 };

} public class TryStealingInnerClass {

 public static void main(String[] a) {
   new TryStealingInnerClass().doIt();
 }
 public void doIt() {
   Object o = new ButtonDemo2$1$();  // EXPECT COMPILE ERROR
   System.out.println(o.toString());
 }

}


 </source>
   
  
 
  



Using inner classes for callbacks

   <source lang="java">

// : c08:Callbacks.java // Using inner classes for callbacks // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt. interface Incrementable {

 void increment();

} // Very simple to just implement the interface: class Callee1 implements Incrementable {

 private int i = 0;
 public void increment() {
   i++;
   System.out.println(i);
 }

} class MyIncrement {

 void increment() {
   System.out.println("Other operation");
 }
 static void f(MyIncrement mi) {
   mi.increment();
 }

} // If your class must implement increment() in // some other way, you must use an inner class: class Callee2 extends MyIncrement {

 private int i = 0;
 private void incr() {
   i++;
   System.out.println(i);
 }
 private class Closure implements Incrementable {
   public void increment() {
     incr();
   }
 }
 Incrementable getCallbackReference() {
   return new Closure();
 }

} class Caller {

 private Incrementable callbackReference;
 Caller(Incrementable cbh) {
   callbackReference = cbh;
 }
 void go() {
   callbackReference.increment();
 }

} public class Callbacks {

 public static void main(String[] args) {
   Callee1 c1 = new Callee1();
   Callee2 c2 = new Callee2();
   MyIncrement.f(c2);
   Caller caller1 = new Caller(c1);
   Caller caller2 = new Caller(c2.getCallbackReference());
   caller1.go();
   caller1.go();
   caller2.go();
   caller2.go();
 }

} ///:~


 </source>
   
  
 
  



With concrete or abstract classes, inner classes are the only way to produce the effect

   <source lang="java">

// : c08:MultiImplementation.java // With concrete or abstract classes, inner classes are the only way to produce the effect // of "multiple implementation inheritance." // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt. class D { } abstract class E { } class Z extends D {

 E makeE() {
   return new E() {
   };
 }

} public class MultiImplementation {

 static void takesD(D d) {
 }
 static void takesE(E e) {
 }
 public static void main(String[] args) {
   Z z = new Z();
   takesD(z);
   takesE(z.makeE());
 }

} ///:~


 </source>