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

java中的内部类

java中很重要的一个知识点是内部类,经常会用到,参考百度百科整理如下:

内部类分为:成员内部类、静态内部类、方法内部类、匿名内部类。

内部类的特点:

1、内部类任然是一个独立的类,编译后内部类会被编译成独立的.class文件,前面冠以外部类名和$符号;
2、内部类是外部类的一个成员,因此可以自由地访问外部类的成员变量,无论是否是private类型的;
3、内部类声明为静态的,就不能随便访问外部类的成员变量了,只能访问外部类的静态成员变量。

一、成员内部类

1、内部类一般形式

public class Out {

    private int age = 18;

    public class In {
        public void printAge() {
            System.out.println(age);
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Out.In in = new Out().new In();
        in.printAge();
        /*下面写法也可以
        Out out=new Out();
        Out.In in=out.new In();
        in.printAge();
        */
    }

}

上面程序输出结果:18

说明内部类可以访问外部类的private类型变量;两种实例化内部类的方式,而且实例化内部类之前需要创建外部类对象;查看编译后的.class文件,发现有两个,Out.class和Out$In.class。

2、同名变量的作用域

public class Out {

    private int age = 18;

    public class In {
        private int age = 19;

        public void printAge() {
            int age = 20;
            System.out.println("局部变量:" + age);
            System.out.println("内部类变量:" + this.age);
            System.out.println("外部类变量:" + Out.this.age);
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Out.In in = new Out().new In();
        in.printAge();
        /*
         * 下面写法也可以 Out out=new Out(); Out.In in=out.new In(); in.printAge();
         */
    }

}

局部变量、内部类变量和外部类变量同名的话会覆盖掉,调用内部和外部类变量时要用this.属性名和Out.this.属性名。

3、私有内部类

public class Out {

    private int age = 18;

    private class In {
        public void printAge() {
            System.out.println(age);
        }
    }

    public void outPrint() {
        new In().printAge();
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        // Out out = new Out();
        // out.outPrint();
        Out.In in = new Out().new In();
        in.printAge();
    }

}

程序输出:18

二、静态内部类

public class Out {

    private static int age = 18;

    static class In {
        public void printAge() {
            System.out.println(age);
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        // Out out = new Out();
        // out.outPrint();
        Out.In in = new Out.In();
        in.printAge();
    }

}

静态内部类只能访问外部类的静态变量,而且可以不用实例化外部类就可以创建外部类的对象。

三、方法内部类

public class Out {

    private int age = 18;

    public void print() {
        final int a = 12;// 方法内部类只能访问方法中的final类型变量
        class In {
            public void printAge() {
                System.out.println(a);
                System.out.println(age);
            }
        }
        new In().printAge();
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Out out = new Out();
        out.print();
    }

}

因为方法的局部变量位于栈上,只存在于函数的生命周期中,内部类位于堆上,它们的生命周期不一样,所以方法内部类不能访问方法中的非final类型变量。

四、匿名内部类

顾名思义,没有名字的内部类。表面上看起来它们似乎有名字,实际那不是它们的名字。
匿名内部类就是没有名字的内部类。什么情况下需要使用匿名内部类?如果满足下面的一些条件,使用匿名内部类是比较合适的:
·只用到类的一个实例 。
·类在定义后马上用到。
·类非常小(SUN推荐是在4行代码以下)
·给类命名并不会导致你的代码更容易被理解。
在使用匿名内部类时,要记住以下几个原则:
·匿名内部类不能有构造方法。
·匿名内部类不能定义任何静态成员、静态方法。
·匿名内部类不能是public,protected,private,static。
·只能创建匿名内部类的一个实例。
·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。

1、继承式的匿名内部类
public class Out {

    public void drive(){
        System.out.println("Driving a car!");
    }
    
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Out out = new Out(){
            public void drive(){
                System.out.println("Driving another car!");
            }
        };
        out.drive();
    }

}

2、接口式的匿名内部类
public class Out {

    interface Car{
        public void drive();
    }
    
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Car car = new Car(){
            public void drive(){
                System.out.println("Driving a car!");
            }
        };
        car.drive();
    }

}

3、参数式的匿名内部类
public class Out {

    void doStuff(Foo f){
        f.foo();
    }
    interface Foo{
        public void foo();
    }
    
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Out out = new Out();
        out.doStuff(new Foo(){
            public void foo(){
                System.out.println("hello");
            }
        });
    }

}

与君共勉。

转载于:https://www.cnblogs.com/nannanITeye/p/3562456.html

相关文章:

  • [IE9] IE9 Beta崩溃问题解决方案
  • ASP.NET MVC Filters 4种默认过滤器的使用【附示例】
  • 总结程序设计几大原则
  • 使用tcpdump抓取HTTP包
  • 客户端的测试
  • 云存储离我们还有多远?
  • CDbConnection failed to open the DB connection
  • 读入图像文件并显示【C#图像处理学习笔记】
  • 分页存储过程(三)
  • 禁用Dropbear中DNS反向查询连接客户端地址补丁
  • Windows Phone开发(29):隔离存储C
  • 马宁的Windows Phone 7开发教程(3)——XNA下使用MessageBox和软键盘
  • STP详解
  • 又见西安
  • 一次失败的网购:在兰蔻官网订购的货不对版
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • 4个实用的微服务测试策略
  • Bootstrap JS插件Alert源码分析
  • C++入门教程(10):for 语句
  • CAP 一致性协议及应用解析
  • interface和setter,getter
  • JS函数式编程 数组部分风格 ES6版
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 对超线程几个不同角度的解释
  • 那些被忽略的 JavaScript 数组方法细节
  • 如何使用 JavaScript 解析 URL
  • 一道闭包题引发的思考
  • 正则与JS中的正则
  • mysql面试题分组并合并列
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • ​批处理文件中的errorlevel用法
  • #includecmath
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • #每日一题合集#牛客JZ23-JZ33
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • (10)ATF MMU转换表
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (定时器/计数器)中断系统(详解与使用)
  • (二)pulsar安装在独立的docker中,python测试
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (三)c52学习之旅-点亮LED灯
  • (原)Matlab的svmtrain和svmclassify
  • (转)socket Aio demo
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务
  • .NET 8.0 发布到 IIS
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .NET gRPC 和RESTful简单对比
  • .NET 同步与异步 之 原子操作和自旋锁(Interlocked、SpinLock)(九)
  • .NET/C# 阻止屏幕关闭,阻止系统进入睡眠状态