`
dandy
  • 浏览: 67258 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

我所得到的都是静态的

    博客分类:
  • java
阅读更多
出自《java puzzle》


下面的程序对巴辛吉小鬣狗和其它狗之间的行为差异进行了建模。如果你不知道什么是巴辛吉小鬣狗,那么我告诉你,这是一种产自非洲的小型卷尾狗,它们从来都不叫唤。那么,这个程序将打印出什么呢?
class Dog {
 public static void bark() {
  System.out.print("woof ");
 }
}
class Basenji extends Dog {
 public static void bark() { }
}
public class Bark {
 public static void main(String args[]) {
  Dog woofer = new Dog();
  Dog nipper = new Basenji();
  woofer.bark();
  nipper.bark();
 }
}

随意地看一看,好像该程序应该只打印一个woof。毕竟,Basenji扩展自Dog,并且它的bark方法定义为什么也不做。main方法调用了bark方法,第一次是在Dog类型的woofer上调用,第二次是在Basenji类型的nipper上调用。巴辛吉小鬣狗并不会叫唤,但是很显然,这一只会。如果你运行该程序,就会发现它打印的是woof woof。这只可怜的小家伙到底出什么问题了?

问题在于bark是一个静态方法,而对静态方法的调用不存在任何动态的分派机制[JLS 15.12.4.4]。当一个程序调用了一个静态方法时,要被调用的方法都是在编译时刻被选定的,而这种选定是基于修饰符的编译期类型而做出的,修饰符的编译期类型就是我们给出的方法调用表达式中圆点左边部分的名字。在本案中,两个方法调用的修饰符分别是变量woofer和nipper,它们都被声明为Dog类型。因为它们具有相同的编译期类型,所以编译器使得它们调用的是相同的方法:Dog.bark。这也就解释了为什么程序打印出woof woof。尽管nipper的运行期类型是Basenji,但是编译器只会考虑其编译器类型。

要订正这个程序,直接从两个bark方法定义中移除掉static修饰符即可。这样,Basenji中的bark方法将覆写而不是隐藏Dog中的bark方法,而该程序也将会打印出woof,而不是woof woof。通过覆写,你可以获得动态的分派;而通过隐藏,你却得不到这种特性。

当你调用了一个静态方法时,通常都是用一个类而不是表达式来标识它:例如,Dog.bark或Basenji.bark。当你在阅读一个Java程序时,你会期望类被用作为静态方法的修饰符,这些静态方法都是被静态分派的,而表达式被用作为实例方法的修饰符,这些实例方法都是被动态分派的。通过耦合类和变量的不同的命名规范,我们可以提供一个很强的可视化线索,用来表明一个给定的方法调用是动态的还是静态的。本谜题的程序使用了一个表达式作为静态方法调用的修饰符,这就误导了我们。千万不要用一个表达式来标识一个静态方法调用。

覆写的使用与上述的混乱局面搅到了一起。Basenji中的bark方法与Dog中的bark方法具有相同的方法签名,这正是覆写的惯用方式,预示着要进行动态的分派。然而在本案中,该方法被声明为是static的,而静态方法是不能被覆写的;它们只能被隐藏,而这仅仅是因为你没有表达出你应该表达的意思。为了避免这样的混乱,千万不要隐藏静态方法。即便在子类中重用了超类中的静态方法的名称,也不会给你带来任何新的东西,但是却会丧失很多东西。

对语言设计者的教训是:对类和实例方法的调用彼此之间看起来应该具有明显的差异。第一种实现此目标的方式是不允许使用表达式作为静态方法的修饰符;第二种区分静态方法和实例方法调用的方式是使用不同的操作符,就像C++那样;第三种方式是通过完全抛弃静态方法这一概念来解决此问题,就像Smalltalk那样。

总之,要用类名来修饰静态方法的调用,或者当你在静态方法所属的类中去调用它们时,压根不去修饰这些方法,但是千万不要用一个表达式去修饰它们。还有就是要避免隐藏静态方法。所有这些原则合起来就可以帮助我们去消除那些容易令人误解的覆写,这些覆写需要对静态方法进行动态分派。
2
0
分享到:
评论

相关推荐

    南方静态解算软件

    在静态模式下,GPS接收机在一段时间内保持不动,记录下卫星信号的数据,然后通过软件进行后期处理,以获得更高精度的位置信息。 南方静态解算软件的核心功能包括: 1. **数据预处理**:软件可以读取多种格式的原始...

    静态库封装另一静态库

    在Linux环境下,静态库是程序编译链接时使用的文件,它们包含了可重用的代码片段。静态库的扩展名通常是`.a`。本主题聚焦于如何创建一个静态库A,这个库不仅包含自身的代码,还封装了另一个静态库B。这涉及到链接器...

    静态页面抓取工具

    这意味着当你在本地访问抓取后的网站时,所有链接都将指向本地文件,无需互联网连接。这提高了离线浏览的便捷性,同时减少了因链接失效而导致的问题。使用httrack,用户可以设置自定义的抓取规则,如排除某些页面或...

    Qt6.22 Mingw64静态编译

    完成上述步骤后,你将得到静态编译的Qt6库。接下来,你可以使用这些库来构建你的Qt应用程序,无需担心运行时的库依赖问题。 在创建新项目时,确保设置项目的构建类型为静态,并链接到你刚才编译的静态Qt库。这样,...

    jsp伪静态,javaweb实现伪静态

    在Java Web开发中,"伪静态"是一种技术手段,它主要用来...通过这种方式,我们可以使Java Web应用在保持动态功能的同时,获得静态URL的诸多优点。在深入理解这些知识点后,你可以根据实际项目需求灵活地应用和扩展。

    HTM页面伪静态 Demo

    这种技术的好处在于,它既能保留动态网站的灵活性,又能获得静态页面在SEO方面的优势。 例如,一个动态的URL可能是"www.example.com/index.php?id=123",而伪静态后的URL可以是"www.example.com/article/123.html"...

    ASP静态化插件

    综上所述,ASP静态化插件是提升ASP网站性能和优化SEO的有效手段,通过合理的配置和使用,能够帮助网站获得更好的用户体验和搜索引擎表现。对于运维人员和开发者来说,理解和掌握这类插件的应用是提高网站质量的重要...

    2020T5友价商城源码系统nginx伪静态重写规则.zip

    在IT行业中,源码系统是开发者的宝贵资源,特别是对于那些想要进行二次开发或学习的人来说。...对于开发者来说,这是一份宝贵的参考资料,无论是用于学习还是实际项目开发,都能从中获得很多有价值的经验和知识。

    asp生成html,asp生成静态

    3. **生成HTML**:将解析得到的HTML内容写入新的静态文件中,文件名通常与原ASP文件对应,但扩展名为`.html`或`.htm`。 4. **链接更新**:静态化过程中,确保所有内部链接都指向新的HTML文件。 5. **清理旧文件**:...

    GPS 苏州一光静态处理软件

    《苏州一光GPS静态处理软件详解与应用》 在现代测绘技术中,GPS(全球定位系统)扮演着至关重要的角色,特别是在精度要求高的静态测量工作中。苏州一光,作为国内知名的测绘仪器制造商,其开发的GPS静态处理软件是...

    Kenics型静态混合器和GK型静态混合器

    综上所述,通过计算流体动力学方法对Kenics型静态混合器与GK型静态混合器进行的流场模拟分析表明,尽管两种类型静态混合器在某些方面存在差异,但GK型静态混合器在实际应用中展现出更好的综合性能,特别是在需要兼顾...

    杰奇伪静态组件

    杰奇伪静态组件是针对杰奇CMS(Joomla CMS)设计的一个重要插件,它主要用于优化网站的URL结构,使其更符合搜索引擎优化(SEO)的标准。在网站开发中,URL的可读性和简洁性对用户体验和搜索引擎爬虫的友好度有着直接...

    锐浪静态编译

    同时,静态编译可能会引起版权问题,因为可能需要获得所有被链接库的授权。 在实际应用中,开发者需要根据具体需求来选择静态编译或动态链接。例如,对于桌面应用,特别是那些需要广泛分发或需要在不受控制的环境中...

    jsoncpp 的静态链接库

    此外,如果 JSONCPP 库更新,静态链接的项目可能不会自动获得更新,需要重新编译整个项目。 总之,JSONCPP 的静态链接库允许你在 C++ 项目中轻松地处理 JSON 数据,而无需在运行时依赖外部库。正确配置构建系统并...

    Qt静态库的下载和安装配置

    Qt静态库的下载和安装配置,可以用于程序基于静态库的编译链接,release得到可执行文件

    企业网站静态模板HTML5

    SVG则是用于创建矢量图,确保图像在任何分辨率下都能清晰显示。 5. **Geolocation API**:通过获取用户地理位置信息,网站可以提供更个性化的服务。 6. **Web Workers**:此特性允许在后台运行脚本,提高网站的...

    南方GPS静态数据导出软件可以导出北斗数据

    标题中的“南方GPS静态数据导出软件可以导出北斗数据”揭示了该软件的主要功能,即不仅支持传统的GPS(全球定位系统)静态数据处理,还兼容北斗导航系统的静态数据。这意味着用户可以使用这款软件处理来自这两种不同...

    华为S5720静态DHCP绑定操作

    而在某些特定情况下,为了确保关键设备能够获得稳定的网络连接,通常会采用静态DHCP绑定的方式,即为特定设备分配固定的IP地址。 #### 二、华为S5720静态DHCP绑定配置步骤 本节将详细介绍如何在华为S5720交换机上...

    在线教程静态网站

    CSS3的新特性如选择器、Flexbox布局模型、Grid布局、阴影、渐变、过渡(transition)和动画(animation)都在此静态首页中得到了应用。 3. C3.js: C3是D3.js的一个衍生库,专为创建数据图表而设计。D3.js是一个强大...

Global site tag (gtag.js) - Google Analytics