嵌套类型的前5个用例

前几天,在reddit上进行了有趣的讨论,即静态内部类。 什么时候太多?

首先,让我们回顾一下Java的基本历史知识。 Java语言提供了四个级别的嵌套类 ,通过“ Java语言”,我的意思是这些构造仅是“语法糖”。 它们在仅了解普通类的JVM中不存在。

(静态)嵌套类

class Outer {static class Inner {}
}

在这种情况下, Inner完全独立于Outer ,除了公共的共享名称空间。

内部班

class Outer {class Inner {}
}

在这种情况下, Inner实例对其所在的Outer实例具有隐式引用。 换句话说,没有关联的Outer实例就不会有Inner实例。

创建此类实例的Java方法如下:

Outer.Inner yikes = new Outer().new Inner();

看起来很尴尬的东西很有道理。 考虑在Outer内部的某个地方创建Inner实例:

class Outer {class Inner {}void somewhereInside() {// We're already in the scope of Outer.// We don't have to qualify Inner explicitly.Inner aaahOK;// This is what we're used to writing.aaahOK = new Inner();// As all other locally scoped methods, we can// access the Inner constructor by // dereferencing it from "this". We just// hardly ever write "this"aaahOK = this.new Inner();}
}

请注意,就像publicabstract关键字一样, static关键字对于嵌套接口是隐式的。 乍看之下,以下假设语法可能很熟悉……:

class Outer {<non-static> interface Inner {default void doSomething() {Outer.this.doSomething();}}void doSomething() {}
}

……不可能写上面的东西。 除了缺少<non-static>关键字外,似乎没有任何明显的理由说明“内部接口”不可行。 我怀疑这是通常的情况–必须有一些与向后兼容和/或多重继承有关的边缘警告。

本地班

class Outer {void somewhereInside() {class Inner {}}
}

本地类可能是Java中鲜为人知的功能之一,因为它们几乎没有用处。 本地类是命名类型,其范围仅扩展到封闭方法。 显而易见的用例是当您想在该方法中多次重用这种类型时,例如在JavaFX应用程序中构造多个类似的侦听器。

匿名班

class Outer {Serializable dummy = new Serializable() {};
}

匿名类是只有一个实例的另一种类型的子类型。

嵌套类的前5个用例

如果未在静态上下文中定义它们,则所有匿名类,本地类和内部类都保留对其封闭实例的引用。 如果让这些类的实例泄漏到它们的范围之外,可能会造成很多麻烦。 在我们的文章中阅读有关该麻烦的更多信息: 不要聪明:Double Curly Braces Anti Pattern 。

但是,通常您确实希望从该封闭实例中获利。 具有某种可以在不公开实际实现的情况下返回的“消息”对象可能非常有用:

class Outer {// This implementation is private ...private class Inner implements Message {@Overridepublic void getMessage() {Outer.this.someoneCalledMe();}}// ... but we can return it, being of// type MessageMessage hello() {return new Inner();}void someoneCalledMe() {}
}

但是,对于(静态)嵌套类,没有封闭范围,因为Inner实例完全独立于任何Outer实例。 那么,使用这样的嵌套类而不是顶级类型有什么意义呢?

1.与外部类型的关联

如果您想与全世界进行交流,嘿,这种(内部)类型与这种(外部)类型完全相关,并且单独使用没有意义,那么您可以嵌套这些类型。 例如,这是通过MapMap.Entry完成的:

public interface Map<K, V> {interface Entry<K, V> {}
}

2.从外部隐藏外部类型

如果软件包(默认)的可见性不足以满足您的类型的需求,则可以创建private static类,这些private static类仅对其封装类型和该封装类型的所有其他嵌套类型可用。 这实际上是静态嵌套类的主要用例。

class Outer {private static class Inner {}
}class Outer2 {Outer.Inner nope;
}

3.保护类型

这确实是一个非常罕见的用例,但是有时,在类层次结构中,您需要只希望对给定类型的子类型可用的类型。 这是protected static类的用例:

class Parent {protected static class OnlySubtypesCanSeeMe {}protected OnlySubtypesCanSeeMe someMethod() {return new OnlySubtypesCanSeeMe();}
}class Child extends Parent {OnlySubtypesCanSeeMe wow = someMethod();
}

4.模拟模块

与Ceylon不同,Java没有一流的模块 。 使用Maven或OSGi,可以向Java的构建(Maven)或运行时(OSGi)环境中添加一些模块化行为,但是如果要用代码表示模块,则实际上是不可能的。

但是,您可以使用静态嵌套类按照约定建立模块。 让我们看一下java.util.stream包。 我们可以将其视为一个模块,并且在此模块中,我们有几个“子模块”或类型组,例如内部java.util.stream.Nodes类,其大致如下所示:

final class Nodes {private Nodes() {}private static abstract class AbstractConcNode {}static final class ConcNode {static final class OfInt {}static final class OfLong {}}private static final class FixedNodeBuilder {}// ...
}

所有java.util.stream包都可以使用其中一些Nodes东西,因此我们可以说,它的编写方式如下:

  • 合成的java.util.stream.nodes子包,仅对java.util.stream “模块”可见
  • 几个java.util.stream.nodes.*类型,也仅对java.util.stream “模块”可见
  • 合成java.util.stream.nodes包中的几个“顶级”函数(静态方法)

对我来说看起来很像锡兰!

5.外观原因

最后一点很无聊。 或者有些人可能会觉得有趣 。 这是关于品味或易于写作的事情。 有些类是如此之小且无关紧要,将它们写在另一个类中更容易。 为您保存一个.java文件。 为什么不。

结论

在Java 8时代,考虑Java的非常古老的功能,该语言可能不会被证明是非常令人兴奋的。 静态嵌套类是一些小众用例的很好理解的工具。

但是,本文的重点是这个。 每次嵌套类时,如果您绝对不需要引用封闭的实例,请确保将其设为static 。 您永远不知道何时该引用会在生产中使您的应用程序崩溃 。

翻译自: https://www.javacodegeeks.com/2015/02/top-5-use-cases-for-nested-types.html

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

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

相关文章

外包以小时计算金额的费用_2020年初级会计各大税种的计算公式,请收藏!

一、各种税的计算方式增值税1、一般纳税人应纳税额销项税额—进项税销项税额销售额税率组成计税价格成本(1成本利润率)组成计税价格成本(1成本利润率)(1-消费税税率)2、进口货物应纳税额组成计税价格税率组成计税价格关税完税价格关税(消费税)3、小规模纳税人应纳税额销售额征收…

VSCode设置ESLint语法检查

转载 "eslint.validate": ["javascript","javascriptreact","vue-html",{"language": "vue","autoFix": true}],"eslint.run": "onSave","eslint.autoFixOnSave": true…

次要GC,主要GC与完整GC

在使用Plumbr中的GC暂停检测功能时&#xff0c;我被迫通过大量有关该主题的文章&#xff0c;书籍和演示工作。 在整个旅程中&#xff0c;我多次对次要&#xff0c;主要和完全GC事件的使用&#xff08;误用&#xff09;感到困惑。 这导致了这篇博客文章&#xff0c;我希望我设法…

怎么改字段名称_精装房这么改!换门框,封阳台,效果出来比毛坯房还好

最近有朋友后台留言&#xff0c;称自己原本想一步到位购买精装房&#xff0c;但收房验收时才发现根本不合心意&#xff0c;空间利用率太低配色也老气&#xff0c;已经打算重新改装了。所谓精装房就是开发商将地板、门、厨房、卫生间、少量天花和部分柜子进行安装,业主只要添加些…

微信小程序 - 富文本图片宽度自适应(正则)

原文连接 引言&#xff1a;在微信小程序里&#xff0c;比如商品展示页面的商品详情会有图片展示&#xff0c;PC端设置的商品详情是PC端的宽度&#xff0c;所以在小程序里图片会显示不全&#xff0c;这时就应该做相应的处理&#xff0c;使小程序里图片显示正确 思路 把图片的宽…

ZF2系列 – Zend Framework 2 MVC實作 (Part 3)

我之所以這麼喜歡Zend Framework的關係&#xff0c;其中一項就是它可以幫你很簡單的實現MVC的架構&#xff0c;所以今天的任務就是要建立一個以MVC為架構的基本網頁。 首先當然要先建立一個測試用的資料庫&#xff0c;因此我簡單的建立了一個名為Employee的資料表來進行展示&am…

从Grunt测试Grunt插件

编写针对grunt插件的测试结果比预期的要简单。 我需要运行多个任务配置&#xff0c;并想通过在主目录中键入grunt test来调用它们。 通常&#xff0c;第一个任务失败后会发出咕声。 这使得不可能在主项目gruntfile中存储多个失败方案。 从那里运行它们将需要--force选项&#…

方向盘左右能摇动_学车这么久了,你还不会打方向盘呢?

刚刚学车的朋友肯定有过这样的问题&#xff1a;教练说&#xff1a;往左打两圈&#xff0c;往右打一圈&#xff0c;往左打半圈……你乖乖听话照做&#xff0c;然后教练说&#xff1a;回正吧。是不是一下就蒙住了&#xff1f;&#xff1f;我刚才打几圈来着&#xff1f;&#xff1…

Asp.Net基础 - 9.Web开发原则

目录&#xff1a; 9.1.Web开发的一些基本原则 9.2 原则一 9.2.1 C#代码是运行在服务器端的&#xff0c;JS代码是运行在浏览器客户端的 9.2.2 在服务器端“弹出消息窗口” 9.2.3 案例说明&#xff08;客户端与服务端互不影响&#xff09; 9.3 原则二 9.4 原则三 9.4.1 客户端…

Spring配置文件简介

这么多的人&#xff0c;那么多的思想。 当我们为不同的客户实施软件时&#xff0c;有时我们需要处理同一项目的各种需求。 例如&#xff0c;客户A需要SAML身份验证&#xff0c;客户B需要LDAP身份验证。 借助Spring Profiles&#xff08;可从Spring 3.1获得&#xff09;&#x…

重置手机_【轻松办税】ITS客户端申报密码重置不会操作?看过来,3分钟包你会!...

ITS扣缴客户端实名办税功能已经上线了&#xff0c;并且在2020年1月1日后将不再支持以CA方式进行登录&#xff0c;可是公司申报密码是很久前去大厅办理的&#xff0c;早就忘记了&#xff0c;这可咋好&#xff1f;别急&#xff0c;快来关注“上海税务”&#xff0c;包你3分钟学会…

vuex mapGetters使用

// formStatisticsFoundation.js &#xff0c;命名空间为formStatisticsFoundation getters: {zzStatisticsData(state) {const statisticsData state.statisticsData;const data [{name: 企业数,number: statisticsData.enterpriseNumber},{name: 品种数,number: statistic…

Ubuntu各大分支版本功能介绍及下载地址

Ubuntu目标&#xff1a;&#xff08;摘自官网&#xff09;快速&#xff0c;免费&#xff0c;易用。特色&#xff1a;带有上千种免费的开源应用软件&#xff0c;支持各种电脑文件设备、打印机、数码相机、音乐播放器和智能手机。每年的4月和10月都会发布一个新版本。官方网站&am…

数控弯管机xyz转换ybc的算法_花了一年时间开发的三维弯管机交互式转档软件(三维管子模型UG,SOLIDWORK,PRO/E文件转成YBC)...

在弯管机加工中,由管子模型生成可直接进行弯管加工的YBC数据可以大大提高弯管编程过程.传统的做法是先用dxf数据文件(用autocad绘制管子的轴心线数据)转出XYZ数据,然后由XYZ数据转成YBC数据,而且大部分厂家对文件版本以及软件做管方式都有不少限制,这大大花费了用户的时间跟精力…

使用rx-java的异步抽象

对我而言&#xff0c;使用Rx-java的最大好处之一就是无论底层调用是同步还是异步&#xff0c;因此代码看起来都完全相同&#xff0c;因此该条目的标题也是如此。 考虑一个非常简单的客户端代码用例&#xff0c;它执行三个缓慢运行的调用并将结果合并到一个列表中&#xff1a; …

js Math函数

在控制台直接打印console.dir(Math)看全部方法. 属性 Math.E //2.718281828459045 自然对数的底数 这是高中知识&#xff1f; Math.LN2 // 0.6931471805599453 Math.LN10 // 2.302585092994046 Math.LOG2E // 1.4426950408889634 Math.LOG10E // 0.4342944819032518 Math.P…

jenkins修改pom文件_jenkins使用小技巧:pom.xml文件里的版本随着每次发布变化怎么办?...

针对这个问题&#xff0c;构建方法不变&#xff0c; 变化在动态去获取每次打出来的包名&#xff0c;比如说&#xff0c;本次打出来的报名mypackage-1.0.3-SNAPSHOT.jar那么&#xff0c;先进入target目录#先进入target目录cd /root/.jenkins/workspace/${JOB_NAME}/XXXXXX/targe…

Mysql Incorrect DATETIME value: ‘01/01/2021 00:00:00‘

服务器时间格式不一致&#xff0c;转换时间格式 start.ToString("yyyy-MM-dd HH:mm:ss")

Drools 6.2.0.Final发布

我们很高兴宣布最新&#xff0c;最出色的Drools 6.2.0.Final版本。 特别是此发行版更加注重改进的可用性和功能&#xff0c;这些功能使项目更易于使用&#xff08;和采用&#xff09;。 新功能包括对工作台UI的大量改进&#xff0c;对社交活动和插件管理的支持以及规则的全新E…

指针(pointers)和引用(references)区别

指针用“*”和“->”操作符&#xff0c;引用用"."操作符&#xff0c;当然这是表面的区别。 引用必须代表一个对象&#xff0c;没有所谓的空引用。指针可以为NULL。即引用必须有初值&#xff0c;指针不然。所以在使用pointers之前&#xff0c;必须测试它是否为null…