文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java内部类如何使用

2023-07-05 22:59

关注

今天小编给大家分享一下Java内部类如何使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

一. 内部类简介

1. 概念

在Java中,我们通常是把不同的类创建在不同的包里面,对于同一个包里的类来说,它们都是同一层次的。但其实还有另一种情况,有些类可以被定义在另一个类的内部,我们把在一个类里面定义的类称为内部类(InnerClass)或嵌套类,把外面定义的类称为外部类(OutClass)或宿主类。 也就是说,在类的内部既可以定义成员变量和方法,也可以定义其他的类。定义内部类的常见格式如下:

class Outer {//外部类        class Inner {//内部类                //方法和属性    }    }

上面的代码中,Outer是普通的外部类,Inner就是内部类。它与普通外部类最大的不同,在于其实例对象不能单独存在,必须依附于一个外部类的实例对象。

内部类可以很好地实现隐藏,一般的非内部类是不允许有private 与 protected权限的,但内部类却可以,而且内部类还拥有外部类中所有元素的访问权限。总之,对内部类的很多访问规则都可以参考变量和方法。

但是要注意,虽然我们使用内部类可以使程序结构变得更加紧凑,但却在一定程度上破坏了面向对象的思想。

2. 优点

内部类的存在,具有如下优点:

3. 分类

Java中的内部类可以分为如下几种类型:

虽然大多数时候,内部类用得并不多,但我们也有必要了解它们是如何具体使用的。

4. 内部类的特点

内部类相比外部类,具有如下特点:

5. Java类的创建要求

我们在创建定义Java类时,应该遵循如下要求:

接下来我们就针对上面提到的几种内部类,分别给大家讲解这几种内部类的用法。

二. 成员内部类

1. 概念

成员内部类就是指没有被static修饰的内部类,也可以称为非静态内部类。

2. 特点

成员内部类具有如下特点:

3. 语法

如果是在外部类中,创建成员内部类对象的基本语法格式如下:

内部类 对象名 = new 内部类();

如果是在外部的其他类中,或者是在外部类的静态方法中,创建成员内部类对象的基本语法格式如下:

内部类 对象名 = new 外部类().new 内部类();

4. 案例

4.1 定义成员内部类

public class OuterClass {// 外部类的非静态成员String name = "一一哥";private String hobby = "撸码";static int age = 30;// 非静态方法public void show() {//这里的this是指OuterClass对象System.out.println("show方法...name="+this.name);        //如果是在外部类里面创建内部类的对象,就不需要创建外部类实例,可以直接new 内部类()//InnerClass inner = new InnerClass();}// 定义一个成员内部类public class InnerClass {// 也可以定义私有属性private int a = 10;//在早期的JDK中,成员内部类中不能定义静态变量;但在新版JDK中,成员内部类中可以定义静态变量static int b = 20;// 非静态方法public void m1() {// 这里的this对象是InnerClass内部类对象System.out.println("成员内部类的成员变量:" + this.a);//外部类.this.属性或方法,这个this是外部类对象System.out.println("外部类的成员变量:" + OuterClass.this.name);            //内部类中可以访问外部类的私有成员和静态成员System.out.println("外部类的私有成员变量:" + hobby);System.out.println("外部类的静态变量:" + age);}//在早期的JDK中,成员内部类中不能定义静态方法;但在新版JDK中,成员内部类中可以定义静态方法public static void m2() {System.out.println("调用成员内部类的静态变量:" + b);System.out.println("调用外部类的静态变量:" + age);            //在静态方法中创建内部类对象,也要通过内部类 对象名 = new 外部类().new 内部类();的格式//InnerClass innerClass = new OuterClass().new InnerClass();}}}

我们要注意,在早期的JDK中,成员内部类中不能定义静态属性和方法;但在新版JDK中,成员内部类中可以定义静态的属性和方法。并且我们要搞清楚在不同的位置上,创建内部类对象的方式,以及this的具体含义。

4.2 定义测试类

我们在外部的其他类中,要想创建出一个成员内部类的对象,需要通过如下形式:

内部类 对象名 = new 外部类().new 内部类();

public class InnerClassTest {public static void main(String[] args) {//在外部的其他类中,不能直接创建内部类对象,否则://No enclosing instance of type OuterClass is accessible. //Must qualify the allocation with an enclosing instance of type OuterClass //(e.g. x.new A() where x is an instance of OuterClass).//InnerClass inner=new InnerClass();        //在外部的其他类中创建内部类对象,需要通过如下格式://内部类 对象名 = new 外部类().new 内部类();//InnerClass inner=new OuterClass().new InnerClass();//也可以拆分成如下格式:OuterClass outer=new OuterClass();InnerClass inner=outer.new InnerClass();inner.m1();InnerClass.m2();}}

5. 访问方式小结

学习到这里,你可能会被内部类与外部类之间的调用访问关系整蒙圈,所以给大家梳理了一下访问方式:

6. 关于this的注意事项

在之前给大家讲过this的作用和用法,但在内部类中,关于this,我们需要注意以下两点:

如果同时存在外部类和内部类,那么this在哪个类中使用,this就代表哪个类的对象;

 如果内部类想要通过this来调用外部类的属性和方法,需要使用外部类名.this.属性或者方法名。

三. 局部内部类

1. 概念

局部内部类是指在方法中定义的内部类。

2. 特点

局部内部类具有如下特点:

3. 语法

创建局部内部类对象的基本语法格式如下:

public class PartClass {        public void method() {        //在方法中定义的内部类,就是局部内部类        class Inner {            //属性            //方法        }    }    }

4. 案例

4.1 定义局部内部类

我们来定义一个局部内部类的案例代码。

public class PartOuterClass {//类的成员变量String name="一一哥";    private int age=30;    static String hobby="java";        public void show() {    //局部变量        //JDK 7之前,匿名内部类和局部内部类中访问外部的局部变量时,该变量需要明确地带有final修饰符        //final int num = 10;                //Effectively final特性        int num = 10;                //局部内部类,类似于是方法中的局部对象        class PartInnerClass{                //内部可以正常定义方法            public void m1() {            //访问外部类的非静态成员,可以使用OuterClass.this.成员的格式,也可以直接访问            //System.out.println("外部类的成员变量"+name);                System.out.println("外部类的成员变量"+PartOuterClass.this.name);                System.out.println("外部类私有的成员变量"+age);                System.out.println("外部类的静态变量"+hobby);                                //局部内部类,可以直接访问方法中的局部变量                System.out.println("访问局部变量"+num);            }                        //在新版的jdk中,也可以定义静态的属性和方法,老版的jdk则不行            static int b=10;                        public static void m2() {            System.out.println("外部类的静态变量,hobby="+hobby+",b="+b);            }        }                //创建局部内部类对象        PartInnerClass inner = new PartInnerClass();        inner.m1();                //在当前类中,局部内部类可以直接访问静态成员        PartInnerClass.m2();            }        }

在JDK 7之前,匿名内部类和局部内部类中访问外部的局部变量时,该变量需要明确地带有final修饰符。但从JDK 8之后,我们可以不带final修饰符,而是由系统默认添加了。

4.2 定义测试类

接下来我们对上面的案例进行测试。

public class PartInnerClassTest {public static void main(String[] args) {//创建外部类对象,调用方法,执行局部内部类PartOuterClass outer=new PartOuterClass();outer.show();}}

4.3 Effectively final特性

一般情况下,Java中的局部内部类和匿名内部类访问局部变量时,该变量必须由 final修饰,以保证内部类和外部类的数据一致性。但从 Java 8开始,我们可以不加 final修饰符,而是由系统默认添加,当然这在 Java 8以前是不允许的。Java将这个新的特性称为 Effectively(有效的、实际的) final 功能

另外在 Lambda表达式中,使用局部变量时也要求该变量必须是 final 修饰的,所以 effectively final特性在 Lambda表达式的上下文中非常有用。

其实effectively final特性,只是让我们不用显式地把变量声明为final修饰的,它给我们自动添加了final修饰词,但并没有取消final,主要是减少了一点不必要的操作,给开发节省了点时间。

四. 匿名内部类

1. 概念

匿名内部类就是指没有类名的内部类,必须在创建时使用 new 语句来声明。匿名内部类不能在Outer Class外部类中定义,而是要在某个方法的内部,通过匿名类(Anonymous Class)的形式来定义。 匿名内部类本身就是一个对象。

通常情况下,如果一个方法的参数是接口类型,且该接口只需要实现一次,那么我们就可以通过匿名内部类的形式来进行定义。另外如果该接口的实现每次都不同,也可以使用匿名内部类的形式进行定义。我们也可以把这种定义形式叫做 “接口回调” 。匿名内部类的代码格式使得代码更加简洁、紧凑,模块化程度也更高。

2. 特点

匿名内部类具有如下特点:

3. 语法

通常匿名内部类有两种实现方式:

创建匿名内部类对象的基本语法格式如下:

new <类或接口> (){
重写类或接口的方法
}

4. 案例

为了给大家演示匿名内部类的用法,接下来壹哥设计一个用于模拟按钮点击事件的案例。当我们进行安卓等设备开发时,面板上有个按钮,点击该按钮,如何监听点击事件?在Android系统中提供了各种对应的按钮点击监听事件。所以这里壹哥就通过实现接口的形式来定义匿名内部类,模拟一个单击事件。

4.1 定义接口

首先我们需要定义一个接口,表示单击监听,内部有个点击事件。

public interface OnClickListener {//点击事件void onClick();}

4.2 定义Button按钮类

然后定义一个Button按钮类,给Button按钮安排一个点击监听方法。

public class Button {//处理案例点击的监听事件    public void setOnClickListener(OnClickListener listener) {        listener.onClick();    }    }

4.3 定义测试类

接下来我们就测试运行上面的代码。

public class AnonyInnerClassTest {public static void main(String[] args) {//外部变量int num=20;//测试匿名内部类Button btn=new Button();//模拟处理按钮的点击事件btn.setOnClickListener(new OnClickListener() {//这里就是一个匿名内部类//在匿名内部类中,可以允许使用非静态代码块进行成员初始化操作。int i; {    // 非静态代码块,在构造方法之后执行        i = 100;    //成员初始化    }@Overridepublic void onClick() {System.out.println("按钮被点击啦...i="+i+",num="+num);}});}}

根据上面的案例可知:

五. 静态内部类

1. 概念

静态内部类和成员内部类的定义类似,但要使用static修饰,所以称为静态内部类(Static Nested Class)。

静态内部类和成员内部类有很大的不同,它不再依附于Outer的实例,而是一个完全独立的类,因此无法引用Outer.this的方式调用。但它可以访问Outer类的private静态字段和静态方法,如果我们把静态内部类移到Outer类之外,就失去了访问private的权限。

2. 特点

静态内部类中可以定义非静态的属性和方法,也可以定义静态的属性和方法;

静态内部类中只能访问静态外部类的静态属性和方法。

3. 语法

创建静态内部类对象的基本语法格式如下:

内部类 对象名 = new 外部类.内部类();

4. 案例

4.1 定义静态内部类

这里我们先简单定义一个静态内部类,后面我们在学习内部类时再专门讲解。在这个静态内部类中,定义了一个方法,来访问外部类中的普通属性和静态属性。我们要记住以下几点:

public class OuterClass {//普通属性,属于外部类static int outerNum=10;//定义一个静态的内部类,如果不带static,就是一个普通的内部类。//内部类的使用,和普通类一样,里面可以正常定义属性、方法、构造方法等。    //static前面可以带public等任意访问修饰符,也可以不带!static class InnerClass{//私有属性无法在类的外部直接访问//private int innerNum=20;int innerNum=20;public void printNum() {//定义外部类对象OuterClass outer=new OuterClass();            //这里的this是指InnerClass内部类对象!System.out.println("innerNum="+this.innerNum+",outerAge="+outer.outerAge+",outerNum="+OuterClass.outerNum);}}}

对于静态内部类而言,static前面可以带public等任意访问修饰符,也可以不带!

4.2 定义测试类

我们再定义一个测试类,看看内部类对象是怎么调用的。

public class InnerClassTest {public static void main(String[] args) {//创建内部类对象,格式为“外部类.内部类 对象名 = new 外部类.内部类的构造方法”OuterClass.InnerClass inner = new OuterClass.InnerClass();//调用内部类的方法inner.printNum();//访问外部类属性    System.out.println("outerNum="+OuterClass.outerNum);        //访问内部类属性    System.out.println("innerNum="+inner.innerNum);}}

5. 访问方式小结

对于静态内部类的访问要求,给大家总结如下:

以上就是“Java内部类如何使用”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯