【1】Java中常见访问修饰符

权限范围:​​private < default < protected < public​​​。理解记忆则为:​​自身->同一包->包和子类->所有​

修饰符

被修饰者

描述

public

外部类,接口,构造器,内部类,方法,成员属性

任意可访问

protectd

内部类,构造器,方法,成员属性

包内访问或包外子类

default

外部类,内部类,接口,构造器,方法,成员属性

同一包内访问

private

内部类,构造器,方法,成员属性

只能够在它们被声明的内部访问

public

公共的​​类、成员变量和方法​​都可以毫无限制的被其它Java程序所使用。

protected

相比default有更高的访问权限。只有​​成员变量和方法​​能够被声明为protected。父类的protected属性能被它的所有子类所共享。即使子类和父类不在同一包中,这种访问也是支持的。

内部类可以被protected修饰。

default/friendly

类中的数据、方法和它本身能够被声明为默认default。类中所有default成员都可以被本包中的其它类所访问。

你可以理解为这是一种​​包权限​

private

私有​​成员变量和方法​​(非外部类)只能被声明它们的类的实例所使用。

内部类可以被private修饰。

方法重载的隐私:

重载后的方法修饰符不能低于被重载的方法,比如父类是protected,子类中重载方法不能置为private。


除了上述基本的访问符之外,下表描述了Java中的其它描述符。它们能够改变类和它的成员(如:方法、变量和内部类)的行为。


【2】Java几个常见的非访问修饰符

修饰符

类/内部类

方法

变量

static

一个静态内部类是其父类的成员,但不是其父类实例对象的成员

一个静态方法可以直接被类访问,并且被该类的对象共享

静态变量是类级变量且在JVM中只能够出现一次

abstract

抽象类不能够被实例化,它只能被其他类所继承

抽象方法只能被声明在抽象类中,它的实现代码只能被包含在子类中

不适用

synchronized

不适用

它在类上加了一个监视器,使得访问该方法只能通过获得该方法所属对象的锁来进行

transient

变量不能够被序列化

final

类不能被继承

方法不能被重写

变量不能够被序列化,变量值为常量不可更改

final

final修饰符只能够作用在类、方法和变量上。它的作用是所有被final修饰的内容不能被改变。

用于修饰类、属性和方法;

  • 被final修饰的类不可以被继承
  • 被final修饰的方法不可以被重写
  • 被final修饰的变量不可以被改变,被final修饰不可变的是变量的引用,而不是引用指向的内容,引用指向的内容是可以改变的

static

static修饰符可以被应用在变量、方法、代码段和内部类中。如果需要Java实例变量被存储在单独的内存中,或需要变量对一个单独类的所有对象所通用,那么静态修饰符需要被应用在该变量的声明中。

  • 静态方法:Java的静态方法对类是通用的并且并不和Java实例相关联。尽管静态方法能够自由的访问类的静态数据和方法,但是它们并不能使用类的非静态功能。静态方法不能够被重载为非静态的。对于Java静态方法不能够使用this关键字。
  • 静态块:静态代码块在类加载时只执行一次。先与构造函数执行。
  • 静态变量:Java的实例变量使用单独的空间进行存储。如果需要变量对一个类的所有对象都是通用的,那么这个变量就需要被声明为静态的。类的所有实例对象都可以修改该类的静态变量。此外,使用对象实例修改静态成员并不是唯一手段,也可以直接使用java类来修改。静态变量也可以被Java对象的方法所访问。当一个常量的值在编译器就已经知晓了,它就需要使用static关键字来声明为final类型。
  • 静态内部类:只有内部类能够使用static修饰符来声明,在Java中它被称为静态嵌套类。

native

native修饰符只能够修饰方法。native修饰符意味着方法的实现体是在JVM之外。通常是用C/C++编写的本地代码块。

注意:抽象方法的实现体是在子类中,而native方法的实现体则完全不在Java的虚拟内存中,而是在其它程序库中。如 *.dll文件。


transient

transient修饰符只能够应用在变量中,transient变量不做为它所属对象的持久状态的一部分进行存储。它并不需要被序列化,主要用作安全键(security key)或者连接(connection)等。


synchronized

synchronized修饰符在多线程程序中对临界区代码的访问进行控制。

synchronized关键字是保持代码线程安全的工具之一。

对于某一对象的一个同步方法进行交叉访问是不可能的。当一个线程在执行某一对象的同步方法时,所有调用该同步方法的其它线程都将被阻塞直到第一个线程完成对该方法的调用。

其次,当一个同步方法执行结束时,对相同对象的后续同步方法调用,它会自动建立之前发生(happens-before)的顺序关系。这保证了该对象的状态更改对所有的线程都可见。

当你将一段代码块标记为同步化时,你需要使用对象作为该同步块的参数。当一个执行线程到达该代码块时,它首先需要等待在该对象的同步块上已经没有其它的执行线程。然而,一个线程可以进入不同对象锁定的同步方法块。

但对同一对象的非同步方法可以直接方法而无需锁检测。

如果你同步化的是静态方法,那么你同步时获取的是该方法类的锁而不是实例的。这就意味着当你同步的是静态方法时,整个类都将被阻塞。这样其它的静态同步方法也将被阻塞。

当一个线程进入同步化实例的方法时,其它线程则不能够再进入该实例的其它同步化方法。

当一个线程进入同步化的静态方法时,其它线程则不能够再进入该类的其它同步化静态方法。

注意:同步化的静态方法和同步化的非静态方法之间是没有多少联系的。例如:如果静态和非静态同步方法能够并发的执行,就需要将你的非静态方法显式的声明为在它自己的类上进行同步(如:同步MyClass.class{…})。


volatile

只有变量能够被定义为volatile。这些变量可能会被异步修改,因此编译器需要对他们额外的关注。volatile修饰符保证任何读取该字段的线程都能够获取它的最近修改值。

volatile和synchronize之间的区别:

volatile关键字只用来在线程内存和主内存之间同步单个变量值,synchronized关键字用来同步线程内存和主内存之间的所有变量值以及如何锁定和释放一个监视器。synchronized比volatile有着更大的开销。

volatile变量不允许出现和当前主存中的数据值不同的的本地副本。

更准确地说,被声明为volatile的变量必须保证它的数据值在所有线程的中是同步的。也就是当你在任一线程中访问或者更新一个变量时,所有其它线程能够立即访问到相同的值。

参考博文:从内存可见性看Volatile、原子变量和CAS算法


abstract

abstract修饰符适用于类和方法。抽象类不能够被实例化,它必须被继承才能够访问。abstract不能够应用到类的成员变量。

注意:

  • 如果类包含一个或多个抽象方法,编译器将强制该类必须声明为抽象的。
  • abstract类和final类是相对的。final类不能够被继承,而抽象类必须被继承。
  • 抽象类不一定拥有抽象方法,但是通常会有抽象方法。

设计上,你希望基类对继承类仅仅只作为接口。这意味着你不希望任何人实例化该基类。你只想进行向上类型转换(隐式转换,它能够提供多态性),这样就只能使用该基类的接口了。这是通过使用abstract关键字来修饰该类实现的。

提供限制来不实例化抽象类,这样就需要任何使用该抽象类的人来实现它,并提供多态性。

strictfp

使用对象:类、方法

介绍:strictfp修饰的类中所有的方法都隐藏了strictfp修饰词,方法执行的所有浮点计算遵守 IEEE 754标准,所有取值包括中间的结果都必须表示为float或double类型,而不能利用 由本地平台浮 点格式或硬件提供的额外精度或表示范围。