1.创建内部类:
将一个类定义在另一个类内部,就是内部类。如果想从外部类的静态方法之外的任意位置创建一个内部类的对象,需要这样指明:OuterClassName.InnerClassName。
实例:outer.java
/**
*
*/
package net.pmpa.innerclass;
/**
* @author liuche
*
*/
public class Outer {
private String outername;
class Inner{
public Inner(String name){
System.out.println("new Inner class "+name);
}
public String toString(){
System.out.println("The field outername of the outer class is "+outername); //直接访问外部类成员outername
return outername;
}
}
public Outer(String outername){
System.out.println("new Outer class");
this.outername = outername;
}
public Inner getInner(String name){
return new Inner(name);
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Outer out = new Outer("SanDiego");
Outer.Inner in = out.getInner("InnerTest");
in.toString();
}
}
2.链接到外部类
内部类对象可以访问创建它的外围对象的所有成员,此外还具有其外围类的所有元素的使用权。当外围类的对象创建了一个内部类的对象时,此内部类对象会获得一个指向外围类对象的引用。内部类的对象只有在与外部类对象相关联时才能被创建。
实例:Sequence.java
/**
*
*/
package net.pmpa.innerclass;
/**
* @author liuche
*
*/
public class Sequence {
class Dog{
private String dogname;
public Dog(String name){
this.dogname = name;
}
public String toString(){
System.out.println(dogname);
return dogname;
}
}
private Object[] items;
private int e = 0;
public Sequence(int size)
{
items = new Object[size];
}
public void add(Object item){
if(e<items.length)
{
items[e++] = item;
}
}
public Dog getDog(String dogname){
return new Dog(dogname);
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Sequence se = new Sequence(3);
Sequence.Dog d1 = se.getDog("d1");
Sequence.Dog d2 = se.getDog("d2");
Sequence.Dog d3 = se.getDog("d3");
Sequence.Dog d4 = se.getDog("d4");
se.add(d1);
se.add(d2);
se.add(d4);
se.add(d3);
for(Object i:se.items)
{
i.toString();
}
}
}
3.使用.this 和.new
(1)需要在内部类中创建外部类的对象时,需要使用外部类.this;
(2)需要在外部类中创建内部类的对象时,需要使用外部类对象.new 内部类;
下边两个类展示了如何使用及原理,House类包含一个内部类Bed,HouseTest类通过main进行测试:
实例:House.java
package net.pmpa.innerclass;
public class House {
private String housename;
public House(String name)
{
this.housename = name;
}
public String getHousename() {
return housename;
}
public void setHousename(String housename) {
this.housename = housename;
}
public class Bed{
private String bedname = "XiMengSi";
public String getBedname() {
return bedname;
}
public void setBedname(String bedname) {
this.bedname = bedname;
}
public House getHouse(){
return House.this; //内部类中创建外部类对象引用
}
}
}
实例:HouseTest.java
/**
*
*/
package net.pmpa.innerclass;
/**
* @author liuche
*
*/
public class HouseTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
House h = new House("wanke");
House.Bed b = h.new Bed(); //通过外部类,创建内部类对象 h.new
House d = b.getHouse();
System.out.println(d.getHousename());
}
}
4.匿名内部类
下面匿名内部类实例,创建了一个继承自E15_AnonymousInnerClass的一个匿名内部类,没有名字的类,因为没有名字所以没有构造方法。通过new表达式返回的引用被自动向上转型为对E15_AnonymousInnerClass的引用。但是通过实例初始化,可以达到为匿名内部类构建一个构造器的效果。
如果在一个方法中创建匿名内部类,并且在匿名内部类的定义体中,应用到了这个变量或者引用。则方法的参数必须定义为final的,例如final String name。
实例:E15_AnonymousInnerClass.java
package net.pmpa.innerclass;
public class E15_AnonymousInnerClass {
private String anonymous;
public E15_AnonymousInnerClass(String anonymous)
{
this.anonymous = anonymous;
}
}
实例:E15_AnonymousSecondClass.java
package net.pmpa.innerclass;
public class E15_AnonymousSecondClass {
public E15_AnonymousInnerClass getE15_AnonymousInnerClass(final String anonymous){ //anonymous作为匿名内部类的参数,使用了就需要是final类型
return new E15_AnonymousInnerClass(anonymous){ //创建一个继承自E15_AnonymousInnerClass的匿名内部类
{System.out.println("construct E15_AnonymousInnerClass's root class!" );} //类似实现匿名内部类的构造方法
private String function;
public String getFunction(){
System.out.println("getFunction()");
return function;};
};
}
public static void main(String[] args) {
// TODO Auto-generated method stub
E15_AnonymousSecondClass s = new E15_AnonymousSecondClass();
E15_AnonymousInnerClass x = s.getE15_AnonymousInnerClass("test");
}
}
5.嵌套类
如果不需要内部类对象与其外部类对象之间有联系,那么可以将内部类声明为static,通常称为嵌套类。
(1)要创建嵌套类的对象,并不需要其外围类的对象。
(2)不能从嵌套类的对象中访问非静态的外围类对象。
实例:E18_NestedClass.java
package net.pmpa.innerclass;
public class E18_NestedClass {
private String outerfield;
static class Nested{
public void f(){
System.out.println("call f() function!");
//System.out.println(outerfield); //!嵌套类内部不可以访问非静态域(对象)
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
E18_NestedClass.Nested ne = new E18_NestedClass.Nested();
ne.f();
}
}
当嵌套类,循环嵌套时,例如A中有B,B中有C,C中有D。生成的class文件,类似于A.class,A$B.class,A$B$C.class,A$B$C$D.class。下例中编译出的class文件分别是:E19_NestedClass.class、E19_NestedClass$E19_Nested1.class、E19_NestedClass$E19_Nested1$E19_Nested2.class、E19_NestedClass$E19_Nested1$E19_Nested2$E19_Nested3.class、E19_NestedClass$E19_Nested1$E19_Nested2$E19_Nested3$E19_Nested4.class
实例:E19_NestedClass.java
package net.pmpa.innerclass;
public class E19_NestedClass {
private String nestedstring;
static class E19_Nested1
{
public void f(){
System.out.println("Nested1 call f() function!");
}
static class E19_Nested2
{
public void f(){
System.out.println("Nested2 call f() function!");
}
static class E19_Nested3
{
public void f(){
System.out.println("Nested3 call f() function!");
}
static class E19_Nested4
{
public void f(){
System.out.println("Nested4 call f() function!");
}
}
}
}
}
}
5.接口内部的类
正常情况下,不能在接口内部放置任何代码,但是嵌套类可以作为接口的一部分。甚至可以在内部类中实现外围接口。
实例:E21_ClassInInterface.java
package net.pmpa.innerclass;
public class E21_ClassInInterface {
interface Inter21{
void f();
static class Test{ //接口内部定义的内部类。
static void call(Inter21 i)
{
System.out.println("Calling f()");
i.f();
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Inter21 i = new Inter21(){
public void f()
{
System.out.println("prinf f()!!!");
}
};
Inter21.Test.call(i);
}
}