类与接口(二)java的四种内部类详解

引言

内部类,嵌套在另一个类的里面,所以也称为 嵌套类;

内部类分为以下四种:

  • 静态内部类
  • 成员内部类
  • 局部内部类
  • 匿名内部类

一、静态内部类

静态内部类: 一般也称”静态嵌套类“,在类中用static声明的内部类。

因为是static,所以不依赖于外围类对象实例而独立存在,静态内部类的可以访问外围类中的所有静态成员,包括private的静态成员。

同时静态内部类可以说是所有内部类中独立性最高的内部类,其创建对象、继承(实现接口)、扩展子类等使用方式与外围类并没有多大的区别。

public class OuterClass {//外围类public int aa; //实例成员private static float f = 1.5f;//private的静态成员static void println() {System.out.println("这是静态方法");}protected static class StaticInnerClass{//protected的静态内部类float a;public StaticInnerClass() {a = f;// 外围类的private静态变量println();//外围类的静态方法}}
}class OtherClass{public static void main(String[] args) {//创建静态内部类的对象OuterClass.StaticInnerClass staticInnerClass = new OuterClass.StaticInnerClass(); } 
}

二、成员内部类

成员内部类: 定义在类的内部,而且与成员方法、成员变量同级,即也是外围类的成员之一,因此 成员内部类 与 外围类 是紧密关联的。

注意:
这种紧密关联指的是,成员内部类的对象的创建必须依赖于外围类的对象(即没有外围类对象,就不可能创建成员内部类)。因此,成员内部类有以下3个特点:

  • 成员内部类可以访问外围类的所有成员,包括私有成员;
  • 成员内部类是不可以声明静态成员(包括静态变量、静态方法、静态成员类、嵌套接口),但有个例外---可以声明 static final的变量, 这是因为编译器对final类型的特殊处理,是直接将值写入字节码;
  • 成员内部类对象都隐式地保存了一个引用,指向创建它的外部类对象;或者说,成员内部类的入口是由外围类的对象保持着(静态内部类的入口,则直接由外围类保持着)

成员内部类中的 this,new关键字:

  • 获取外部类对象:OuterClass.this
  • 明确指定使用外部类的成员(当内部类与外部类的名字冲突时):
    OuterClass.this.成员名
  • 创建内部类对象的new:外围类对象.new
//先创建外围类对象
OuterClass outer=new OuterClass();
//创建成员内部类对象
OuterClass.InnerClass inner=outer.new InnerClass();

1. 成员内部类的对象创建

  我们知道,成员内部类就像外围类的实例成员一样,一定要存在对象才能访问,即成员内部类必须绑定一个外围类的对象。上面已经介绍了成员内部类的创建格式了,我们直接看一个例子

public class OuterClass {//外围类public int aa; //实例成员private static float f = 1.5f;//private的静态成员public void initInnerClass() {System.out.println("内部类的初始化方法");}public void createInnerClass() {////外围类的成员方法中创建成员内部类对象InnerClass innerClass = new InnerClass();}class InnerClass{//成员内部类private double aa; //与围类的变量aa的名字重复public InnerClass(){this.aa = OuterClass.this.aa + f;//明确指定两个aa的所属initInnerClass();}}   
}//其他类
class OtherClass{public static void main(String[] args) {//其他类中创建成员内部类OuterClass oc = new OuterClass();//外部类对象//创建内部类对象OuterClass.InnerClass innerClass = oc.new InnerClass();}
}

  注意上面的例子中,在外围类的成员方法中创建成员内部类 与 在其他类中或静态方法中创建成员内部的方式是不一样的。

补充几点:

  • 成员内部类可以继续包含成员内部类,而且不管一个内部类被嵌套了多少层,它都能透明地访问它的所有外部类所有成员;
  • 成员内部可以继续嵌套多层的成员内部类,但无法嵌套静态内部类;静态内部类则都可以继续嵌套这两种内部类。

下面的例子是基于上面的例子进行改造:

class InnerClass{//成员内部类private double aa; //与围类的变量aa的名字重复public InnerClass(){this.aa = OuterClass.this.aa + f;//明确指定两个aa的所属initInnerClass();}public  class InnerInnerCalss2{//成员内部类中的成员内部类protected double aa = OuterClass.this.aa;//最外层的外围类的成员变量}//InnerInnerCalss2}//InnerClass

2. 继承成员内部类

在内部类的访问权限允许的情况下,成员内部类也是可以被继承的。由于成员内部类的对象依赖于外围类的对象,或者说,成员内部类的构造器入口由外围类的对象把持着。因此,继承了成员内部类的子类必须要与一个外围类对象关联起来。同时,子类的构造器是必须要调用父类的构造器方法,所以也只能通过父类的外围类对象来调用父类构造器。

下面的例子也是基于上面的例子的,只贴出多出的部分代码。

class ChildClass extends OuterClass.InnerClass{//成员内部类的子类的构造器的格式public ChildClass(OuterClass outerClass) {outerClass.super();//通过外围类的对象调用父类的构造方法}
}

三、局部内部类

局部内部类: 就是在方法、构造器、初始化块中声明的类,在结构上类似于一个局部变量。因此局部内部类是不能使用访问修饰符。

局部内部类的两个访问限制:

  • 对于局部变量,局部内部类只能访问final的局部变量。不过,后期JDK(忘了是JDK几了)局部变量可不用final修饰,也可以被局部内部类访问,但你必须时刻记住此局部变量已经是final了,不能再改变。
  • 对于类的全局成员,局部内部类定义在实例环境中(构造器、对象成员方法、实例初始化块),则可以访问外围类的所有成员;但如果内部类定义在静态环境中(静态初始化块、静态方法),则只能访问外围类的静态成员。
public class OuterClass {private int a = 21;static {//静态域中的局部内部类class LocalClass1{//  int z = a; //错误,在静态的作用域中无法访问对象成员}}{//实例初始化块中的局部内部类class localClass2{          }}public OuterClass(){int x = 2;final int y = 3;// x = 3;//若放开此行注释,编译无法通过,因为局部变量x已经是final类型//构造器中的局部内部类class localClass3{int z = y; //可以访问final的局部变量int b = a;//可以访问类的所有成员//访问没有用final修饰的局部变量int c = x;}}public void createRunnable() {final int x = 4;//方法中的局部内部类class LocalClass4 implements Runnable {//@Overridepublic void run() {System.out.println("局部final变量:"+x);System.out.println("对象成员变量:"+a);}}}
}

四、匿名内部类

匿名内部类: 与局部内部类很相似,只不过匿名内部类是一个没有给定名字的内部类,在创建这个匿名内部类后,便会立即用来创建并返回此内部类的一个对象引用。

作用:匿名内部类用于隐式继承某个类(重写里面的方法或实现抽象方法)或者实现某个接口。

匿名内部类的访问限制: 与局部内部类一样,请参考局部内部类;

匿名内部类的优缺点:
优点: 编码方便快捷;
缺点:

  • 只能继承一个类或实现一个接口,不能再继承其他类或其他接口。
  • 只能用于创建一次对象实例;

下面的例子是我们创建线程时经常用到的匿名内部类的方式来快速地创建一个对象的例子:

 class MyOuterClass {private int x = 5;void createThread() {final int a = 10;int b = 189;// 匿名内部类继承Thread类,并重写Run方法Thread thread = new Thread("thread-1") {int c = x;  //访问成员变量int d = a;  //final的局部变量int e = b; //访问没有用final修饰的局部变量@Overridepublic void run() {System.out.println("这是线程thread-1");}};// 匿名内部类实现Runnable接口Runnable r = new Runnable() {@Overridepublic void run() {System.out.println("线程运行中");}};}
}

总结

类 型访问修饰符声明静态成员绑定外围类
静态内部类四种访问修饰符可以声明不绑定
成员内部类四种访问修饰符final static 的变量外,其余静态成员都不行绑定
局部内部类不可以声明不可以声明取决于此内部类的声明环境
匿名内部类不可以声明不可以声明取决于此内部类的声明环境


转载于:https://www.cnblogs.com/jinggod/p/8503143.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/252267.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单例设计模式和多线程

单例设计模式 单例&#xff1a;整个项目中&#xff0c;有某个类或者某些特殊的类&#xff0c;属于该类的对象只能建立一个。 #include<iostream> using namespace std;class MyCAS { private:MyCAS(){}private:static MyCAS *m_instance;public:static MyCAS *GetInstanc…

运行imgui例程

背景&#xff1a;目前在做一个视觉测试系统&#xff0c;需要做一个界面&#xff0c;将相机获取的图像&#xff0c;以及测试过程中的数据呈现在界面上&#xff0c;在我印象里&#xff0c;做界面就用qt吧&#xff0c;直到这个月真要开始做界面了&#xff0c;我的领导给我建议用im…

性能测试总结(三)--工具选型篇

性能测试总结(三)--工具选型篇 本篇文章主要简单总结下性能测试工具的原理以及如何选型。性能测试和功能测试不同&#xff0c;性能测试的执行是基本功能的重复和并发&#xff0c;需要模拟多用户&#xff0c;在性能测试执行时需要监控指标参数&#xff0c;同时性能测试的结果不是…

创建一个最简单的imgui测试用例

在上一篇文章中&#xff0c;我们初步认识了一下imgui,并且成功运行了他提供的demo。这只是开始学习imgui的第一步&#xff0c;在实际使用时&#xff0c;我们需要将imgui应用到自己的工程中去&#xff0c;所以你需要具备将imgui加到你工程中去的能力&#xff0c;简单起见&#x…

idea中maven的setting.xml的配置

2019独角兽企业重金招聘Python工程师标准>>> <?xml version"1.0" encoding"UTF-8"?> <settings xmlns"http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance&qu…

ref和out区别总结

ref&#xff1a;是必需要先初始化才能用,但调用时可以对它什么也不做.out&#xff1a;可以不初始化也能用,但调用时一定要对其赋值(即使已经初始化的也要赋值,哪怕是赋一个和原来一样的值).转载于:https://www.cnblogs.com/gjnsmallworld/p/7216206.html

继 承(面向对象特征之一)

1&#xff1a;成员变量。 当子父类中出现一样的属性时&#xff0c;子类类型的对象&#xff0c;调用该属性&#xff0c;值是子类的属性值。 如果想要调用父类中的属性值&#xff0c;需要使用一个关键字&#xff1a;super This&#xff1a;代表是本类类型的对象引用。 Super&…

如何将cv::Mat类型转换为imgui中的ImTextureID类型

背景&#xff1a; 我原来的工程是使用opencv的&#xff0c;所以程序中的图像都是表示为cv::Mat类型&#xff0c;为了能够在imgui窗口中显示我的cv::Mat的图像&#xff0c;我找到了下面这个函数&#xff1a; void ImGui::Image(ImTextureID user_texture_id, const ImVec2&…

react native 原生模块桥接的简单说明

原文出自&#xff1a;https://github.com/prscX/awes...博客链接&#xff1a;https://ssshooter.com/2019-02... Android 创建原生模块包 通过继承 ReactPackage 为你的原生模块包创建 Java 类&#xff0c;可以这么写&#xff1a;覆盖 createNativeModules 和 createViewManage…

UVa 1354 天平难题 枚举二叉树

题意&#xff1a;给出房间宽度 r 和 s 个挂坠的重量 wi&#xff0c;设计一个尽量宽的天平&#xff0c;挂着所有挂坠。天平由一些长度为 1 的木棍组成&#xff0c;木棍的每一端要么挂一个挂坠&#xff0c;要么挂另外一个木棍。 这题卡了很久&#xff0c;看了很多大神的代码&…

通过指针便利图像元素

for (size_t y 0; y < image.rows; y) {//row_ptr为第y行的头指针&#xff0c;unsigned char* row_ptr image.ptr<unsigned char>(y);for (size_t x 0; x < image.cols; x) {//data_ptr: 指向待访问像素unsigned char* data_ptr &row_ptr[x*image.channels…

[精华][推荐]SSO CAS单点登录框架学习 搭建详细步骤及源码

1.了解单点登录 SSO 主要特点是: SSO 应用之间使用 Web 协议(如 HTTPS) &#xff0c;并且只有一个登录入口. SSO 的体系中有下面三种角色: 1) User(多个) 2) Web 应用(多个) 3) SSO 认证中心(一个) 2.SSO 实现包含以下三个原则 1) 所有的登录都在 SSO 认证中心进行。 2) SS…

电脑下载的M4A格式文件怎么转换为MP3格式

M4A文件格式并不是一个家喻户晓的名字&#xff0c;与&#xff2d;&#xff30;&#xff13;格式相比&#xff0c;知名度远远落后。但是&#xff0c;这并不意味着它无关紧要&#xff0c;有时候我们下载的音乐可能就是M4A格式的&#xff0c;如果换一个设备播放可能就会出现格式不…

python-for循环

一、功能 for 循环提供了python中最强大的循环结构&#xff08;for循环是一种迭代循环机制&#xff0c;而while循环是条件循环&#xff0c;迭代即重复相同的逻辑操作&#xff0c;每次操作都是基于上一次的结果&#xff0c;而进行的&#xff09; Python for循环可以遍历任何序列…

六、利用frp穿透连接内网的linx系统和windows系统

服务端的配置 # frps.ini [common] bind_port 7000 说明&#xff1a;防火墙放行该端口 启动&#xff1a;./frps -c ./frps.ini 后台启动&#xff1a;nohup ./frps -c ./frps.ini & 客户端的配置 (1)windows系统 # frpc.ini [common] server_addr x.x.x.x server_port 70…

根据相机内参进行图像去畸变

cv::Mat img; cv::Mat img_undistort; double fx,fy, cx, cy, k1, k2, p1, p2, k3;for(int v 0; v < img.rows; v){for(int u 0; u < img.cols; u){//根据内参数&#xff0c;计算归一化坐标系下的坐标点double x (u-cx)/fx;double y (v-cy)/fy;double r2 x*x y*y;/…

initialize方法与load方法比较

load方法和initialize方法类似点 1. 都只会调用一次2. 父类在子类之前加载 复制代码不同点在于&#xff1a; 1. 加载时间不同&#xff0c;load方法在main()函数前进行调用&#xff0c;initialize在第一次调用类的所属方法时在调用<可能永远不调用>。2. load方法不会被Cat…

KindEditor

1、进入官网 2、下载 官网下载&#xff1a;http://kindeditor.net/down.php 3、文件夹说明 ├── asp asp示例 ├── asp.net asp.net示例 ├── attached 空文件夹&#xff0c;放置关联文件attached ├── …

service mysqld start,Failed to start mysqld.service: Access denied

service mysqld start 然后报&#xff1a; AUTHENTICATING FOR org.freedesktop.systemd1.manage-units Authentication is required to start mysqld.service.Authenticating as: lll,,, (lll)Password: polkit-agent-helper-1: pam_authenticate failed: Authentication fa…

使用realsense t265测试svo2.0视觉里程计

毕业三年了&#xff0c;现在是第二份工作&#xff0c;第一份工作已经结束一年半了&#xff0c;这意味着&#xff0c;我有一年半的时间没有搞视觉SLAM相关的东西了&#xff0c;虽然在第二份工作也是做视觉相关的&#xff0c;但是只是用到一些目标识别和跟踪的知识&#xff0c;并…