请问方法的参数如果是fianl的对象,有什么作用,为什么这样定义?
class TTT
{
void change1(M a)
{
a.i=10;
System.out.println( "Hello World! "+a.i);
}
void change2(final M a)
{
a.i=20;
System.out.println( "Hello World! "+a.i);
}
}
change2中的参数是fianl类型的有什么用呢?
fianl修饰引用类型,表示此引用不可以指向其它对象,而并不是对象的值不可改变,因此上面的change1和change2中都可以改变a对象的属性。那么,讲参数用fianl修饰可以带来什么好处呢?
[解决办法]
提示LZ:研究一下内部类、匿名内部类^_^
[解决办法]
首先,final表示一个变量一旦初始化以后,值就不能再被更改。
对于参数设为final是一样的。要知道的是,参数的值是在实际调用的时候给的,所以在函数体中不能更改参数的值。
change2的参数为final M a,那么a在函数change2中不能再被赋予其他值,也就是说,你不能写类似于a = new M()之类的语句。但是对于a所指向的对象,当然是可以更改值的,因为尽管这样,a的值(可以看成是对象的地址)并未变化。
[解决办法]
To pczhouji(咱也进城了):
这个跟内部类、匿名类似乎没什么关系吧?
[解决办法]
final使得被修饰的变量 "不变 ",但是由于对象型变量的本质是“引用”,使得“不变”也有了两种含义:引用本身的不变,和引用指向的对象不变。
引用本身的不变:
final StringBuffer a=new StringBuffer( "immutable ");
final StringBuffer b=new StringBuffer( "not immutable ");
a=b;//编译期错误
引用指向的对象不变:
final StringBuffer a=new StringBuffer( "immutable ");
a.append( " broken! "); //编译通过
可见,final只对引用的“值”(也即它所指向的那个对象的内存地址)有效,它迫使引用只能指向初始指向的那个对象,改变它的指向会导致编译期错误。至于它所指向的对象的变化,final是不负责的。这很类似==操作符:==操作符只负责引用的“值”相等,至于这个地址所指向的对象内容是否相等,==操作符是不管的。
理解final问题有很重要的含义。许多程序漏洞都基于此----final只能保证引用永远指向固定对象,不能保证那个对象的状态不变。在多线程的操作中,一个对象会被多个线程共享或修改,一个线程对对象无意识的修改可能会导致另一个使用此对象的线程崩溃。一个错误的解决方法就是在此对象新建的时候把它声明为final,意图使得它“永远不变”。其实那是徒劳的。
[解决办法]
1.final用在域中时,表示为常量,即运行时变量不可修改.
2.用在方法前时,如public final methodName...指定了子类对此方法不可重写,
一般在abstract类中多用,
3.用来限定传入的参数,就是楼上所说的在ni名内部类,比如你给一个启动线程ni名内部类要传入参数,则必须是final型.
一下就想起这么多,供你参考.
________________________________________________
www.NetJava.cn 领先的.Net&Java技术推广者.
[解决办法]
关系大大滴有,请注意LZ已经强调他不明白的是final出现在形参之前。
[解决办法]
引用指向的对象不变:
final StringBuffer a=new StringBuffer( "immutable ");
a.append( " broken! "); //编译通过
==========
final修饰对象 仅仅是饮用不变 不是只想的对象不变
你给的例子 对象的内容变化了 赫赫
引用确实没有变 但是内容却是变化了
[解决办法]
6.8.2 final方法
之所以要使用final方法,可能是出于对两方面理由的考虑。第一个是为方法“上锁”,防止任何继承类改变它的本来含义。设计程序时,若希望一个方法的行为在继承期间保持不变,而且不可被覆盖或改写,就可以采取这种做法。
采用final方法的第二个理由是程序执行的效率。将一个方法设成final后,编译器就可以把对那个方法的所有调用都置入“嵌入”调用里。只要编译器发现一个final方法调用,就会(根据它自己的判断)忽略为执行方法调用机制而采取的常规代码插入方法(将自变量压入堆栈;跳至方法代码并执行它;跳回来;清除堆栈自变量;最后对返回值进行处理)。相反,它会用方法主体内实际代码的一个副本来替换方法调用。这样做可避免方法调用时的系统开销。当然,若方法体积太大,那么程序也会变得雍肿,可能受到到不到嵌入代码所带来的任何性能提升。因为任何提升都被花在方法内部的时间抵消了。Java编译器能自动侦测这些情况,并颇为“明智”地决定是否嵌入一个final方法。然而,最好还是不要完全相信编译器能正确地作出所有判断。通常,只有在方法的代码量非常少,或者想明确禁止方法被覆盖的时候,才应考虑将一个方法设为final。
类内所有private方法都自动成为final。由于我们不能访问一个private方法,所以它绝对不会被其他方法覆盖(若强行这样做,编译器会给出错误提示)。可为一个private方法添加final指示符,但却不能为那个方法提供任何额外的含义。
[解决办法]
final表示不可修改的
上面说了很多了
------解决方案--------------------
表示参数不能或者不会在方法体中被修改,这好像是一般编程规范的一部分,就是说当方法体不改变所引用的对象值的时候,该对象在方法的参数表中应该被定义成final。这样,如果方法体内试图对该对象做修改,编译就会报错
[解决办法]
楼主如果看看汇编,会理解得更好一些。
许多困惑都是因为我们不想只知其然不知其所以然,这就需要了解很多背景知识和它们的发展历程。
[解决办法]
final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载。
finally—再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。
finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。
[解决办法]
主要限定了引用。这个对象只能指向这个向存块。但这个对象内容的改变final是无法限定的
[解决办法]
个人认为,楼主用反编译来理解final所得出的结论可能有问题:
因为 final 限制是在编译时检查的,所以如果
1.编译通过,final关键字会自动去掉:用反编译是看不到final关键字的;
2.编译如果通不过,编译器报错。
所以用反编译.class来查看final是不对的。
而final关键字,无论在哪,作用都是那几个,在dongdandan()所给的例子也不例外。
[解决办法]
final 修饰的参数表示 该参数不能被重新分配内存空间!但是他的属性可以被修改!
可以修改属性 a.i=20;
但不能写 a=new M();
[解决办法]
更正一下,用反编译看final关键字判断final是否有用是不太合理的。
final关键字编译器是否会优化掉取决于:
代码执行时期是否有可能改变该变量的值:方法内的局部变量不能在后期绑定中改变,所以final被去掉了;而类的变量是有可能在执行时改变值,所以final关键应该保留。
[解决办法]
常量用它就对了
[解决办法]
up