给定一个扩展了实现接口" DeeDum"的类" Foo"的类" Bar"

public interface DeeDum {

public String getDee();

public String getDum();

}

public class Foo implements DeeDum {

public String dee ="D";

public String dum;

public String getDee() { return dee; }

public String getDum() { return dum; }

}

public class Bar extends Foo {

public String dee ="DEE";

public String dum ="DUM";

}

为什么不起作用?

public static Bar mybar = new Bar();

Assert.assertEquals("DEE", mybar.getDee());

Assert.assertEquals("DUM", mybar.getDum());

我得到" D"和null。换句话说,Bar不会从Foo继承访问器,也无法覆盖属性。以某种方式调用mybar.getDum()会调用Foo类的静态实例,并从父类返回静态属性。即使该属性在子类中被覆盖!这是否意味着您不能继承任何方法或属性?

我不能把头缠住它。 Java为什么不能继承访问器(为什么它们选择了这种奇怪的选择?)

还是我做错了什么?

实际上,我仍然看到一些奇怪且不确定的东西。如果您还有另一个扩展Foo的类" Bar",并在初始化块中设置继承的访问器

虽然您可以在上面的块中设置父属性,但实际上并不会为子类创建一个副本。

对于多个类,这似乎是非确定性的初始化。

因此,如果您有Bar和Baz都扩展了foo并具有初始化块,则似乎两者都继承了Bar设置的值。

public class Bar extends Foo {

{

dee ="dee";

dum ="dum";

}

}

public class Baz extends Foo {

{

dee ="DEE";

dum ="DUM";

}

}

public static Bar bar = new Bar();

public static Baz baz = new Baz();

System.out.println("mybaz:" + mybaz.getDee() + mybaz.getDum());  // DEEDUM

System.out.println("mybar:" + mybar.getDee() + mybar.getDum());  // DEEDUM

但是如果以不同的顺序实例化它们,我将得到:

public static Baz baz = new Baz();

public static Bar bar = new Bar();

System.out.println("mybaz:" + mybaz.getDee() + mybaz.getDum());  // deedum

System.out.println("mybar:" + mybar.getDee() + mybar.getDum());  // deedum

如果在基类Foo中设置了默认值,结果会有所不同。

我想我现在知道,Bar和Baz中的初始化块实际上是在设置Foo :: dee和Foo :: dum,但是为什么声明有所不同?在我看来"未定义"。

然后开始疯狂的进食...

请不要喂巨魔

再一次经典的案例是"我不知道X的实际工作原理,所以X一定是完全错误的。"

" Java学校不教Java。磁带在11点开课"。

问题是在Bar中Foo的成员dee和dum的重复声明隐藏了Foo的成员。 Bar有其自己的成员; Foo的那些将永远不会被Bar使用。你的意思是像

public class Bar extends Foo {

{

dee ="DEE";

dum ="DUM";

}

}

恰恰相反。 他的问题是他没有覆盖它们-他将它们隐藏了。

是的,不好的例子。 我试图为" Eclipse编译器"编写一个简单的示例-摆脱槽中的所有图标并假定其正确。

对于我的下一个技巧,我将尝试通过在MS Word中写一篇有关"为什么独角兽比格里芬更酷"的文章来学习西班牙语,然后让clippy纠正我的拼写和语法。

您将用子类中定义的变量隐藏继承的变量。

public class Bar extends Foo {

public Bar() {

dee ="DEE";

dum ="DUM";

}

}

应该更好。

调用mybar.getDee()时,您正在调用Foo基类中定义的方法。 (该方法是Bar继承的。否则,首先不允许您在Bar实例变量上调用它。)该方法返回dee字段的值,但它是在Foo类(定义方法本身的类)中定义的dee字段。编译器在Foo类中解析了方法编译时对该字段的引用。

其他一些答案使用覆盖(override)一词通过在Bar中声明一个名为dee的字段来定义您所做的事情,但是事实并非如此。您不能覆盖字段,因为字段不是虚拟的。不过,也许您认为它们是。如果存在"虚拟字段"之类的东西,我也可能希望getDee()返回该字段的运行时类版本(Bar中的版本),而不是当时范围内的版本。该方法已编译(Foo)。但这根本不是Java(或C#,C ++,Delphi或我所知道的任何其他语言)的工作方式。您习惯用哪种语言工作?

访问器方法本身(例如getDee())是继承的,但实例变量不是。

如果实例变量可以在子类中被覆盖(如您在此处尝试执行的操作),则将导致比解决的问题更多的问题。

这就是我试图找出的。 它会引起什么问题?

那静态变量呢?

嗯,我想到我要给出的答案介于"您不应该那样做"和"为什么要那样做?"之间。 因此,请原谅我去寻找参考文献。 :)

至于第二个"问题" ...

Actually, I'm seeing something weird and undeterministic still...

...

"...System.out.println(baz.getDee()); // 'DEE' but would expect 'dee'"

如果在发布问题以查看实际结果之前运行程序,这将很有用。

这就是我得到的。如您所料,它是"迪"。

您可以通过创建文件,编译并运行它们来亲自查看它,如下所示:

C:\oreyes\samples\java\dee>type DeeDum.java Foo.java Bar.java Baz.java Test.java

DeeDum.java

public interface DeeDum {

public String getDee();

public String getDum();

}

Foo.java

public class Foo implements DeeDum {

public String dee ="D";

public String dum;

public String getDee() { return dee; }

public String getDum() { return dum; }

}

Bar.java

public class Bar extends Foo {

{

dee ="DEE";

dum ="DUM";

}

}

Baz.java

public class Baz extends Foo {

{

dee ="dee";

dum ="dum";

}

}

Test.java

class Test {

public static Bar bar = new Bar();

public static Baz baz = new Baz();

public static void main( String [] args ) {

System.out.println(bar.getDee()); // 'DEE'

System.out.println(baz.getDee()); // 'DEE' but would expect 'dee'

}

}

C:\oreyes\samples\java\dee>javac *.java

C:\oreyes\samples\java\dee>java Test

DEE

dee

C:\oreyes\samples\java\dee>

PEBKAC?

访问器不是问题,这是领域。访问器引用的是Foo.this.dee,而不是单独的Bar.this.dee。

java为属性提供访问器方法_关于继承:Java不继承访问器方法吗?相关推荐

  1. java怎么访问私有类_如何从Java类的外部访问类的私有方法?

    您可以使用java反射包访问类的私有方法. 步骤1-通过传递声明为私有的方法的方法名称来实例化java.lang.reflect包的Method类. 步骤2-通过将值true传递给setAccessi ...

  2. java怎么区分变量和方法_如何测试Java的变量和方法

    方法二:利用安全管理器 安 全性管理器与反射机制相结合,也可以达到我们的目的.Java 运行时依靠一种安全性管理器来检验调用代码对某一特定的访问而言是否有足够的权限.具体来说,安全性管理器是 java ...

  3. 基于matlab的fisher线性判别及感知器判别_基于嵌入表示的网络实体对齐方法进展概述...

    网络实体对齐是指给定两个网络,把两个网络中等价的实体合并.实体对齐在很多领域都有重要应用,比如,跨平台社交网络的用户对齐可以用于用户画像.用户兴趣挖掘,跨语言知识图谱的实体对齐可以辅助机器翻译.跨语言 ...

  4. java中的invoke方法_详解Java中Method的Invoke方法

    在写代码的时候,发现从父类class通过getDeclaredMethod获取的Method可以调用子类的对象,而子类改写了这个方法,从子类class通过getDeclaredMethod也能获取到M ...

  5. 直接访问静态图片_详解nginx和tomcat访问图片和静态页面的配置方法

    概述 生产环境下,有时候需要访问图片,正常需要应用ftp.nginx等配套使用,但是有时候为了简化,可以用以下的两种简单的访问,说实话,就是为了偷懒,但是效果是能有的,这就行了,所以今天做这个简化版的 ...

  6. java时间中间加横杠方法_知识点:java一些方法会有横线?以Date 过期方法为例...

    原因:他们的开发者在升级方法后,添加了@Deprecated注释, 目的是为了提醒我们,这个方法现在已经有新的方法了,不建议继续使用! 比如: JAVA中Date的tolocalstring为什么不建 ...

  7. java 异步调用方法_乐字节Java编程之方法、调用、重载、递归

    一.概述 方法是指人们在实践过程中为达到一定目的和效果所采取的办法.手段和解决方案. 所谓方法,就是解决一类问题的代码的有序组合,是一个功能模块.编程语言中的方法是组合在一起来执行操作语句的集合.例如 ...

  8. java中gettext方法_深入理解Java中方法的参数传递机制

    形参和实参 我们知道,在Java中定义方法时,是可以定义参数的,比如: public static void main(String[] args){ } 这里的args就是一个字符串数组类型的参数. ...

  9. java JLabel改变大小后如何刷新_到底一行java代码是如何在计算机上执行的

    不知道你是否思考过,每次我们在IDEA中右键Run Application启动主方法,假如程序运行正常,控制台也打印出了你所要打印的信息,在这个过程中你知道这台计算机上那些硬件及其软件都是以什么样的方 ...

最新文章

  1. Keras【Deep Learning With Python】实现线性回归模型
  2. document对象相关信息
  3. c 语言冒泡排序,c 语言冒泡排序
  4. Web服务之四:httpd虚拟主机
  5. 卸载idea2020不干净_强制卸载软件程序、以及清理注册表
  6. 前端之 BOM 和 DOM
  7. 一个自动化测试的案例之记事狗微博篇
  8. 使用阿里云镜像仓库构建国外 Docker 镜像
  9. netcat,nmap常用例子
  10. 美国在线教育的启示:教育领域正在革命
  11. 利用obs技术进行推流直播
  12. 读书、生活经典语录随笔
  13. MySQL安装教程包含所有平台(图解),MySQL下载步骤详解(带安装教程)
  14. 十年电影票房数据爬取与分析 | 免费数据教程
  15. mysql-mmm的搭建
  16. 018-JL,JNGE JLE,JNG JG,JNLE JGE,JNL带符号条件转移指令小结
  17. go sync.Mutex
  18. 二狗子的C语言学习之路(数组)
  19. 图片合成gif如何做?怎样将图片合成动图效果?
  20. uni-app实现PDA的离线语音(二)MT-TTS离线语音合成插件下载及集成

热门文章

  1. 刷脸打卡真的太方便了
  2. ​怎么翻译一段音频文件?教你轻松翻译音频文件方法
  3. Go标准库日志打印,以及同时输出到控制台和文件
  4. 设计和《金瓶梅》——那点不得不说的事
  5. GridView导出Excel的超好例子
  6. 达梦数据库架构和其它数据库架构的区别
  7. OSG官网——GettingStarted翻译
  8. 交换机上如何测试出口带宽速度_万兆NAS模拟测试:是什么限制了性能?
  9. 什么是生命周期,分为几个阶段
  10. 使用IDEA创建一个通过url链接生成二维码的java程序|自动生成二维码