Java/Class/Inner Class

Материал из Java эксперт
Версия от 18:01, 31 мая 2010; (обсуждение)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Accessing its enclosing instance from an inner class

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





A named inner class is used to

 
/** 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();
  }
}





An inner class cannot be overriden like a method

 
// : 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();
  }
} ///:~





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

 
/*
 * 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();
    }
  }
}





Creating a constructor for an anonymous inner class

 
// : 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();
  }
} ///:~





Creating inner classes

 
// : 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");
  }
} ///:~





Creating instances of inner classes

 
// : 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");
  }
} ///:~





Demonstrate an Inner Child class

 
/*
 * 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());
  }
}





Demonstrate simple inner class

 
/** 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);
    }
  }
}





Holds a sequence of Objects

 
// : 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());
  }
} ///:~





Inheriting an inner class

 
// : 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);
  }
} ///:~





Just to show that there is no such thing as inner methods in 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();
  }
}





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

 
// : 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();
      }
    }
  }
}





Nested Class Static

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





Nesting a class within a scope

 
// : 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();
  }
} ///:~





Proper inheritance of an inner class

 
// : 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();
  }
} ///:~





Putting test code in a nested class

 
// : 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();
    }
  }
} ///:~





Returning a reference to an inner class

 
// : 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");
  }
} ///:~





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

 
/*
 * 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());
  }
}





Using inner classes for callbacks

 
// : 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();
  }
} ///:~





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

 
// : 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());
  }
} ///:~