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

Java内部类,看这一篇就够了!

闻道梅花坼晓风

雪堆遍满四山中


目录

 内部类的概念

成员内部类

内部类访问外部类

外部类访问内部类

内部类中同名变量的优先级

小结:

静态内部类

内部类访问外部类

 小结:

局部内部类

小结:

匿名内部类

 

 内部类的概念

在 Java 中,我们通常将不同的类组织到一个包下,对于一个包中的类来说,它们是同一个层次,可以说在没有使用继承等条件下,类与类之间是没有联系的。还有一种类,它是定义在另一个类或者一个方法的内部,这样的类叫做内部类。内部类也是封装的一种体现 ~ 

//A是外部类
class A{//B是内部类class B{}
}

注意: 

内部类和外部类共用同一个 java 源文件,但是经过编译之后,内部类会形成单独的字节码文件

一般来说,内部类分为成员内部类、局部内部类、匿名内部类和静态内部类

成员内部类

成员内部类是最普通的内部类,它的定义为位于另一个类的内部,形如下面的形式:

//外部类
class A{public int a = 10;private int b = 20;static int c = 30;//内部类class B{ public int d = 10;}}

看起来 内部类 B 就好像 A 的一个成员,成员内部类可以无限制访问外部类的所有成员属性

 

内部类访问外部类

//外部类
class A{public int a = 10;private int b = 20;static int c = 30;public void PrintA(){System.out.println("PrintA()");}//内部类class B{public int d = 10;void PrintB(){System.out.println("a = "+a);System.out.println("b = "+b);System.out.println("c = "+c);PrintA();}}
}class Test{public static void main(String[] args) {A a = new A();A.B b= a.new B();b.PrintB();}
}

注意:我们要初始化内部类的对象时,必须先初始化外部类的对象,因为内部类是依附于外部类的

不然编译器就会报错

下面这段代码的意思是:先创建 外部类A 的对象a ,再 [.] 符号引用外部类中 内部类B 的成员,最后在初始化内部类 B

        A a = new A();A.B b= a.new B();

 

外部类访问内部类

虽然内部类访问可以随意的访问外部类,但是外部类想要访问内部类可就没那么容易了

我们发现外部类想要访问内部类是不能直接访问的,那该怎么访问呢?---  可以先创建一个成员内部类的对象,再通过这个对象来访问:

//外部类
class A{public int a = 10;private int b = 20;static int c = 30;public void PrintA(){System.out.println("PrintA()");}public void PrintA_B(){B b = new B();System.out.println(b.d);System.out.println("-------------");b.PrintB();}//内部类class B{public int d = 10;void PrintB(){System.out.println("a = "+a);System.out.println("b = "+b);System.out.println("c = "+c);PrintA();}}
}class Test{public static void main(String[] args) {A a = new A();A.B b= a.new B();a.PrintA_B();}
}

 

内部类中同名变量的优先级

如果外部类与内部类相同的属性,如下图中的 a,那么我们调用 PrintB 时访问的是哪个 a 呢?

class A{public int a = 10;class B{public int a = 40;void PrintB(){System.out.println("a = "+a);}}
}class Test{public static void main(String[] args) {A a = new A();A.B b= a.new B();b.PrintB();}
}

所以:如果是同名变量,优先访问内部类中的

问:要是这种情况,该怎么访问外部类中的 a 呢?
 

System.out.println("a = "+ A.this.a);

PrintB 在内部类B中 ,所以 this.a = 当前 内部类B 对象的 this 引用,A.this.a = 外部类A 的 this 引用

这种创建内部类的方式在实际开发中并不常用,因为内部类和外部类紧紧地绑定在一起,使用起来非常不便

小结:

外部类中的任何成员都可以在实例内部类方法中直接访问
实例内部类对象必须在先有外部类对象前提下才能创建
实例内部类的非静态方法中包含了一个指向外部类对象的引用
外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象

 

静态内部类

静态内部类其实就是在原来的内部类的基础上用 “static” 修饰,你看不要小看这个 static,加上后还是有不小的改变的

内部类访问外部类

以上面的代码为例,我们直接给内部类加上 static 修饰后:就不能只能访问外部类非静态成员,原因是静态的 内部类B 没有 外部类A 的 this 引用,那么有没有什么访问的方法呢?

-- 还是与之前一样,创建一个外部类对象,再进行调用

class A{public int a = 10;private int b = 20;static int c = 30;public void PrintA(){System.out.println("PrintA()");}static class B{public int d = 40;void PrintB(){A a1 = new A();System.out.println("a = "+a1.a);System.out.println("b = "+a1.b);System.out.println("c = "+c);System.out.println("d = "+d);a1.PrintA();}}
}class Test{public static void main(String[] args) {A.B b = new A.B();b.PrintB();}
}

     A.B b = new A.B();

生成静态的内部类的时候,不需要外部类的引用,也就是说:我们可以不用先初始化外部类

 小结:

在静态内部类中只能访问外部类中的静态成员
创建静态内部类对象时,不需要先创建外部类对象

局部内部类

局部内部类是定义在一个方法或者一个作用域里面的类,所以局部内部类的生命周期仅限于作用域内

class A {public int a = 0;public void PrintA(){class B {public int b;}}
}

注意,局部内部类就像是方法里面的一个局部变量一样,是不能有 public、protected、private 以及 static 修饰符的

class A {public int a = 10;public void PrintA(){class B {public int b = 20;public void PrintB(){System.out.println("a = "+a);System.out.println("b = "+b);}}B b = new B();b.PrintB();}
}class Test {public static void main(String[] args) {A a = new A();a.PrintA();}
}

切记 ~ 局部内部类只能在当前方法内部使用,出了该方法则不能被使用

小结:

局部内部类只能在所定义的方法体内部使用
不能被 public、protected、private 以及 static 修饰符修饰
编译器也有自己独立的字节码文件,命名格式:外部类名字$数字内部类名字 .class

匿名内部类

匿名内部类应该是平时我们编写代码时用得最多的,尤其是启动多线程的时候,会经常用到,并且 IDEA 也会帮我们自动生成。

 匿名对象一般运用于接口中,请看下面这段代码:

interface A{void Test();
}class Test{public static void main(String[] args) {new A(){@Overridepublic void Test(){System.out.println("Test()");}}.Test();}
}

 

这里相当于一个类实现了这个 A接口 同时重写了 Test() 方法,但是你不知道这个类叫什么,所以这就是匿名对象

[.Test()] 是一种调用方式

匿名内部类的作用主要是用来继承其他类或者实现接口,并不需要增加额外的方法,方便对继承的方法进行实现或者重写


http://www.mrgr.cn/news/27675.html

相关文章:

  • 畅聊未来-- AIGC 的发展方向与趋势
  • 直流保护电路设计及保护器件参数说明和选型
  • LabVIEW弧焊参数测控系统
  • 使用阿里云远程访问 Synology Web Station 的指南
  • Hadoop + Hive + Apache Ranger 源码编译记录
  • ThriveX 博客管理系统前后端项目部署教程
  • synchronized的详解、锁的升级过程和优缺点比较
  • 什么是快充协议,最常见的快充协议有哪些
  • 进程间通信之消息队列详解
  • 个人虚拟物品商城网站源码,后台试Thinkphp6.0开发的,前端是vue的。
  • 三、(JS)JS中常见的表单事件
  • 返回当前栈内最小元素
  • Dubbo SPI源码
  • 面试题总结(三) -- 内存管理篇
  • Java--图书管理系统(新版详细讲解)
  • Scrapy 2.6 Spider Middleware 爬虫页中间件基本使用
  • 基于python+django+vue的学生考勤管理系统
  • 86-java jmap分析内存
  • Java API 之集合框架进阶
  • 24年云南省下半年事业单位少有人知的10个真相
  • 【Android Studio】API 29(即Android 10)或更高版本,在程序启动时检查相机权限,并在未获取该权限时请求它
  • 约瑟夫环和一元多项式修正版
  • 乌俄冲突下AI和计算机的使用
  • protobuf中c、c++、python使用
  • 基于SSM的二手车管理系统的设计与实现 (含源码+sql+视频导入教程)
  • 【C#生态园】深度剖析:C#嵌入式开发工具大揭秘