阅读 24

【Java基础】static和final

我是 啤酒就辣条,一个Java。
学而时习之,不亦说乎?希望通过博客的形式,总结、分享,梳理自己、帮助他人。
另外,啤酒就辣条,味道不错哦~

static

static 关键字是将某些属性(变量、方法、代码块、类等等)直接归属于类。由于static的存在,实现了共享,极大的节约了内存空间

静态变量

被static修饰的变量,可以不生成对象,直接用类.变量的形式调用。应用场景一般为全局常量,例如redis的key值前缀。

public class RedisConstant {
    public static String BLOG_VIEWS = "blog_views_";
}
复制代码

静态方法

被static修饰的方法,可以不生成对象,直接用类.方法名的形式调用。当静态方法想使用外部数据(变量或者方法)时,外部数据也必须是静态的。这些方法都是类的某种特性,不依赖于其类的某一对象。应用场景一般为各种工具类。(此处强推hutool,一个Java工具类合计,让Java也可以“甜甜的”)

public final class Objects {
    // 此方法为JDK1.8,新加入的方法,用于判断,都object是否为空
    public static boolean isNull(Object obj) {
        return obj == null;
    }
}
复制代码

静态代码块

被static所修饰的代码块。作为代码块,肯定不能直接被调用。静态代码块在类加载到内存时执行,并且只能执行一次。

public class RedisConstant {
    public static String BLOG_VIEWS = "blog_views_";
    static {
        System.out.println("我是RedisConstant的静态代码块");
    }

    public static void main(String[] args) {
        System.out.println("main方法开始了");
        RedisConstant redisConstant1 = new RedisConstant();
        RedisConstant redisConstant2 = new RedisConstant();
    }
}
// 执行结果
我是RedisConstant的静态代码块
main方法开始了
复制代码

这里有个经典的应用场景:定义静态集合。

public class RedisConstant {
    public static List<String> phones;
    static {
        phones = new ArrayList<>();
        phones.add("苹果");
        phones.add("小米");
        phones.add("华为");
    }
    public static void main(String[] args) {
        phones.stream().forEach(System.out::println);
    }
}
复制代码

执行顺序

由于静态代码块是类的属性,而构造方法为产生对象的行为,所以静态代码块先执行,嗯,不错,完全符合Java的设计思想。

public class RedisConstant {
    RedisConstant(){
        System.out.println("俺是构造方法");
    }
    static {
        System.out.println("请叫我静态代码块");
    }
    public static void main(String[] args) {
        RedisConstant redisConstant = new RedisConstant();
    }
}
// 输出结果
请叫我静态代码块
俺是构造方法
复制代码

静态类

将静态属性提升为package级别,用的比较少。

final

final关键字将保证被修饰元素(变量、方法、类)的引用不可修改。显示保证数据不被篡改,final字段验证篡改与否在编译阶段

修饰变量

final修饰的变量,如果是基本数据类型,就不能更改其值;引用数据类型,就不能改变引用地址。

public class FinalTest {
    public static void main(String[] args) {
        final String string = "初始值";
        string = "更新了"; // 此行编辑阶段报错
    }
}
复制代码
public class FinalTest {
    public static void main(String[] args) {
        final Object object = new Object();
        object = new Object(); // 此行编辑阶段报错
    }
}
复制代码

修饰方法

final修饰的方法,不可以被子类重写,保证了此方法时代的逻辑统一。

 class FinalTest {
    final void test(){
        System.out.println("FinalTest");
    }
}

class FinalTestSon extends FinalTest{
    @Override // 此行编辑阶段报错
    final void test(){
        System.out.println("FinalTestSon");
    }
}
复制代码

修饰类

final修饰的类,不可以被继承。像String、StringBuffer、StringBuilder都是被final修饰的。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
        
    }
复制代码

static和final的火花

一般static和final经常搭配起来。他们一般一起修饰不变的共享值

static让数据在被JVM加载入内存的时候仅有一次的加载,节省内存空间,而final让数据引用指向不变,保证数据统一准确。