通常情况下, 类成员需要通过它的类的对象访问,如果一个成员被声明为static,它能够在它的类的任何对象创建之前被访问, 而不用引用任何对象。
声明为static
的一个类变量或方法,所有的该类的实例都会共享这个static
变量或方法。
static
static修饰变量
静态变量在内存中只有一份, jvm只为静态变量分配一次内存,随着类的加载而加载到静态方法区内存中。由于静态变量属于类,和类的实例无关, 所以可以直接通过类名进行访问。
对于成员变量,每创建一个该类的实例就会创建该成员变量的一个拷贝,分配一次内存,由于成员变量是和类的实例绑定的,所以不能直接通过类名对它进行访问。
static修饰方法
- 只能调用其他的static方法
- 只能访问static数据
- 不能以任何方式引用
this
和super
静态方法可以直接通过类名调用, 任何该类的实例也可以调用它的静态方法, 所以静态方法不能用this
或者super
。
static 方法独立于任何实例, 所以static方法必须被实现,不能是抽象的absract,在static方法里引用任何的实例变量都是违法的。
static 修饰类
普通类不允许被声明为静态, 只有内部类才可以。被static
修饰的内部类可以作为一个普通类来使用, 而不需实例一个外部类(不需要new,直接静态加载)。
内部类没有使用static
关键字,不能直接创建实例。
不使用static修饰内部类
1 | public class OuterClass { |
使用static修饰内部类
1 | public class OuterClass { |
static修饰代码块
1 | static { |
它独立于类成员,可以有多个, jvm 加载类的时候会执行这些静态代码块, 如果有static
代码块多个,jvm会按照他们在类中出现的顺序执行且每个只执行一次。可以通过静态代码块对static变量进行赋值。
final
final可以修饰非抽象类, 非抽象类成员方法和变量
final修饰变量
一个变量可以声明为final
, 目的是阻止它的内容被修改, 这意味着声明final
变量的时候, 必须对其进行初始化,这种用法有点类似于c++的const
。
通常,我们会用 final
定义一些常量 , 如
1 | final float PI=3.14 |
按照编码约定, final变量的所有字符选择大写,final修饰的变量实际中不占用内存, 它实质上是一个常数。
final修饰方法
被final修饰的方法可以被子类继承, 但不能被子类的方法覆盖。 如果一个类不想让其子类覆盖它的某个成员方法, 就可以用 final
关键字修饰该方法。
final不能修饰构造方法。 由于父类中
private
成员方法不能被子类覆盖, 所有由private
修饰的方法默认也是final
的。
使用final修饰成员方法除了不想让子类覆盖外, 还有一个原因就是高效,Java编译器在遇到final
修饰的方法的时候会转入内嵌机制, 提高执行效率。
内嵌机制 ,类似于c++ inline, 调用方法的时候直接将方法的主题插入到调用处, 而不用去访问类或者对象, 这样会提高50%左右效率。然而,如果方法主体比较庞大, 且多处被调用将导致主体代码膨胀, 同时也产生效率问题, 所以需要慎用。
final修饰类
final
修饰的类不能被继承。
final和static同时使用
同时使用 final
和static
修饰类成员, 该类成员拥有二者特性。
1 | static final int LIMIT=100; // LIMIT表示全局常量 |
如果是方法的话,方法可以被继承, 可以通过类名被访问, 但是不能被子类覆盖。
对于一些用
final
和static
修饰的容器类型(比如,ArrayList
、HashMap
)的实例变量,不可以改变容器变量本身,但可以修改容器中存放的对象。