您的位置:首页 > 编程语言 > Java开发

Java 开发中static 和 final 关键字

2016-06-04 08:40 561 查看
我们在Java 开发中大量使用staticfinal关键字,面试中也经常被提到.下面就这两个关键字的用法进行讲解.

static关键字

通常我们在下述两种情况下用static :

1.只想为特定域分配单一存储空间,而不考虑究竟要创建多少对象,甚至不创建任何对象.

2.希望某个方法不与包含他的类的对象关联在一起.即使没有创建对象也能够调用这个方法.

那么这两句话的含义是啥呢,我们还是来看一个示例.

static 修饰字段:

public class StaticTest {
static int i =26;
public static void main(String[] args){
StaticTest st1 = new StaticTest();
StaticTest st2 = new StaticTest();
System.out.println(st1.i);
System.out.println(st2.i);
}

}

输出结果:
26
26


上面这个结果是大家都可以猜到的,接着我们让st1.i 或st2.i 自增,看一下输出结果.

public class StaticTest {
static int i =26;
public static void main(String[] args){
StaticTest st1 = new StaticTest();
StaticTest st2 = new StaticTest();
st1.i++;
System.out.println(st1.i);
System.out.println(st2.i);
}
}
输出结果:
27
27


大家看出区别了吧,static 字段对每个类来说都只有一份存储空间 StaticTest 中的i 变量占据了单一的存储空间,保证了创建多个StaticTest 对象时, 变量i 也只有一份. st1.i和st2.i指向了同一个存储空间.

static 修饰方法:

一句话,没有创建对象,也能使用该类中的方法.这里就不贴代码了.

static 是不是很简单,下面我们看final 关键字,讲解的过程中会穿插着用一下static 关键字

final 关键字

final 关键字的意思是 “这里是无法改变的”,下面我们会讨论被final 修饰的三种情况.

1.fianl 修饰”数据”

我们开发的时候可能希望数据是恒定不变的,比如:

1.一个永不改变的编译时常量.

2.一个在运行时被初始化的值,而你不希望它被改变.

当对基本类型时,final 使数值恒定不变,而应用于对象引用,final 使引用恒定不变,但是对象自身确实可以被修改的.

下面的示例示范了final 修饰数据的情况.

package com.example;
import java.util.Random;
public class FinalData {
private static Random rand = new Random(47);
private String id;
public FinalData(String id){
this.id = id;
}
private final int valueOne = 9;
private static final int VALUE_TWO = 99;
public  static final int VALUE_Three = 39;
private  final int i4 = rand.nextInt(20);
static final  int INT_5 =rand.nextInt(20);
private Value v1 = new Value(11);
private final Value v2 = new Value(11);
private static final Value VAL_3 = new Value(33);
private final int[]  a = {6,5,4,3,2,1};
public String toString(){
return id+": "+i4+", INT_5=" + INT_5;
}
public static void main(String[] args){
FinalData fd1 = new FinalData("fd1");
fd1.v2.i++;
fd1.v1 = new Value(9);
for(int i=0;i<fd1.a.length;i++){
fd1.a [i]++;
//fd1.v2 = new Value(0);//  error
//fd1.VAL_3 = new Value(1);// error
//fd1.a = new int[3]; //error
}
FinalData fd2 = new FinalData("fd2");
System.out.println(fd1);
System.out.print(fd2);
}
}
class  Value{
int i;
public Value(int i){
this.i =i;
}
}
输出结果:
fd1: 15, INT_5=18
fd2: 13, INT_5=18


代码中无法通过编译器检测的我已经在注释中标上了大大的error.原因就是上面提到的被fianl 修饰过的引用,一旦被初始化指向一个对象,就没有办法把它改为指向另一个对象了, 好专一啊………..

专一的人是不是都被final 修饰过~~~ 有点扯远了

我们还需要注意一个细节,当我输出i4 和 INT_5 ,一个没有被static 修饰过一个被修饰过,没有被修饰的,两个对象,两个不同的值.被static修饰过 在类中只有一份,同时又是不可以修改的,因此一但被赋值,也就不会改变了.

空白final:

允许刚开始时,被final 修饰的变量不用初始化,但后面使用的时候一定要初始化.

package com.example;
/**
*  blank final
*/
public class BlankFinal {
private  final int i= 0;
private  final int j;
private  final Poppet p;
public BlankFinal(){
j=1;
p =new Poppet(1);
}
public BlankFinal(int x){
j=x;
p=new Poppet(x);
}
public static void main(String[] args ){
new BlankFinal();
new BlankFinal(26);
}
}
class  Poppet{
private  int i;
Poppet(int ii){
i = ii;
}
}


final修饰参数

fianl 修饰的参数,无法在方法中更改参数引用所指向的对象.

public final class People {
public void swim(){}
}
class Animail{
void with(final People people){
// people = new People();//error
}
}


final 修饰方法

被final 修饰过的方法,子类是无法覆盖的,需要注意的一点private 修饰方法都隐式的指定为方法 添加了final .下面的代码有点迷惑性.

public class withFinals {
private final void f(){
System.out.println("withFinals.f()");
}
// automatically add fianl
private void g(){
System.out.println("widthFinals.g()");
}
}
class OverringPrivate extends  withFinals{
private final void f(){
System.out.println("OverringPrivate.f()");
}
private  final void g(){
System.out.println("OverringPrivate.g()");
}

}
class OverringPrivate2 extends  OverringPrivate{
public final void f(){
System.out.println("OverringPrivate2.f()");
}
public final  void g(){
System.out.println("OverringPrivate2.g()");
}
}
class FinalOverridingIllusion{
public static void main(String[] args){
OverringPrivate2 op2 = new OverringPrivate2();
op2.f();
op2.g();
OverringPrivate op = op2;
// op.f(); error
// op.g(); error
withFinals wf = op2;
// wf.f(); error
// wf.g(); error

}
}


方法貌似被”覆写”了,其实不然,覆写的概念: “只有非private 方法才能被覆写”,对于private 修饰的方法是没有覆写这个概念的.可以把它看做是隐藏在类中的程序代码,只不过具有相同的名字而已! 好坑啊~~

final 修饰类

也是一句话,被final 修饰过得类,就表明该类是无法继承的,子类是无法继承和覆写.这里我们就不贴代码了,大家可以写个代码测一下.

ok 这两个关键字就介绍到这里,相信你再次使用它们的时候,会有更加清晰的认识.

参考文章:

thinking in java
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息