java内部类与外部类

  • java内部类与外部类
    • 一、内部类的作用
    • 二、内部类分类
      • 一、成员内部类
        • 1、非静态内部类
        • 2、静态内部类
      • 二、局部内部类
      • 三、匿名内部类(重要)

java内部类与外部类

概念:在一个类的内部再定义一个完整的类。
特点:

  • 编译之后可生成独立的字节码文件。
  • 内部类可直接访问外部类的私有成员,而不破坏封装。
  • 可为外部类提供必要的内部功能组件。

一、内部类的作用

提供良好的封装环境

二、内部类分类

成员内部类、局部内部类、匿名内部类

一、成员内部类

在类的内部定义一个类,与成员方法和成员变量同级,成员内部类又分为静态内部类和非静态内部类

1、非静态内部类

1)非静态内部类相当于是特殊的成员变量
2)非静态内部类可以在内部类中直接调用外部类的所有权限的成员变量和成员方法,外部类不能直接调用内部类的成员变量和成员方法
3)与成员变量和局部变量的优先级一致,当外部类与内部类存在同名属性时,优先访问内部类属性,要访问外部类的属性,可以这样写:
外部类名.this.属性名 即 Outer.this.name 或外部类对象.属性名 即new outer().name
4)内部类属于外部类对象,所以必须与外部类对象绑定在一起(理解为对象调用属性的方式,其中内部类对象就是外部类的属性):
Inclass in = new Outclass().new Inclass();
new outclass()可以写成引用方式,如:
Outclass outer = new Outclass();
Inclass in = outer.new Inclass();
5)如果在外部类调用外部类方法,则可以不用new:
Inclass in = new Outclass().out();
6)非静态内部类中不能含有静态方法、变量、代码块,但是可以包含静态常量
7)在外部类的静态方法、代码块不能访问非静态内部类,不能使用非静态内部类定义变量、创建实例
8)其他外部类访问内部类的三种方式:
第一种方式: Outclass outer = new Outclass(); Inclass in = outer.new Inclass();
第二种方式:Inclass in = new Outclass().new Inclass();
第三种方式:在内部类所属外部类中定义一个方法,在该方法中创建内部类对象
Inclass in = new Outclass().getInclassInstance();

2、静态内部类

1)相当于外部类,即使用方法跟外部类一致
不依赖外部类对象,可以直接创建或通过类名访问,可声明静态成员
2)属于类的,不属于具体对象
3)外部类属性与内部类属性的用法

public class Test {public static void main(String[] args) {new Outer.Inner().P();//第一种调用方式System.out.println("----------------");new Outer().show();//第二种调用方式}
}
class Outer{int name = 1;//Test test = new Test();//包含静态内部类时,不能在外部类体非方法中实例化外部类对象static class Inner{int name = 5;static int name1 = 5;public static void P(){//静态和非静态方法访问属性的方式基本相同System.out.println(new Outer().name);//访问外部类属性System.out.println(new Inner().name);//访问内部类非静态属性System.out.println(name1);//访问内部类静态属性}}public void show(){Inner.P();}
}

二、局部内部类

在方法中定义内部类,只能在该方法中使用,不能添加任何访问修饰符
1)局部内部类不能定义为静态类,不能存在静态方法、属性,静态常量除外
2) 要想使用局部内部类,必须在外部类方法中实例化内部类对象,因为外部类对象只能调用外部类方法,无法在方法外面调用方法内的变量,而局部内部类的等级与局部变量相同,所以外部类对象也无法直接调用局部内部类,而当我们调用方法时,会被方法忽略,因为方法被调用时局部内部类没有创建对象,所以要想局部内部类有效,则必须在方法体内实例化内部类,并使用局部内部类对象调用内部类的方法
3)外部的其他类不能访问局部内部类(因为局部内部类相当于是一个局部变量)
4) 局部内部类不能添加访问修饰符

public class Test {int name = 1;static int i = 2;public void outer() {String n = "北方";/***  注意:这里的局部变量正常情况下不是常量,即系统没有默认添加final修饰*  当局部变量被局部内部类调用时,系统会自动添加final修饰该变量*  即内部类没有调用的局部变量还是可以做出二次赋值的,但是如果该变量被*  局部内部类调用或者可能会被调用的局部变量都不应该进行二次赋值,因为*  被调用之后会变成常量,赋值的时候不会报错,但是当局部内部类调用时将会*  报错*/class Inner {int name = 5;int name1 = 5;public void P() {System.out.println(i);//访问外部类静态属性System.out.println(new Inner().name);//访问内部类非静态属性System.out.println(name1);//访问内部类静态属性/*** 注意:在jdk1.7时,要在外部类局部变量前加上final修饰*       在jdk1.8时,默认在外部类局部变量前加上final,所以可以直接*       访问* 原因:局部变量在方法结束时销毁,但是对象还在调用该变量,这样会出*      错,所以必需变为常量*/System.out.println(n);//访问外部类的局部变量}}/*** 要想使用局部内部类,必须在内部类所在的外部类方法中实例化内部类对象,再调用内部类方法*/Inner inner = new Inner();inner.P();}
}

三、匿名内部类(重要)

定义类、实现类、创建对象的语法合并,只能创建一个对象,用于只使用一次的类,比如监听器,因为构造器名必须与类名一致,而匿名内部类没有类名,所以匿名内部类不能有构造方法

  • 没有类名的局部内部类(一切特征都与局部内部类相同)注意:这里所谓的没有类名是指程序员无法给他指定类名,其实在jvm中还是会给他定义类名的,格式为声明所在的外部类$数字,即在哪个类创建匿名内部类,类名就是该类$数字。
public class Test {public static void main(String[] args) {A a = new A();a.aaa();new Test().bbb();System.out.println(a);}public void bbb() {/*** jvm会自动为匿名内部类命名,规则是  声明匿名内部类的外部类名$数字*/new A() { // 类名Test$1public void bb() {System.out.println(getClass());}}.bb();new A() {// 类名Test$2public void bb() {System.out.println(getClass());}}.bb();}
}
class A {public void aaa() {new A() {// 类名A$1public void i() {System.out.println(getClass());}}.i();}
}
  • 必须继承一个父类或者实现一个接口。
  • 定义类、实现类、创建对象的语法合并,只能创建一个该类的对象。匿名内部类是类也是对象,即它本质上是一个类,同时也代表着它是一个子类对象,即匿名内部类是继承该类或实现该接口的子类匿名对象
public class Test {public static void main(String[] args) {new Test().bbb();}public void bbb() {/*** 注意有对象名和没有对象名的区别:* 1. 不使用对象名时,该匿名对象只能使用一次,且可以调用子类/实现类自身特有的方法* 2. 有对象名时,该对象可以多次使用,但只可以调用父类/接口/抽象类拥有的方法(向上转型)*/new A() { // 类名Test$1public void bb() { System.out.println(getClass()); }}.bb();/*** 相当于:*  A a = new Test$2() {*      public void bb() { System.out.println(getClass());}*  };* class Test$2 extends A{*      ....* }*/A a = new A() {// 类名Test$2public void bb() { System.out.println(getClass());}};a.aaa();//a.bb();// 不能调用子类特有的方法}
}
class A {public void aaa() { System.out.println("aaa"); }
}
  • 优点:减少代码量。
  • 缺点:可读性较差。

匿名内部类的使用场景

当做实参直接传递

public class Test {public static void main(String[] args) {new Test().bbb(new A() { // 将匿名内部类当做实参直接传递public void bb() { System.out.println(getClass()); }});}public void bbb(A a) {System.out.println(a.getClass());}
}
class A {public void aaa() { System.out.println("aaa"); }
}

java内部类与外部类相关推荐

  1. Java内部类引用外部类中的局部变量为何必须是final问题解析

    Java内部类引用外部类中的局部变量为何必须是final问题解析 今天编写一个多线程程序,发现在方法内定义内部类时,如果内部类调用了方法中的变量,那么该变量必须申明为final类型,百思不得其解,后来 ...

  2. Java内部类、外部类之间访问权限

    Java内部类.外部类之间访问权限 啥是内部类 内部类可以访问外部类的所有成员吗 那外部类能访问内部类的所有成员吗 匿名内部类 静态内部类呢 为啥会这样呢 得出结论 啥是内部类 顾名思义,内部类就是在 ...

  3. JAVA内部类、外部类

    一.内部类                内部类就是将一个类A定义在类B里边,里边的那个类A称为内部类,外边的类B称为外部类 成员内部类定义格式:class 外部类{ class 内部类{ } } c ...

  4. Java内存泄露系列--内部类持有外部类导致内存泄露--原因/解决方案

    原文网址:Java内存泄露系列--内部类持有外部类导致内存泄露--原因/解决方案_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Java内部类持有外部类导致内存泄露的原因以及其解决方案. 为什么内部 ...

  5. java内部类为什么会持有外部类的引用_为什么内部类持有外部类的引?

    对普通类(没有内部类的类)来说,内部类和外部类都与他无关:对有内部类的类来说,它们就是其内部类的外部类,外部类是个相对的说法,其实就是有内部类的类.所以,要回答这个问题,只需要讲解内部类是什么:Jav ...

  6. JAVA基础系列:内部类获取外部类的成员变量

    内部类获取外部类的成员变量,使用 外部类类名.this.变量名 的形式获取 public class Outer {public String name = "outer";cla ...

  7. java的内部类和外部类_java内部类 和外部类的区别

    下面说一说内部类(Inner Class)和静态内部类(Static Nested Class)的区别: 定义在一个类内部的类叫内部类,包含内部类的类称为外部类.内部类可以声明public.prote ...

  8. 内部类和外部类的详解

    一*相关概念: 当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类.内部类也是封装的一种体现. 1.1.内部类 ...

  9. Python内部类,内部类调用外部类属性,方法

    一 Python中内部类 典型定义: class MyOuter:age=18def __init__(self,name):self.name=nameclass MyInner:def __ini ...

最新文章

  1. 从零开始学计算机组装与维修技术,从新手到高手:电脑组装、维护与故障排除...
  2. Linux中read接收用户输入
  3. LLE(局部线性嵌入)matlab代码实现
  4. 手机抓包HTTPS (Fiddler Packet Capture)
  5. 压力测试工具siege的用法
  6. 文章中运用到的数学公式
  7. 安卓boot.img文件详细介绍-解包,编辑,打包
  8. Atitit、 知识管理法 目录 1. 信息管理的演进 1 2. 显性知识管理 1 3. 隐形知识 1 4. 知识产权保护 1 1.信息管理的演进 文献管理,计算机管理,信息资源管理,情报管理,直
  9. Android面试问题收集总结
  10. python运维是什么_什么是python自动化运维?
  11. 《硅谷之火》书评:时代变迁中的硅谷摇滚明星
  12. 【FeignClient报错】Cannot deserialize value of type``from Object value (token `JsonToken.START_OBJECT`)
  13. java 使用的钩子_Java 钩子程序
  14. 观察者模式与推拉模型
  15. WebSocket 是什么原理?为什么可以实现持久连接
  16. 【Ubuntu18.04系统开启防火墙】
  17. 蚂蚁开放平台开发第三方授权登陆(三):Android端
  18. 基于springboot的校园跑腿系统
  19. 5、店铺管理 - 后端功能开发 - 微擎小程序模块应用开发
  20. 两年经验的阿里、头条面经(已拿offer),大厂面试套路屡试不爽

热门文章

  1. 写个性签名也要花心思,做短视频如何设置个签?四个小技巧来帮忙
  2. python随机种子的作用_python – 如何使用TensorFlow获得稳定的结果,设置随机种子...
  3. 追女孩子要用滴短信~~哈哈
  4. 迅雷看看网站设计分析
  5. 小Q大数据-Hbase数据模型的“旋风之旅”
  6. 联想M7650DF打印机加墨粉
  7. MySQL中日期时间类型与格式化
  8. 【2020 ACM Fellow 华人学者】 Wang Yi 乌普萨拉大学
  9. 华为路由器ppp配置
  10. C语言基础——连续大于连续小于的多种表示方式,及符号优先级