对象属性初始化有3种
- 声明该属性的时候初始化
- 构造方法中初始化
- 初始化块
类属性初始化有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);
}
}
终极总结:
顺序, 静态成员初始化 -->静态代码块初始化 -->普通对象成员初始哈 -->普通代码块初始化-->构造方法初始化