Java Static关键字详解

先思考两个问题:

1.为何要使用Static关键字?

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

Static

一.为何要使用Static关键字?编程

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

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

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

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

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

 

2.static修饰属性和方法对象

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

 

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初始化
     *///~
}
相关文章
相关标签/搜索