final的特点:
1.被final修饰的变量,不能再次被赋值。(表示常量)
2.final类不能被继承,没有子类,final类中的方法默认是final的
3.final方法不能被子类重写
String为什么是被final修饰的?
主要是出于**安全和性能**的考虑,可归纳为如下4点:
由于字符串无论在任何 Java 系统中都广泛使用,会用来存储敏感信息,如账号,密码,网络路径,文件处理等场景里,保证字符串 String 类的安全性就尤为重要了,如果字符串是可变的,容易被篡改,那我们就无法保证使用字符串进行操作时,它是安全的,很有可能出现 SQL 注入,访问危险文件等操作。
在多线程中,可以在多个线程中共享数据。由于 String 天然的不可变,当一个线程”修改“了字符串的值,只会产生一个新的字符串对象,不会对其他线程的访问产生副作用,访问的都是同样的字符串数据,不需要任何同步操作。
在一些集合容器之中,存放元素都要根据对象的 hashCode() 方法来确定元素的位置。由于字符串 hashcode 属性不会变更,保证了唯一性,使得类似 HashMap,HashSet 等容器才能实现相应的缓存功能。由于 String 的不可变,避免重复计算 hashcode,只要使用缓存的 hashcode 即可,这样一来大大提高了在散列集合中使用 String 对象的性能。
当字符串不可变时,字符串常量池才有意义。字符串常量池的出现,可以减少创建相同字面量的字符串,让不同的引用指向池中同一个字符串,为运行时节约很多的堆内存。若字符串可变,字符串常量池失去意义,基于常量池的 String.intern() 方法也失效,每次创建新的字符串将在堆内开辟出新的空间,占据更多的内存。
因为要保证String类的不可变,那么将这个类定义为final的就很容易理解了。如果没有final修饰,那么就会存在String的子类,这些子类可以重写String类的方法,强行改变字符串的值,这便违背了String类设计的初衷。
static的特点:
static变量:被修饰的属性属于类,它随类的信息存储在方法区,并不随对象存储在堆中,类变量可以通过类名来访问,也可以通过对象名来访问,但建议通过类名访问它。
static方法也叫(类方法),它先于任何的对象出现。静态方法可以直接通过类名调用,静态方法中不能用this和super关键字.
因为this指针是指向堆区中的类的对象,而static域不属于this指向的范围所在,所以不能调用。
super代表子类对父类满参构造函数的初始化,也是需要产生对象才可以使用但是考虑到虚拟机加载顺序为先加载类,当被实例化才产生对象。所以如果并存则表示类和对象同时加载,显然是不合逻辑的。
静态块:被static修饰的初始化块叫静态初始化块。静态块属于类,它在类加载的时候被隐式调用一次,之后便不会被调用了。