class A{
static{
System.out.print("1");
}
public A(){
System.out.print("2");
}
}
class B extends A{
static{
System.out.print("a");
}
public B(){
System.out.print("b");
}
}
public class Hello{
public static void main(String[] ars){
A ab = new B(); //执行到此处,结果:
ab = new B(); //执行到此处,结果:
}
}
各位大哥,帮下忙,结果是什么呀,能不能解释一下?
解释好了再加100
static{
System.out.print("1");
}
public A(){
System.out.print("2");
}
}
class B extends A{
static{
System.out.print("a");
}
public B(){
System.out.print("b");
}
}
public class Hello{
public static void main(String[] ars){
A ab = new B(); //执行到此处,结果:
ab = new B(); //执行到此处,结果:
}
}
各位大哥,帮下忙,结果是什么呀,能不能解释一下?
解释好了再加100
所以结果是:
A ab = new B(); //执行到此处,结果:
a12b
ab = new B(); //执行到此处,结果:
2b
仅供参考!
2b看看这两篇blog
http://blog.csdn.net/wong_q/archive/2007/07/29/1714955.aspxhttp://hi.baidu.com/dxcmd/blog/item/21fd434e930dabf3d72afc71.html
ab = new B();
个人理解 执行A ab = new B();先执行new B()加载类B,有父类,然后找到父类A加载,加载后执行static
所以先有1然后是a然后执行public B(),有父类,所以先调用public A();打印2,然后是B
ab = new B();
由于static只有在文件加载时执行一次,所以这次不执行,执行public B(),有父类,所以先调用public A();所以先调用public A();打印2,然后是B
就是这个结果了
类加载时先加载静态代码块所以是1a
调用父类构造方法,在调用子类构造方法所以打印2b
ab=new B();
因为静态代码块只加载一次所以不用在加载,所以现在只打印2b
所以打印结果为1a2b2b
楼主的疑惑应该是出在static关键字方面的问题,就是静态方法会在什么时候初始化。
我们经常调用类中的静态方法的时候,一般只用类名,就可以看到他所有的静态方法,而不用产生任何的实例对象。所有可以看出静态方法(或代码块)的初始化会在new一个实例前就执行,且只初始化一次。
所以在A ab = new B(); 的时候就出现以下过程。先执行父类静态代码块--》子类静态代码块--》父类构造方法--》子类构造方法。所有出现的结果应该是1a2b当再执行new B()时,就只执行对应构造方法就可以啦,结果应该还是2b以上的解释,希望楼主明白类的基本初始化过程。
执行A ab = new B();时,JVM第一步会先加载B类的父类(也就是A类),所以第一步会执行A类中的static{...}静态块,然后JVM再加载B类,再执行B类中的static{...}。
等两个类加载完以后,这时才会执行B类的构造方法。但是,在执行子类的构造方法之前会默认先调用父类的构造方法。这时JAVA预言的规则,改不了的。所以到此为止执行的结果为:1a2b。当执行ab = new B();时,不需要再加载A类和B类了,所以两个类中的static{...}块也不用再执行了。只执行B类的构造方法。同样是先调用父类的构造方法后,再执行自己的构造方法。所以执行的结果是2b。总的结果自然就是1a2b2b了。说的够详细了,LZ应该明白了吧。
静态代码块只加载一次
1)也就是说静态代码块执行的优先级高于构造方法。也就是说为什么1和a会在2和b的前面。
2)B类继承A类,在new B();时调用B类的构造方法,但B类首先调用它父类A的无参构造方法,然后在调用自己的构造方法。也就是为什么总是先输出2后输出b了。
整个顺序是随之A类B类出现的顺序执行A类中的静态代码块,B类中的静态代码块。接着执行构造方法.new B类
首先调用A类构造方法,再调用自身。
over ,楼主给分哈...
会先执行 静态代码快 所以 是 1 a 然后执行构造方法(先执行父类后执行子类)
所以是 2b然后在看这句
应为静态代码块不能重复执行 所以只执行构造方法
所以是 2b
ab = new B(); //执行到此处,结果: la2b2b
调用子类的构造时,会先调用父类的构造,调用构造前会先加载静态代码块,且静态代码快只加载一次。
还是1a2b, 2b呀
class A{
static{
System.out.print("1");
}
public A(){
System.out.print("2");
}
}
class B extends A{
static{
System.out.print("a");
}
public B(){
System.out.print("b");
}
}
public class Hello{
public static void main(String[] ars){
A ab = new B(); //执行到此处,结果:
ab = new B(); //执行到此处,结果:
}
} 楼上说得挺好的
static块会在类加载的时候执行一次,后面再用刀该类就不会再执行了。在用构造方法构造类的实例的时候如果是第一次加载类的话会先调用静态块的代码,然后再调用构造方法。调用子类构造方法时如果子类没有显示指出要调用的父类构造方法,那么子类会调用父类的默认构造方法。
所以:执行这句A ab = new B();时,因为B继承了A,所以类A要优先于类B加载进JVM,因此会先执行A的静态块、然后是B的静态块,由于B的构造方法没有显示的指出要调用的父类(A)的构造方法,因此在执行B的构造方法之前会先调用A的构造方法。调用顺序为:A的静态块、B的静态块、A的构造方法、B的构造方法,输出结果也就是1a2b。执行ab = new B();时,由于类A、B都已经加载过了,所以静态块就不再执行了,同理在执行B的构造方法前会先执行A的默认构造方法,即输出结果为:2b.
class B extends A{
static{
System.out.print("a");
}
public B(){
super();//调用父类构造方法,jdk编译时加上
System.out.print("b");
}
}
题:给你两个类的代码,它们之间是继承的
关系,每个类里只有构造器方法和一些变量,构造器里可能还有一段代码对变量值进行了某
种运算,另外还有一些将变量值输出到控制台的代码,然后让我们判断输出的结果。这实际
上是在考查我们对于继承情况下类的初始化顺序的了解。
我们大家都知道,对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化
顺序依次是(静态变量、静态初始化块)>(变量、初始化块)>构造器。我们也可以通过下
面的测试代码来验证这一点:
Java 代码
public class InitialOrderTest {
// 静态变量
public static String staticField = "静态变量";
// 变量
public String field = "变量";
// 静态初始化块
static {
System.out.println(staticField);
System.out.println("静态初始化块");
}
// 初始化块
{
System.out.println(field);
System.out.println("初始化块");
}
// 构造器
public InitialOrderTest() {
System.out.println("构造器");
}
public static void main(String[] args) {
new InitialOrderTest();
}
}运行以上代码,我们会得到如下的输出结果:
1. 静态变量
2. 静态初始化块
3. 变量
4. 初始化块
5. 构造器
这与上文中说的完全符合。那么对于继承情况下又会怎样呢?我们仍然以一段测试代码来获
取最终结果:
Java代码 :
class Parent {
// 静态变量
public static String p_StaticField = "父类--静态变量";
// 变量
public String p_Field = "父类--变量";
// 静态初始化块
static {
System.out.println(p_StaticField);
System.out.println("父类--静态初始化块");
}
// 初始化块
{
System.out.println(p_Field);
System.out.println("父类--初始化块");
}
// 构造器
public Parent() {
System.out.println("父类--构造器");
}
}
public class SubClass extends Parent {
// 静态变量
public static String s_StaticField = "子类--静态变量";
// 变量
public String s_Field = "子类--变量";
// 静态初始化块
static {
System.out.println(s_StaticField);
System.out.println("子类--静态初始化块");
}
// 初始化块
{
System.out.println(s_Field);
System.out.println("子类--初始化块");
}
// 构造器
public SubClass() {
System.out.println("子类--构造器");
}
// 程序入口
public static void main(String[] args) {
new SubClass();
}
}运行一下上面的代码,结果马上呈现在我们的眼前:
1. 父类--静态变量
2. 父类--静态初始化块
3. 子类--静态变量
4. 子类--静态初始化块
5. 父类--变量
6. 父类--初始化块
7. 父类--构造器
8. 子类--变量
9. 子类--初始化块
10.子类--构造器
现在,结果已经不言自明了。大家可能会注意到一点,那就是,并不是父类完全初始化完毕
后才进行子类的初始化,实际上子类的静态变量和静态初始化块的初始化是在父类的变量、
初始化块和构造器初始化之前就完成了。
那么对于静态变量和静态初始化块之间、变量和初始化块之间的先后顺序又是怎样呢?是否
静态变量总是先于静态初始化块,变量总是先于初始化块就被初始化了呢?实际上这取决于
它们在类中出现的先后顺序。我们以静态变量和静态初始化块为例来进行说明。
同样,我们还是写一个类来进行测试:
Java 代码
public class TestOrder {
// 静态变量
public static TestA a = new TestA();
// 静态初始化块
static {
System.out.println("静态初始化块");
}
// 静态变量
public static TestB b = new TestB();
public static void main(String[] args) {
new TestOrder();
}
}
class TestA {
public TestA() {
System.out.println("Test--A");
}
}
class TestB {
public TestB() {
System.out.println("Test--B");
}
}运行上面的代码,会得到如下的结果:
1. Test--A
2. 静态初始化块
3. Test--B
可以随意改变变量a、变量b以及静态初始化块的前后位置,就会发现输出结果随着它
们在类中出现的前后顺序而改变,这就说明静态变量和静态初始化块是依照他们在类中的定
义顺序进行初始化的。同样,变量和初始化块也遵循这个规律。
了解了继承情况下类的初始化顺序之后,如何判断最终输出结果就迎刃而解了。
A ab = new B(); //1a2b
ab = new B(); //2b分析:从main()方法看起,A ab = new B(); 由于 B继承于A,所以先执行A中的static块,再执行B中的static块.然后分别是A的构造方法和B的构造方法A()和B().
第二句:ab = new B();
相当于再new 一个B对象,把其引用传给ab.
前面A ab = new B(); 执行后,static块不再执行,因为static只执行一次.所以第二句话就是A()和B().知识点:1,static 块先执行,并且只执行一次.
2,子类对象的构造方法会先调用基类的构造方法.
//1a2b
ab = new B();
//2b
static{
System.out.print("1");
}
public A(){
System.out.print("2");
}
}
class B extends A{
static{
System.out.print("a");
}
public B(){
System.out.print("b");
}
}
public class Hello{
public static void main(String[] ars){
A ab = new B(); //执行到此处,结果:
ab = new B(); //执行到此处,结果:
}
} 答案是:1a2b2b
从父类到子类实例化
实例化顺序:
父类静态块
子类静态块
父类构造函数
子类构造函数静态块只会实例化一次,所以ab = new B(); 只会输出2b 而A ab = new B();输出1a2b
2.但我们在使用Java类是首先会把有关该类的信息家在到内存中(用static修饰的东西是属于类的而不是某个具体事例的当然只有一份),同时会初始化一些static的熟悉和函数当然还有static修饰的静态块。3.在new出来一个对象时必须先调用父类的构造方法,这就和我们和我们的父亲的关系一样没有父亲哪来的我们。
4.分析并的出结果。
4.1 A ab = new B();//当new出一个B对象时必须先加载A类到内存然后调用其构造方法,再加载B类到内存并调用构造方法
结果会输出 1a2b 。
4.2 ab = new B(); //在执行这句时由于A类已经加载到内存中所以只调用构造方法,同理B也只调用构造方法
结果只输出2b。