class A
{
public A()
{
System.out.println("aaaaaaaaa");
}
}
class B
{
public B()
{
System.out.println("bbbbbbbbbbb");
}
}
class Aa
{
private static A a=new A();
private static B b=new B();
public Aa()
{
System.out.println("111111111");
f();
}
private A aaa=new A();
private void f()
{
System.out.println("ffffffffff");
}
}
public class TestExtend extends Aa{
public TestExtend()
{
super();
System.out.println("subclass");
}
public static void main(String[] args)
{
TestExtend test=new TestExtend();
}
}输出:
aaaaaaaaa
bbbbbbbbbbb
aaaaaaaaa
111111111
ffffffffff
subclass谁来解释下为什么运行结果是这样的?
{
public A()
{
System.out.println("aaaaaaaaa");
}
}
class B
{
public B()
{
System.out.println("bbbbbbbbbbb");
}
}
class Aa
{
private static A a=new A();
private static B b=new B();
public Aa()
{
System.out.println("111111111");
f();
}
private A aaa=new A();
private void f()
{
System.out.println("ffffffffff");
}
}
public class TestExtend extends Aa{
public TestExtend()
{
super();
System.out.println("subclass");
}
public static void main(String[] args)
{
TestExtend test=new TestExtend();
}
}输出:
aaaaaaaaa
bbbbbbbbbbb
aaaaaaaaa
111111111
ffffffffff
subclass谁来解释下为什么运行结果是这样的?
解决方案 »
- 用Math.random()产生13个0~51没有重复的随机数,放入suit数组中
- socket接受的对象是否能用字符流接受?
- 为什么byte数组转为String在转回byte数据,长度就变了呢
- 请问修改了JList的模型如何立即更新?
- 请问现在最流行高效的连接数据库的方式是什么?教科书上的jdbc-odbc早就过时了吧
- 非常想知道答案的面试题~
- 高手请进
- new ServerSocket() 不成功
- 救命,怎样才能产生java.io.IOException异常
- 高手帮忙:我在linux用gcj编译一个java程序,先用javac把其编译为class文件,再用gcj编译,可是出现如下错误,而直接用java虚拟机来执行
- java MD5加密算法问题
- 有人用java做C/S应用的成功案例吗?
{
public Test()
{
System.out.println("tttttttttttttt");
}
}class Father
{
private int i=0;
private String s="8888888888";
private Test t=new Test();
public Father()
{
method_1();
method_2();
method_3();
method_4();
}
protected void method_1()
{
System.out.println("method_1");
}
protected void method_2()
{
System.out.println("method_2");
}
protected void method_3()
{
System.out.println("method_3");
}
protected void method_4()
{
System.out.println("method_4");
}
}public class SubClass extends Father{
public SubClass()
{
super();
method_1();
method_2();
method_3();
method_4();
}
protected void method_1()
{
System.out.println("method_111");
}
protected void method_2()
{
System.out.println("method_222");
}
protected void method_3()
{
System.out.println("method_333");
}
protected void method_4()
{
System.out.println("method_444");
}
public static void main(String[] args)
{
new SubClass();
}
}
还有这段代码.都是我写来测试的.
先是static变量和方法(类初始化),由clinit来初始化;
然后是实例变量,实例模块初始化,构造方法初始化,由init来初始化;
如果有继承关系,则先执行父类的初始化,然后才是子类的!
1.从程序的入口开始.
程序先执行TestExtend test=new TestExtend();
这样就会调用TestExtend的构造方法.
public TestExtend()
{
super();
System.out.println("subclass");
}
你也看到了,这里调用super();换句话说是调用父类的构造方法.然后是打印"subclass".
那么程序会先进入父类中执行,最后才会打印"subclass".从这里就知道为什么"subclass"是最后打印出来的了.2.进入到super()后.先会构造那些类的成员对象.然后是自己的构造方法.
这里静态的有2个a和b.而他们在构造的时候分别打印了"aaaaaaaaa"和"bbbbbbbbbbb";
还有一个aaa.所以会再打印一下"aaaaaaaaa";
这就是你看到前3个输出的结果.然后Aa 这时再构造它自己,这时打印出"111111111".然后它还调用了"f(); "方法.
f(); 方法中打印出了"ffffffffff"以上就是整个的过程了.
另外建议在eclipse进行单步调试,看看程序是怎么执行的
class A
{
public A()
{
System.out.println("aaaaaaaaa");
}
}
class B
{
public B()
{
System.out.println("bbbbbbbbbbb");
}
}
class Aa
{
private static A a=new A(); //1,aaaaaaaaa 静态域首先执行
private static B b=new B(); //2,bbbbbbbbbbb 按顺序
public Aa()
{
System.out.println("111111111"); //4,111111111 打印
f(); //5,ffffffffff 方法调用
}
private A aaa=new A(); //3,aaaaaaaaa 域初始化
private void f()
{
System.out.println("ffffffffff");
}
}
public class TestExtend extends Aa{
public TestExtend()
{
super();
System.out.println("subclass"); //6,subclass 打印
}
public static void main(String[] args)
{
TestExtend test=new TestExtend();
} } 输出:
aaaaaaaaa
bbbbbbbbbbb
aaaaaaaaa
111111111
ffffffffff
subclass
函数体外面的表达试,象
private static A a=new A();
private static B b=new B();
这些在类加载的时候就被先执行了,优先度很高的,接着再调用构造函数,
先是基类的再到子类的,
主要是class创建时,对成员变量、构造函数等的先后顺序。
private 是一个访问修饰符,楼主是不是认为,继承关系是子类无法访问父类的private成员的。对,这一点错都没有。问题是这里你并没去通过子类去访问父类。只是你public class TestExtend extends Aa 装载这个类时,JVM会发现这个类是一个子类所以他会去先装载其父类并初始化父类,以便class TestExtend使用。它只是一个初始化问题,初始化问题是跟访问修饰符没关系的。至于初始化顺序,上几楼都说过了。
所以你这里的super();加不加都无所谓。顺便鄙视一下17楼的hhunter,中国不缺少你这种尖酸刻薄的程序员。
public TestExtend()
{
super();
System.out.println("subclass");
}
调用super()执行父类的构造方法.然后才是打印"subclass".
程序会先进入父类中执行,最后打印"subclass".因为方法要顺序执行嘛
到父类找构造.先会构造那些父类的成员对象.然后是自己的构造方法.
静态的有2个a和b串.而他们在构造的时候分别打印了"aaaaaaaaa"和"bbbbbbbbbbb";
还有一个成员的.所以会再打印一下"aaaaaaaaa";
这就是前3个输出的结果.然后Aa 这时再构造它自己,这时打印出1…….然后它还调用了f()方法.
f(); 方法中打印出了"ffffffffff"
就这样了
我相信在类的初始化顺序上面很多人都说不清,还是谦虚学习比较好,
上面说了很多了,我在补充下,private只是访问权限的控制,子类是会继承父类private的东西的.下面文章可以证明这个事实.只是不能直接访问而已.
http://blog.csdn.net/sunyujia/archive/2008/06/01/2501709.aspx
TestExtend test=new TestExtend(); 需要将TestExtend载入虚拟机
TestExtend继承Aa
所以先将Aa载入虚拟机
默认状况下先载入Aa的static属性
执行private static A a = new A();
新建A的实例调用A的构造器
System.out.println("aaaaaaaaa"); //aaaaaaaaa
同上执行private static B b = new B();
新建B的实例调用B的构造器
System.out.println("bbbbbbbbbbb"); //bbbbbbbbbbb
此时虚拟机载入完成接着要创建TestExtend的实例
public TestExtend() {
super();
System.out.println("subclass");
}
首先执行super();
创建父类Aa的实例(若这里没有显示调用super();虚拟机也会隐式调用其父类无参构造器)
执行构造器实例化之前要先初始化实例变量
private A aaa = new A();
执行了System.out.println("aaaaaaaaa"); //aaaaaaaaa
父类初始化完成
执行构造器
public Aa() {
System.out.println("111111111"); //111111111
f(); //ffffffffff
}
此时父类实例化完成
执行子类实例化
System.out.println("subclass"); //subclass
通过设置多个断点可以验证以上结论
可以看出一个简单的实例化并不是真的那么简单
只是很多事情jvm隐式的完成了
不用我们关心而已
我们只要记住 初始化的顺序就可以了
默认情况下 也就是用new来实例化
执行顺序是先父类后子类
先static
然后实例变量
然后构造器
可以看出一个简单的实例化并不是真的那么简单
只是很多事情jvm隐式的完成了
不用我们关心而已
我们只要记住 初始化的顺序就可以了
默认情况下 也就是用new来实例化
执行顺序是先父类后子类
先static
然后实例变量
然后构造器
掌握这点就足够了