abstract
final
修饰类
被final修饰的类不能被继承
修饰方法
“使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。在最近的Java版本中,不需要使用final方法进行这些优化了。”
由此可见,被final修饰的方法最主要的目的就是防止方法被重写
修饰变量
对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
对象的引用无法改变,但是对象的属性值可不可以改变呢?
因为payStatus是int类型,初始化时候会给定默认值:0
此时输出结果
1
10
从结果来看,final”锁定”的是对象的引用,并没有”锁定”属性的值;
注意事项
final与static的区别,static作用于成员变量用来表示只保存一份副本,而final的作用是用来保证变量不可变。
示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15final class Father{
public final Double i = Math.random();
public static Double j = Math.random();
}
public static void main(String[] args){
Father f = new Father();
Father ff = new Father();
System.out.println(f.i);
System.out.println(f.j);
System.out.println();
System.out.println(ff.i);
System.out.println(ff.j);
}
输出结果:
0.41791403026319096
0.8147697161273327
0.9571817275395188
0.8147697161273327
参考资料
static
- 静态方法内部不能调用非静态方法,非静态方法没有此限制。
- 被
static
修饰的变量属于类变量
,可以通过类名.变量名直接引用,而不需要new出一个类来 - 被
static
修饰的方法属于类方法
,可以通过类名.方法名直接引用,而不需要new出一个类来
静态资源是类初始化的时候加载的,类实例之间共享,一处变,处处变。
并且被static
修饰的方法是没有this
的,他不依附于任何对象。但是非静态方法是依赖于具体对象而调用的。这就是为什么静态方法内部不能调用非静态方法。
既然静态资源不依赖于任何对象,那为什么还要放在不同对象里呢。是不是可以把所有静态资源全都放到一起?
- 避免重名,通过不同对象使同名静态资源区分开。
- 资源分类清晰,功能明确。
- 放到一起,那存放静态资源的这个类会特别大。
静态资源(变量/方法/代码块)
static变量也称作静态变量,静态变量和非静态变量的区别是:
静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。
而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。
注意事项
静态资源真的没有this吗?
1 | final class Father{ |
输出:
31
this是指当前对象,printWg中的wg是局部变量,无法与this内联。
常见面试题
一
1 | public class Son extends Father{ |
输出:
father static
son static
main()
father constructor
son constructor
程序执行顺序:
- main()作为程序入口;
- 需要加载Son,发现Son继承Father,加载Father;
- Father中有static块,初始化加载这个static块;
- 返回Son,Son中有static块,初始化这个static块;
- 打印输出字符串”main()”
- 执行new Son();
- Son继承Father,Father有构造函数,执行构造函数;
- 返回Son,Son有构造函数,执行构造函数;
第2~4步是对象的加载过程,第5~7步是对象的执行过程;输出结果与执行顺序的对应关系
输出行 | 对应执行顺序 |
---|---|
father static | 3 |
son static | 4 |
father constructor | 7 |
son constructor | 8 |
不难发现即使mian()中并没有语句,但仍然会有输出。就像之前所说,jvm会把所有不在方法内部的的静态资源初始化。
参考资料
包和访问权限控制关键字
package
- 包是可以理解为命名空间,他能有效解决类重名问题。
- 为了方便组织和管理,多用倒置域名来标识。
默认访问权限(包访问权限)、public、private和protected
一个.java文件只能有一个被public修饰的类,并且类名必须与文件名相同。如果没有public关键字,则对类的命名没有要求。
修饰类
- 默认访问权限(包访问权限):用来修饰类的话,表示该类只对同一个包中的其他类可见。
- public:用来修饰类的话,表示该类对其他所有的类都可见。
- 如果你想实现其他任何人都不能访问该类,可以通过将类的所有构造器都指定为private。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package com.qigou.b2cex.test;
class People {
private String name = null;
public People(String name) {
this.name = name;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
1 | package com.qigou.b2cex.test; |
输出结果:
BBDog
将People的包名改为test1后
修饰方法和变量
作用域 | 当前类 | 同包下 | 子孙 | 所有类 |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
默认 | √ | √ | × | × |
private | √ | × | × | × |
1 | package com.qigou.b2cex.test; |
1 | package com.qigou.b2cex.test; |
变更getName()的权限,每次初始化包名。
public
正常输出: BBDog
默认
同包下正常输出: BBDog
修改People包名为test1
protected
同包下正常输出: BBDog
修改People包名为test1
创建Kids类继承People
1
2
3
4
5
6
7
8
9
10
11
12
13package com.qigou.b2cex.test;
import com.qigou.b2cex.test1.People;
public class Kids extends People {
public Kids(String name){
super(name);
}
public String toString() {
return getName();
}
}子类拥有权限,但是调用子类仍然不被允许
private
参考资料