回顾几个 Java 关键字

温故而知新,却还是那一套。

static 关键字

  1. static 方法:一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问。但是要注意的是,虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。
  2. static 变量:也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
  3. static 代码块:用来形成静态代码块以优化程序性能。在类初次被加载的时候,会按照 static 块的顺序来执行每个 static 块,并且只会执行一次。
  4. static 内部类:如果一个类要被声明为 static 的,只有一种情况,就是静态内部类。静态内部类使用场景一般是当外部类需要使用内部类,而内部类无需外部类资源,并且内部类可以单独创建的时候会考虑采用静态内部类的设计。

    典型应用场景:如果类的构造器或静态工厂中有多个参数,设计这样类时,最好使用 Builder 模式,特别是当大多数参数都是可选的时候,例如 Android 里的 AlertDialog:

    1
    AlertDialog.Builder builder = new AlertDialog.Builder(this).setTitle("标题").setMessage("你好呀").create();

final 关键字

  1. final 类:当用 final 修饰一个类时,表明这个类不能被继承,final 类中的所有成员方法都会被隐式地指定为 final 方法。
  2. final 方法:如果想禁止该方法在子类中被覆盖,可以将方法设置为 final,此外类的 private 方法会隐式地被指定为 final 方法。
  3. final 变量:对于一个 final 变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。

synchronized 关键字

  1. 修饰代码块:被修饰的代码块称为同步语句块,其作用的范围是大括号 {}括起来的代码,作用的对象是调用这个代码块的对象。

    • 一个线程访问一个对象中的 synchronized(this) 同步代码块时,其他试图访问该对象的线程将被阻塞。
    • 当一个线程访问对象的一个 synchronized(this) 同步代码块时,另一个线程仍然可以访问该对象中的非 synchronized(this) 同步代码块。
    • 当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的对象来充当锁:

      1
      2
      3
      4
      5
      private byte[] lock = new byte[0];

      synchronized(lock) {
      // todo 同步代码块
      }
  2. 修饰普通方法:synchronized 修饰方法和修饰一个代码块类似,只是作用范围不一样,修饰代码块是大括号括起来的范围,而修饰方法范围是整个函数。

    • synchronized 关键字不能继承。
    • 在定义接口方法时不能使用 synchronized 关键字。
    • 构造方法不能使用synchronized关键字,但可以使用 synchronized 代码块来进行同步。
  3. 修饰静态方法:由于静态方法是属于类的而不属于对象的所以 synchronized 修饰的静态方法锁定的是这个类的所有对象。
  4. 修饰一个类:synchronized 作用于一个类 T 时,是给这个类 T 加锁,T 的所有对象用的是同一把锁。
    1
    2
    3
    synchronized(ClassName.class) {
    // todo 同步代码块
    }

volatile 关键字

volatile,字面意思是易变的,不稳定的, 一般用于修饰变量。

  1. 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
  2. 禁止进行指令重排序。
    • 当程序执行到 volatile 变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见;在其后面的操作肯定还没有进行;
    • 在进行指令优化时,不能将在对 volatile 变量访问的语句放在其后面执行,也不能把 volatile 变量后面的语句放到其前面执行。
  3. volatile 关键字在某些情况下性能要优于 synchronized,但是要注意 volatile 关键字是无法替代 synchronized 关键字的,因为 volatile 关键字无法保证操作的原子性。

assert 关键字

assert,字面意思是声称,断言,有两种用法:

  1. assert <boolean 表达式>
    如果表达式为 true,则程序继续执行。
    如果为 false,则程序抛出 AssertionError,并终止执行。

  2. assert <boolean 表达式> : <错误信息表达式>
    如果表达式为 true,则程序继续执行。
    如果为 false,则程序抛出 java.lang.AssertionError,并输出<错误信息表达式>。

在 Android 开发中除非在 debug 模式下,否则 assert 根本无法工作,所以不太建议在生产环境下使用 assert,此外主流的 Java IDE 工具默认都没有开启断言检查功能。

  • Android Studio 或者 IDEA 开启 assert 的方式:Tools -> Edit Configurations -> VM options, 输入 -enableassertions 或者 -ea 保存即可。
  • Android 设备开启 assert 检查可以使用以下命令:adb shell setprop debug.assert 1