概述:
内部类,顾名思义,就是在一个类中再定义一个类,再次定义的那个类就称为内部类。这个就很容易理解啦。内部类可分为成员内部类、局部内部类、匿名内部类以及静态内部类。使用内部类可以节省编译后产生的字节码(.class)文件的大小,而且在实现事件监听时,采用内部类很容易实现。但是,使用内部类的最大问题是会使结构不清晰,所以在程序开发时,不用刻意的去追求使用内部类。
目录
一、成员内部类
在一个类中使用内部类,可以在内部类中直接存取其所在外部类的私有成员变量。在内部类中可以使用外部类的所有成员变量和成员方法,即使成员被修饰为 private 。
内部类的对象实例化操作必须在外部类或外部类的非静态方法中实现。
外部类不可以直接访问内部类成员变量。
内部类的实例一定要绑定在外部类对象上,如果从外部类中初始化一个内部类对象,那么内部类对象就会绑定在外部类对象上。
如果在外部类和非静态方法之外实例化内部类对象,需要使用(外部类.内部类)的形式指定该对象。
内部类对象与外部类对象关系非常紧密,内外可以交互使用彼此类中定义的变量。
案例:创建一个TestOuterClass外部类,在类中定义TestInnerClass内部类。我列出来很多种情况,注释掉的是不可用的
package cn.cou.pack;
public class TestOuterClass { //外部类
TestInnerClass in = new TestInnerClass();//在外部类中实例化内部类对象
//in.engine();//不可用
public void ccar()
{
System.out.println("滴滴滴滴");
//sname = "sn";//外部类不可以直接访问内部类成员变量
in.sname="sn";
in.age = 3;//外部类可以访问内部类私有成员变量
in.engine();//在外部类方法中调用内部类方法
}
private void go() { //外部类私有方法
System.out.println("出发");
}
private String name;//外部类私有成员变量
class TestInnerClass{ //内部类
String sname ;
private int age;
public void engine()
{
System.out.println(".......");
}
void outen() {
go(); //内部类的方法中可以使用外部类的所有成员变量和方法
System.out.println("name="+name);
}
}
public static void main(String[] agrs) {
TestOuterClass out = new TestOuterClass();//外部类实例化对象
out.name = "car";
out.ccar();
out.go();
out.in.age=3;
out.in.engine();
out.in.sname = "carmotor";
System.out.println("out.name ="+out.name+"\n"+"out.in.sname ="+out.in.sname);
//out.sname = "carmo";//外部类不能直接访问内部类成员
//out.in.age; //不能使用内部类私有变量
TestOuterClass.TestInnerClass in1 = out.new TestInnerClass();//在主方法中实例化内部类对象
in1.sname = "motor";
in1.engine();
//in1.age;
//in1.ccar();
//in1.name;
//TestInnerClass in2 = new TestInnerClass();
//TestOuterClass.TestInnerClass in2 = out.ccar();
}
}
成员内部类向上转型为接口:
如果将一个private修饰的内部类向上转型为其父类对象,或者直接向上转型为一个接口,在程序中就可以完全隐藏内部类的具体实现过程。可以在外部提供一个接口,在接口中声明一个方法,如果在实现该接口的内部类中实现该接口的方法,那么就可以定义多个内部类用不同的方式实现接口中的一个方法,而一般的类是不能多次实现接口中同一个方法的,这个技巧通常用在Swing编程中。
案例:
package cn.cou.pack;
public interface OutInterface {
public void OutIF();
}
package cn.cou.pack;
public class InnerInterface {
public static void main(String[] agrs) {
OuterClass out = new OuterClass();//实例化OuterClass对象
OutInterface outinter = out.doit();//调用doit方法,返回一个OuterClass接口
outinter.OutIF();//调用OutIF()方法
}
}
class OuterClass{
private class InnerClass implements OutInterface{ //定义内部类实现OutInterface接口
InnerClass(String s){ //内部类构造方法
System.out.println(s);
}
public void OutIF() { //实现接口中的OutIF()方法
System.out.println("访问内部类中的OutIF()方法");
}
}
public OutInterface doit() { //定义一个方法,返回值值类型为OutInterface接口
return new InnerClass("访问内部类构造方法");
}
}
二、局部内部类
内部类不仅可以在类中进行定义,也可以在类的局部位置定义,比如说在类的方法或任意的作用域中均可定义内部类。当内部类被定义在局部时不可以再被成员修饰符修饰,仍然可以访问外部类中的成员,因为其还持有外部类的引用。但是不可以访问它所在局部中的变量,如果需要在局部内部类中使用局部变量,该局部变量需要被设置为final类型,即在方法中定义的局部内部类只能访问方法中final类型的局部变量。由于该局部变量内设置为final,所以不能在内部类中改变该局部变量的值。
案例:
package cn.cou.pack;
public class TestTopoClass {
public static void main(String[] args) {
TestTopoClass topo = new TestTopoClass();
OutInterface outerface = topo.doit(null);
outerface.OutIF();
}
public OutInterface doit(final String x) {
class TopointerClass implements OutInterface{
TopointerClass(String s){
s=x;
System.out.println(s);
}
public void OutIF()
{
System.out.println("OutIF方法");
}
}
return new TopointerClass("doit");
}
}
三、匿名内部类
匿名内部类就是没有名字的内部类,就是内部类的简写格式。匿名内部类就是一个匿名子类对象,可以理解为带内容的对象。匿名内部类没有构造方法,不能定义静态成员,不能用private、public、protected、static、final、abstract等修饰,只可以创建一个匿名类实例。
匿名内部类格式:
new 父类或者接口(){
//定义子类的内容
}
四、静态内部类
在内部类前添加修饰符static,那么这个内部类就变成静态内部类,一个静态内部类可以声明静态成员, 在非静态内部类中不可以声明静态成员。静态内部类最大的特点就是不能使用外部类的非静态成员,所以静态内部类在开发中比较少见。