目录
一、什么是内部类
一个类在另一个类的内部,这个就叫内部类。
如下图,InnerClass 类就是内部类,而 OuterClass 类就叫外部类
二、内部类简单介绍
在Java中,可以将一个类定义在另一个类或者一个方法的内部,前者为内部类,后者为外部类。
内部类是封装的一种体现
创建内部类时,我们要明确两点:
1.定义在class 类名{} 花括号外部的,即使是在一个文件夹里,都不能称为内部类!!
class OuterClass{ class InnerClass{ } } public class Demo3 { }
OuterClass 和 Demo3 彼此互相独立,不能为对方的内部类
2.内部类和外部类共用一个java 源文件,但是经过编译之后,内部类会形成单独的字节码文件。
内部类生成的字节码文件名:外部类$内部类.class
同时,内部类类型可以分为四种,分别为 实例内部类、静态内部类、本地内部类 (了解)、匿名内部类 ,下面我将依依为大家介绍。
三、实例内部类
实例内部类是内部类中比较普通的,如下类型就是实例内部类
class Out{
//实例内部类
class Inner{
}
}
(1)实例内部类的成员变量和方法的构建
跟普通类的一样,实例内部类也能构建自己的成员变量和方法(包括构造方法)
class Out{
class Inner{
public int data2 = 3;
private int data3 = 4;
public void Inner(){
System.out.println("实例内部类的构造方法");
}
public void InnerFunc(){
System.out.println("实例内部类的普通方法");
}
}
}
需要注意:
① 在实例内部类中,不能构建静态的成员变量,要想构建静态的成员变量,必须加 final
② 在实例内部类中,不能构建静态的成员方法,就算加 final 也不行!!
(2)实例内部类在类外创建
由于内部类的特殊性,不能用类名实例化对象!!必须要借助外部类的实例化对象辅助,如下
外部类.内部类 变量名 = 外部类实例.new 内部类;
class Out{
class Inner{
public int data2 = 3;
public void Inner(){
System.out.println("实例内部类的构造方法");
}
public void InnerFunc(){
System.out.println("实例内部类的普通方法");
}
}
}
public class Demo2 {
public static void main(String[] args) {
Out out = new Out();
Out.Inner inner = out.new Inner();
//也可以写为 Out.Inner inner = new Out().new Inner();
inner.InnerFunc();
System.out.println(inner.data2);
}
}
为什么要借助外部类对象才能实例化内部类?
我们可以把内部类Inner 当成外部类 Out 的一个实例成员,实例成员的调用都是依赖对象的。这也就是为啥要有 外部类对象才能获取 实例内部类的原因。
注意:
在外部类的方法中,能直接用内部类实例化成员变量,不必再借用外部类的实例化对象
class Out{
class Inner{
public void Inner(){
System.out.println("实例内部类的构造方法");
}
public void InnerFunc(){
System.out.println("实例内部类的普通成员方法");
}
}
// 外部类 的成员方法
public void Func(){
Inner inner = new Inner();
inner.InnerFunc();
}
}
(3)在内部类访问外部类的成员变量
在内部类中可以访问外部类的成员变量
例如:
class Out{
public int data1 = 1;
private int data2 = 2;
class Inner{
public int data3 = 3;
private int data4 = 4;
public void InnerFunc(){
System.out.println(data1);
System.out.println(data2);
System.out.println(data3);
System.out.println(data4);
}
}
}
在内部类中访问外部类的成员变量都几条规则需要大家掌握:
① 当实例内部类的成员变量跟外部类的成员变量同名时,按就近原则访问
class Out{
public int data1 = 1;
class Inner{
public int data1 = 11;
public void InnerFunc(){
System.out.println(data1);
}
}
}
② 访问同名的外部类成员变量 需要外部类名+this才能访问 Out.this.data1
class Out{
public int data1 = 1;
class Inner{
public int data1 = 11;
public void InnerFunc(){
System.out.println(data1);
System.out.println("外部类的data1:"+Out.this.data1);
}
}
}
③ 访问静态同名的外部类成员变量 需要外部类 才能访问 Out.data2
class Out{
public int data1 = 1;
public static int data2 = 2;
class Inner{
public int data1 = 11;
public static final int data2 = 22;
public void InnerFunc(){
System.out.println(data2);
System.out.println("外部类的data2:"+Out.data2);
}
}
}
(4)总结 ![](https://img-blog.csdnimg.cn/0425fc9ebc05491cbfbf20f182a6a5e5.png)
四、静态内部类
被 static 修饰的内部成员类称为静态内部类
class Out{
//静态内部类
static class Inner{
}
}
(1)静态内部类的成员变量和方法的构建
跟实例内部类类似,静态内部类也可以创建成员变量和方法,唯一不同的是,静态内部类可以创建静态的方法和 静态的成员变量!!
静态内部类中的静态成员变量可以不被 final 修饰
class Out{
//静态内部类
static class Inner{
public int data1 = 1;
private int data2 = 2;
public static int data3 = 3;
public void Inner(){
System.out.println("静态内部类的构造方法");
}
public void func1(){
System.out.println("静态内部类的普通方法");
}
public static void func2(){
System.out.println("静态内部类的静态方法");
}
}
}
(2)静态内部类在实外创建
由于静态内部类是静态的,不依赖与外部类实例化对象,所以实例化就不需要创建外部类对象!!
外部类.内部类 变量名 = new 外部类.内部类;
class Out{
//静态内部类
static class Inner{
public void Inner(){
System.out.println("静态内部类的构造方法");
}
public void func1(){
System.out.println("静态内部类的普通方法");
}
public static void func2(){
System.out.println("静态内部类的静态方法");
}
}
}
public class Demo2 {
public static void main(String[] args) {
Out.Inner inner = new Out.Inner();
inner.func1();
}
}
注意:在外部类中,实例化静态内部类也是直接用类名实例化!
(3)在静态内部类中访问外部类成员变量
注意:在静态内部类中不能直接方法外部类中非静态的成员变量
class Out{
public int data1 = 1;
private int data2 = 2;
public static int data3 = 3;
//静态内部类
static class Inner{
public int data4 = 4;
private int data5 = 5;
public static int data6 = 6;
public void Inner(){
System.out.println("静态内部类的构造方法");
}
public void func1(){
System.out.println("静态内部类的普通方法");
System.out.println("外部类中静态成员变量 data3:"+data3);
System.out.println(data4);
System.out.println(data5);
System.out.println(data6);
}
}
}
① 在静态内部类中访问外部类非静态的成员变量
因为静态内部类是静态的,不依赖于外部类对象,所以我们要想在静态内部类中访问,就要构建一个外部类对象。
class Out{
public int data1 = 1;
private int data2 = 2;
public static int data3 = 3;
//静态内部类
static class Inner{
public void Inner(){
System.out.println("静态内部类的构造方法");
}
public void func1(){
Out out = new Out();
System.out.println("外部类非静态成员变量 data1:"+out.data1);
System.out.println("外部类非静态成员变量 data2:"+out.data2);
}
}
}
(4)总结
五、局部内部类
局部内部类是在方法内部定义的内部类
public class Demo3 {
public void Func(){
/**
* 局部内部类
* 不能被 public static 修饰
*/
class Inner{
}
}
public static void main(String[] args) {
}
}
注意:
① 局部内部类只能在所定义的方法体内部使用
② 不能被public、static等修饰符修饰
③ 因为局部内部类局限性很大,所以平时很少用
六、匿名内部类
匿名类是一个没有类名的特殊内部类,也叫匿名内部类,适合于只使用一次的类。创建匿名内部类是须继承一个已有的父类或则实现一个接口。
new 父类名/接口名(){
//类体
};
(1)静态内部类在实外创建
因为匿名内部类既是一个类的定义,同时它本身也是一个对象,在类外创建是可以使用该继承的父类名或实现的接口名接收!
父类名/接口名 变量名 = new 父类名/接口名(){
//类体
};
① 继承父类实现内部类
匿名内部类继承的父类可以是 普通类 也可以是 抽象类!
class B{
public void func2(){
};
}
abstract class C{
abstract void func3();
}
public class Demo1 {
public static void main(String[] args) {
B b = new B(){
public void func2(){
System.out.println("继承普通类的匿名内部类");
};
};
C c = new C() {
@Override
void func3() {
System.out.println("继承抽象的匿名内部类");
}
};
b.func2();
c.func3();
}
}
② 实现接口创建内部类
interface A{
public abstract void func1();
}
public class Demo1 {
public static void main(String[] args) {
A a = new A() {
@Override
public void func1() {
System.out.println("实现接口的匿名内部类");
}
};
a.func1();
}
}
这里创建内部类的过程类似于,一个类实现了A接口,这不过这个类是没有名字的。
(2)匿名内部类的成员变量和方法的构建
匿名内部类由于本身没有名字,所以就不存在构造方法,同时也不能包含静态的成员!!但是普通的成员直接可以创建
A a = new A() {
public int data1 = 1;
@Override
public void func1() {
System.out.println("实现接口的匿名内部类");
}
public void func2(){
System.out.println("匿名内部类的普通方法");
}
};
注意:匿名内部类中可以有许多方法,但是在类外只能调用重写的方法!!
简而言之就是,与 继承的父类 或 实现的接口中方法 同名的,匿名内部类才能调用
(3)匿名内部类访问外部类的成员变量和局部变量
在匿名内部类中,可以直接访问外部类的静态成员变量和局部变量!
非静态成员变量需要构建外部类实例才能访问
interface A{
void func();
}
public class Out {
public static int data1 = 1;
public int data2 = 2;
private int data3 = 3;
public static void main(String[] args) {
String name ="威威";
A a = new A() {
@Override
public void func() {
System.out.println(name);
System.out.println(data1);
Out out = new Out();
System.out.println(out.data2);
System.out.println(out.data3);
}
};
a.func();
}
}
注意:外部其他类不能访问匿名内部类,因为匿名内部类实际上就是一个局部变量!!
(4)总结
以上就是内部类的讲解,有错误的地方希望大家能批评指正,别忘了点赞👍+收藏⭐️哦
😜 关注我!带来等多精彩🎉🎉