java基础-对象-练习集锦

对象属性初始化有3种

  1. 声明该属性的时候初始化
  2. 构造方法中初始化
  3. 初始化块

类属性初始化有2种

  1. 声明该属性的时候初始化
  2. 静态初始化块

===========================

练习-属性初始化

对象属性的初始化有三种方式
故意把初始化块,放在构造方法下面,问题:

这三种方式,谁先执行?谁后执行?

package charactor;
  
public class Hero {
    public String name =Hero.getName("属性声明") ;
      
    public Hero(){
        name = Hero.getName("构造方法");
    }
    {
        name = Hero.getName("初始化块");
    }
     
    public static String getName(String pos){
        String result= "name "+pos;
        System.out.println(result);
        return result;
    }
     
    public static void main(String[] args) {
        new Hero();
    }
     
}

=============================
解读静态代码块,构造代块和构造函数的先后顺序。
顺序:
初始化属性-->代码块-->构造函数

静态变量初始化 的 值 只跟随 最后一次 初始化

总结

静态类属性顺序: 1:静态声明 2:静态代码块
普通对象属性顺序:1: 属性声明 2:代码块 3:构造方法

public class Hero {
	public static int a=9;
	static{
		a=10;
	}
	public static void main(String[] args) {
		System.out.println(Hero.a);  //10
	}

	
}
public class Hero {
	public String name ="1";
	public Hero(){
		name ="2";
	}
	{
		name="3";
	}

	public static void main(String[] args) {
		Hero hero = new Hero();
		System.out.println(hero.name);//输出2
	}
}

===============================
static 面试题

1.

至于为什么是这个结果,我们先不讨论,先来想一下这段代码具体的执行过程,在执行开始,先要寻找到main方法,因为main方法是程序的入口,但是在执行main方法之前,必须先加载Test类,而在加载Test类的时候发现Test类继承自Base类,因此会转去先加载Base类,在加载Base类的时候,发现有static块,便执行了static块。在Base类加载完成之后,便继续加载Test类,然后发现Test类中也有static块,便执行static块。在加载完所需的类之后,便开始执行main方法。在main方法中执行new Test()的时候会先调用父类的构造器,然后再调用自身的构造器。因此,便出现了上面的输出结果。

笔记:static代码块 是先于static main()方法执行的, 它是在类加载时 就开始的。 比运行main()还要先
凡是涉及到类加载的时候,就要首先执行static代码块里的东西,如果有继承的话,再继续加载父类,执行父类里的代码块
类的成员属性初始化,再到普通代码块初始化,然后再到构造方法初始化
如果是静态的话, 静态成员属性初始化先,再到静态代码块初始化

这段代码的输出结果是什么?

public class Test {
    Person person = new Person("Test");
    static{
        System.out.println("test static");
    }
     
    public Test() {
        System.out.println("test constructor");
    }
     
    public static void main(String[] args) {
        new MyClass();
    }
}
 
class Person{
    static{
        System.out.println("person static");
    }
    public Person(String str) {
        System.out.println("person "+str);
    }
}
 
 
class MyClass extends Test {
    Person person = new Person("MyClass");
    static{
        System.out.println("myclass static");
    }
     
    public MyClass() {
        System.out.println("myclass constructor");
    }
}

类似地,我们还是来想一下这段代码的具体执行过程。首先加载Test类,因此会执行Test类中的static块。接着执行new MyClass(),而MyClass类还没有被加载,因此需要加载MyClass类。在加载MyClass类的时候,发现MyClass类继承自Test类,但是由于Test类已经被加载了,所以只需要加载MyClass类,那么就会执行MyClass类的中的static块。在加载完之后,就通过构造器来生成对象。而在生成对象的时候,必须先初始化父类的成员变量,因此会执行Test中的Person person = new Person(),而Person类还没有被加载过,因此会先加载Person类并执行Person类中的static块,接着执行父类的构造器,完成了父类的初始化,然后就来初始化自身了,因此会接着执行MyClass中的Person person = new Person(),最后执行MyClass的构造器。

3.这段代码的输出结果是什么?

public class Test {
     
    static{
        System.out.println("test static 1");
    }
    public static void main(String[] args) {
         
    }
     
    static{
        System.out.println("test static 2");
    }
}

自己给自己个考题

package zsc.czy.object;

public class Hero {
	public String name = "hahah";
	public Hero(){
		name ="2";
	}
	static{
		System.out.println("静态代码块");
	}
	{
		System.out.println(name);
	}

	public static void main(String[] args) {
		Hero hero = new Hero();

	}
}

输出:
静态代码块
hahah

package zsc.czy.object;

public class Hero {
	public String name = "hahah";
	public Hero(){
		name ="2";
	}
	static{
		System.out.println("静态代码块");
	}
	{
		System.out.println(name);
	}

	public static void main(String[] args) {

	}
}

以上证明了:
1:在执行开始,先要寻找到main方法,因为main方法是程序的入口,但是在执行main方法之前,必须先加载Hero类,而在加载Hero类时,发现有static块,便执行了static块
2:每new XX() ; 就会加载这个XX类。如果加载XX类的时候发现XX类继承自AA类,因此会转去先加载AA类 ,这里发现有static块,便执行了static块
3:类在加载完之后,就通过构造器来生成对象。而在生成对象的时候,必须先初始化父类的成员变量

自己弄的问题

package zsc.czy.object;

public class Hero {
	public static Hero hero = new Hero();
	static {
		System.out.println("静态代码块");
	}
	public Hero(){
		System.out.println("被初始化了");
	}
	
	
	public static void main(String[] args) {
	}
}

说明了:执行main()方法前,先Hero类加载, 按顺序,先静态成员初始化,再执行静态代码块 ;

package zsc.czy.object;

public class Hero {
	public static Hero hero = new Hero();
	static {
		System.out.println("静态代码块");
	}
	{
		System.out.println("普通代码块");
	}
	public Hero(){
		System.out.println("被初始化了");
	}
	
	
	public static void main(String[] args) {
	}
}

证实了:执行main()方法前,先Hero类加载, 按顺序,先静态成员初始化,执行有new 对象的语句,(顺序,先普通成员初始化,再普通代码块初始化,再到构造函数) 。完后再接着到执行静态代码块 ;

自己想出的题目

package zsc.czy.object;

public class Hero {
	
	public static Hero hero = new Hero();
	
	static {
		System.out.println("静态代码块");
	}
	
	public String name ="1";
	
	{
		name="2";
	}
	
	
	public Hero(){
		System.out.println(name);
	}
	
	
	public static void main(String[] args) {
		
	}
}

自己出的题

package zsc.czy.object;

public class B {
			public static String name="33";   
		
			static {   
				name = "2";
			}
			
		 
			{
				System.out.println("普通代码块");
			}
			
			public B(){
				System.out.println("构造方法");
			}
			
			public static void main(String[] args) {
				System.out.println(B.name);
			}

	}



终极总结:

顺序, 静态成员初始化 -->静态代码块初始化 -->普通对象成员初始哈 -->普通代码块初始化-->构造方法初始化

posted @ 2018-04-25 13:06  Pororo  阅读(262)  评论(0编辑  收藏  举报