Java Static关键字详解

先思考两个问题:

1.为什么要使用Static关键字?

2.加了Static关键字修饰后会有什么不同?  

Static

一.为什么要使用Static关键字?

这里摘录一下《Java编程思想(第四版)》里关于static关键字的一段原话:(P29)通常来说,当创建类时,就是在描述那个类的对象的外观与行为。除非用new创建那个对象,否则,实际上并未获得任何对象。执行new来创建对象的时候,数据存储空间才被分配,其方法才供外界调用。有两种情形用上述方法是无法解决的。一种情形是,只想为某特定域分配单一存储空间,而不去考虑究竟要创建多少个对象,甚至根本不需要创建任何对象。另一种情形是,希望某个方法不与包含他的类的任何对象关联在一起。也就是说,即使没有创建对象,也能够调用方法。简单来说,static的主要目的就是创建独立于具体对象的域变量与方法。

二.加了Static关键字修饰会有什么不同?

1.this不能调用被static修饰的属性字段。

   因为被static修饰的会在类加载的时候初始化,被称为类级变量(属于类);而类的实例是在运行的时候初始化,属于对象级变量(属于对象)。

   this是指当前对象的实例,super是指父类对象的实例。this(super)不能调用被static修饰的属性字段的原因:jvm有类加载器,第一次加载时执行static域,jvm会专门划分一个内存区域给static程序块,所以什么时候都可以调用这个被static修饰的属性字段或者方法,属于类。this指针是指向类的对象,在实例化对象时候jvm会在堆区分配给一个具体对象,this指向该对象。所以在静态方法中不能调用非静态属性或者方法,如果在静态方法中使用this关键字,则this无法指向合适的对象。(通俗一点的话:即jvm的类加载机制决定了加载静态会先与非静态,即加载静态的时候非静态属性和方法都不存在)

 

2.static修饰属性和方法

1.static修饰属性时候,即所有该类对象共享一份存储空间。

 

public class StaticTest {
    public static int staticA;
    public int A;
    
    public static void main(String[] args){
       StaticTest test;
       StaticTest A1=new StaticTest();
       StaticTest A2=new StaticTest();
       A1.staticA++;
       A2.staticA++;
       A1.A++;
       A2.A++;
       System.out.println("StaticAInfo:"+A1.staticA+" "+A2.staticA);
       System.out.println("AInfo"+A1.A+" "+A2.A);
    }
}

/** 运行结果
 * StaticAInfo:2 2
 * AInfo1 1
 **/

 

即static修饰的不是某个具体对象所有,而是该类所有对象共有的,StaticTest.staticA只有一份存储空间。

2.static修饰方法时候,类和对象都能调用该方法,没有被static修饰的方法只能被实例化对象调用。

public class StaticTest {
    public static void staticTest(){
        
    }    
    public void test(){
        
    }
      
    public static void main(String[] args){
       StaticTest.staticTest();
       //StaticTest.test();  该调用是错误的
       StaticTest test=new StaticTest();
       test.staticTest();
       test.test();
    }
}

static修饰成员方法最大的作用,就是可以使用"类名.方法名"的方式操作方法,避免了先要new出对象的繁琐和资源消耗,一个static修饰的类中,不能使用非static修饰的成员变量和方法,这很好理解,因为static修饰的方法是属于类的,如果去直接使用对象的成员变量,它会不知所措(不知该使用哪一个对象的属性)。

static修饰成员方法的时候最大的好处是可以节省new一个对象的开销,即可以直接通过类来调用方法。

3.static修饰内部类

一般用的比较少只能用来修饰内部类,一个static修饰的内部类中,不能使用非static修饰的成员变量和方法,这很好理解,因为static修饰的方法是属于类的,如果去直接使用对象的成员变量,它会不知所措(不知该使用哪一个对象的属性)。

4.静态块

class Book{
    public Book(String msg) {
        System.out.println(msg);
    }
}

public class Person {

    Book book1 = new Book("book1成员变量初始化");
    static Book book2 = new Book("static成员book2成员变量初始化");
    
    public Person(String msg) {
        System.out.println(msg);
    }
    
    Book book3 = new Book("book3成员变量初始化");
    static Book book4 = new Book("static成员book4成员变量初始化");
    
    public static void funStatic() {
        System.out.println("static修饰的funStatic方法");
    }
    
    public static void main(String[] args) {
        Person.funStatic();
        System.out.println("****************");
        Person p1 = new Person("p1初始化");
    }
    /**Output
     * static成员book2成员变量初始化
     * static成员book4成员变量初始化
     * static修饰的funStatic方法
     * ***************
     * book1成员变量初始化
     * book3成员变量初始化
     * p1初始化
     *///~
}

在上面的例子中我们可以发现两个有意思的地方,第一个是当我们没有创建对象,而是通过类去调用类方法时,尽管该方法没有使用到任何的类成员,类成员还是在方法调用之前就初始化了,这说明,当我们第一次去使用一个类时,就会触发该类的成员初始化。第二个是当我们使用了类方法,完成类的成员的初始化后,再new该类的对象时,static修饰的类成员没有再次初始化,这说明,static修饰的类成员,在程序运行过程中,只需要初始化一次即可,不会进行多次的初始化

 

class Book{
    public Book(String msg) {
        System.out.println(msg);
    }
}

public class Person {

    Book book1 = new Book("book1成员变量初始化");
    static Book book2;
    
    static {
        book2 = new Book("static成员book2成员变量初始化");
        book4 = new Book("static成员book4成员变量初始化");
    }
    
    public Person(String msg) {
        System.out.println(msg);
    }
    
    Book book3 = new Book("book3成员变量初始化");
    static Book book4;
    
    public static void funStatic() {
        System.out.println("static修饰的funStatic方法");
    }
    
    public static void main(String[] args) {
        Person.funStatic();
        System.out.println("****************");
        Person p1 = new Person("p1初始化");
    }
    /**Output
     * static成员book2成员变量初始化
     * static成员book4成员变量初始化
     * static修饰的funStatic方法
     * ***************
     * book1成员变量初始化
     * book3成员变量初始化
     * p1初始化
     *///~
}

 

   

 

 

 

 

posted @ 2017-10-23 22:04  阿行不太冷  阅读(420)  评论(0编辑  收藏  举报