iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Java内部类示例分析
  • 466
分享到

Java内部类示例分析

2023-06-29 13:06:26 466人浏览 八月长安
摘要

这篇文章主要介绍“Java内部类示例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java内部类示例分析”文章能帮助大家解决问题。1.内部类概念及分类将一个类定义在另一个类的内部或者接口内部或者

这篇文章主要介绍“Java内部类示例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java内部类示例分析”文章能帮助大家解决问题。

    1.内部类概念及分类

    将一个类定义在另一个类的内部或者接口内部或者方法体内部,这个类就被称为内部类,我们不妨将内部类所在的类称为外围类,除了定义在类,接口,方法中的内部类,还有一种特殊的内部类,那就是使用关键字new创建一个匿名类的对象,而这个匿名类其实就是一个内部类,具体说是一个匿名内部类,经常用于传入构造器实参构造对象,例如PriorityQueue对象的创建。

    一个类定义在另一个类的内部或者接口内部,并且没有static修饰时,这个内部类就称为实例内部类,使用static修饰时,这个内部类被称为静态内部类(嵌套类),将一个类定义在代码块内部,特别是方法体内部,这个内部类被称为本地内部类或者局部内部类,还有一种就是上面所说的匿名内部类。

    2.实例内部类

    2.1实例内部类的创建

    实例内部类的定义很简单,就直接定义在外围类的里面就可以了。问题是如何创建一个内部类对象,首先,需要明白内部类与外围类中的成员变量与方法是平起平坐的,都是属于外围类对象的(无static修饰),所以想要内部类对象先得有外围类对象,第一种创建内部类对象的方式就是使用一个方法返回一个内部类对象,并且这个内部类对象的类型为OutClassName.InnerClassName,即外围类名.内部类名。

    public class Outer {    class Inner1 {        private String str;        public Inner1(String s) {            this.str = s;        }        public String readStr() {            return this.str;        }    }    class Inner2 {        private int val;        public Inner2(int i) {            this.val = i;        }        public int readVal() {            return this.val;        }    }    //创建内部类    public Inner1 creatInner1(String s) {        return new Inner1(s);    }    public Inner2 creatInner2(int i) {        return new Inner2(i);    }    public static void main(String[] args) {        Outer outer = new Outer();        Outer.Inner1 inner1 =  outer.creatInner1("Inner1");        Outer.Inner2 inner2 = outer.creatInner2(2);        System.out.println(inner1.readStr());        System.out.println(inner2.readVal());    }}
    //output:Inner12Process finished with exit code 0

    2.2使用.this和.new

    当然,创建一个内部类还有其他的方法,就是使用外围类的对象.new来创建一个内部类对象,语法为:

    外部类对象.new 内部类构造方法;

    public class Outer {    class Inner1 {        private String str;        public Inner1(String s) {            this.str = s;        }        public String readStr() {            return this.str;        }    }    class Inner2 {        private int val;        public Inner2(int i) {            this.val = i;        }        public int readVal() {            return this.val;        }    }    public static void main(String[] args) {        Outer outer = new Outer();        Outer.Inner1 inner1 =  outer.new Inner1("Inner1");        Outer.Inner2 inner2 = outer.new Inner2(2);        System.out.println(inner1.readStr());        System.out.println(inner2.readVal());    }}
    //output:Inner12Process finished with exit code 0

    内部类的特性不止如此,内部类还能与外围类链接,首先实例内部类对象的创建是依赖外围类对象的引用,实例内部类与外围类的成员变量地位一样,如果想要通过内部类对象访问外围类的成员变量与方法(特别是同名变量)。在内部类中,可以使用外围类名.this获取外围类对象,然后使用获得的这个外围类对象来使用外围类的变量与方法。

    public class Outer {    private String outStr;    public Outer(String str) {        this.outStr = str;    }    public void printOuter() {        System.out.println(this.outStr);    }    class Inner {        private String str;        public Inner(String s) {            this.str = s;        }        public String readStr() {            return this.str;        }        //使用.this获取父类对象引用        public Outer outer() {            return Outer.this;        }    }    public static void main(String[] args) {        Outer outer = new Outer("outerString");        Outer.Inner inner = outer.new Inner("innerString");        Outer out = inner.outer();        out.printOuter();    }}
    //output:outerStringProcess finished with exit code 0

    其实内部类对象中有两个this,直接使用this.成员获取的是内部类对象自己的成员,而像上面使用外围类名.this.成员获取的是外围类的成员,也就是说在内部类中this指向内部类对象自己的引用,外部类名.this指向外围类对象的引用。

    当出现内部类与外围类变量名相同时,这两个this就有很大的用处了。

    public class Outer {    public int a = 12;    public int b = 16;    public int c = 20;    class Inner{        public int a = 8;        public int c = 48;        public int d = 2;        public void printVal() {            System.out.println("外围类变量a=" + Outer.this.a);            System.out.println("外围类变量b=" + Outer.this.b);            System.out.println("外围类变量c=" + Outer.this.c);            System.out.println("内部类变量a=" + this.a);            System.out.println("内部类变量c=" + this.c);            System.out.println("内部类变量d=" + this.d);        }    }    public Inner creatInner() {        return new Inner();    }    public static void main(String[] args) {        Outer outer = new Outer();        Outer.Inner inner = outer.creatInner();        inner.printVal();    }}
    //output:外围类变量a=12外围类变量b=16外围类变量c=20内部类变量a=8内部类变量c=48内部类变量d=2Process finished with exit code 0

    如果没有出现同名,直接获取的成员即可,可以不用使用上面所说的this,出现同名,直接访问的成员默认是内部类对象的。

    2.3内部类实现迭代打印

    内部类可以与外围类的所有元素的访问权限,所以我们可以尝试使用内部类来遍历输出外围类中的元素,虽然内部类与外围类的成员地位是平等,但内部类毕竟也是类,它也可以像外围类一样继承类和实现接口。

    import java.util.Arrays;interface Selector{    //判断是否迭代完全部元素    public boolean end();    //获取当前元素    public Object current();    //迭代下一个元素    public void next();}public class SequeArray {    private Object[] items;    private int usedSize;    public SequeArray(int capacity) {        items = new Object[capacity];    }    public void add(Object val) {        if (usedSize == items.length) items = Arrays.copyOf(items, 2 * usedSize);        items[usedSize++] = val;    }    private class SequeSelector implements Selector{        private int index;        public boolean end() {            return index == usedSize;        }        public Object current() {            return items[index];        }        public void next() {            if (index < usedSize) index++;        }    }    public SequeSelector sequeSelector() {        return new SequeSelector();    }    public static void main(String[] args) {        SequeArray array = new SequeArray(10);        for (int i = 0; i < 10; i++) {            array.add(i+1);        }        //发生了向上转型        Selector selector = array.sequeSelector();        while (!selector.end()) {            System.out.print(selector.current() + "   ");            selector.next();        }    }}
    //output:1   2   3   4   5   6   7   8   9   10   Process finished with exit code 0

    2.4内部类的继承

    内部类的继承有一点麻烦,因为内部类的构造器必须依赖外围类的引用,所以需要一段特殊的语法来说明内部类与外围类的关联:

    外围类引用.super();

    具体怎么使用看如下一段代码:

    public class Outer {    class Inner{            }}class Person extends Outer.Inner {    private String str;    private int id;    public Person(Outer out, String str, int id) {        out.super();        this.str = str;        this.id = id;    }    public void readVal() {        System.out.println(this.str + this.id);            }}

    当内部类被继承的时候,需要通过外围类的引用传入父类的构造方法中并调用super()才能通过编译。

    如果内部类继承外部类,直接继承即可,不需要这么麻烦。

    程序生成一个java文件的字节码文件时,命名为公共外部类$内部类。

    内部类可以无限嵌套,一般没人这么干。

    3.静态内部类

    静态内部类也称嵌套类,它就是在实例内部类的定义前加入一个static关键字,像下面这样:

    public class Outer {        static class Inner{            }}

    与实例内部类的区别是静态内部类是属于类的而不是属于对象的,因此静态内部类的创建不依赖与外部类对象,这是和实例内部类最大的区别之一。

    public class Outer {    static class Inner{        private String str;        public Inner(String s) {            str = s;        }    }    public static void main(String[] args) {        Outer.Inner inner = new Outer.Inner("我是静态内部类!");        System.out.println(inner.str);    }}
    //output:我是静态内部类!Process finished with exit code 0

    4.匿名内部类

    匿名内部类的用法我们已经见过了,就是创建PriorityQueue对象时,默认创建的是小堆,需要传入比较器来创建大堆。

            PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new Comparator<Integer>() {            @Override            public int compare(Integer o1, Integer o2) {                return o1 - o2;            }        });

    像上面这种在方法中使用new关键字创建一个匿名类的对象作为实参,里面这个匿名类就是匿名内部类,创建过程中的Comparator匿名类对象是继承所需传参类型的,在这里也就是Comparator类。

    如果使用自定义类型传入优先队列,是一定要实现比较器的,实现比较器最常见的方式就是匿名内部类与Lambda表达式。

    假设我有一个Person类数组,需要对他们的name排序,如果不使用内部类,就需要在Person类中实现比较器。

    import java.util.Arrays;import java.util.Comparator;class Preson {    public String name;    public Integer id;    public Preson(String name, Integer id) {        this.name = name;        this.id = id;    }    @Override    public String toString() {        return "Preson{" +                "name='" + name + '\'' +                ", id=" + id +                '}';    }}class PersonComparator implements Comparator<Preson> {    @Override    public int compare(Preson o1, Preson o2) {        return o1.name.compareTo(o2.name);    }}public class Main {    public static void main(String[] args) {        Preson preson1 = new Preson("aboluo", 24);        Preson preson2 = new Preson("zhousi", 25);        Preson preson3 = new Preson("syyfjy", 2);        Preson[] presons = {preson1, preson2, preson3};        Arrays.parallelSort(presons, new PersonComparator());        System.out.println(Arrays.toString(presons));    }}
    //output:[Preson{name='aboluo', id=24}, Preson{name='syyfjy', id=2}, Preson{name='zhousi', id=25}]Process finished with exit code 0

    使用内部类上述代码就变为:

    import java.util.Arrays;import java.util.Comparator;class Preson {    public String name;    public Integer id;    public Preson(String name, Integer id) {        this.name = name;        this.id = id;    }    @Override    public String toString() {        return "Preson{" +                "name='" + name + '\'' +                ", id=" + id +                '}';    }}public class Main {    public static void main(String[] args) {        Preson preson1 = new Preson("aboluo", 24);        Preson preson2 = new Preson("zhousi", 25);        Preson preson3 = new Preson("syyfjy", 2);        Preson[] presons = {preson1, preson2, preson3};        Arrays.parallelSort(presons, new Comparator<Preson>() {            @Override            public int compare(Preson o1, Preson o2) {                return o1.name.compareTo(o2.name);            }        });        System.out.println(Arrays.toString(presons));    }}
    //output:[Preson{name='aboluo', id=24}, Preson{name='syyfjy', id=2}, Preson{name='zhousi', id=25}]Process finished with exit code 0

    还有一个本地内部类,就是类定义在方法中,就不多说了,基本上不用,用法如下:

    public class Outer {    public void func() {        class Inner{            //        }    }}

    关于“Java内部类示例分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网精选频道,小编每天都会为大家更新不同的知识点。

    --结束END--

    本文标题: Java内部类示例分析

    本文链接: https://www.lsjlt.com/news/325140.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • c++中函数返回值的类型是由什么决定的
      在 c++ 中,函数返回值类型由其函数原型的类型决定,包括:函数原型指定返回值类型:在函数名称后跟冒号,再跟返回值类型。默认返回值类型为 int:如果不指定返回值类型,默认类型为 int...
      99+
      2024-05-14
      c++
    • 在c++中,什么叫函数的返回值
      在 c++ 中,函数只能返回一个值。解决方法:引用传递、结构体或类、out 参数。没有返回值的函数可以使用 void 类型,表示不返回任何值。 什么是 C++ 中函数的返回值? 在 C...
      99+
      2024-05-14
      c++
    • c++中static的作用和用法
      c++ 中的 static 关键字用于声明静态变量、函数或类成员,使其在程序生命周期内存在或与类的每个实例关联。具体用法如下:静态变量:在函数外声明,仅创建一份副本,在程序启动时初始化且...
      99+
      2024-05-14
      c++
    • static在c和c++中的区别
      static关键字在c和c++中用于控制变量的生命周期和作用域。在c中,它延长局部变量和限制全局变量的作用域。在c++中,它还用于定义类成员变量和函数、命名空间中的变量和函数,以及函数内...
      99+
      2024-05-14
      c语言 c++ 作用域
    • c++中a++与++a的区别
      c++ 中 a++ 和 ++a 区别:后缀递增 a++ 先返回原始值,再递增;前缀递增 ++a 先递增,再返回递增后的值。 C++ 中 a++ 与 ++a 的区别 在 C++ 中,a+...
      99+
      2024-05-14
      c++
    • if else在c++中的用法
      在 c++ 中,if else 语句根据条件执行不同代码块的语法为:if (condition) { } else { }。它可用于:检查数字是否为正数根据条件执行嵌套 if els...
      99+
      2024-05-14
      c++
    • struct在c和c++中的区别
      c和c++中struct的区别包括:c中成员默认公开访问,c++中默认私有访问。c++可以在struct定义中初始化成员,c中不允许。c++支持成员函数,c不支持。c++不支持匿名str...
      99+
      2024-05-14
      c++
    • c++中的所有函数都是传值调用吗
      函数调用类型可分为传值调用和引用调用,默认采用传值调用,传值调用中形参接收实参副本,引用调用中形参接收实参引用,对形参进行的修改也会影响实参。 C++中的函数调用类型 C++中,函数调...
      99+
      2024-05-14
      c++
    • c++中ifdef的用法
      c++ 中的 #ifdef 预处理器指令用于根据预定义宏是否存在来编译或不编译代码块。它的语法是 #ifdef ,其作用包括:检查宏是否存在,如果宏已定义,则编译其后的代码块;实现条件编...
      99+
      2024-05-14
      c++
    • c++中的函数调用有哪几种方式?它们有什么区别
      c++ 中的函数调用方式有 4 种:值传递(复制实参值,不影响实参)、引用传递(传递实参地址,修改形参值会修改实参)、指针传递(传递实参指向的内存地址,修改指向的值会影响实参)、rval...
      99+
      2024-05-14
      c++
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作