Java中的内部类你了解吗
作者:哈哈怪.... 发布时间:2022-12-11 08:29:10
成员内部类
1.定义
成员内部类是直接定义在类中,不加任何修饰符的(特指不加static修饰的)的内部类,可以类比着成员变量来理解,如下面这个代码段中的Inn类就是一个成员内部类
public class Inner1 {
private String o = "外部类属性";
public class Inn{
private String i = "成员内部类属性";
}
}
2.成员内部类的使用规则
内部类可以直接的访问外部类的成员变量,但是因为内部类也是一个类,所以外部类必须通过内部类的对象才能访问内部类的成员变量
内部类就相当于外部类的成员变量,故而内部类与外部类之间可以方便的相互访问,包括privte权限修饰的属性和方法
成员内部类可以实现“曲线救国”,通过多个内部类继承别的类,变相的实现多继承
//成员内部类
public class Inner1 {
// 外部类的私有属性o
private String o = "外部类属性";
public class Inn{
// 内部类的私有属性i
private String i = "成员内部类属性";
private void Itest(){
// 内部类直接访问外部类的属性,包括私有属性
System.out.println(o);
}
}
public void Otest(){
// 外部类则要先创建内部类的对象再访问其成员变量,这里注意,也可以访问其私有属性
Inn in = new Inn();
in.Itest();
System.out.println(in.i);
}
public static void main(String[] args) {
Inner1 i1 = new Inner1();
i1.Otest();
}
}
3.成员内部类对象的创建:
外部类的内部创建:与正常类的对象创建方法一样,
内部类名称 对象名 = new 类名()
public class Inner1 {
private String str1 = "外部类";
// 外部类内部创建内部类对象
Inn i1 = new Inn();
private class Inn{
private String str2 = "内部类";
}
}
外部类的外部创建:成员内部类就相当于是外部类的一个特殊的成员变量,故而,我们知道,成员内部类依赖于外部类的存在而存在,也就是说,必须先有外部类的对象才能创建成员内部类的对象
外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称()
当前,在外部类的外部创建内部类对象时,前提也需得内部类对外部类的外部是可见的
如下图, 内部类为private,在外部类的外部无法创建该对象
修改内部类访问权限为public时正确创建 :
public class Inner1 {
private String str1 = "外部类";
// 外部类内部创建内部类对象
Inn i1 = new Inn();
public class Inn{
private String str2 = "内部类";
}
}
class Test{
// 外部类的外部创建外部类的内部类对象
Inner1.Inn i2 = new Inner1().new Inn();
}
4.内部类与静态域
成员内部类可以访问外部类的静态域,但是自己不能定义静态变量(成员内部类是依赖于外部类的,如果它自己能定义静态变量,没有外部对象也能访问了,失去其意义)
外部类中的静态方法也不能使用成员内部类(相当于在静态变量中调用成员变量,是不可行的)。
为此,特别注意,main方法就是static方法,故而不能直接在外部类的main方法中创建内部类对象,要借助外部类才能创建
public class Inner1 {
private String str1 = "外部类";
// 外部类内部创建内部类对象
Inn i1 = new Inn();
public class Inn{
private String str2 = "内部类";
}
public static void main(String[] args) {
// main中创建
Inner1.Inn inn = new Inner1().new Inn();
System.out.println(inn.str2);
}
}
静态内部类:
1.定义:
静态内部类也是定义在类中,但是与成员内部类不同的是,它用static修饰,是静态内部类,可类比静态变量进行理解
static修饰,所以它无需依赖外部类对象,我们可以把它看作一个普通类
public class Inner2 {
private String str1 = new String("外部");
// 静态内部类
public static class Inn{
private String str2 = new String("静态内部");
}
}
2.静态内部类的使用规则:
静态内部类不能直接访问外部类的普通成员变量 (普通成员变量有对象才能访问,所以static不能访问普通的成员变量),当然,可以通过new一个外部类的对象来达到访问外部类成员变量的目的
public class Inner2 {
private String str1 = new String("外部");
private static String str3 = new String("外部静态属性");
// 静态内部类
public static class Inn {
private String str2 = new String("静态内部");
public void fun(){
// 静态内部类不能直接访问外部类的普通成员变量
System.out.println(str1);
// 但可以通过new一个外部类对象访问
Inner2 i2 = new Inner2();
System.out.println(i2.str1);
// static家族互通
System.out.println(str3);
}
}
}
但是,静态内部类虽然不能直接访问外部类的成员变量,但是是可以拥有自己的普通成员变量 的
3.静态内部类对象的创建
外部类内部:和普通类的用法相同 ,且不同于成员内部类,在静态内部类这里,外部类的静态方法中是可以创建静态内部类的对象(static家族互访),当然,没有对象都可以,那么,外部类的成员方法中也是可以创建静态内部类对象的
内部类名称 对象名 = new 类名()
public class Inner2 {
private String str1 = new String("外部");
// 静态内部类
public static class Inn{
private String str2 = new String("静态内部");
}
// 直接在类的内部创建静态内部类的对象
Inn i = new Inn();
public static void main(String[] args) {
// 外部类的静态方法中创建使用静态内部类的对象
Inn inn = new Inn();
}
}
外部类的外部:
外部类名称.内部类名称 对象名 = new 外部类名称. 内部类名称()
public class Inner2 {
private String str1 = new String("外部");
// 静态内部类
public static class Inn {
private String str2 = new String("静态内部");
}
}
class Test{
// 外部类的外部创建静态内部类的对象
Inner2.Inn i = new Inner2.Inn();
}
成员内部类 VS 静态内部类
成员内部类可以访问外部类的成员域和静态域,但是不能拥有自己的静态域
静态内部类不可以直接访问外部类的成员域,但可以拥有自己的成员域,另外,static家族互访,随意
方法内部类:
1.定义:
直接定义在方法内部,不允许使用任何修饰符修饰(包括访问权限修饰符,static等),对外部完全隐藏,出了这个方法,这个类就没有了,可以类比局部变量进行理解
2.方法内部类的使用规则:
除了无法定义static域外,和成员内部类基本一样,这里不再赘述
3.注意形参的使用
方法内部类中若使用了方法的形参, 该形参为隐式的final声明(JDK8之前,必须手动显式定义为final ,但JDK8以后,直接隐式一定为final)
如下面这个例子:
public class Inner3 {
public void fun(int num){
// 方法内部类
class Inn{
public void test(){
// 将下面这行代码注释掉,num正常可作运算
// System.out.println(num);
}
}
num ++;
System.out.println(num);
}
public static void main(String[] args) {
Inner3 i3 = new Inner3();
i3.fun(3);
}
}
但如果我们的方法内部类使用了方法的形参,编译报错
匿名内部类(函数式编程)
是方法内部类的特殊版本,直接不写类名称
遵从方法内部类的所有要求
默认会继承一个类或实现一个接口,继承类一般是继承抽象类
通常是在传参的过程中使用该类,可以简化写法
如之前我们写的接口传参:
public class Inner4 {
public static void fun(MessageImpl m) {
m.printMessage();
}
public static void main(String[] args) {
MessageImpl l = new MessageImpl();
fun(l);
}
}
interface IMessage {
void printMessage();
}
class MessageImpl implements IMessage {
public void printMessage() {
System.out.println("aaa");
}
}
使用匿名内部类可以这样写:
public class Inner4 {
public static void fun(IMessage m ){
m.printMessage();
}
public static void main(String[] args) {
// 匿名内部类
fun(new IMessage() {
@Override
public void printMessage() {
System.out.println("aaa");
}
});
}
}
interface IMessage {
void printMessage();
}
最后,重点掌握成员内部类与静态内部类,以及二者使用区别。
来源:https://blog.csdn.net/m0_58652786/article/details/122641307


猜你喜欢
- 这个东西我已经用了有段时间了,从开始写文章就在用这个,主要原因还是因为我比较懒。懒得去寻找图片,同时又怕万一惹来版权争议。。。跟我所有的文章
- 周末这天手痒,正好没事干,想着写一个分页的例子出来给大家分享一下。这个案例分前端和后台两部分,前端使用面向对象的方式写的,里面用到了一些回调
- 一、前言我们经常会接触各种池化的技术或者概念,包括对象池、连接池、线程池等,池化技术最大的好处就是实现对象的重复利用,尤其是创建和使用大对象
- 随机数的定义为:产生的所有数字毫无关系.在实际应用中很多地方会用到随机数,比如需要生成唯一的订单号.在C#中获取随机数有三种方法:一.Ran
- 本文实例讲述了Android实现模仿UCweb菜单效果的方法。分享给大家供大家参考。具体如下:UCWeb的菜单看起来不错,自己模仿做一个,思
- 概念二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:1、若它的左子树不为空,则左子树上所有节点的值都小于根结点的值。
- 错误内容:com.alibaba.druid.pool.GetConnectionTimeoutException: wait millis
- 1. 简单说明嗨,大家好!今天给大家分享的是Mybatis-plus 插件的分页机制,说起分页机制,相信我们程序员都不陌生,今天,我就给大家
- 前言Spring框架对Bean进行装配提供了很灵活的方式,下面归纳一下主要的方式:在XML中进行显示配置在Java中进行显示配置隐式的bea
- 一、实现方式@ConfigurationProperties 注解(最好加上前缀prefix=“person”,标明是和配置文件中哪个开头的
- java实现五子棋小游戏package Gomoku;import java.awt.Toolkit;import javax.swing.
- 前言最近项目中需要与andorid端进行交互,采用了MQTT消息进行通信,生产环境中偶尔会出现Too many publishesin pr
- Java 向上转型和向下转型的详解转型是在继承的基础上而言的,继承是面向对象语言中,代码复用的一种机制,通过继承,子类可以复用父
- Jackson 日期格式化技巧使用 Spring Boot 时,需要使用 Jackson 处理一些 Java Time API 类型的 JS
- gateway网关与前端请求的跨域问题最近因项目需要,引入了gateway网关。可是发现将前端请求的端口指向网关后,用postman发送请求
- 第一次进入应用的时候,都会有一个引导页面,引导页面的实现起来也很简单,实现的方式也有很多,下面是自己写的一个引导页面的效果,大致的实现思路为
- 前言Basic编码是标准的BASE64编码,用于处理常规的需求:输出的内容不添加换行符,而且输出的内容由字母加数字组成。最近做了个Web模版
- 前言有时候我们在项目中,会用到一些本地 jar 包文件,比如隔壁公司自己打包的;此时无法从maven远程仓库拉取;那么我们可以考虑把 jar
- 本文实例为大家分享了安卓实现单行多列横向滚动,供大家参考,具体内容如下<GridLayout android:layou
- 运用到的MongoDB支持的C#驱动,当前版本为1.6.0下载地址:https://github.com/mongodb/mongo-csh