内部类定义
一个类定义在另一个类的内部,这个类称作内部类。
内部类作用
- 内部类提供了更好的封装,可以把内部类隐藏在外不累之内,不允许同一包下的其他类直接访问.
- 内部类成员可以直接访问外部类所有成员,包括private成员,因为外部类对象创建内部类对象时,内部类对象持有一个指向外部类对象的引用,然后在你访问外部类成员的时候,就是这个引用来选择外部类成员。也就是我们常说的,非静态内部类持有外部类的引用。
内部类的分类
非静态内部类
package com.example.patterns;
public class OuterClass {
private String name = "tom";
class InnerClass {
String getOutClassName() {
return name;
}
}
public static void main(String[] args) {
OuterClass.InnerClass innerClass = new OuterClass().new InnerClass();
String sName = innerClass.getOutClassName();
System.out.print(sName);
}
}
非静态内部类成员可以访问外部类成员,反之就不行,除非你先创建内部类实例.
非静态内部类不能含有静态成员
静态内部类
static修饰的就是静态内部类,注意:静态内部类属于外部类本身,而不属于外部类的某个实例,也就是说static修饰的是类相关,而不是实例相关。
静态内部类可以包含静态和非静态成员,但静态内部类不可以访问外部类的实例成员,也就是非静态成员,
只能访问外部类静态成员,
public class OutClass {
private int age = 12;
private static String name = "Jhon";
static class InnerClass {
void getAge(){
System.out.println(name);
//这里编译报错,static内部类不可以访问非静态外部类成员
//System.out.println(age);
}
}
public static void main(String[] args) {
OutClass.InnerClass innerClass=new OutClass.InnerClass();
innerClass.getAge();
}
}
局部内部类
定义在方法体内,就是局部内部类,且只在此方法内有效。
如果要在局部内部类创建实例只能在方法内,因为作用域就在方法内,外界不可访问。
public class OutClass {
private int age = 12;
private static String name = "Jhon";
void setName(){
class InnerClass {
private String hobby="play";
}
InnerClass innerClass=new InnerClass();
System.out.println(innerClass.hobby);
}
public static void main(String[] args) {
OutClass outClass=new OutClass();
outClass.setName();
}
}
这里编译后的class文件需要区别普通的内部类,因为外部类不同方法里可以创建同名的局部内部类,所以你便后你会看到,class文件格式是这样的,下面我举个例子:
public class OutClass {
void setName(){
class InnerClass {
}
}
void setAge(){
class InnerClass{
}
}
}
看下我们编译后的class文件:
局部内部类的字节码文件名格式:外部类+数字+内部类,就是为了区分。
匿名内部类
匿名内部类适合创建那种只需要一次使用的类,android中也比较常见,比如点击事件。
- 匿名内部类不能是抽象类,因为系统创建匿名内部类对象时,会立即创建匿名内部类的对象,因此不允许将匿名内部类定义成抽象类。
- 匿名内部类不可以定义构造器,但可以定义实例初始化块。
- 匿名内部类访问外部类局部变量时,需要final修饰。
举个例子:
public class OutClass {
void onSale(Product product){
}
interface Product{
void sale();
void stop();
}
public static void main(String[] args) {
OutClass outClass=new OutClass();
outClass.onSale(new Product() {
@Override
public void sale() {
}
@Override
public void stop() {
}
});
}
}