一、嵌套类入门
1.1概述
Java嵌套类是指在一个类中定义另一个类的一种方式,它可以提高代码的可读性、可维护性和封装性。Java嵌套类分为两种类型:静态嵌套类和非静态嵌套类。
静态嵌套类:Static nested classes,即类前面有static修饰符
非静态嵌套类:Non-static nested classes, 又名内部类,Inner classes
- 普通内部类(亦翻译为:成员内部类)
- 局部内部类(Local classes)
- 匿名内部类(Anonymous classes)
1.2嵌套类的分类
静态嵌套类
普通内部类
局部内部类
匿名内部类
1.3使用原因
- 不同的访问权限要求,更细粒度的访问控制
- 简洁,避免过多的类定义
- 语言设计过于复杂,较难学习和使用
二、匿名内部类和局部内部类
2.1 匿名内部类
匿名内部类是一种没有名字的内部类,它通常用来实现接口或继承抽象类,并且只使用一次。匿名内部类的本质是一个带具体实现的父类或者父接口的匿名的子类对象。匿名内部类可以使你的代码更加简洁,你可以在定义一个类的同时对其进行实例化。
一没有类名的内部类,必须继承一个父类/实现一个父接口
一在实例化以后,迅速转型为父类/父接口
一这种类型的对象,只能new一个对象,之后以对象名字操作
一可在普通语句和成员变量赋值时使用内部类
interface MyInterface {
void display();
}
class OuterClass {
public void test() {
// 使用匿名内部类实现接口
MyInterface obj = new MyInterface() {
@Override
public void display() {
System.out.println("我是匿名内部类");
}
};
// 调用接口方法
obj.display();
}
}
package org.example;
public class Outer1 {
private String name = "abc";
//匿名内部类
public void fl()
{
String name = "def"; // 加上 final 修饰符
Runnable r = new Runnable() {
//匿名内部类不能定义静态变量,除非是常量
public final static int a = 1; // 加上 final 修饰符并赋值
public void run(){
System.out.println("hello " + Outer1.this.name); // 加上 Outer1.this.
};
};
//静态方法不能在匿名内部类定义
// public void static f2{
//
// }
new Thread(r).start();
System.out.println(r.getClass().getName());
Runnable r2 = new Runnable() { // 加上 new Runnable()
String name = "def";
public void run(){
System.out.println("hello " + name);
};
};
new Thread(r2).start();
System.out.println(r2.getClass().getName());
}
public static void main(String[] args) {
Outer1 obj = new Outer1(); // 创建外部类对象
obj.fl(); // 调用外部类方法
// 调用r2对象
}
}
2.2局部内部类
package org.example;
public class Outer2 {
private String name = "abc";
// 局部内部类
public void fl() {
String name = "def";
class Inner2 {
final static int a = 1;
String name = "ghi";
public void f2() {
System.out.println(name); // 输出 ghi
System.out.println(Outer2.this.name);
}
}
Inner2 obj1 = new Inner2();
obj1.f2();
System.out.println(obj1.getClass().getName()); // 输出 Outer2$1Inner2
}
public static void f2() {
String name = "def";
class Inner2 {
public void f2() {
System.out.println(name); // 输出 ghi
//System.out.println(Outer2.this.name);
}
}
Inner2 obj1 = new Inner2();
obj1.f2();
System.out.println(obj1.getClass().getName()); // 输出 Outer2$1Inner2
}
public static void main(String[] args) {
Outer2 obj = new Outer2(); // 创建外部类对象
obj.fl(); // 调用外部类方法
f2(); // 调用外部类静态方法
}
}
2.3异同
匿名内部类和局部内部类的相同点是:
- 匿名内部类和局部内部类都是在方法中定义的内部类,它们都只能在该方法中使用,不能在其他地方访问。
- 匿名内部类和局部内部类都可以访问外部类的成员,但是如果要访问方法中的局部变量,那么该局部变量必须用final修饰。
匿名内部类和局部内部类的主要区别是:
- 匿名内部类没有名字,而局部内部类有名字。
- 匿名内部类只能创建一次对象,而局部内部类可以在方法中创建多个对象。
- 匿名内部类通常用来实现接口或继承抽象类,并且只使用一次。局部内部类可以继承或实现任意的类或接口。
- 匿名内部类的语法格式是:new 类名或者接口名(){ 重写方法; }。局部内部类的语法格式是:class 类名{ 成员; }
三·、 普通内部类和静态嵌套类
3.1普通内部类
class OuterClass {
private int data = 10;
public void test() {
System.out.println("我是外部类成员方法");
}
class InnerClass {
// 访问外部类的私有数据成员
void getData() {
System.out.println("data is " + data);
}
// 访问外部类的成员方法
void getTest() {
OuterClass.this.test();
}
}
}
public class Test {
public static void main(String[] args) {
// 创建外部类对象
OuterClass myOuter = new OuterClass();
// 创建内部类对象
OuterClass.InnerClass myInner = myOuter.new InnerClass();
// 调用内部类方法
myInner.getData();
myInner.getTest();
}
}
3.2 静态嵌套类
静态嵌套类有以下几个特点:
- 静态嵌套类是外部类的静态成员,它可以直接使用外部类名.静态嵌套类名来访问自身
- 静态嵌套类不能访问外部类的非静态成员,它只能通过对象引用来使用它们。
- 静态嵌套类可以使用private、public、protected或包私有的访问权限修饰符。
- 静态嵌套类在行为上就是一个顶级类,只是为了方便打包而放在外部类中
class OuterClass {
private static int data = 10;
public static void test() {
System.out.println("我是外部类静态方法");
}
static class StaticNestedClass {
// 访问外部类的静态数据成员
void getData() {
System.out.println("data is " + data);
}
// 访问外部类的静态方法
void getTest() {
OuterClass.test();
}
}
}
public class Test {
public static void main(String[] args) {
// 创建静态嵌套类对象
OuterClass.StaticNestedClass myNested = new OuterClass.StaticNestedClass();
// 调用静态嵌套类方法
myNested.getData();
myNested.getTest();
}
}