Java内部类
2015-10-20 20:15
423 查看
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);
}
}