一个关于构造方法的问题

带参构造方法 package cn.hpu.animal; public class CatTest { public static void main(String[] args) { // TODO Auto-generated method stub //对象实例化 Cat one=new Cat("花花",3,"中华田园猫"); Cat two=new Cat(); ... 阅读详情
今天看到一帖子。

原文:
http://community.youkuaiyun.com/Expert/topic/4657/4657161.xml?temp=.0378992
Abstract class A{
  public A(){draw();}
  abstract draw();
}

class B extends A{
  public B(){}
  void draw(){}
}

public class Test{
  public static void main(String[] args){
    B b=new B();
  }
}
根据java里构造函数的递归调用过程,
1,B构造器构造对象的时候先调用A的构造器,
2,而A的构造器则会调用A的draw方法,
3,而B又是实现A的子类,则A的draw方法会调用B的draw方法,这时B又要调用A的构造器,
这样一来不是死循环了?不知道我这样理解对不对,

-----------------------------------------

雨痕解答:

好像不少人都有这样的疑问,其实该问题在《Thinking in Java》中有记述(《Java编程思想》第二版,239页)。为了便于理解,我采用C#来说明,并添加一点代码。
abstract class A
{
  public A()
  {
    Console.WriteLine("A Constructor...");
    Draw();
  }

  public abstract void Draw();
}

class B : A
{
  private int x = 10;

  public B()
  {
    Console.WriteLine("B Constructor...");
    x = 15;
    Console.WriteLine(x);
  }

  public override void Draw()
  {
    Console.WriteLine(x);
    Console.WriteLine("Draw...");
  }
}

class Program
{
  static void Main()
  {
    B d = new B();
  }
}

输出:
A Constructor...
10
Draw...
B Constructor...
15

仔细思考输出结果,你明白了什么?OK,我们接着看看反编译的IL代码。
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed // B构造方法
{
 .maxstack 8
 L_0000: ldarg.0
 L_0001: ldc.i4.s 10
 L_0003: stfld int32 ConsoleApplication1.B::x // 对x赋值
 L_0008: ldarg.0
 L_0009: call instance void ConsoleApplication1.A::.ctor() // 调用A构造方法
 L_000e: nop
 L_000f: nop
 L_0010: ldstr "B Constructor..."
 L_0015: call void [mscorlib]System.Console::WriteLine(string)
 L_001a: nop
 L_001b: ldarg.0
 L_001c: ldc.i4.s 15
 L_001e: stfld int32 ConsoleApplication1.B::x
 L_0023: ldarg.0
 L_0024: ldfld int32 ConsoleApplication1.B::x
 L_0029: call void [mscorlib]System.Console::WriteLine(int32)
 L_002e: nop
 L_002f: nop
 L_0030: ret
}

.method public hidebysig specialname rtspecialname instance void .ctor() cil managed // A构造方法
{
 .maxstack 8
 L_0000: ldarg.0
 L_0001: call instance void object::.ctor()
 L_0006: nop
 L_0007: nop
 L_0008: ldstr "A Constructor..."
 L_000d: call void [mscorlib]System.Console::WriteLine(string)
 L_0012: nop
 L_0013: ldarg.0
 L_0014: callvirt instance void ConsoleApplication1.A::Draw()
 L_0019: nop
 L_001a: nop
 L_001b: ret
}

有没有发现在B构造方法中,调用A构造方法前,就已经对x进行赋值操作。为什么是这样?难道不是先调用A构造方法吗?其实原贴的作者和很多人都犯了一个错误,那就是构造方法究竟是用来创建对象,还是初始化对象。

严格意义上来说创建一个对象的步骤是:
1. 分配对象空间。
2. 创建该对象成员,包括未"初始化"的字段和方法表指针等。
3. 调用构造方法初始化对象成员。

一个 "new B()" 语句实际上包含了上述三个步骤,也就是说在调用构造方法前,未初始化的对象已经存在,其成员空间和成员引用也已经分配,只不过为了安全原因,构造方法初始化失败,CLR就认为创建对象失败而已。既然B对象已经存在,A()中通过callvirt指令调用B.Test也自然不会调用其构造方法了。理解了这点,我们就很容易明白原贴不会引起死循环的原因了。  
Python super()函数:调用父类的构造方法 Python 中子类会继承父类所有的类属性和类方法。严格来说,类的构造方法其实就是实例方法,因此毫无疑问,父类的构造方法,子类同样会继承。但我们知道,Python 是一门支持多继承的面向对象编程语言,如果子类继承的多个父类中包含同名的类实例方法,则子类对象在调用该方法时,会优先选择排在最前面的父类中的实例方法。显然,构造方法也是如此。 阅读详情

相关推荐

从PX4的FRD到Mavros的FLU:手把手教你正确配置`setpoint_raw/local`话题发布无人机目标点

本文详细解析了PX4的FRD与Mavros的FLU坐标系转换问题,手把手教你正确配置`setpoint_raw/local`话题发布无人机目标点。通过实战指南和常见错误排查,帮助开发者避免方向错乱问题,提升无人机控制精度。

weixin_33712987的博客 422

关于一个子类继承父类构造方法问题

来自csdn论坛的一个帖子,问题如下: class A{ public int i=0; A(int m){ i=1; } } class B extends A{ B(int m){ i=2; } } public class E{ public static void main(String ar...

叶遮沉阳的博客 8728

Android 12 HAL开发避坑实录:手把手教你用AIDL在Native层实现一个可开机自启动的Service

本文详细介绍了在Android 12 HAL开发中,如何通过AIDL在Native层实现一个可开机自启动的Service。从环境准备、AIDL接口定义、服务实现到VINTF集成与SELinux策略配置,提供了完整的实战指南,帮助开发者避开常见陷阱,提升开发效率。

weixin_28314575的博客 321

关于Java构造方法的一个问题

关于Java构造方法的一个问题 2013-03-27 23:52921755683 | 分类:JAVA相关 | 浏览428次 以下选项中正确的是() A、 一个class只能定义一个constructor B、 constructor 必须与class同名,但普通方法不能与class同名 C、 class中constructor不可省略 D、 construtcor只会在一个

evilcry2012的专栏 856

# 芯片良率是怎么算出来的?——从泊松到负二项分布,一个芯片测试工程师的视角

- 良率=好Die/总Die,但选错模型可能差17个百分点 - Poisson模型过于悲观,Murphy居中,**Negative Binomial才是业界标配** - 关键不是良率数字,是**跟踪聚类因子α的变化**——它能早几周预警工艺漂移 - Chiplet时代,10颗90%良率的Die封在一起,整体良率只有35%

Freezeblur的博客 654

如何免费访问和使用Gemini API?

Gemini Ultra具有最先进的性能,在几个指标上超过了GPT-4的性能。它是第一个在大规模多任务语言理解基准测试中超越人类专家的模型,该基准测试57个不同学科的世界知识和解决问题的能力。Gemini是谷歌迄今为止开发的最先进、最庞大的AI模型。它为多模态而建,理解并处理不同类型的数据,比如文本、代码、音频、图像和视频。下面我们将加载Masood Aslami的图像,并用它来测试Gemini Pro Vision的多模态性。有了Gemini可以为查询提供图像、音频和文本,获得几乎完美的答案。

java_cjkl的博客 1万+

遇到了一个粗心的问题,实体类的构造方法忘写了。

实体类居然忘写了构造方法,导致映射的时候无法赋值,哎,这种东西居然都……编程编到头大了。

suncky的博客 304

QT-使用ECharts显示地图,还有更多惊艳的图表等待你的使用

QT-使用ECharts显示地图前言一、使用步骤1.下载示例2. QT使用HTML文件配置3.使用HTML文件4. 数据交互及自适应总结注意:这个地图是百度的在线地图,需要百度API密钥和在联网的状态下使用。离线使用图表 前言 我上文QT图表chart-饼状图,使用qt自带的图表库charts来显示图表,实现数据可视化,但是QT自带的图表库显示效果并不佳,通俗说,就是不好看。 然而,有这么一个开源图表库,图表种类极多,并且效果良好,能够实现具有很好的视觉冲击的数据可视化。 它就是Apache ECharts

博咯的博客 4898

写一个使用String的构造方法的时候遇到的小问题

交代背景 使用工具 :idea 使用环境: IO流 当时心情:(╥╯^╰╥) 好了,开始讲一下为什么会遇到这个问题。 **在看IO流中 FileInputStream 中的一个方法。 ** FileInputStream fis = new FileInputStream(); byte[] bys = new byre[10]; int len = fis.read(bys) Syst...

weixin_43590648的博客 5770

用Stata复现经典文献:上市公司全要素生产率(TFP)计算全流程(含LP/OP代码解读)

本文提供了使用Stata软件复现上市公司全要素生产率(TFP)计算的完整实战指南。重点解读了主流的Levinsohn-Petrin(LP)和Olley-Pakes(OP)半参数估计方法,通过详细的数据清洗、变量构建与价格平减步骤,手把手演示了如何准确测算TFP,并强调了LP方法在处理中国上市公司数据时的稳定性和适用性。

b0c1d2的博客 596

初探802.11协议(6)——Wi-Fi 6新特性简介

Wi-Fi 6新机制(特性)介绍

FanFF的博客 1522

关于构造方法的一个有趣的问题:初始化队伍

下面这段代码是有问题的,问题当然是关于构造方法: 1: class A 2: { 3: private: 4: int i; 5: int j; 6: public: 7: A ( int val ) 8: :j ( val ), i ( j...

weixin_30246221的博客 80

17 指挥AI写Mamba相关模型代码,快速适配大模型场景

本文为《30天掌控AI编程:从指令到落地,手把手教你指挥AI写代码》系列第十七篇,属于第三阶段多场景实战核心内容。本篇聚焦当下大模型领域热门的**Mamba架构**,针对零基础大模型开发、无深度学习基础的使用者,拆解指挥AI生成Mamba基础模型、微调适配、推理部署代码的核心方法,覆盖Mamba基础模块搭建、简易序列建模、小样本微调、本地推理等高频场景,提供可直接复用的高质量指令模板、完整可运行代码、环境配置与避坑指南,无需精通Transformer、状态空间模型等底层原理,轻松上手Mamba大模型开发。

coreopt的博客 61

java中类的构造方法与默认构造方法的关系

先看代码1: class Demo_11 { public static void main(String[] args) { A a= new A(); a.print(); } } class A{ String s; public void print(){ System.out.println(s); } } 代码2: class Demo_11 {

yk979057033的专栏 4339

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Activity加入构造方法,必须同时带无参的默认构造方法

Android 2.3.3 Eclipse Version: 3.7.0 LogCat 主要错误:   04-05 14:10:38.163: ERROR/AndroidRuntime(3991): Caused by: java.lang.InstantiationException: com.taobao.htc.manage.Nba 04-05 14:10:38.

DebugLog的专栏 5904

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

构造方法

1 问题设计一个构造方法,参数名分别是String namefloat hpfloat armorint moveSpeed并且在这个构造方法中,调用这个构造方法 。2 方法2.1 带一个参数的构造方法2.2带两个参数的构造方法2.3 带四个参数的构造方法2.4 调用构造方法public class Hero { String name; float hp; float armo...

算法与编程之美 630

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Java中定义一个空参的构造方法

Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造函数,而子类的构造方法中没有用super()来调用父类中特定的构造方法,则编译时将发生出错,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决方法是在父类里加一个不做事且没有参数的构造方法 ...

hanwb1的博客 4197

构造方法:构造方法的格式和执行时机;构造方法的作用;构造方法的注意事项;

构造方法:构造方法的格式和执行时机;构造方法的作用;构造方法的注意事项;

weixin_46589095的博客 454

【Java】构造方法私有化

每一个类中都一定会存在有至少一个构造方法,并且构造方法是产生实例化对象的主要支持。然而构造方法本身也属于方法,那么方法也可以利用private来实现封装,这里将通过构造方法的封装讲解单例设计模式(Singleton) 的基础实现。

m0_74956284的博客 1065

[PowerMock]Mock构造方法失败解决之道

当使用PowerMock来mock一个对象的构造方法: /** * do test for constructor */ @Test public void testConstructor() throws Exception { Hello hello = mock(Hello.class); // mock one object ...

古辛博格 6391

mybatis传递对象参数 有参构造方法的问题(已解决)

闲来复习一下mybatis,结果还找出新问题来了,不错 不错 这是xml 解决办法 加上 无参构造方法 原因 mybatis通过反射来获取mapper,发射通常需要无参构造方法和getset方法,而我当时new student的时候想偷懒,就写了个有参构造方法。结果就没了无参构造方法,就会报错。 ...

Zlucien的博客 756

构造方法的注意事项

我们其实一直在使用构造方法,但是我们没有定义构造方法,那么它是哪来的呢?

JavaCoder_juejue的博客 794

java继承与构造方法_java继承之构造方法

今天被人问得劈头盖脸,回来自己亲自试验一下,感觉还是很爽。下面把代码贴出来。请高手不要笑话我,本人底子差。public class ParentClass {public ParentClass(){System.out.println("default farther class");}public ParentClass(String str){System.out.println("fart...

weixin_39942474的博客 226

为什么子类继承父类后,必须要在子类构造方法中调用父类的构造方法?

一个类在继承一个类之后,是必须要初始化这个父类的,不然你子类继承父类的那些参数,无法初始化,使用时可能会出现异常。所以在子类继承父类后,必须要在子类构造方法中调用父类的构造方法。 eg: public class Test { public static void main(String[] args) { //通过无参构造创建Zi对象并调用baby() Zi xx = new Zi(); xx.baby();//结果为null } } cl

贝贝的博客 1848

【构造方法】调用构造方法

调用构造方法

qq_65258277的博客 417
上一篇: 关于构造方法
下一篇: 面向图形可扩展矢量图形规范:SVG
fjp813
博客等级 码龄23年 4粉丝 97原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值