Java面向对象(OOP)--static修饰符(static变量static方法代码块和静态代码块创建和初始化对象的过程静态导入)

Posted Z && Y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java面向对象(OOP)--static修饰符(static变量static方法代码块和静态代码块创建和初始化对象的过程静态导入)相关的知识,希望对你有一定的参考价值。

1. static修饰符


1.1 static变量

在类中,使用static修饰的成员变量,就是静态变量,反之为非静态变量。

静态变量和非静态变量的区别

  • 静态变量属于类的,"可以"使用类名来访问,非静态变量是属于对象的,"必须"使用对象来访问

示例:

public class Student {
    private static int age;
    private double score;

    public static void main(String[] args) {
        Student s = new Student();
        //推荐使用类名访问静态成员
        System.out.println(Student.age);
        System.out.println(s.age);
        System.out.println(s.score);
    }
}

  • 静态变量对于类而言在内存中只有一个,能被类的所有实例所共享。实例变量对于类的每个实例都有一份,它们之间互不影响。

示例:

public class Student {
    private static int count;
    private int num;

    public Student() {
        count++;
        num++;
    }

    public static void main(String[] args) {
        //因为还是在类中,所以可以直接访问私有属性
        Student s1 = new Student();
        Student s2 = new Student();
        System.out.println("s1.num: " + s1.num);
        System.out.println("s2.num: " + s2.num);
        System.out.println("Student.count: " + Student.count);
        System.out.println("s1.count: " + s1.count);
        System.out.println("s2.count: " + s2.count);
    }
}

小结

  • 在加载类的过程中为静态变量分配内存,实例变量在创建对象时分配内存,所以静态变量可以使用类名来直接访问,而不需要使用对象来访问.

1.2 static方法

在类中,使用static修饰的成员方法,就是静态方法,反之为非静态方法。

静态方法和非静态方法的区别:

  • 静态方法数属于类的,"可以"使用类名来调用,非静态方法是属于对象的,"必须"使用对象来调用。

  • 静态方法"不可以"直接访问类中的非静态变量和非静态方法,但是"可以"直接访问类中的静态变量和静态方法

  • 非静态方法"可以"直接访问类中的非静态变量和非静态方法,也"可以"直接访问类中的静态变量和静态方法

  • 注意:this和super在类中属于非静态的变量.(静态方法中不能使用)

  • 父类的静态方法可以被子类继承,但是不能被子类重写

  • 父类的非静态方法不能被子类重写为静态方法


1.3 思考:为什么静态方法和非静态方法不能直接相互访问? 加载顺序的问题!

究其原因是因为类加载机制:有static关键字修饰,会先加载在内存中,且只执行一次。


1.4 代码块和静态代码块

【类中可以编写代码块和静态代码块】

【匿名代码块和静态代码块的执行】

  • 因为没有名字,在程序并不能主动调用这些代码块。
  • 匿名代码块是在创建对象的时候自动执行的,并且在构造器执行之前。同时匿名代码块在每次创建对象的时候都会自动执行.
  • 静态代码块是在类加载完成之后就自动执行,并且只执行一次.。注:每个类在第一次被使用的时候就会被加载,并且一般只会加载一次。

示例

public class Person {
    {
        System.out.println("匿名代码块");
    }

    static {
        System.out.println("静态代码块");
    }

    public Person() {
        System.out.println("构造器");
    }

    public static void main(String[] args) {
        Person s1 = new Person();
        System.out.println();
        Person s2 = new Person();
        System.out.println();
        Person s3 = new Person();
    }
}

【匿名代码块和静态代码块的作用】

  • 匿名代码块的作用是给对象的成员变量初始化赋值,但是因为构造器也能完成这项工作,所以匿名代码块使用的并不多。
  • 静态代码块的作用是给类中的静态成员变量初始化赋值。

例如:
注:在构造器中给静态变量赋值,并不能保证能赋值成功,因为构造器是在创建对象的时候才指向,但是静态变量可以不创建对象而直接使用类名来访问.


1.5 创建和初始化对象的过程

对于: Student s = new Student();

【Student类之前没有进行类加载】

  1. 类加载,同时初始化类中静态的属性
  2. 执行静态代码块
  3. 分配内存空间,同时初始化非静态的属性(赋默认值,0/false/null)
  4. 调用Student的父类构造器
  5. 对Student中的属性进行显示赋值(如果有的话)
  6. 执行匿名代码块
  7. 执行构造器
  8. 返回内存地址

注:子类中非静态属性的显示赋值是在父类构造器执行完之后和子类中的匿名代码块执行之前的时候

public class Person {
    public Person() {
        System.out.println("Person构造器");
    }
}

class Student extends Person {
    private String name = "tom";

    {
        System.out.println("name = " + name);
        System.out.println("Student匿名代码块");
    }

    static {
        System.out.println("Student静态代码块");
    }

    public Student() {
        System.out.println("Student构造器");
    }

    public static void main(String[] args) {
        new Student();
    }
}

【Student类之前已经加载过(不会执行上面的一二步骤)】

1.分配内存空间,同时初始化非静态的属性(赋默认值,0/false/null)
2.调用Student的父类构造器
3.对Student中的属性进行显示赋值(如果有的话)
4.执行匿名代码块
5.执行构造器
6.返回内存地址

public class Person {
    public Person() {
        System.out.println("Person构造器");
    }
}

class Student extends Person {
    private String name = "tom";

    {
        System.out.println("name = " + name);
        System.out.println("Student匿名代码块");
    }

    static {
        System.out.println("Student静态代码块");
    }

    public Student() {
        System.out.println("Student构造器");
    }

    public static void main(String[] args) {
        new Student();
        System.out.println();
        new Student();
    }
}


1.6 静态导入

  • 静态导包就是java包的静态导入,用import static代替import,静态导入包是JDK1.5中的新特性。意思是导入这个类里的静态方法。
  • 好处:这种方法的好处就是可以简化一些操作,例如打印操作System.out.println(…);就可以将其写入一个静态方法print(…),在使用时直接print(…)就可以了。但是这种方法建议在有很多重复调用的时候使用,如果仅有一到两次调用,不如直接写来的方便。

示例:



以上是关于Java面向对象(OOP)--static修饰符(static变量static方法代码块和静态代码块创建和初始化对象的过程静态导入)的主要内容,如果未能解决你的问题,请参考以下文章

Java面向对象(OOP)--final修饰符 & abstract修饰符

Java面向对象_static修饰符

Java面向对象(OOP)--内部类(静态内部类)

面向对象编程(OOP)————修饰符

面向对象编程(OOP) 权限修饰符

java面向对象之static修饰符