final关键字
概述
java中final代表的是最终、不可改变的意思,是一个关键字。可以被用来修饰类、变量和成员方法。
final修饰类
当使用final修饰一个类时,这个类会成为最终类,不可被继承(即没有子类)。
//类名为Person的类被final关键字修饰,代表其不能被继承
public final class Person{
}
//现在类名为Man 的类想继承Person这个类,编译器会报错
public class Man extends Person{
}
final修饰方法
当final关键字修饰d的是成员方法时,则意味着这个方法不能被覆盖重写,但是可以被继承。
public class Person(){
//final修饰的方法,不能被覆盖重写
public final void func(){
}
}
public class Man extends Person(){
//这里会报错
public void func(){
}
}
final修饰变量(包括成员变量和局部变量)
final修饰成员变量,一定要被赋值且只能被赋值一次,且必须是在这个成员变量所在的类对象创建之前被赋值。
如何赋值?
1、直接初始化
public class Demo01(){
private final int a = 10;
public static void main(String[] args) {
}
}
2、在构造代码块儿中初始化
private final int a;
//构造代码块儿会在该类对象创建之前执行
{
a=5;
}
public static void main(String[] args) {
}
3、在成员变量所在类的构造方法中初始化
public class Demo01 {
private final int a;
public Demo01(int n){
this.a = n;
}
public static void main(String[] args) {
}
}
final修饰局部变量,该变量可以不初始化但必须在使用之前赋值且只能被赋值一次。
public class Demo01 {
public static void main(String[] args) {
}
public void test(){
final int num;
}
}
注意:
对于基本类型,不可变说的是变量当中的数据不可改变
对于引用类型,不可变说的是变量当中的地址值不可改变,但是内容可以变改变(即地址所指向的对象)
static关键字
在类中,用static声明的成员变量为静态成员变量,也称为类变量。类变量的生命周期和类相同,在整个应用程序执行期间都有效。
被 static修饰的方法或者变量可以通过类名去进去访问。
static方法又称为静态方法,因为不依赖任何对象,所以没有 this。在静态方法中是不能访问非静态方法和非静态的成员变量,因为非静态的方法和非静态的成员变量必须依赖具体的对象才能被调用。反过来是可以调用的。
public class StaticExample {
private static int num = 10;
private int sum = 20;
public StaticExample(){
}
public void func1(){
System.out.println(num);//非静态方法可以使用静态成员变量
System.out.println(sum);
}
public static void func2(){
System.out.println(num);
System.out.println(sum);//这里会报错:静态方法不能使用非静态成员变量
}
}
特别说明:static方法是属于类的,非实例对象,在JVM加载类时,就已经存在内存中,不会被虚拟机GC回收掉,这样内存负荷会很大,但是非static方法会在运行完毕后被虚拟机GC掉,减轻内存压力
static变量也称为静态变量,静态变量和非静态变量的区别:
-
静态变量被所有对象共享,在内存中只有一个副本,在类初次加载的时候才会初始化
-
非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响
static块:
构造方法用于对象的初始化。静态初始化块,用于类的初始化操作。
静态初始化块的作用:提升程序性能
public class Person {
private Date birthDate;
public Person(Date birthDate) {
this.birthDate = birthDate;
}
boolean isBoolBirthDay(){
Date startDate = Date.valueOf("1846");
Date endDate = Date.valueOf("1864");
return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate)<0;
}
}
上述代码中,每次调用isBoolBirthDay的时候都会生成 startDate 和 endDate两个对象。造成空间浪费。
public class Person {
private Date birthDate;
public static Date startDate, endDate;
static {
startDate = Date.valueOf("1846");
endDate = Date.valueOf("1864");
}
public Person(Date birthDate) {
this.birthDate = birthDate;
}
public boolean isBoolBirthDay(){
return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate)<0;
}
}
改成如上代码,只需要初始化一次就可以直接调用。
静态初始化块可以置于类中的任何地方,类中可以有多个静态初始化块。在类初次被加载时,会按照静态初始化块的顺序来执行每个块,并且只会执行一次。
注意:static关键字不会改变类中成员的访问权限。
static常见的面试题类型:
public class Test extends Base{
static{
System.out.println("test static");
}
public Test(){
System.out.println("test constructor");
}
public static void main(String[] args) {
new Test();
}
}
class Base{
static{
System.out.println("base static");
}
public Base(){
System.out.println("base constructor");
}
}
//输出结果如下:
base static
test static
base constructor
test constructor
分析:
-
找到main方法入口,main方法是程序入口,但在执行main方法之前,要先加载Test类
-
加载Test类的时候,发现Test类继承Base类,于是先去加载Base类
-
加载Base类的时候,发现Base类有static块,而是先执行static块,输出base static结果
-
Base类加载完成后,再去加载Test类,发现Test类也有static块,而是执行Test类中的static块,输出test static结果
-
Base类和Test类加载完成后,然后执行main方法中的
new Test(),调用子类构造器之前会先调用父类构造器 -
调用父类构造器,输出base constructor结果
-
然后再调用子类构造器,输出test constructor结果
final在Java中表示不可变,可以修饰类、方法和变量。final修饰的类不能被继承,修饰的方法不能被重写,修饰的变量一旦赋值后不能改变。static关键字用于声明静态成员变量和静态方法,它们属于类而非对象,可以在类加载时初始化。静态方法不能访问非静态成员,反之可以。静态初始化块用于类的初始化,只执行一次。
145

被折叠的 条评论
为什么被折叠?



