final关键字
他的作用:(这三点大家都知道)
1.被final修饰的类不能被继承
2.被final修饰的方法不能被重写
3.被final修饰的变量不能被改变
前俩都好理解,重点就第三句,被final修饰的变量不能被改变,通常会理解为值不变,也就是内容不变(我觉得是因为String是不可变的,导致有这个错觉),到底是变量的引用还是引用的内容不变呢?
可以看见16-18行,用final修饰的变量fs的内容是可以被改变的,而在20行会出错,可见,被final修饰不可变的是变量的引用,而不是引用指向的内容,引用指向的内容是可以改变的。
下面看一下final修饰的数组
变量和数组一样,都是引用不可变,引用指向的内容可变。实际上如果用过FindBugs插件的应该知道,假如代码里面用final修饰了一个数组,那么改行代码会被作为findBugs的一个bug被查找出来,因为“用final修饰数组是没有意义的”。
final修饰的方法参数也是如此。
总结
引用–是java中非常重要的一个概念,被final修饰的变量,不管是哪种变量,都是变量的引用不能被改变,而非引用所指向的内容。
另外,final还有俩作用:
1.被final修饰的方法,JVM会尝试为之寻找内联,这对于提升Java效率是非常重要的,因此,如果能确定方法不会被重写,就尽量将方法定义为final,(Java虚拟机11:运行期优化,学一下)。
2.被final修饰的常量,在编译阶段会存入调用类的常量池中?(类加载,Java虚拟机2:Java内存区域及对象学一下)
static
static 的基本作用
1.被static修饰的变量或者方法属于类变量或者类方法,可以直接通过类.变量名来使用,不需要先实例化(我觉得是因为不需要实例化就加载这部分了)
2.一个类的不同实例中,对被static修饰的变量,方法是同一个内存地址,也就是:被static修饰的变量、被static修饰的方法统一属于类的静态资源,是类实例之间共享的。
3.静态代码块
4.静态内部类
静态方法能不能引用非静态资源?
不能
静态方法能不能引用静态资源?
可以
非静态方法能不能引用静态资源?
可以
原理:、
静态资源是类初始化的时候加载的,而非静态资源是在类的实例化的时候加载的,类的初始化早与实例化(还不一定实例化呢),比如,利用反射Class.forName(“xxx”)方法,就是初始化了一个类,但是并没有new它,只是加载这个类的静态资源罢了。
所以:
1、静态方法能不能引用非静态资源?不能,new的时候才会产生的东西,对于初始化后就存在的静态资源来说,根本不认识它。
2、静态方法里面能不能引用静态资源?可以,因为都是类初始化的时候加载的,大家相互都认识。
3、非静态方法里面能不能引用静态资源?可以,非静态方法就是实例方法,那是new之后才产生的,那么属于类的内容它都认识。
静态代码块
静态块也是static的重要应用之一。也是用于初始化一个类的时候做操作用的,和静态变量、静态方法一样,静态块里面的代码只执行一次,且只在初始化类的时候执行。静态块很简单,不过提三个小细节:
1.如下代码:
可以看出:静态资源的加载顺序是按照资源的定义顺序来加载的(我理解是先引用了静态方法B(),在有了静态代码块,因此B在前面)
可以看出,在静态代码块中,可以对下面定义的静态变量进行赋值,但不能访问,(我觉得是因为类加载时,先加载静态变量,后加载静态代码块)
可以看出:父类的静态代码块和方法的加载顺序早于子类的
static修饰类
这个用得相对比前面的用法少多了,static一般情况下来说是不可以修饰类的,如果static要修饰一个类,说明这个类是一个静态内部类(注意static只能修饰一个内部类),也就是匿名内部类。像线程池ThreadPoolExecutor中的四种拒绝机制CallerRunsPolicy、AbortPolicy、DiscardPolicy、DiscardOldestPolicy就是静态内部类。静态内部类相关内容会在写内部类的时候专门讲到。(有空学一下)
import static
这个比较冷门,基本很少看见有地方用,
这么写意味着我导入了Math下的所有静态资源