内部类
Java内部类(Inner Class)是定义在另一个类(外部类)内部的一个类。这种嵌套类的定义允许更紧密的代码组织和更高的封装性。内部类可以访问其外部类的所有成员,包括私有成员,反之则不然。内部类可以有不同的修饰符,比如可以是私有的(private),保护的(protected),默认的(包内访问),或者静态的(static)。如果被static修饰,它只能访问外部类中的静态成员。
获取成员内部类对象的两种方式:
方式一:外部类编写方法,对外提供内部类对象
方式二:直接创建
格式:
外部类名.内部类名 对象名 = 外部类对象.内部类对象
内部类可以分为几种不同的类型:
成员内部类(非静态内部类):
这是最常见的内部类形式,它定义在外部类的成员位置。成员内部类对象隐含地持有其外部类对象的引用,因此可以访问外部类的所有成员,包括私有成员。创建成员内部类对象时,需要首先创建外部类对象,然后使用外部类对象来创建内部类对象。
public class OuterClass {
private int outerField = 100;
class InnerClass {
void display() {
System.out.println("Outer field value: " + outerField);
}
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
inner.display();
}
}
//在上面的示例中,InnerClass 是 OuterClass 的一个非静态内部类。
//在 main 方法中,我们首先创建了 OuterClass 的一个对象 outer,
//然后使用 outer 来创建 InnerClass 的对象 inner。
//注意我们使用 outer.new InnerClass() 来创建内部类的实例。
静态内部类:
静态内部类使用static
关键字修饰,它属于外部类本身,而不是外部类的某个对象。静态内部类只能访问外部类的静态成员。创建静态内部类对象时,不需要外部类对象,可以直接通过外部类来创建。
public class ABCD {
//注意事项:
//1.静态内部类也是成员内部类的一种
//2.静态内部类只能访问外部类中的静态变量和静态方法
//如果想要访问非静态的需要创建外部类的对象
//创建静态内部类对象的格式
//外部类名.内部类名 对象名 = new 外部类名.内部类名();
//调用静态方法的格式
//外部类名.内部类名.方法名()
//创建静态内部类的对象
//只要是静态的东西,都可以用类名点直接获取
int a=10;
static int b=20;
static class Inner{
public void show1(){
ABCD abcd=new ABCD();
System.out.println(abcd.a);
System.out.println(b);
}
public static void show2(){
ABCD abcd=new ABCD();
System.out.println(abcd.a);
System.out.println(b);
}
}
}
--------------------------------------------------
public class OuterClass {
private static int staticOuterField = 200;
static class StaticInnerClass {
void display() {
System.out.println("Static outer field value: " + staticOuterField);
}
}
public static void main(String[] args) {
OuterClass.StaticInnerClass inner = new OuterClass.StaticInnerClass();
inner.display();
}
}
//在上面的示例中,StaticInnerClass 是 OuterClass 的一个静态内部类。
//在 main 方法中,我们直接通过 OuterClass.StaticInnerClass 创建了
// StaticInnerClass 的一个对象 inner,而不需要先创建 OuterClass 的对象。
局部内部类:
是定义在一个方法或作用域中的内部类。它与局部变量一样,不能使用访问控制修饰符(public、private和protected)和static修饰符修饰。局部内部类只在当前方法或作用域中有效,并且它可以访问外部类的所有成员,但只能访问当前方法中final类型的参数与变量。这种限制是为了确保局部内部类对象的生命周期与方法的执行期一致,防止在方法执行完毕后,局部内部类对象仍然持有对局部变量的引用,导致内存泄漏。外界无法直接使用,需要在方法内部创建对象并使用。该类可以直接访问外部类的成员,也可以访问方法内的局部变量。
匿名内部类:
匿名内部类是Java中一种特殊的内部类,是没有名字的内部类,它通常用于创建某个接口或类的子类或实现类的对象,而无需显式定义这个子类或实现类。匿名内部类在定义时直接实例化,通常用于一次性的对象创建。
匿名内部类主要用在以下几种情况:
-
实现接口或继承类:当你需要临时实现一个接口或继承一个类,并且这个实现或子类只需要被使用一次时,可以使用匿名内部类。
-
作为方法或构造方法的参数:当需要将一个接口或抽象类的实例作为参数传递给方法时,可以使用匿名内部类来快速创建这个实例。
-
在GUI编程中:在Java Swing等GUI框架中,经常需要为组件添加事件监听器,而这些监听器通常只需要实现一个或少数几个方法,此时可以使用匿名内部类来简化代码。
匿名内部类的基本语法如下:
new 父类构造器(参数列表) | 实现接口() {
// 匿名内部类的类体部分
};
或者
接口 变量名 = new 接口() {
// 实现接口的方法
};
大家可以看看这个博主写的匿名内部类,真的超级 好,很详细的。
需要注意的是,由于匿名内部类没有明确的类名,所以它不能定义构造方法(因为构造方法必须与类名相同)。同时,匿名内部类也不能定义静态成员或静态初始化块。
虽然匿名内部类在某些情况下可以使代码更简洁,但它也可能导致代码的可读性和可维护性降低。因此,在使用匿名内部类时,需要权衡利弊,根据具体情况来决定是否使用。
小练习:
打印a的值
package 内部类;
public class Outer {
private int a = 10;
class Inner {
private int a = 20;
public void show() {
int a = 30;
System.out.println(a);//30
System.out.println(this.a);//20
System.out.println(Outer.this.a);//10
}
}
}
package 内部类;
public class Test {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
内部类的用途
内部类在Java中有多种用途,包括但不限于:
- 实现回调(Callback)或事件监听器(Event Listener)
- 封装“只在一个地方使用”的类
- 实现多重继承的功能(通过内部类继承其他类)
- 实现类型安全的枚举(在Java 5之前)
- 隐藏实现细节,使代码更整洁