当前位置: 首页 > news >正文

Java开发 | 内部类 | 静态内部类 | 非静态内部类 | 匿名内部类

目录

1.内部类

1.1内部类的简单创建 

1.2内部类的分类

1.2.1普通内部类

1.2.2静态内部类

1.3匿名内部类

1.4局部内部类

1.内部类

内部类就是一是一个类里面装着另外一个类,就像俄罗斯套娃一样。最外层的类我们叫外部类,内层的类我们叫内部类


1.1内部类的简单创建 

内部类就是一个类中的包含的另外一个类我们称之内部类,内部类外面那个类我们称之为外部类。如以下代码:

//这是一个外部类
class OutClass {//这是一个普通内部类class NeiBuClass {}
}

以上代码中OutClass为外部类,NeiBuClass为内部类。这样的一段代码就构成了一个类包含另一个类,当然你也可以在一个类里面定义多个类。以上是对外部类与内部类的一个简单创建,详细讲解请看下方。


1.2内部类的分类

内部类可分为:静态内部类、实例内部类、匿名内部类、局部内部类。其中的局部内部类是在方法里面定义的类,几乎不用。匿名内部类是没有名称的类,也几乎不用。因此我们今天主要掌握前两种内部类,但后两种我们也会讲到。


1.2.1普通内部类

普通内部类是非静态内部类/实例内部类。它是没有任何修饰符修饰的一个内部类。它的语法格式为: class 类名。如以下代码展示:

//外部类
class OutClass { //普通内部类/非静态内部类class NeiBuClass {}
}

以上代码中OutClass为外部类,NeiBuCass为一个普通内部类,下面我就来讲解它的用法。

class OutClass {public int num1;private int num2;protected int num3;public void fun() {System.out.println("今天过得很开心!");}class NeiBuClass {public void show() {//外部类里的任何属性都内被内部类使用num1 = 1;num2 = 2;num3 = 3;System.out.println(num1+" "+num2+" "+num3);//访问外部类成员方法fun();}}
}
public class Test {public static void main(String[] args) {//实例化内部类前得先实例化外部类OutClass.NeiBuClass neiBuClass = new OutClass().new NeiBuClass();neiBuClass.show();}
}

运行后输出:

通过上述代码,我们可以看到外部类中的成员变量和成员方法都能被我们的普通内部类使用。无论外部类是被public还是private或者protected修饰都能使用。此外,我们在实例化内部类时,必须先实例化外部类。这样才能得到一个内部类引用。

因此我们有一个问题,在我们学习封装的时候知道了一个概念。一个类里面被private修饰的属性,不能在其他类中使用,比如:

class Try1 {private int num = 10;
}
class Try2 {num = 20;
}

报错:

那为什么在外部类与内部类的关系中,我们能使用呢?大家不必惊慌,这是语法所规定的。我们只需要知道这是一个特例就好了,可以放心使用。


注意,当我们外部类与内部类中有相同的属性时,我们优先访问内部类中的属性,如下代码:

class OutClass {//外部类成员变量public int num = 10;//外部类成员变量public void fun() {System.out.println("今天过得很开心!");}class NeiBuClass {//内部类成员变量public int num = 20;//内部类成员方法public void fun() {System.out.println("今天过得不开心!");}public void show() {//优先访问内部类自己的成员System.out.println(num);//优先访问内部类自己的方法fun();}}
}
public class Test {public static void main(String[] args) {//实例化内部类前得先实例化外部类OutClass.NeiBuClass neiBuClass = new OutClass().new NeiBuClass();neiBuClass.show();}
}

运行后输出:

如果我们非得访问外部类中的属性怎么办呢?我们可以用外部类名.this.属性名来访问外部类的属性。如:

class OutClass {public int num = 10;public void fun() {System.out.println("今天过得很开心!");}class NeiBuClass {public int num = 20;public void fun() {System.out.println("今天过得不开心!");}public void show() {//访问了外部类成员变量System.out.println(OutClass.this.num);//访问外部类成员方法OutClass.this.fun();}}
}public class Test {public static void main(String[] args) {//实例化内部类前得先实例化外部类OutClass.NeiBuClass neiBuClass = new OutClass().new NeiBuClass();neiBuClass.show();}
}

运行后输出:

通过以上代码,很好的展示了通过外部类名.this.外部属性名就能访问到外部类中的属性。


那么我们的外部类能不能访问内部类中的成员变量或方法呢?我们来看一组代码:

class OutClass {//外部类成员变量public int num1 = 10;//外部类成员方法public void show() {fun();System.out.println(num2);}class NeiBuClass {//内部类成员变量public int num2 = 20;//内部类成员方法public void fun() {System.out.println("今天过得很开心!");}
}

报错: 

因此,外部类不能直接访问内部类中的属性,如果我们要访问的化,可以创建一个内部类对象。通过引用这个对象就可以访问内部类中的属性,如下代码:

class OutClass {//实例化了内部类的一个对象NeiBuClass neiBuClass = new NeiBuClass();//外部类成员变量public int num1 = 10;//外部类成员方法public void show() {neiBuClass.fun();System.out.println(neiBuClass.num2);}class NeiBuClass {//内部类成员变量public int num2 = 20;//内部类成员方法public void fun() {System.out.println("今天过得很开心!");}}
}public class Test {public static void main(String[] args) {OutClass outClass = new OutClass();outClass.show();}
}

运行后输出:

以上代码展示了,在外部类访问内部类的方法就是实例化内部类出一个对象即可访问内部类属性。

总结

  • 外部类的属性可以在内部类中使用(实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束)
  • 当外部类的属性与内部类中的属性同名时,在内部类中使用该属性时会优先访问内部类中该属性
  • 在内部类中访问同名属性时,可以使用外部类名.this.属性名来访问外部类属性
  • 实例化内部类时,必须先实例化外部类(借助外部类来访问内部类)
  • 外部类不能直接访问内部类中的属性,必须得实例化一个内部类对象才可访问

1.2.2静态内部类

静态内部类是由static修饰的类,它的语法格式为:static class 类名。下面我们来看代码:

//外部类
class OutClass {//静态内部类static class NeiBuClass {}
}

以上代码就是一个静态内部类的创建方式,下面我们来看它的用法。当我们直接在静态内部类访问外部类中的非静态属性时是访问不到的,我们只能访问静态的成员属性。因为静态不依赖于类。

//外部类
class OutClass {//外部类成员public int num1 = 10;private int num2 = 10;protected int num3 = 20;public static int num4 = 30;//静态内部类static class NeiBuClass {public void show() {//num1-num3不能直接访问System.out.println(num1);System.out.println(num2);System.out.println(num3);System.out.println(num4);}}
}

报错:

因此,如果我们要在静态内部类中访问外部类中的非静态属性的话,我们要先实例化一个外部类对象。通过引用来访问外部类中的非静态属性,如以下代码:

//外部类
class OutClass {//外部类成员public int num1 = 10;private int num2 = 20;protected int num3 = 30;public static int num4 = 40;//静态内部类static class NeiBuClass {public void show() {//实例化一个外部类对象OutClass outClass = new OutClass();//通过外部类对象来引用外部类属性System.out.println(outClass.num1);System.out.println(outClass.num2);System.out.println(outClass.num3);System.out.println(num4);}}
}public class Test {public static void main(String[] args) {//创造一个静态内部类对象OutClass.NeiBuClass neiBuClass = new OutClass.NeiBuClass();neiBuClass.show();}
}

运行后输出:

以上代码展示了静态内部类如何访问外部类中的非静态成员。我们在类和对象中学到了,一个类中的静态成员我们可以直接使用类名来访问该成员。因此在上述实例化静态内部类时,我们不用像普通内部类那样得先实例化外部类在实例化内部类。我们直接通过外部类引用静态内部类来创建一个静态内部类对象。


外部类访问静态内部类:

//外部类
class OutClass {//实例化一个惊天内部类对象NeiBuClass neiBuClass = new NeiBuClass();//外部类方法public void show() {System.out.println(neiBuClass.num1);System.out.println(neiBuClass.num2);System.out.println(neiBuClass.num3);neiBuClass.fun();}//静态内部类static class NeiBuClass {//静态内部类中的成员变量int num1 = 1;int num2 = 2;int num3 = 3;//静态内部类中的方法public void fun() {System.out.println("今天天气很糟糕!");}}
}public class Test {public static void main(String[] args) {//实例化一个外部类对象OutClass outClass = new OutClass();//引用外部类中的show方法outClass.show();}
}

运行后输出:

以上代码展示了外部类访问静态内部类属性的方法,就是实例化一个静态内部类对象即可访问。

总结:

  • 静态内部类无法访问外部类中的非静态成员变量或成员方法
  • 静态内部类要访问外部类中非静态属性时可创建一个外部类对象来访问
  • 静态属性不依赖于类,因此可以使用类名来引用静态属性
  • 外部类想访问静态内部类属性时,可以实例化一个静态内部类对象即可访问
  • 静态内部类不能直接实例化,要通过外部类名的引用来实例化

1.3匿名内部类

匿名内部类,简单的来说就是没有类名的内部类。一般在是在接口对象中定义的内部类。

//定义一个名为IUSB的接口
interface IUSB {void show();
}
//Try类使用了这个接口
class Try implements IUSB{//重写了接口中的show方法@Overridepublic void show() {System.out.println("今天你开心吗?");}
}public class Test {public static void main(String[] args) {//new一个接口new IUSB() {@Overridepublic void show() {System.out.println("这就是一个匿名内部类");}}.show();}
}

运行后输出:

以上代码展示了,匿名类内部类的用法。这种内部类我们几乎不用,大家可以看到我们必须在一个接口中定义一个方法,并且要有一个类使用这个接口并实现重载接口中的方法才能达到这个方法的可用性,然后我们再才能new一个接口对象这个对象没有类名没有修饰,这就是匿名内部类。可见这种内部类我们使用的非常之少。


1.4局部内部类

局部内部类是在方法里面的定义的类,例如:

public class Test {//一个名为show的方法public void show() {//这是一个局部内部类class Dog {//局部内部类的成员变量public int num = 10;//局部内部类中的成员方法public void fun() {System.out.println("这是局部内部类中的fun()方法");}}//实例化一个局部内部类对象Dog dog = new Dog();//通过dog引用来方法这两个属性System.out.println(dog.num);dog.fun();}public static void main(String[] args) {//再通过实例化一个主类才能调用show方法Test test = new Test();test.show();}
}

运行后输出:

我们发现,在一个方法里面定义一个类然后去创建一些属性我们还得在这个方法中实例化对象和main方法中实例化对象才能访问到这些属性,真是脱裤子放弃多费手续。因此,这种内部类我们也是不怎么常用的。


好了,今天的博文到这里就结束了,感谢你的阅读。

 下期预告:图书管理系统的实现、通讯录的实现

http://www.lryc.cn/news/42005.html

相关文章:

  • Portal认证
  • 论文解读:ChangeFormer | A TRANSFORMER-BASED SIAMESE NETWORK FOR CHANGE DETECTION
  • Redis 内存优化技巧
  • 【java】笔试强训Day2【​倒置字符串​与排序子序列】
  • 【Linux】基础IO(一) :文件描述符,文件流指针,重定向
  • 【C语言】通讯录的实现(静态版)
  • IDEA一键构建Docker镜像
  • QT的使用3:鼠标事件
  • 线程安全之单例模式
  • “二分”带来“十分”快感——二分思想的奥秘解析
  • 一台服务器最大能支持多少条 TCP 连接?问倒一大片。。。
  • 蓝桥杯嵌入式RTC实时时钟
  • Centos7 挂载 ISO镜像
  • 三级数据库备考--数据库应用系统开发方法第一次练习(刷题库知识点记录)
  • 免费空间主机是什么?怎么申请免费空间主机
  • 网络安全文章汇总导航(持续更新)
  • AI-TestOps —— 软件测试工程师的一把利剑
  • Linux内核进程管理原理详解
  • 通过Linux串口实现树莓派与电脑通信
  • 全球变暖 蓝桥杯 178
  • Java现在好找工作吗?
  • Flink 第1章 基础介绍和特性
  • docker 安装 nginx无坑版
  • 自己动手做chatGPT:向量的概念和相关操作
  • 【洛谷刷题】蓝桥杯专题突破-深度优先搜索-dfs(7)
  • Python嵌套函数(Nested function)和闭包(closure)
  • 【实战】React 必会第三方插件 —— Cron 表达式生成器(qnn-react-cron)
  • C# 教你如何终止Task线程
  • 整合SpringCache
  • 05 - 环境变量编程