Java 中的修饰符

Java的修饰符主要分为两种

  • 访问修饰符
  • 非访问修饰符

访问修饰符

访问修饰符用于控制对类、方法、变量的访问权限,使用中有private、default、protected、public四个修饰符,其访问权限从小到大。其中default不是一个保留字,而是当任何修饰符都不加的时候的默认权限。

四种修饰符的区别如下所示

修饰符 属性
private 仅对同一个类(class)内部可见
default 对同一个包(package)内的所有类可见
protected 对同一个包内的所有类及其子类可见(即使子类在另外一个包)
public 对所有包的所有类均可见

访问权限的继承的一个原则就是子类从父类继承过来的方法和变量的访问权限只能变大,private除外,因此就有了以下几条原则

  • 父类中声明为public的方法在子类中也必须为public。
  • 父类中声明为protected的方法在子类中要么声明为protected,要么声明为public。不能声明为private。
  • 父类中声明为private的方法,不能够被继承。

非访问修饰符

非访问修饰符指的是一些实现其他功能的修饰符,为了与控制访问权限的访问修饰符区别,就命名为了非访问修饰符。

非访问修饰符主要包含static,final, abstract, synchronized和volatile。其主要区别如下:

修饰符 属性
static 声明方法或变量属于整个类而不是变量
final 声明方法或变量不可被修改
abstract 仅仅声明了类或方法的名称而让子类对抽象类进行拓展和修改
synchronized和volatile 用于线程的同步

关于上面的几个修饰符有以下几点需要注意:

static

  • 静态(static)方法不能使用类的非静态变量
  • 静态变量或方法可通过类直接调用:如class.staticVariableclass.staticMethod

final

  • final变量需要在声明的时候显式初始化并且只能初始化一次
  • final方法可以被子类继承,但是不能被子类修改,或者说重写(override)
  • final类不能被继承,没有类能够继承final类的任何特性
  • final修饰符通常和static修饰符一起使用来创建类常量

abstract

  • 抽象(abstract)方法是一种没有任何实现的方法(没有花括号),该方法的的具体实现由子类提供
  • 抽象方法的声明以分号结尾,且例如:public abstract sample();
  • 任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。
  • 如果一个类包含抽象方法,那么该类一定要声明为抽象类;但是抽象类可以不包含抽象方法,也可以同时包含抽象方法和非抽象方法

一个抽象类的定义

1
2
3
4
5
6
7
8
abstract class Caravan{
private double price;
public abstract void goFast(); //抽象方法
public abstract void changeColor()
{
// 抽象类中可以包含实现了的方法
}
}

抽象方法:

1
2
3
4
5
6
7
8
9
10
public abstract class SuperClass{
abstract void m(); //抽象方法
}

class SubClass extends SuperClass{
//实现抽象方法
void m(){
.........
}
}

这里顺便穿插抽象类和接口(interface)的一些差异:

接口(interface)就是给出一些没有内容的方法,封装到一起,到某个类需要使用的时候,再根据具体情况将这些方法写出。

与抽象类不同的是抽象类中的方法可以有主体(也就是实现了该方法);而接口中的所有方法都不可以有主体(也就是所有方法都不可以实现)

除此之外,一个类可以实现多个接口,实现了类似于多继承的特性;但是一个类不能继承多个类,并且一个类在实现一个接口的同时也可以继承一个类,如:class son extends father implements interface{}

synchronized和volatile

  • synchronized关键字声明的方法同一时间只能被一个线程访问,通过synchronized修饰符可以实现线程锁的功能
  • volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值

关于violate的一个列子如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MyRunnable implements Runnable
{
private volatile boolean active;
public void run()
{
active = true;
while (active) // 第一行
{
// 代码
}
}
public void stop()
{
active = false; // 第二行
}
}

通常情况下,在一个线程调用 run() 方法(在 Runnable 开启的线程),在另一个线程调用 stop() 方法。 如果 第一行 中缓冲区的 active 值被使用,那么在 第二行 的 active 值为 false 时循环不会停止。但是以上代码中我们使用了 volatile 修饰 active,所以该循环会停止。

在对变量和方法使用修饰符时,访问修饰符和非访问修饰符可以混用,且对访问修饰符只能选择其中一个,而非访问修饰符则没有这个限制。因此以下修饰符都是合法的

1
2
3
4
public static void main() // 执行类的入口--main 方法
public static final pi = 3.14 //不可修改的变量π
public final class Test // 不能被继承的类
.............


Referer

  • http://www.runoob.com/java/java-modifier-types.html