Java中final、static关键字使用总结
一、final关键字
可修饰非抽象类、非抽象类成员方法、变量。
阻止改变:
1.final类中不能被继承,没有子类,final类中方法默认为final的
2.final方法不能被子类的方法覆盖,但可以被继承
3.final成员变量表示常量,只能被赋值一次,赋值后不再改变
4.final不能用于修饰构造方法
注意:父类的private成员方法是不能被子类方法覆盖的,因此private类默认是final类型的
1、final类
final类不能被继承,成员方法默认为final的,没有机会被覆盖。若一个类不需要有子类,实现细节不允许改变,并且不会扩展,则选择为final类。
2、final方法
第一、final方法会锁定,防止任何继承类修改它的意义和实现
第二、高效(编译器在遇到调用final方法时会转入内嵌机制,提高执行效率)
示例代码:
class Super{
public final void m1(){
System.out.println("m1() in Super");
}
public void m1(int i){
System.out.println("m1(int) in Super");
}
}
class Sub extends Super{
/*public void m1(){
System.out.println("m1(int) in Sub");//编译出错
}*/
public void m1(int i){
System.out.println("m1(int) in Sub");//Super类中重载的方法m1(int i)被覆盖
}
public void m1(double d){
System.out.println("m1(double) in SUb");
}
}
public class Test3{
public static void main(String[] args){
Sub s = new Sub();
s.m1(); //从父类继承的final方法
s.m1(10);
s.m1(1.5);
}
}
3、final变量、参数
final修饰的变量有三种:静态变量、实例变量、局部变量
final修饰的成员变量表示常量(值给定就无法改变)
final变量定义的时候也可以不赋初值,这种变量称为final空白,但编译器确保final空白在使用之前被初始化,这样在final的使用上提供了更大的灵活性,使final数据成员依据对象而有所不同,却保持了不变性,更加灵活。
final在代码中有体现
class MyClass {
public void printValue(final int value) {
//value++; **定义final参数不允许改变**
System.out.println(value);
}
public void changeValue(int value) {
value = value * 2;
System.out.println(value);
}
}
public class Test3 {
public static void main(String args[]) {
MyClass mc = new MyClass();
int value = 5;
final int fvalue = 10;
mc.printValue(value);
mc.printValue(fvalue);
mc.changeValue(value);
mc.changeValue(fvalue);//这里fvalue只是一个引用所以会输出20
}
}
运行结果
5
10
10
20
另外还有一个final修饰引用
修饰引用的时候地址是不可变的,但引用的指向是可以变的,如下面代码:
class MyValue {
int value;
}
public class Test3 {
public static void main(String args[]) {
final MyValue mv = new MyValue();
mv.value = 100;
//mv = new MyValue();编译不通过
System.out.println(mv.value);
}
}
二、static关键字
static表示全局或者静态的意思,用来修饰成员变量和成员方法,也可形成静态代码块
被static修饰的成员变量和成员方法独立于类的任何对象它不属于特定的实例,而是被类的所有实例共享。类只要加载,虚拟机就能根据类名在运行时数据区找到他们
访问语法为:
类名.静态方法名(参数列表…)
类名.静态变量名
关于static成员函数的重写
static成员方法能不能被重写?
结论是,可以在子类中重写一个static函数,但是这个函数并不能像正常的非static函数那样运行。也就是说,虽然你可以定义一个重写函数,但是该函数没有多态特性
原因在于方法被加载的顺序
当一个方法被调用时,JVM首先检查其是不是类方法。如果是,则直接从调用该方法引用变量所属类中找到该方法并执行,而不再确定它是否被重写(覆盖)。如果不是,才会去进行其它操作
小例子:
class MyClass{
static int count = 0;
public MyClass(){
count++;
System.out.println("这是第"+count+"个对象");
}
}
public class Test3{
public static void main(String[] args){
MyClass m1 = new MyClass();
MyClass m2 = new MyClass();
MyClass m3 = new MyClass();
MyClass m4 = new MyClass();
}
}
运行结果:
这是第1个对象
这是第2个对象
这是第3个对象
这是第4个对象
1、修饰static关键字
- public修饰
public修饰的static成员变量和成员方法本质上是全局变量和全局方法,当声明对象时不会生成副本,而是共享一个static变量 - private修饰
表示这个变量可以在类的静态代码块中、类的其他静态成员方法中使用,但是不能其他类中直接通过类名来调用
static修饰的代码块表示静态代码块,当Java虚拟机(JVM)加载类时,就会执行该代码块
2、static变量
静态变量,在加载静态类的过程中完成静态变量的内存分配,且只分配一次(节省内存)
3、static方法
前面中提到,静态方法可直接通过类名调用,任何的对象也可调用,所以静态方法中不能使用this、super关键字,不能直接访问实例变量和方法(实例成员方法与特定的对象关联)
4、static代码块
独立于类成员的static语句块,加载类是执行,若是有多个,按照出现顺序执行。
在另一篇博客中有提到可以参考
三、static、final在一块的作用
用static、final修饰的方法和变量表示全局常量的意思
对于变量,表示一旦给值就不可修改,并且通过类名可以访问;
对于方法,表示不可覆盖,并且可以通过类名直接访问
注意:对于被static和final修饰过的实例常量,实例本身不能再改变了,但对于一些容器类型(比如,ArrayList、HashMap)的实例变量,不可以改变容器变量本身,但可以修改容器中存放的对象