Java/Class/Inner Class
Содержание
- 1 Accessing its enclosing instance from an inner class
- 2 A named inner class is used to
- 3 An inner class cannot be overriden like a method
- 4 Compiler will generate a synthetic constructor since SyntheticConstructor() is private
- 5 Creating a constructor for an anonymous inner class
- 6 Creating inner classes
- 7 Creating instances of inner classes
- 8 Demonstrate an Inner Child class
- 9 Demonstrate simple inner class
- 10 Holds a sequence of Objects
- 11 Inheriting an inner class
- 12 Just to show that there is no such thing as inner methods in Java
- 13 Nested classes can access all members of all levels of the classes they are nested within
- 14 Nested Class Static
- 15 Nesting a class within a scope
- 16 Proper inheritance of an inner class
- 17 Putting test code in a nested class
- 18 Returning a reference to an inner class
- 19 This file is to show what happens if you try to access an inner class created in another class
- 20 Using inner classes for callbacks
- 21 With concrete or abstract classes, inner classes are the only way to produce the effect
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());
}
} ///:~