局部内部类
定义
在一个方法中定义的内部类
public class Test {
public void method() {
// 局部内部类
class Inner {
}
}
}
注意
-
局部内部类与局部变量一样,不能使用访问控制修饰符(public、private 和 protected)和static修饰符修饰;
-
局部类的作用域被限定在声明这个局部类的块中;
public class InnerClassTest01 {
// 编译出错 Inner inner1 = new Inner(); // 编译出错 InnerClassTest01.Inner inner2 = new InnerClassTest01.Inner(); // 编译出错 InnerClassTest01.Inner inner3 = new InnerClassTest01().new Inner(); public void method() { class Inner{ } // 正常编译 Inner inner4 = new Inner(); }
}
-
局部内部类中不能定义static成员;
-
局部内部类中还可以包含内部类,但这些内部类中也不能使用访问控制修饰符(public、private 和 protected)和 static修饰符修饰;
-
在局部内部类中可以访问外部类的所有成员;
-
不允许局部内部类要访问的局部变量的值发生改变,即局部内部类中只能访问所在方法的最终变量(final修饰)或实际上的最终变量(只赋值1次不会改变);
-
如果方法中的成员与外部类中的成员同名,则可以使用 .this. 的形式访问外部类中的成员。
public class InnerClassTest02 {
int outerA = 0; int b = 0; public void method() { int methodA = 0; methodA = 1; final int b = 0; final int methodC = 10; class Inner { // 访问外部类中的成员 int innerA01 = outerA; // 编译出错(因为methodA由0变成了1,发生了改变) int innerA02 = methodA; // 访问方法中的成员 int inneB01 = b; // 访问方法中的成员 int innerC = methodC; // 访问外部类中的成员 int innerB02 = InnerClassTest02.this.b; } Inner inner = new Inner(); // 输出10 System.out.println("inner.innerC是:" + inner.innerC); // 输出0 System.out.println("inner.innerB02是:" + inner.innerB02); } public static void main(String[] args) { InnerClassTest02 innerClassTest02 = new InnerClassTest02(); innerClassTest02.method(); }
}
匿名内部类
定义
匿名内部类,就是没有名字的嵌套类。它是局部内部类一种特殊形式,也就是没有变量名指向这个类的实例,而且具体的类实现会写在这个类里面。匿名内部类可以使你的代码更加简洁,你可以在定义一个类的同时对其进行实例化。如果某个局部类你只需要用一次,那么你就可以使用匿名内部类
public class InnerClassTest03 {
interface HelloWorld {
void greet();
void greetSomeone(String someone);
}
public void method() {
new HelloWorld() {
@Override
public void greet() {
// TODO:
}
@Override
public void greetSomeone(String someone) {
// TODO:
}
};
}
}
注意
- new的内容可以是接口,如果是接口,内部类就要实现这个接口(如示例代码);
- new的内容可以是一个类,如果是接口如果是类,内部类就要扩展这个类;
- 由于构造器的名字必须与类名相同,而匿名部内类没有类名,所以匿名内部类不能有构造器。
静态内部类
定义
有时候,使用内部类只是为了把一个类隐藏在另外一个类的内部,并不需要内部类有外围类对象的一个引用。为此,可以将内部类声明为static,这样就不会生成那个引用。这样声明的内部类就叫静态内部类。
public class InnerClassTest04 {
/**
* 定义一个静态内部类
*/
public static class Inner {
};
}
注意
-
只有内部类可以声明为static,静态内部类就类似于其他内部类,只不过静态内部类的对象没有生成它的外围类对象的引用;
-
只要内部类不需要访问外围类对象,就应该使用静态内部类;
-
静态内部类也叫嵌套类;
-
与常规内部类不同,静态内部类可以有静态字段和方法;
-
在接口中声明的内部类自动是static和public。
public interface InnerClassTest05 {
/** * 定义一个静态内部类 */ class Inner { //定义一个静态变量 private static int result; // 定义一个静态方法 public static void walk() { }; }
}
成员内部类
定义
定义在外部类中的成员位置的一个类
@Data
public class InnerClassTest06 {
private String name;
private Integer age;
/**
* 定义一个成员内部类
*/
class Inner {
};
}
注意
-
调用成员内部类的方法和访问成员内部类里变量,需要先创建成员内部类对象,创建成员内部类对象必须要先创建外部类对象;
Outer outer = new Outer();
Outer.Inner inner = outer.new.Inner()。 -
和成员变量一样,可以使用全部的四种权限修饰符和final修饰符;
-
在成员内部类里可以定义非静态成员变量,也可以使用static final定义静态成员常量,但是不能使用static定义静态变量;
-
在成员内部类里可以访问外部类的所有成员变量,调用所有方法,包括静态的。内部类作为外部类的成员,可以访问外部类的私有成员或属性,即使将外部类声明为private,但是对于处于其内部的内部类还是可见的;
-
当内部类和外部类有同名的成员时,内部类可通过【外部类名.this.变量名】访问外部类成员;
-
内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。
@Data
public class InnerClassTest07 {private String name; private Integer age; /** * 定义一个成员内部类 */ @Data class Inner { private String name; private Integer age; private static final String STATIC_FINAL_STRING = "test01"; // 编译失败 //private static String STATIC_STRING = "test02"; // 同名时,访问外部类成员。 private String outerName = InnerClassTest07.this.name; };
}
内部类的作用
- 内部类可以对同一包中的其他类隐藏起来;
- 内部类提供了某种进入其继承的类或实现的接口的窗口;
- 与外部类无关,独立继承其他类或实现接口;
- 为外部类提供了“多重继承”的解决办法,弥补了单继承的不足;
- 内部类方法可以访问该类定义所在作用域中的数据,包括被private修饰的私有数据;
- 当我们想要定义一个回调函数却不想写大量代码的时候我们可以选择使用匿名内部类来实现。