初识内部类
在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。
内部类是一个非常有用的特性但又比较难理解使用的特性(我到现在都没有怎么使用过内部类,对内部类也只是略知一二)。
内部类我们从外面看是非常容易理解的,无非就是在一个类的内部在定义一个类。
public class OuterClass {
private String name ;
private int age;
class InnerClass{
public InnerClass(){
name = "chenssy";
age = 23;
}
}
}
在这里InnerClass就是内部类,对于初学者来说内部类实在是使用的不多。
广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类、静态内部类和匿名内部类。下面就先来了解一下这四种内部类的用法。
一、成员内部类
public class Outer{
private int a =99;//外部类的私有变量
//内部类Inner
public class Inner{
int b = 2;//内部类的变量
public void test() {
System.out.println("访问外部类的a:"+a);
System.out.println("访问内部类的b:"+b);
}
}
public static void main(String[] args) {
Outer o = new Outer();//创建外部类对象o
Inner i = o.new Inner();//使用外部类创建内部类对象i
i.test();//调用test方法
}
}
结果为
访问外部类的a:99
访问内部类的b:2
这样看起来,类Inner像是类Outer的一个成员,Outer称为外部类。
从上面的代码中我们可以看到,成员内部类的使用方法:
- Inner 类定义在 Outer 类的内部,相当于 Outer 类的一个成员变量的位置,Inner 类可以使用任意访问控制符,如public 、 protected 、 private 等
- Inner 类中定义的 test() 方法可以直接访问 Outer 类中的数据,而不受访问控制符的影响,如直接访问 Outer类中的私有属性a
- 定义了成员内部类后,必须使用外部类对象来创建内部类对象,而不能直接去 new 一个内部类对象,即:内部类 对象名 = 外部类对象.new 内部类( );
不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类.this.成员方法
二、局部内部类
局部内部类就是内部类定义在外部类的方法中,局部内部类只在该方法的内部可见,即只在该方法内可以使用。
public class Outer{
public void show() {
final int a = 25;
// 局部内部类
class Inner {
public void print() {
System.out.println("访问外部方法中的a:"+a);
}
}
Inner mi = new Inner();//创建局部内部类对象
mi.print();//调用方法
}
public static void main(String[] args) {
Outer o = new Outer();//创建外部类对象
o.show();//调用方法
}
}
注意:由于方法内部类不能在外部类的方法以外的地方使用,因此方法内部类不能使用访问控制符和 static 修饰符。
三、静态内部类
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。
public class Outer{
static int b = 1;
//静态内部类
public static class Inner{
int b =2;
public void test() {
System.out.println("外部类b"+ Outer.b);
System.out.println("内部类b"+ b);
}
}
public static void main(String[] args) {
Inner i = new Inner();
i.test();
}
}
静态内部类的特点是:
- 静态内部类不能直接访问外部类的非静态成员,但可以通过 new 外部类().成员 的方式访问。
- 如果外部类的静态成员与内部类的成员名称相同,可通过“类名.静态成员”访问外部类的静态成员;如果外部类的静态成员与内部类的成员名称不相同,则可通过“成员名”直接调用外部类的静态成员。
- 创建静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名= new 内部类();
四、匿名内部类
匿名内部类应该是平时我们编写代码时用得最多的
abstract class Person{//声明一个抽象类
public abstract void eat();
}
public class train{
public static void main(String[] args) {
Person p =new Person() {//匿名内部类
@Override
public void eat() {
System.out.println("吃点什么。。");
}
};
p.eat();
}
}
可以看到,我们直接将抽象类Person中的方法在大括号中实现了,这样便可以省略一个类的书写,并且,匿名内部类还能用于接口上。
interface Person{//声明一个抽象类
public abstract void eat();
}
public class train{
public static void main(String[] args) {
Person p =new Person() {//匿名内部类
@Override
public void eat() {
System.out.println("吃点什么。。");
}
};
p.eat();
}
}
上下两个运行结果都是:吃点什么。。
由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现。
使用匿名内部类的过程中,我们需要注意如下几点:
- 使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
- 匿名内部类中是不能定义构造函数的。
- 匿名内部类中不能存在任何的静态成员变量和静态方法。
- 匿名内部类为局部内部类(即方法内部类),所以局部内部类的所有限制同样对匿名内部类生效。
- 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
文章部分来源于网络,再次整理