1.1、前言
1.1.1、说明
在一次偶然工作中,发现对类中的内部类和静态内部类的相关知识点有些不明确,因此通过本文章对相关知识点进行一个学习,如果有存在问题,欢迎指出纠正。
1.1.2、参考文章
1.1.3、示例代码
后续文章会对如下的代码进行引用说明,方便理解
// 外部类
class Banana {
// 外部类的私有属性
private String privateAttr;
// 外部类的共有属性
public String publicAttr;
// 外部类静态属性
public static String publicStaticAttr = "静态属性";
// 构造方法
public Banana() {
System.out.println("外部类的构造器被调用");
this.privateAttr = "外部类私有属性";
this.publicAttr = "外部类共有属性";
}
// 外部类的私有方法
private void privateMethod(){
System.out.println("外部类的私有方法被调用");
}
// 外部类的共有方法
public void publicMethod(){
System.out.println("外部类的公有方法被调用");
}
// 外部类的静态方法
public static void publicStaticMehtod(){
System.out.println("外部类的静态方法被调用");
}
// 内部类
class InnerBanana {
// 内部类私有属性
private String privateInnerAttr;
// 内部类共有属性
public String publicInnerAttr;
// 内部类构造方法
public InnerBanana() {
System.out.println("内部类InnerBanana的构造器被调用");
this.privateInnerAttr = "内部类InnerBanana私有属性";
this.publicInnerAttr = "内部类InnerBanana共有属性";
}
// 内部类共有方法
public void publicInnerMethod(){
System.out.println("内部类innerBanana的共有方法publicInnerMethod被调用");
// 打印外部类的共用属性(Banana.this可以简写省略,如Banana.this.publicAttr直接写为publicAttr)
System.out.println(publicAttr);
// 打印外部类的私有属性
System.out.println(privateAttr);
// 调用外部类的共有方法
publicMethod();
// 调用外部类的私有方法
privateMethod();
}
// 内部类私有方法
private void privateInnerMethod(){
System.out.println("内部类innerBanana的私有方法privateInnerMethod被调用");
}
}
// 静态内部类
static class InnerStaticBanana {
// 静态内部类类私有属性
private String privateInnerStaticname;
// 静态内部类类共有属性
private String publicInnerStaticname;
// 静态内部类构造方法
public InnerStaticBanana() {
System.out.println("静态内部类InnerStaticBanana的构造器被调用");
this.privateInnerStaticname = "静态内部类InnerStaticBanana私有属性";
this.publicInnerStaticname = "静态内部类InnerStaticBanana共有属性";
}
// 静态内部类共有方法
public void publicInnerStaticMethod() {
System.out.println("静态内部类innerStaticBanana的共有方法publicInnerMethod方法被调用");
// 打印外部类静态属性
System.out.println(Banana.publicStaticAttr);
// 调用外部类静态方法
Banana.publicStaticMehtod();
}
// 静态内部类私有方法
private void privateInnerStaticMethod() {
System.out.println("静态内部类innerStaticBanana的私有方法privateInnerMethod方法被调用");
}
public static void publicStaticInnerStaticMethod() {
// 打印外部类静态属性
System.out.println(Banana.publicStaticAttr);
// 调用外部类静态方法
Banana.publicStaticMehtod();
}
}
}
1.2.2、为什么内部类又要分成静态和非静态
1、非静态内部类(内部类, inner classes)
非静态内部类是属于外部类实例的一部分(即不能够自己独立,以外部类的对象实例存在为前提),它可以访问外部类的所有成员(包括私有的属性和方法),并且可以与外部类实例相互直接访问。
特点:
- 使用外部类的实例化对象(Banana.this),在内部类中访问外部类的成员(包括私有成员)和方法(包括私有方法)
- 内部类可以实现接口、继承其他类,并且可以被其他类继承或实现
- 内部类需要与外部类实例产生强耦合关系(即内部类不能够自己独立,以外部类的对象实例存在为前提)
2、静态内部类(静态嵌套类, static nested classes)
静态内部类与外部类实例无关,它可以直接访问外部类的静态成员,但不能直接访问外部类的非静态成员。
特点:
-
将一个类嵌套在另一个类中,使得两个类的关系更加紧密
-
可以实现逻辑上的分组,提高代码的结构性和可读性
-
静态内部类可以直接访问外部类的静态成员(属性和方法),但无法访问非静态成员
-
静态内部类可以作为外部类的静态成员,可以通过外部类名直接访问
-
静态内部类可以完全独立存在,可以在不创建外部类的实例的情况下使用,只是借外部类的“壳”一用,来隐藏自己
3、补充
不存在静态类的概念,如下这种写法是不合法的
static class staticBanana {
}
4、总结
根据Oracle官方的说法:
Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are called static nested classes. Non-static nested classes are called inner classes.
从字面上看,一个被称为静态嵌套类,一个被称为内部类。
从字面的角度解释是这样的:
什么是嵌套?嵌套就是我跟你没关系,自己可以完全独立存在,但是我就想借你的壳用一下,来隐藏一下我自己(真TM猥琐)。
什么是内部?内部就是我是你的一部分,我了解你,我知道你的全部,没有你就没有我。(所以内部类对象是以外部类对象存在为前提的)
作者:昭言
链接:https://www.zhihu.com/question/28197253/answer/39814613
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
1.2.3、具体说明
1、内部类和静态内部类的实例化方式
内部类的实例化
Banana.InnerBanana innerBanana = new Banana().new InnerBanana();
说明:this$0
是内部类中的一个隐含字段,用于表示内部类实例所属的外部类实例。它是编译器生成的一个字段,用于在内部类中获取对外部类实例的引用。
静态内部类的实例化
Banana.InnerStaticBanana innerStaticBanana = new Banana.InnerStaticBanana();
2、内部类访问外部类的成员
对内部类的私有方法进行修改
// 内部类
class InnerBanana {
// 内部类私有属性
private String privateInnerAttr;
// 内部类共有属性
public String publicInnerAttr;
// 内部类构造方法
public InnerBanana() {
System.out.println("内部类InnerBanana的构造器被调用");
this.privateInnerAttr = "内部类InnerBanana私有属性";
this.publicInnerAttr = "内部类InnerBanana共有属性";
}
// 内部类共有方法
public void publicInnerMethod(){
System.out.println("内部类innerBanana的共有方法publicInnerMethod被调用");
// 打印外部类的共用属性(Banana.this可以简写省略,如Banana.this.publicAttr直接写为publicAttr)
System.out.println(Banana.this.publicAttr);
// 打印外部类的私有属性
System.out.println(privateAttr);
// 调用外部类的共有方法
Banana.this.publicMethod();
// 调用外部类的私有方法(省略获取外部类的实例Banana.this)
privateMethod();
}
// 内部类私有方法
private void privateInnerMethod(){
System.out.println("内部类innerBanana的私有方法privateInnerMethod被调用");
}
}
在测试类中进行调用
Banana.InnerBanana innerBanana = new Banana().new InnerBanana();
innerBanana.publicInnerMethod();
运行结果
外部类的构造器被调用
内部类InnerBanana的构造器被调用
内部类innerBanana的共有方法publicInnerMethod被调用
外部类共有属性
外部类私有属性
外部类的公有方法被调用
外部类的私有方法被调用
3、静态内部类访问外部类的静态属性和静态方法
在外部类中定义一个静态属性和静态方法
// 外部类
class Banana {
// 外部类静态属性
public static String publicStaticAttr = "静态属性";
// 外部类的静态方法
public static void publicStaticMehtod(){
System.out.println("外部类的静态方法被调用");
}
// 其他内容在这里省略
}
修改静态内部类共有方法
// 静态内部类共有方法
public void publicInnerStaticMethod() {
System.out.println("静态内部类innerStaticBanana的共有方法publicInnerMethod方法被调用");
// 打印外部类静态属性
System.out.println(Banana.publicStaticAttr);
// 调用外部类静态方法
Banana.publicStaticMehtod();
}
在测试类中进行调用
Banana.InnerStaticBanana innerStaticBanana = new Banana.InnerStaticBanana();
innerStaticBanana.publicInnerStaticMethod();
运行结果
静态内部类InnerStaticBanana的构造器被调用
静态内部类innerStaticBanana的共有方法publicInnerMethod方法被调用
静态属性
外部类的静态方法被调用
当然,我们也可以在今天内部类中通过静态方法去调用外部类的静态属性和方法,在静态内部类中定义一个静态方法
public static void publicStaticInnerStaticMethod() {
// 打印外部类静态属性
System.out.println(Banana.publicStaticAttr);
// 调用外部类静态方法
Banana.publicStaticMehtod();
}
调用
Banana.InnerStaticBanana.publicStaticInnerStaticMethod();
运行结果
静态属性
外部类的静态方法被调用