目录
内部类
内部类的分类
实例内部类
静态内部类
局部内部类
内部类
什么是内部类:
在Java中,如果一个类可以定义在另一个类的内部,那么就称为内部类。内部类的位置与外部类成员所处位置相同,因此又称作成员内部类。
内部类也是封装的一种体现。
内部类的分类
内部类分为四种:实例内部类(也叫成员内部类)、静态内部类、局部内部类、匿名内部类。
我们先用代码直观感受一下:
package Blog;
public class Test3 {
private int a;
int b;
public int c;
//1.实例内部类:
public class InnerClass1{
//...
}
//2.静态内部类:
static class InnerClass2{
//...
}
//3.局部内部类
//先创建外部类的方法:
public void fun(){
class InnerClass3{
//...
}
}
}
实例内部类
成员内部类,即普通内部类,未被static修饰的内部类。
先来看一段代码1:
package Blog;
class OutClass {
private int a;
int b;
public int c;
public void fun(){
System.out.println("这是一个外部类成员方法");
}
// 1.实例内部类:
public class InnerClass1{
//内部类的成员方法
public void innerFunc1(){
a = 1;
b = 2;
c = 3;
fun(); //内部类调用外部类的成员方法
//内部类调用外部类的成员变量
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
}
}
public class Test{
public static void main(String[] args) {
//实例化一个外部对象
OutClass out = new OutClass();
//通过外部类的对象引用实例化一个内部类对象
OutClass.InnerClass1 inner = out.new InnerClass1();
//内部类对象调用内部类方法
inner.innerFunc1();
}
}
其输出结果如下:
下面我们将一一解析~
通过代码1,我们提出这些疑问和总结:
- 实例内部类所处的位置与外部类成员的位置相同,因此也受访问限定修饰符的约束;
(说明:正如定义中所说,内部类它的位置与外部类中所有成员的位置相同,换言之,内部类的地位与外部类的其他成员一样,所以实例内部类写的时候可以用public、private等修饰)
- 如何创建内部类的对象?
(首先要明白内部类对象是需要外部类对象来引用创建的,所以需要先创建外部类对象)
(以下是两种创建方式):
- 在实例内部类中可以直接访问被任何访问限定符修饰的成员(变量或者方法);
(说明:在上面的代码1中,外部类OutClass中的a,b,c以及 fun方法既有private,也有public,还有默认属性的,但我们通过内部类 InnerClass1中的成员方法 innerFunc1可以将它们全部访问到,甚至可以将变量值改变。)
- 在外部类中不能直接访问实例内部类中的成员,如果要访问必须先创建内部类的对象;
(说明:比如上述代码1中,main方法里创建了一个内部类对象inner,通过内部类对象调用内部类函数innerFunc1)
- 如果外部类与实例内部类存在相同名的成员变量会发生什么?
(说明:一般不加修饰的情况下,内部类优先访问的是其自己的)
- 在此基础上,如果我们非要访问外部类中的成员变量b,该怎么做呢?
(说明:外部类名称.this.变量名)即:
(其实外部类与内部类存在相同名的变量这样的操作并无多大意义~)
以上便是实例内部类的重点知识,这里还有一点需要注意:
实例化内部类中不能定义static静态属性的成员:
因为实例内部类的实例化过程需要外部对象的引用,但是static是类的属性,不属于某个对象,不存储在某个对象的空间中,是先加载后运行的,因此static的时机优于类的时机,即先执行static再实例化对象。
若非要在其内部定义一个静态的成员,可以在static后面加上一个“final”关键字,这样可以让变量成为常量,这样一来在程序编译时该成员已经有值了。
其次还需要注意一个细节:final一旦初始化了就不能改变了,并且一般常量名为大写;
静态内部类
被static修饰的内部成员类。
依旧先看一段代码2:
package Blog;
class OutClass2{
public int a = 1;
int b = 2;
static int c = 3;
static int d = 4;
//静态内部类:
static class InnerClass2{
public void show(){
/* //静态内部类访问外部类中非静态成员——error
System.out.println(a);
System.out.println(b);*/
//静态内部类访问外部类中静态成员
System.out.println("c = "+c);
System.out.println("d = "+d);
}
}
}
public class Test2 {
public static void main(String[] args) {
//创建静态类的对象
OutClass2.InnerClass2 inner2 = new OutClass2.InnerClass2();
inner2.show();
}
}
输出:
通过代码2,我们提出这些疑问和总结:
- 如何创建静态内部类对象?
(说明:直接通过外部类名的引用来创建,这里不需要先创建外部对象)
- 一般情况下静态内部类中只能访问外部类中的静态成员
(说明:在上述代码2中,a和b均属于非静态变量,所以想要在静态内部类中直接访问是做不到的)
- 如果非要访问外部类中的非静态成员该怎么做?
(说明:通过外部类对象来引用)
局部内部类
定义在外部类的方法体中或{}中,该种内部类只能在其定义的位置使用。一般使用的非常少,因为它的范围较为局限。
先看代码3:
package Blog;
class OutClass3{
public int a;
private int b;
int c;
//局部内部类
public void fun3() {
class InnerClass3 {
public void show() {
a = 1;
b = 2;
c = 3;
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println("调用了一个局部内部类");
}
}
InnerClass3 inner3 = new InnerClass3();
inner3.show();
}
}
public class Test3 {
public static void main(String[] args) {
OutClass3 out3 = new OutClass3();
out3.fun3();
}
}
输出结果:
通过代码3,我们提出这些疑问和总结:
- 局部内部类不能被public、static等修饰,因为其属于自身方法的;
- 局部内部类只能在其所在方法内部使用;
(说明:在上述代码3中,若想脱离fun3方法来引用InnerClass3类是不能实现的)