内部类
定义在一个类内部的类,其实,类中不仅仅可以有内部类,也可以有内部接口。
内部类按照定义的位置和修饰符不同,分为以下几种:
1.成员内部类:
- 定义在类中,和方法、属性平级,作为外部类的一个成员。这个内部类是非静态的。
- 访问权限可以是任意权限
- 实例化对象
Outter outer = new Outter();
Outter.Inner inner = outter.new Inner();
- 成员内部类是没有静态成员的
- 编译后生成的字节码文件名为:外部类$内部类.class
class Outter{
public String name;
public class Inner{
}
}
2.局部内部类
- 定义在某个代码块中的类
- 不允许写访问权限修饰符
- 局部内部类只能在当前代码中,起到一个临时的数据格式化的作用
- 编译后生成的字节码文件:外部类 $ 序号 内部类.class
public class Program{
public static void main(String[] args){
class Test{
}
Test test = new Test();
}
}
3.静态内部类
- 定义在类中,和方法、属性平级,作为外部类的一个成员。这个内部类是静态的。
- 访问权限可以是任意权限
- 实例化对象
Outter.Inner inner = new Outter1.Inner();
- 编译后生成字节码文件:外部类 $ 内部类.class
class Outter{
public static class Inner{
public String name;
public void test() {
}
}
}
4.匿名内部类
- 没有名字的类
- 定义:匿名内部类离不开父类或接口,且定义在代码段中
- 匿名内部类其实是指定类的子类,或者指定接口的实现类
- 一般情况下,使用内部类是配合抽象类或接口使用,配合接口使用较多
- 编译后生成的字节码文件:外部类 $ 序号.class
抽象类内部类案例:
public class Program {
public static void main(String[] args) {
//这并不是实例化Animal对象,而是实例化animal子类的对象,
//向上转型为animal,调用test1就是调用其子类特有的方法
Animal animal = new Animal() {
@Override
public void test1() {
System.out.println("匿名内部类重写的方法");
test2();
}
public void test2() {
System.out.println("内部类自己的方法");
}
};
animal.test1();
// 不能调用匿名内部类自己的方法,可以在匿名内部类中重写的方法中调用
//animal.test2();
}
}
abstract class Animal{
public abstract void test1();
}
接口内部类案例:
public class Program {
public static void main(String[] args) {
//这并不是实例化接口对象(且接口并不能实例化对象),而是实现匿名实现类的对象
//向上转型为animal,调用test1就是调用其实现类的方法
Animal animal = new Animal() {
@Override
public void test1() {
System.out.println("匿名内部类重写的方法");
test2();
}
public void test2() {
System.out.println("内部类自己的方法");
}
};
animal.test1();
}
}
interface Animal{
public void test1();
}
lamba表达式只能在接口只有一个必须实现的抽象方法时使用,而如果有多个抽象方法需要实现,那么,可以使用匿名内部类来实现。