Java中final作用于变量、参数、方法及类该如何处理
Java中方法用final修饰参数的作用
在方法参数前面加final关键字就是为了防止数据在方法体重被修改。
主要分为两种情况:第一,用final修饰基本数据类型;第二,用final修饰引用数据类型。
第一种情况,修饰基本数据类型,这时参数的值在方法体内是不能被修改的,即不能被重新赋值。否则编译就不通过。
第二种情况,修饰引用类型。这时参数变量所引用的对象是不能被改变的。但是对于引用数据类型,如果修改其属性的话是完全可以的。
所以,final这个关键字,想用的话就用基本数据类型,还是很有作用的。
final变量:
对于基本类型使用final:它就是一个常量,数值恒定不变
对于对象引用使用final:使得引用恒定不变,一旦引用被初始化指向一个对象,就无法再把它改为指向另一个对象。然而,对象自身却是可以被修改的,java并没有提供使任何对象恒定不变的途径。这一限制同样也使用数组,它也是对象。
例子:
classValue{
inti;
publicValue(inti){
this.i=i;
}
}
publicclassFinalData{
privatestaticRandomrandom=newRandom(47);
privateStringid;
publicFinalData(Stringid){
this.id=id;
}
privatefinalintvalueOne=9;
privatestaticfinalintVALUE_TWO=99;
publicstaticfinalintVALUE_THREE=39;
privatefinalinti4=random.nextInt(20);
staticfinalintINT_5=random.nextInt(20);
privateValuev1=newValue(11);
privatefinalValuev2=newValue(22);
privatestaticfinalValueVAL_3=newValue(33);
privatefinalint[]a={1,2,3,4,5,6};
publicStringtoString(){
returnid+":"+"i4="+i4+",INT_5="+INT_5;
}
publicstaticvoidmain(String[]args){
FinalDatafd1=newFinalData("fd1");
//!fd1.valueOne++;//因为valueOne是基本类型常量,其数值恒定不变
fd1.v2.i++;//final修饰的对象的内容可以改变
fd1.v1=newValue(9);
for(inti=0;i
分析:
对于fd1,fd2两个对象,其中i4是唯一的,即每个对象都有一个i4,但INT_5被声明为static,即是类共享的,fd1和fd2共享INT_5,在装载时已经被初始化,而不是每次创建新对象时初始化(例如i4);但它同时被设置成final,所以它的引用是不可改变的,即不能被修改指向另一个对象。
空白final:
被声明为final但又没有给定初值。必须在域的定义或者每个构造器中使用表达式对final进行赋值,这正是final域在使用前总是初始化的原因。
final参数:
这意味着你无法在方法中更改参数引用,使其指向另一个参数,但可以修改final对象所指向的内容
例子:
classGizmo{
inti=0;
publicvoidspin(){}
}
publicclassFinalArguments{
voidwith(finalGizmog){
//!g=newGizmo();//无法修改final修饰的引用,使它指向另一个对象
g.i++;//但可以修改final对象所指向的内容
}
voidwithout(Gizmog){
g=newGizmo();
g.spin();
}
//intg(finalinti){
////!i++;//因为参数i是常量值
//}
intg(finalinti){
returni+1;
}
publicstaticvoidmain(String[]args){
FinalArgumentsbf=newFinalArguments();
bf.without(null);
bf.with(null);
}
}
分析:
参数被声明为final,若是基本参数,那它就是一个常量,不能被修改;若是一个引用变量,那么它就不能被修改指向另一个对象,但可以修改该引用所指对象的内容。
fianl方法:
使用原因:
- 把方法锁定,以防任何继承类修改它的含义,即该方法不会被继承的类覆盖
- 效率,若一个方法指明为final,那么就同意编译器将针对该方法的所有调用转为内嵌调用。
类中所有的private方法都隐式地指定为final,由于无法取用private方法,所以也就无法覆盖它。可以对private方法添加final修饰词,但这并不会给该方法带来任何额外的意义。
例子:
classWithFinals{
privatefinalvoidf(){
System.out.println("WithFinals.f()");
}
privatevoidg(){
System.out.println("OverridingPrivate.f()");
}
}
classOverridingPrivateextendsWithFinals{
privatefinalvoidf(){
System.out.println("OverridingPrivate.f()");
}
privatevoidg(){
System.out.println("OverridingPrivate.g()");
}
}
classOverridingPrivate2extendsOverridingPrivate{
/*
*当使用Override注解强制使f()方法覆盖父类的f()方法时,会报错
*因为它不知道父类是否有该方法,对于g()方法来说,它只是生成了一个新的方法,
*并没有覆盖掉父类中的g()方法。
*/
//@Override
publicfinalvoidf(){
System.out.println("OverridingPrivate2.f()");
}
publicvoidg(){
System.out.println("OverridingPrivate2.g()");
}
}
publicclassFinalOverridingIllusion{
publicstaticvoidmain(String[]args){
OverridingPrivate2op2=newOverridingPrivate2();
op2.f();
op2.g();
//可以向上转型
OverridingPrivateop=op2;
//!op.f();//父类中final方法对子类来说是不可见的
//!op.g();
WithFinalswf=op2;
//wf.f();
//wf.g();
}
}
/*output:
OverridingPrivate2.f()
OverridingPrivate2.g()
*/
分析:
覆盖何时发生:
1,子类中出现与父类完全一致的方法
2.子类可以通过向上转型为父类,并调用父类中的那个方法
若父类中某个方法被声明为final或者private,那么这个方法对子类来说是不可见的,就算在子类中创建了与父类一模一样的方法,这也是一个新的方法,而不是从父类中覆盖的方法。
final类:
即该类不能被继承,不管是你还是别人,也就是这个类不需要做任何变动,也不需要任何子类,例如String类。
例子:
classSmallBrain{}
finalclassDinosaur{
inti=7;
intj=1;
SmallBrainx=newSmallBrain();
voidf(){}
}
//error:ThetypeFurthercannotsubclassthefinalclassDinosaur
//Dinosaur类不能有子类
//classFurtherextendsDinosaur{}
publicclassJurassic{
publicstaticvoidmain(String[]args){
Dinosaurn=newDinosaur();
n.f();
n.i=40;
n.j++;
}
}
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。