在 Java 中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。内部类的出现,再次打破了Java单继承的局限性。
内部类一般分为4种:成员内部类、静态内部类、局部内部类和匿名内部类。
注意:内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两个类。
内部类的位置
内部类与外部类的依赖
内部类可以拥有的成员
内部类访问外部类成员
外部类访问内部类成员
内部类成员和外部类成员重名
内部类使用成员时,当外部类的成员和内部类的成员重名时,会发生隐藏现象(外部类的成员会被隐藏),默认情况下访问的是内部类的成员(就近原则),所以一般建议:
内部类和外部类的编译
外部类和内部类在编译后是两个不同的class文件。
内部类可分为四种:
成员内部类是最普通的内部类,它的定义为位于另一个类的内部。类似于成员方法,成员内部类不能拥有静态域但是可以访问外部类的静态部分。
public class OuterClass {
private static String a = "outer static filed";
private String b = "outer filed";
public static String method1() {
return "outer static method";
}
public String method2() {
return "outer method";
}
class InnerClass {
public void getOuter() {
// 1.成员内部类访问外部类的静态变量
System.out.println(OuterClass.a);
// 2.成员内部类访问外部类的静态方法
System.out.println(OuterClass.method1());
// 3.成员内部类访问外部类的成员变量
System.out.println(OuterClass.this.b);
System.out.println(b);// 不建议使用这种方式
// 4.成员内部类访问外部类的普通方法
System.out.println(OuterClass.this.method2());
System.out.println(method2());// 不建议使用这种方式
}
}
}
public static void main(String[] args) {
// 方式1:
OuterClass.InnerClass innerClass = new OuterClass().new InnerClass();
// 方式2:
OuterClass outerClass = new OuterClass();
InnerClass innerClass1 = outerClass.createInnerClass();
}
创建成员内部类实例
格式:外部类名.内部类名 成员内部类对象名 = new 外部类名().new 内部类名()
静态内部类也是定义在另一个类里面的类,使用static修饰,类似于静态方法,静态内部类不需要外部类对象产生就能使用,静态内部类只能访问外部类的静态部分,不能访问外部类的实例部分。
public class OuterClass {
private static String a = "outer static filed";
private String b = "outer filed";
public static String method1() {
return "outer static method";
}
public String method2() {
System.out.println(b);
return "outer method";
}
static class InnerClass {
private static String b = "inner filed";
public String method2() {
return "outer method";
}
public void getOuter() {
System.out.println(a);
}
}
}
创建静态内部类实例
格式:外部类名.内部类名 成员内部类对象名 = new 外部类名.内部类名()
public class Test {
public static void main(String[] args) {
OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
}
}
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内,类似于局部变量。
public class OuterClass {
private static String a = "outer static filed";
private String b = "outer filed";
static {
class InnerClass1 {
public void method2() {
System.out.println(a);
}
}
}
{
class InnerClass1 {
public void method2() {
System.out.println(a);
System.out.println(b);
}
}
}
public static void method1() {
class InnerClass1 {
public void method2() {
System.out.println(a);
}
}
}
public void method2() {
class InnerClass1 {
public void method2() {
System.out.println(a);
System.out.println(b);
}
}
InnerClass1 innerClass1 = new InnerClass1();
}
}
创建局部内部类实例
在局部内部类的作用域内通过new对象的方式创建对象。
格式:局部内部类名 局部内部类对象名 = 局部内部类名();
匿名内部类应该是我们编写代码时用得最多的,它满足了我们动态自定义代码的需求。
匿名内部类可以看作是特殊的局部内部类,其本质就是一个继承/实现了某个类(接口,普通类,抽象类)的子类匿名对象。
匿名内部类的定义
格式:new 接口名|类名(){重写方法}
如果重写方法为非必要的,原则上是可以没有重写方法部分的。
public class Test {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
}
};
Runnable runnable1 = new Runnable() {
@Override
public void run() {
}
};
}
}
从Java8开始,引入了Lambda表达式,将代码块作为参数使用更简洁的代码来创建只有一个抽象方法的接口(这种接口被称为函数式接口)的实例。
Lambda表达式的代码块就是实现接口方法的方法体。
public class Test {
public static void main(String[] args) {
Runnable runnable = () -> {
System.out.println("run.... ");
};
}
}
Lambda代码块写的是Runnable接口的run方法的方法体。
两者的不同之处: