JAVA非访问控制修饰符详解

JAVA非访问控制修饰符包括: final, abstract, static,synchronized 和 volatile。

final 关键字

含义: 最终的,不可被改变的
用途: 用于修饰类、方法、属性和变量。
特性:

  1. 用final修饰类时,被修饰的类不可以被继承。final类中的所有成员方法都会被隐式地指定为final方法。
  2. 用final修饰方法时,被修饰的方法不能被重写。在早期的Java版本中被final修饰的方法会转为内嵌调用从而提升性能。(注:类的private方法会隐式地被指定为final方法。)
  3. 用fina修饰的变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。(注:用fianl修饰的类属性变量必须进行初始化(包括在构造方法中初始化))

static 关键字

含义: 静态的,全局的
用途: 用于修饰类、方法、变量和代码块。
描述: static关键字表示静态的,全局的可以用来修饰类、方法、变量和代码块。在通常的开发中最常见的是用static修饰的成员变量和成员方法,被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象,可以通过类名加“.”进行直接访问。
无论是变量,方法,还是代码块,只要用static修饰,就是在类被加载时就已经"准备好了",也就是可以被使用或者已经被执行,都可以脱离对象而执行。反之,如果没有static,则必须要依赖于对象实例。

特性:

  1. 如果一个类要被声明为static的,只有一种情况,就是静态内部类。静态内部类可以声明普通成员变量和方法,而普通内部类不能声明static成员变量和方法。
  2. 用static修饰的代码块也叫静态代码块,是在类中独立于类成员的static语句块,它不在任何的方法体内,可以有多个,位置可以随便放,JVM加载类时会执行这些静态的代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。
  3. 用static修饰的方法,只能调用static变量和static方法,不能以任何形式引用this和super,是抽象方法abstract
  4. 用static修饰的变量,在定义时必须要进行初始化,且初始化时间要早于非静态变量。

native 关键字

含义: 原生的,本地的
用途: 用于修饰方法
描述: native关键字用来修饰方法。被native关键字修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。Java不是完美的,Java的不足除了体现在运行速度上要比传统的C++慢许多之外,Java语言本身不能对操作系统底层进行访问和操作(如系统硬件等),为此Java使用native方法来扩展Java程序的功能,通过JNI接口调用其他语言来实现对底层的访问。

volatile 关键字

含义: 易变的,不稳定的
用途: 用于修饰变量
描述: Java 语言中用 volatile 修饰的变量通常是为了保证不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。volatile是Java提供的一种轻量级的同步机制,在并发编程中,它也扮演着比较重要的角色,可以被看作是一种 “程度较轻的 synchronized ”。与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是 synchronized 的一部分。

特性:

  1. 保证内存可见。 当一个共享变量被 volatile 修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去主存中读取新值。也就是每次取值在都会取内存中的值,每次更新都会立即更新主存中的值。

  2. 禁止指令重排。 volatile 关键字能禁止指令重排序,所以 volatile 能在一定程度上保证有序性。volatile 关键字禁止指令重排序有两层意思,1)当程序执行到 volatile 变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见,在其后面的操作肯定还没有进行;2)在进行指令优化时,不能将在对 volatile 变量访问的语句放在其后面执行,也不能把 volatile 变量后面的语句放到其前面执行。

注意:

volatile 无法保证对变量的任何操作都是原子性,可以采用 synchronized,Lock 或用java.util.concurrent.atomic 包下提供了一些原子操作类来保证操作的原子性。

synchronized 关键字

含义: 同步,在时间上一致,同速进行
用途: 用于修饰方法和代码块。
描述: Java 语言中用 synchronized 修饰方法和代码块来控制在同一时刻只有一个线程执行该段代码,从而保证多并发情况下的数据安全。简单讲 synchronized 就是给修饰的方法或代码块声明一个锁,拥有这个锁的线程可以执行区块里面的指令,其他的线程只能等待获取锁,然后才能执行相同的操作。用synchronized 修饰方法和代码块通常被称为“加锁”。

特性:

类锁: 当 synchronized 修饰静态方法或 synchronized 修饰代码块时传入某个class对象(synchronized (XXXX.class))时被称为类锁。某个线程得到了一个类锁之后,其他所有被该类锁加锁方法或代码块是锁定的, 其他线程是无法访问的,但是其他线程还是可以访问没有被该类锁加锁的任何代码。

  1. 对象锁: 当 synchronized 修饰非静态方法或 synchronized 修饰代码块时传入非class对象(synchronized this))时被称为对象锁。某个线程得到了对象锁之后,该对象的其他被 synchronized修饰的方法(同步方法)是锁定的,其他线程是无法访问的。但是其他线程还是可以访问没有进行同步的方法或者代码;当获取到与对象关联的内置锁时,并不能阻止其他线程访问该对象,当某个线程获得对象的锁之后,只能阻止其他线程获得同一个锁。

  2. 类锁和对象锁的关系: 如同每个类只有一个class对象而类的实例可以有很多个一样,每个类只有一个类锁,每个实例都有自己的对象锁,所以不同对象实例的对象锁是互不干扰的。但是有一点必须注意的是,其实类锁只是一个概念上的东西,并不是真实存在的,它只是用来帮助我们理解锁定实例方法和静态方法的区别的。类锁和对象锁是不一样的锁,是互相独立的,两者不存在竞争关系,线程获得对象锁的同时,也可以获得该类锁,即同时获得两个锁,这是允许的。

  3. 其他特性: 因为被 synchronized 修饰的代码在同一时刻只有一个线程执行,所以也就保证了操作的原子性和内存可见性。

总结: synchronized 的本质就是给一段代码加个锁,来保证同一时刻只有一个线程执行该段代码。所以不管是类锁还是对象锁,被加锁了的代码,每个线程只有获取了对应的锁之后才能执行,未加锁的代码任何情况下都能立即执行。

你可能感兴趣的:(java,java)