文章目录
final/static
final:
在声明时修饰类:类的指向无法改变,但其(成员变量的)值可以改变。
final StringBuffer a=new StringBuffer("a");
final StringBuffer b = new StringBuffer("b");
a=b;//无法通过编译
a.append(b);//编译通过
在定义时修饰类: 无法被扩展,修改
修饰方法:无法被子类重写,且提升执行效率(编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率)。
修饰变量:一旦给定就无法改变。(言外之意final空白可以先声明,而不给初值,通过构造器来初始化,这样不同实例也可以拥有不同的变量值)
另外,final变量定义的时候,可以先声明,而不给初值,这中变量也称为final空白,无论什么情况,编译器都确保空白final在使用之前必须被初始化。
但是,final空白在final关键字final的使用上提供了更大的灵活性,
为此,一个类中的final数据成员就可以实现依对象而有所不同,却有保持其恒定不变的特征
static:(只跟类有关,跟实例无关,与多态无缘
static方法不能被覆盖,因为static方法跟类的实例无关,即多态无法生效。
再者因为方法覆盖是基于运行时动态绑定的,而 static 方法是编译 时静态绑定的
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Test t = new Son();
t.test();//Father
}
public static void test(){
System.out.println("Father");
}
}
class Son extends Test{
int a ;
public Son(){
test(); //Son
}
public static void test(){
System.out.println(new Son().a);
System.out.println("Son");
}
}
static代码加载顺序:父类静态代码块-》子类静态代码块-》父类非静态代码块-》父类构造函数(new后才会调用)->子类非静态代码块-》子类构造函数
class Test {
public Test(){
System.out.print("Test gouzhao");
}
private static Test a=new Test(); //1 加载类信息,执行非静态代码块然后构造函数
static{//2
System.out.print("static");
}
{
System.out.print("Test1");
}
public static void main(String[] args) {
System.out.println("0000");//3
B b=new B();//4 去掉就只显示Test1Test gouzhaostatic0000
}
}
class B extends Test{
public B(){
System.out.print("B");
}
}
/*
Test1Test gouzhaostatic0000
Test1Test gouzhaoB
*/
为什么String设计为Final
安全高效(经常需要使用,又不需要在进行扩展,那么就可以设置为final,让类无法被继承,防止随意修改,保证数据安全性又提升数据访问效率)。主要是安全。至于效率难说提升多少
1.String和其他八大基本类型都是final不可被继承,防止被修改,保证数据安全性。
而String的成员变量是final char[] value;虽然value引用地址无法改变,但是array数组是可变的,array是在stack上的一个引用,数组的本体结构在堆中。String类里的value用final修饰,只是说stack里的这个叫value的引用地址不可变。没有说堆里array本身数据不可变。
由String的不可变性引申到其他基本数据类型: Byte,Short,Integer,Long,Double,Float,Character,Boolean 八种基本数据的包装类,仔细查看发现也是final修饰的,再仔细查看一下enum枚举类型,发现用javac编译后再用javap反编译也是被编译为final修饰的类,并且其枚举值全部定义为static final 修饰的成员变量。