Java static关键字使用小结

static修饰类变量和方法

static关键字最常见的用法就是用来修饰类的成员变量和方法。这样创建出的成员变量属于类而非具体的实例,这种用法不再详述。

需要注意的是类方法不能访问instance变量和方法,类方法中不能使用this关键字。

static修饰常量

static结合final用来定义常量,例如:static final double PI = 3.141592653589793;

需要注意的是,定义的常量是基本类型(primitive type)或者字符串类型(String),这种常量是编译器常量(compile-time constant),如果引用外部的编译期常量并且该常量值发生变化,需要对引用外部常量的类重新编译。

static修饰内嵌类

Java内嵌类分为静态内嵌类(nested class)和非静态内嵌类,其中非静态内嵌类也叫内部类(inner class).

不同于内部类(内部类不能定义静态成员),静态内嵌类不能访问外部类的成员。
静态内嵌类实例化:

OuterClass.StaticNestedClass nestedObject =
     new OuterClass.StaticNestedClass();

内部类实例化(先必须创建出外部类实例):

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

static修饰import

为了避免访问其他类的静态成员时必须使用类名来引用,例如double r = Math.cos(Math.PI * theta);,可以用static import:

import static java.lang.Math.PI;
double r = cos(PI * theta);

static import声明不应当被滥用,否则会使代码难于阅读和维护,仅仅在经常使用的静态成员上使用static import。

static修饰代码块

什么是static block

static修饰的代码是类的初始化代码块,没有static关键字修饰的是实例初始化代码块。

类的初始化代码块在类第一次被加载时(被Resolve时)按照代码块定义的顺序执行,由于Java代码是按需加载,有可能被引用类的初始化代码块不会被执行(参见后面的例子)。

public class StaticExample{
    static {
        System.out.println("This is first static block");
    }

    public StaticExample(){
        System.out.println("This is constructor");
    }

    public static String staticString = "Static Variable";

    static {
        System.out.println("This is second static block and "
                + staticString);
    }

    public static void main(String[] args){
        System.out.println("====main start...===");
        StaticExample statEx = new StaticExample();
        StaticExample.staticMethod2();
    }

    static {
        staticMethod1();
        System.out.println("This is third static block");
    }

    public static void staticMethod1() {
        System.out.println("This is static method1");
    }

    public static void staticMethod2() {
        System.out.println("This is static method2");
    }
}

以上代码的执行结果,请注意其中static block和main函数以及本类自己的构造函数的执行顺序:

This is first static block
This is second static block and Static Variable
This is static method1
This is third static block
====main start...===
This is constructor
This is static method2

实例的初始化代码块是当被类实例化时执行,并且执行的时机是在父类构造函数执行完毕,自己的构造函数执行之前。

public class ConstructorBlockExample{

    {
        System.out.println("This is first constructor block");
    }

    public ConstructorBlockExample(){
        System.out.println("This is no parameter constructor");
    }

    public ConstructorBlockExample(String param1){
        System.out.println("This is single parameter constructor");
    }

    public ConstructorBlockExample(String param1, String param2){
        System.out.println("This is two parameters constructor");
    }

    {
        System.out.println("This is second constructor block");
    }

    public static void main(String[] args){
        ConstructorBlockExample constrBlockEx =
                new ConstructorBlockExample();
        ConstructorBlockExample constrBlockEx1 =
                new ConstructorBlockExample("param1");
        ConstructorBlockExample constrBlockEx2 =
                new ConstructorBlockExample("param1", "param2");
    }
}

以上代码的执行结果,请注意其中非static block和几个构造函数的执行顺序,每一次实例化构造函数执行前,非static block的代码均会被执行:

This is first constructor block
This is second constructor block
This is no parameter constructor
This is first constructor block
This is second constructor block
This is single parameter constructor
This is first constructor block
This is second constructor block
This is two parameters constructor

static block的用途

实现一个线程安全的单例Singleton

public class Singleton {
    private static final Singleton instance;

    static {
        try {
            instance = new Singleton();
        } catch (Exception e) {
            throw new RuntimeException("Darn, an error occurred!", e);
        }
    }

    public static Singleton getInstance() {
        return instance;
    }

    private Singleton() {
        // ...
    }
}

实现全局注册信息的初始化

在Android 6.0的framework代码中,一大部分系统服务的注册由新增加的SystemServiceRegistry类来管理,在该类中使用的静态代码块实现了类加载时就注册好所管理的系统服务信息:
(frameworks/base/core/java/android/app/SystemServiceRegistry.java)

final class SystemServiceRegistry {
127    private final static String TAG = "SystemServiceRegistry";
128
...
139
140    static {
141        registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
142                new CachedServiceFetcher<AccessibilityManager>() {
143            @Override
144            public AccessibilityManager createService(ContextImpl ctx) {
145                return AccessibilityManager.getInstance(ctx);
146            }});
147
148        registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class,
149                new CachedServiceFetcher<CaptioningManager>() {
150            @Override
151            public CaptioningManager createService(ContextImpl ctx) {
152                return new CaptioningManager(ctx);
153            }});
...

Reference

  1. http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
  2. http://stackoverflow.com/questions/70324/java-inner-class-and-static-nested-class
  3. http://docs.oracle.com/javase/1.5.0/docs/guide/language/static-import.html
  4. http://stackoverflow.com/questions/2943556/static-block-in-java
  5. https://en.wikipedia.org/wiki/Singleton_pattern
  6. http://www.jusfortechies.com/java/core-java/static-blocks.php
  7. http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值