Skip to content

Java高手训练营第五章第五节:static静态

ufofVincent edited this page Jan 1, 2016 · 1 revision

5.5 static静态

5.5.1 static概述

我们之前在定义字段或者方法时都必须要实例化其所在的类才可以调用。因为这些字段和方法属于实例。 在讲静态之前,先举一个例子: 每一个学生都有自己的课本和笔,但是他们都共用教室里的饮水机。假如说学生是一个类,课本和笔这两个字段是属于实例的、饮水机是大家公用的,所以属于类。

static是一个修饰符。如果一个类的字段/方法属于整个类而非单个实例,可以用static修饰。 没有被声明为static的成员叫做实例成员、反之称之为静态成员。 被声明为static的成员有以下特点:

  • 类一旦被加载、其也被加载
  • 静态成员优先于实例成员
  • 静态成员多了一种被调用的方式:类名.字段名/类名.方法名

5.5.2 static实例

class Resource{
    static int staticNum = 2;                      //定义静态字段
    int num = 7;                                   //定义实例字段
}

class StaticDemo{
    public static void main(String[] args){
        //打印staticNum字段
        System.out.println(Resource.staticNum);    //通过“类名.字段”格式访问静态字段staticNum
        //打印num字段
        Resource mc = new Resource();
        System.out.println(mc.num);                //通过实例mc调用实例字段num
    }
}

结果:

在Resource类当中,定义了一个静态字段叫做staticNum以及一个实例字段num。在主方法中,使用了"Resource.staticNum"格式直接访问了staticNum这个静态字段。没有被声明为static的实例字段num只能通过传统的先实例化然后通过实例访问的方式来访问。

学生提问:既然被声明为static的字段/方法能如此方便的被调用,干脆全部声明为static可以吗?
答:不现实。再引用一下刚才学生的例子。如果每一个学生都给一个饮水机,会很占空间。所以说是否声明为static需要判断这个成员到底是共享的还是实例的。

再写一个静态方法的实例:

class Resource{
    static void staticMethod(){
        System.out.println("我是静态方法");
    }
    void instanceMethod(){
        System.out.println("我是实例方法");
    }
}

class StaticDemo{
    public static void main(String[] args){
        Resource.staticMethod();       //通过“类名.方法”格式调用staticMethod
        Resource r = new Resource();
        r.instanceMethod();            //通过实例化类然后用实例调用instanceMethod方法
    }
}

结果:

和刚才字段的例子一样。staticMethod()是静态方法,所以他可以直接被“Resource.staticMethod()”的方式调用。instanceMethod()是实例方法,必须实例化Resource类然后通过实例才能调用它。

5.5.3 内存中的静态

当一个成员被声明为静态后,其就不会出现在堆内存之中了。其会被调往内存共享区。 而且,静态成员在内存中只有一个实体。不可能像实例成员那样每实例化一个对象就出现一个新的实体。

堆内存中的对象自动获得内存共享区的静态成员。

class Resource{
    static int staticNum = 30;
    int num = 20;
}

class StaticDemo{
    public static void main(String[] args){
        Resource r1 = new Resource();    //实例化
        Resource r2 = new Resource();
        Resource r3 = new Resource();
    }
}

这个程序在内存中是这样的:

5.5.4 注意事项

  • 实例成员不能被“类名.成员”方式调用;
  • 静态成员也可以被“实例.成员”方式调用,但是不建议这样做。因为饮水机是大家的,不是你的;
  • 静态方法只能调用静态方法。因为静态方法更加早加载,那个时候实例方法还没有出生呢;(现在大家可以明白我们在讲方法的时候为什么直接被主方法调用的方法也得要是static了)
  • 实例方法既可以调用静态方法也可以调用实例方法。因为实例方法出生的晚,其他人早就都存在了;
  • 局部变量/常量(就是在方法中定义的变量/常量)不能被声明为静态。因为他的生命周期仅局限于方法当中。不足以被共享。

本章小结:

  • static是一个修饰符。如果一个字段或方法被static修饰,他就成为了一个静态字段/静态方法
  • 被声明为静态的成员多了一种被调用的方式:“类名.成员”
  • 被静态修饰的成员会被调往内存共享区
  • 静态这个知识点有许多的注意事项
Clone this wiki locally