1、总体定义
定义在一个类中的类,就称之为内部类。
2、为什么要使用内部类
(1)使用匿名内部类,无需对只使用一次的接口实现类进行创建,方便了对于接口和抽象类的实现及其使用。
(2)每个内部类都可以独立的继承一个(接口)的实现,所以无论外部类是否已经继承了某个接口的实现对于内部类都没有影响。简单来说,内部类实现了java中的多重继承。
3、内部类的分类和使用
3.1、成员内部类
成员内部类即所定义内部类作为外部类的一个成员变量。成员内部类的特点如下:
(1)内部类随意访问外部类,外部类必须通过实例化来访问内部类;
(2)成员内部类中不能存在任何static的变量和方法;
(3)成员内部类的创建必须依附于外部类;
成员内部类的创建方式:
外部类名称.内部类名称 对象名=new 外部类名称().new 内部类名称()
成员内部类的使用:
(1) 间接方式:在外部类的方法中使用内部类,通过调用外部类的方法来使用内部类;
(2) 直接方式:先创建再使用;
代码示例
public class Insertclass {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//成员内部类的间接使用方法
public void methodBody(){
System.out.println("外部类");
//外部类中使用内部类
Heart h=new Heart();
h.beat();
}
//成员内部类
public class Heart{
public void beat(){
System.out.println("心脏跳动");
System.out.println("我叫"+name);
}
}
}
3.2、局部内部类
局部内部类即所定义内部类定义在外部类的方法中。局部内部类的特点如下:
局部内部类只能在定义了该内部类中的方法中被使用。
成员内部类的创建方式:
外部类类名.内部类类名 xxx = 外部类对象名.new 内部类类名()
代码示例
public class Insertclass {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void methodOuter(){
//局部内部类
class Inner{
int num=10;//必须为有效final
public void show(){
System.out.println(num);
}
}
}
}
3.3、静态内部类
使用static关键字进行修饰的内部类称之为静态内部类,或者嵌套内部类。静态内部类的特点如下:
(1)静态内部类的创建不需要依附于外部类
(2)静态内部类由static修饰,故而只能调用外部类中由static修饰的变量和方法
静态内部类的创建方式:
外部类类名.内部类类名 xxx = new 外部类类名.内部类类名()
代码示例
public class OutClassTest {
static int a;
int b;
public static void main(String[] args) {
// new一个外部类
OutClassTest oc = new OutClassTest();
// 不依赖于外部类实例,直接实例化内部静态类
OutClassTest.InnerStaticClass inner = new OutClassTest.InnerStaticClass();
// 调用静态内部类的非静态方法
System.out.println(inner.getValue());
}
//静态内部类
private static class InnerStaticClass {
// 静态内部类可以有静态成员,而非静态内部类则不能有静态成员。
private static String static_value = "0";
private int flag = 0;
//静态内部类方法
public InnerStaticClass() {
System.out.println("InnerClass create a:" + a);
// 静态内部类不能够访问外部类的非静态成员
// System.out.println("InnerClass create b:" + b);
System.out.println("InnerStaticClass flag is " + flag);
System.out.println("InnerStaticClass tt is " + static_value);
}
public int getValue() {
// 静态内部类中的非静态方法
test();
return 1;
}
}
}
其实到此处,内部类的分类就已经结束,但对于局部内部类中的匿名内部类由于使用较多,需要着重介绍一下。
3.4、匿名内部类
匿名内部类是一种特殊的局部内部类,它可以在不创建新类的条件下对于现有接口(或者抽象类)进行实现。匿名内部类的特点如下:
(1) 匿名内部类没有访问修饰符。
(2) 匿名内部类对于类的实例化,没有任何变量名称,这就导致匿名内部类所定义的类在保证简便的同时有着不可复用的缺点。
(3)匿名内部类中不能存在任何静态变量和静态方法。
(4)匿名内部类中不能定义构造函数。
匿名内部类的创建方式:
new 现有接口名称{ 接口中需要实现的内容 }
代码示例
interface MyInterface{
public void show();
}
public class AnymiousClass {
public static void main(String[] args){
//使用局部内部类之匿名内部类
MyInterface obj=new MyInterface() {
@Override
public void show(){
System.out.println("匿名内部类实现了方法");
}
};
//匿名内部类实现的接口实体类
new MyInterface() {
@Override
public void show(){
System.out.println("匿名内部类实现了方法");
}
}.show();
}
}
4、内部类的注意事项
(1)内用外,随意调用;外用内,需要内部类对象;
(2)局部内部类引用局部变量,这个局部变量必须是有效final的,也即是必须要被final关键字修饰的。
原因:new出来的对象在堆内存中,而局部变量跟随方法在栈内存中。方法运行结束立即出栈,局部变量消失。 new的对象会保持在堆中,直到垃圾回收时才消失。
此时要保证栈中的对象的功能正常,就必须保证对象所引用的局部变量的生存周期和对象的相同,故而使用局部变量必须是有效final的。