内部类(innerclasses)
内部类的定义
在一般情况下,我们将类定义为一个独立的单元,而在有些情况下,我们会将一个类定义在另一个类的内部,这样的类就成为内部类
内部类一般分为四种:成员内部类、局部内部类、匿名内部类、静态内部类
成员内部类
- 成员内部类可以简单理解为成外部类的一个属性
- 因此它可以访问该类的所有属性或方法,尽管它们的权限级别高(private)
- 实例化成员内部类时显然需要通过外部类的帮助
- 内部类同样可以拥有自己的属性和方法
- 当内部类的某一属性和外部类的某一属性同名时,在访问时由于就近原则,为内部类的属性
- 若在上条情况下想要调用外部类的同名属性,应该如此访问:外部类名.this.属性名
例如:
class Hello{
//如何实例化内部类
//方法一
OutClass outClass = new OutClass();
OutClass.InClass inClass1 = outClass.new InClass();
//先创建外部类的对象,再通过该对象new内部类的对象
//方法二
OutClass.InClass inClass2 = new OutClass().new InClass();
//思路与方法一一致,但缩略了为外部类对象命名的过程
}
class outClass{
public int outNum1;
private int outNnum2;
public int num;
public void outFunc(){
System.out.println("outClass.outFunc");
}
class inClass{
public int num;
public void inFunc1(){
System.out.println(outNum1 + "--" + outNum2);
//可以成功访问
}
public void inFunc2(){
System.out.println(num);
//输出值为inClass的num
System.out.println(this.num);
//因为当前对象为inClass,所以输出值仍为inClass的num
System.out.println(outClass.this.num);
//可通过该方法调用外部类的同名属性
}
}
}
局部内部类
- 局部内部类定义在外部类的一个方法中
- 因此局部内部类的作用域仅在该方法中,即只能在该方法体中实例化该类
- 局部内部类可以访问外部类的全部属性和方法
- 局部内部类可以拥有自己的属性和方法
- 当局部内部类有和外部类同名的属性时,其情况和访问方法与成员内部类一致
- 当局部内部类访问了该方法中的一个变量,则默认该变量为静态变量(final),所以该变量只能赋值一次
- 上条的原因为:可能会存在该方法执行完毕,而该类仍在访问该方法的变量的情况(多线程)
例如:
class Hello{
public int num;
private int helloNum;
public void func(){
int funcNum = 1; //默认该变量被final修饰,所以i的值不能再修改
class funcClass{
public int num;
public funcClassFunc(){
System.out.println(helloNum);
//可以成功访问
System.out.println(num + "--" + this.num);
//两个都为funcClass的num
System.out.println(Hello.this.num);
//为Hello的num
System.out.println(i);
//可以访问外部方法中的变量
//但为了避免外部方法执行完毕而该类仍在执行的情况,
//所以默认该变量为静态变量
}
}
}
}
静态内部类
- 静态内部类就是在成员内部类的基础上增加了static修饰词
- 静态内部类只能访问外部类的静态属性和静态方法
- 静态内部类直接隶属于外部类,因此可通过外部类直接创建对象而不必先创建外部类的对象
例如:
class Hello{
public static void main(String[] args){
OutClass.InClass inClass = new OutClass.InClass();
//跳过创建外部类对象,直接通过外部类创建内部类对象
}
}
class OutClass{
public int num1;
public static int num2;
static class InClass{
public void func(){
// System.out.println(num1);
// 静态内部类只能访问外部类的静态属性,故错误
System.out.println(num2); //输出num2
}
}
}
匿名内部类
- 一些情况下,某个类以及它的对象只使用一次,则可以将类的定义和对象的创建一起完成,这样没有名字的类就叫做匿名内部类
- 由于匿名内部类没有名字,所有类体中不能定义构造方法
- 匿名内部类通常用于创建一个接口或一个抽象类的对象(因为接口和抽象类无法实例化对象)
- 匿名内部类只能继承一个类或实现一个接口,不能继承一个类的同时实现一个接口,也不能同时实现两个或以上的接口
- 匿名内部类继承一个内或实现一个接口时不需要extends或implements关键字
例如:
class Hello{
public static void main(String[] args){
AbsClass absClass = new AbsClass(){
//必须重写所继承抽象类的抽象方法
public void absFunc(){
System.out.println("继承抽象类");
}
}//该花括号内则为匿名内部类的类体
InterFace inter = new InterFace(){
//必须重写所实现接口的方法
public void interFunc(){
System.out.println("实现接口");
}
}
}
}
abstract class AbsClass{
public abstract void absFunc();
}
interface InterFace{
void interFunc();
}