——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
黑马程序员–Java之内部类06
一、内部类的概念以及种类
在Java中,允许在一个类的内部定义类,这样的类称作内部类,这个内部类所在的类称作外部类。根据内部类的位置、修饰符和定义的方式可以分为成员内部类、静态内部类、方法内部类。
二、成员内部类
在一个类中除了可以定义成员变量、成员方法,还可以定义类,这样的类被称作成员内部类。在成员内部类中可以访问外部类的所有成员,成员内部类的实例如下:
class Outer{//外部类
private int num = 4;//外部类的成员方法
Inner inner = new Inner();
inner.show();
//下面的代码定义了一个成员内部类
class Inner{//内部类
void show(){//在成员内部类的方法中访问外部类的成员变量
System.out.println("num =" + mun);
}
}
public calss Test{
public static void main(String[] args){
Outer outer = new Outer();//创建外部类对象
outer.test();//调用test()方法
}
}
Outer类是一个外部类,在该类中定义了一个内部类Ineer类和一个test方法,在Inner类中有一个show方法,show方法中访问外部类的成员变量num,test方法中创建了内部类Inner的实例对象,并通过该对象调用show方法,将num的值进行打印。运行上示程序可以看出,内部类可以在外部类中被使用,并能访问外部类的成员。
内部类的实例一定要绑定在外部类的实例上,如果从外部类中初始化一个内部类对象,那么内部类对象就会绑定在外部类。内部类对象会依赖于外部类对象,除非已经存在一个外部类对象,否则类中不会出现内部类对象。内部类初始化方式与其他类初始化方式相同都是使用new关键字,外部类创建内部类实例与其他类创建对象引用时相同。外部类可以访问它的外部类成员,但内部类的成员只有在内部类的范围内是可知的,不能被外部类使用。外部类对象和内部类对象关系到非常紧密,内外可以交互使用彼此类中定义的变量,但如果想通过外部类访问内部类,则需要通过外部类对象去创建内部类对象,语法格式为:外部类名.内部类名.变量名 = new 内部类名(); 。
三、静态内部类
在内部类前添加修饰符static,这个内部类就变为静态内部类了。一个静态内部类中可以声明static成员,但是在非静态内部类中不可以声明静态成员。静态内部类有一个最大的特点,就是不可以使用外部类的非静态成员,所以静态内部类在程序开发中比较少见。
普通的内部类对象隐匿地在外部保存了一个引用,指向创建它的外部类对象,但如果内部类被定义为static,就会有更多的限制。静态内部类具有以下两个特点:
- 如果创建静态内部类的对象,则不需要其外部类的对象。
- 不能比静态内部类的对象中访问非静态外部类的对象。
如果在每一个Java文件中都设置一个主方法,将出现很多额外代码,而程序本身并不需要这些方法,为了解决这个问题,可以将主方法写入静态内部类中。如下所示:
public class StaticInnerClass{
int x = 100;
static class Inner{
void runInner(){
//System.out.println("外部类" + x);
}
}
public static void main(String[] args){
System.out.println("a");
}
}
编译上示类,将会生成一个名称为StaticInnerClass$Inner
的独立类和一个StaticInnerClass
类,只要使用java StaticInnerClass$Inner
,就可以运行主方法中的内容,这样当完成测试,需要将所有.class文件打包时,只要删除StaticInnerClass$Inner
独立类即可。
四、方法内部类
内部类不仅可以在类中进行定义,也可以在类的局部位置定义,如在类的方法或任意的作用域中均可以定义内部类。方法内部类是指在成员方法中定义的类,在定义内部类时没有起名称,则该内部类为匿名内部类。匿名内部类使用默认构造方法来生成内部方法的对象。在匿名内部类定义结束后,需要加分号标识,这个分号并不是代表定义内部类结束的标识,而是代表创建方法对象引用表达式的标识。匿名内部类类编译后,会产生以“外部类名$序号”为名称的.class文件,序号以1~n排列,分另代表1~n个匿名内部类。代码如下所示:
class OuterClass2{
public OutInterface doit(){//定义doit()方法
return new OutInterface(){//在方法体中声明匿名内部类
private int i =0;
public int getValue(){
return i;
}
}
}