Reading "Thinking in Java" #5

本文深入探讨Java中final关键字的使用,包括其在基本类型、对象引用、方法参数、方法和类成员上的不同作用,以及如何利用final实现不变性和效率优化。

6. Reusing Classes

Java编译器并不会给任何reference产生缺省对象,这样就避免了大多数情况下的不必要的负担。初始化需要的对象可以在以下地点:

1,对象定义处。由于类初始化顺序的规则,这样做可以保证以此方法初始化的对象将会在构造函数被调用前完成初始化。
2,构造函数内部。
3,当需要使用该对象时,这种方式被称为(缓式初始化)lazy initialization。如果一个对象并非总是必须,那么这种方式可以减少额外负担。

关于清理动作,要注意的是顺序:首先执行当前类的所有清理动作(其中次序和生成次序相反),而后再调用base class的清理函数。外带一句,除了内存,最好永远不要相信垃圾回收机制。

Final data

Bruce在这部分说:Java中final修饰对于基本类型和对象引用(object reference)而言,意义是不同的。用于基本类型时,final让value(数值)保持不变。用于object reference时,final让reference保持不变,但对象本身的内容却是可以更动的恶。Java并未提供让任何对象保持不变的机制,虽然可以自己编写具有保持不变效果的class。特别提醒,array也是对象。

我要说的是,我没发现final在基本类型与对象引用的意义有何不同。final都是让两者的value保持不变,基本类型的value就是对应的数值或者bool值。而对象引用的value在理解上可以解释为指向object的地址。当然,这里似乎对于Java的底层实现做了假设而我确实也没细究过Java如何实现object reference的。但是,就Java语法及我个人的体会而言,我觉得这是很好的一种理解方式。

Blank finals

Java允许把数据成员声明为final却不赋予初始值。当然,final修饰的数据成员必须在其被使用前完成初始化,这一点由编译器保证。这个特性让我们可以把某个数据成员声明为final具有不变的特性,却在每个对象中为不同的值。

Final arguments

Java中还可以把method的arguments声明为final,意义不变,只是不变特性的范围仅仅在此method内。对于对象引用,即是在此method内拥有此对象的一个不可变更的引用,而不影响此对象存在其他非final的引用。

Final method

有两个原因把一个method修饰成final。第一,对于类A中的某个method,你希望在类A所有子类中此方法的表现不变,即此方法不可被覆写(overriding)。第二,处于效率考虑,因为编译器会尝试把不太长的final method改为inner method。而Bruce Eckel建议我们不要相信编译器的智商,只在确实处于设计的考虑需要时,才把method修饰为final。

final & private

private的method对于子类是不可见的,自然也无法覆写(overriding)。似乎,private隐含了final?如果一个函数已经是private,似乎final修饰与否都无关紧要? 
首先,这两个假设,前者错误,后者正确。因为private的method对于子类是不可见的, 所以对于子类而言如此的函数就如同是父类中的一段普通代码。如果此时在子类中声明一个与父类中的private method同名的函数,编译器是允许的。然而,注意,此时只是在这个继承体系中加入了一个新函数而已,并非是一个覆写。因为覆写(overriding)的前提是,被覆写的函数是可见,是父类的对外的界面。至于对private函数再加final修饰,编译器是允许的。但毫无意义,因为private的函数对于子类不可见,所以也就无需声明是否允许覆写(overriding)。

下面还是贴段代码来解释:

ExpandedBlockStart.gifContractedBlock.gif/**//*
InBlock.gif * Created on 2004-11-30
InBlock.gif *
InBlock.gif * TODO To change the template for this generated file go to
InBlock.gif * Window - Preferences - Java - Code Style - Code Templates
ExpandedBlockEnd.gif 
*/

None.gifpackage com.smilereader.test;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**//**
InBlock.gif * @author Sinbadblue Kong
InBlock.gif *
InBlock.gif * TODO To change the template for this generated type comment go to
InBlock.gif * Window - Preferences - Java - Code Style - Code Templates
ExpandedBlockEnd.gif 
*/

ExpandedBlockStart.gifContractedBlock.gif
class Treasure dot.gif{
InBlock.gif    
ExpandedSubBlockStart.gifContractedSubBlock.gif    
private final void f()dot.gif{
InBlock.gif        System.
out.println("Treasure.f()");
ExpandedSubBlockEnd.gif    }

InBlock.gif    
ExpandedSubBlockStart.gifContractedSubBlock.gif    
private void g()dot.gif{
InBlock.gif        System.
out.println("Treasure.g()");        
ExpandedSubBlockEnd.gif    }

InBlock.gif    
ExpandedSubBlockStart.gifContractedSubBlock.gif    final 
void e()dot.gif{
InBlock.gif        System.
out.println("Treasure.e()");
ExpandedSubBlockEnd.gif    }

InBlock.gif    
ExpandedBlockEnd.gif}

None.gif


ExpandedBlockStart.gifContractedBlock.gif/**//*
InBlock.gif * Created on 2004-12-5
InBlock.gif *
InBlock.gif * TODO To change the template for this generated file go to
InBlock.gif * Window - Preferences - Java - Code Style - Code Templates
ExpandedBlockEnd.gif 
*/

None.gifpackage com.smilereader.test;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**//**
InBlock.gif * @author Sinbadblue Kong
InBlock.gif *
InBlock.gif * TODO To change the template for this generated type comment go to
InBlock.gif * Window - Preferences - Java - Code Style - Code Templates
ExpandedBlockEnd.gif 
*/

ExpandedBlockStart.gifContractedBlock.gif
class Gemstone extends Treasure dot.gif{
InBlock.gif    
InBlock.gif    
//    add a new method Gemstone.f(), it isn't an overriding
ExpandedSubBlockStart.gifContractedSubBlock.gif
    public final void f()dot.gif{
InBlock.gif        System.
out.println("Gemstone.f()");
InBlock.gif        
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
//  add a new method Gemstone.g(), it isn't an overriding
ExpandedSubBlockStart.gifContractedSubBlock.gif
    public void g()dot.gif{
InBlock.gif        System.
out.println("Gemstone.g()");
ExpandedSubBlockEnd.gif    }

InBlock.gif 
InBlock.gif    
//can't overriding Treasure.e()
InBlock.gif
//    public void e(){
InBlock.gif
//        System.out.println("Gemstone.e()");
InBlock.gif
//    }
InBlock.gif

ExpandedBlockEnd.gif}

None.gif


我觉得Java的编译器在此处的处理不太合适,容易导致混淆。如果对于private 与 final修饰做互斥处理,我个人觉得会是比较合适的又容易理解的方式。

转载于:https://www.cnblogs.com/sinbadblue/archive/2004/11/30/71059.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值