1.static关键字:static标记的方法,字段不是属于java中创建实例的,它是属于类的,一般,如果这个静态字段或者静态方法是pulic,那么在其他方法中使用这个类的static字段或方法都是可以通过类名直接引用。
注意事项:
静态字段:判断某个字段是否是线程安全的,除了该变量得是方法中的局部字段,还得判断该字段是否逃离了该方法的作用范围。
/**
*局部变量的线程安全问题
*/
public class Test03 {
public static void main(String[] args) {
}
public static void m1(){
//线程方法内的局部变量,不会有线程安全问题
StringBuilder sb = new StringBuilder();
sb.append(1);
sb.append(2);
sb.append(3);
System.out.println(sb);
}
public static void m2(StringBuilder sb){
//不是线程安全的,StringBuilder 是作为方法参数传入的,
// 可能有别的线程也可能访问到该 StringBuilder 对象
sb.append(1);
sb.append(2);
sb.append(3);
System.out.println(sb.toString());
}
public static StringBuilder m3(){
//不是线程安全的,虽然 StringBuilder 是方法内的局部变量,但是作为返回值返回了
//所以将来有可能别的线程会拿到该对象的引用,对该对象的值进行改变
StringBuilder sb = new StringBuilder();
sb.append(1);
sb.append(2);
sb.append(3);
return sb;
}
}
static方法:
1.调用类的方法时是需要把方法入栈存储,为每一个方法开辟一个内存,这个内存称为栈帧(Frames)。如果这个方法是static,同时没有调用static变量,那么这是线程安全的(线程是否安全,看该变量是多线程共享的还是单线程私有的),因为即使方法是属于类的,但是变量本身是局部变量,随方法使用而创建初始化,不可共享。
2.静态方法是不能被重写的:Java中为什么静态方法不能被重写?为什么静态方法不能隐藏实例方法?_Yang Special的博客-优快云博客_静态方法为什么不能被重写
3.静态方法不能使用this变量,因为静态方法是属于类的,无法访问实例变量。但是实例变量能调用静态方法,因为编译器自动帮我们把实例改写成类名。
接口:
1.纯抽象类称为接口,里面的字段都是public final static的。去掉修饰符,编译器也会自动将变量转为这种修饰的数据。
2.final关键字:final与访问权限不冲突。
(1)用final修饰 class可以阻止被继承,
(2)用final修饰method可以阻止被子类覆写,
(3)用final修饰field可以阻止被重新赋值。
修饰成员变量
如果final修饰的是类变量,只能在静态初始化块中指定初始值或者声明该类变量时指定初值。
如果final修饰的是成员变量,可以在非静态初始化块、声明该变量或者构造器中执行初始值。
修饰局部变量
系统不会为局部变量进行初始化,局部变量必须由程序员显示初始化。
修饰基本类型数据和引用类型数据
如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;
如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。但是引用的值是可变的。
3.面试题:
1、简述final作用
(1)用final修饰 class可以阻止被继承,
(2)用final修饰method可以阻止被子类覆写,
(3)用final修饰field可以阻止被重新赋值。
2、为什么局部内部类和匿名内部类只能访问局部final变量?
匿名内部类:
局部内部类:
首先需要知道的一点是:内部类和外部类是处于同一个级别的,内部类不会因为定义在方法中就会随着方法的执行完毕就被销毁。
这里就会产生问题:当外部类的方法结束时,局部变量就会被销毁了,但是内部类对象可能还存在(只有没有人再,引用它时,才会死亡)。这里就出现了一个矛盾:内部类对象访问了一个不存在的变量。为了解决这个问题,就将局部变量复制了一份作为内部类的成员变量,这样当局部变量死亡后,内部类仍可以访问它,实际访问的是局部变量的"copy"。这样就好像延长了局部变量的生命周期将局部变量复制为内部类的成员变量时,必须保证这两个变量是一样的,也就是如果我们在内部类中修改了成员变量,方法中的局部变量也得跟着改变,怎么解决问题呢?
就将局部变量设置为final,对它初始化后,我就不让你再去修改这个变量,就保证了内部类的成员变量和方法的局部变量的一致性。这实际上也是一种妥协。使得局部变量与内部类内建立的拷贝保持一致。