06-9-23:
第六章:类之间的关系
(为什么跳到这章?因为这几天研究COM,发现接口非常的重要,因为在C++中,没有接口的概念,我也没有在项目中过多的使用类的继承特性,所以呢,对于接口的好处,理解的不是很深刻,随着COM的深入,渐渐的接口在我的头脑中越来越明显了,我只是想要系统的学习一下)
子类和继承:简单介绍了在java中的类的层次关系。
隐藏变量:不管是子类同名同类型还是不同类型变量,都是隐藏了父类的同名变量,这些变量都只是隐藏。我们可以使用super关键字来引用父类的同名变量。
方法超载:(即子类多态,类似于C++中的虚函数,有一点容易搞混。在C++中,我们可以直接用子类override一个方法,但是这个方法是一个静态的选择,你只有使用virtual关键字,才是动态的。这在之后的final性能中有说明)与变量的隐藏不同,override方法,是动态的。这表示java中的方法定位是动态的,方法的搜索也是从子类到父类。子类可以实现的方法,java不会在更加一般化的superclass中去查找。
@override:(第一次看到这个东东)因为在override的时候,我们很容易犯错误,但是这个错误编译器可能不会发现,从而造成了两个方法的产生。Java5.0提供了一个注释来解决这个问题,@Override告诉编译器,这个被标识的方法是override它的超类的一个方法的,这样可以使得编译器提前检查匹配。
overriden方法和动态绑定:overload方法在编译的时候被编译器选择。而overriden方法是在运行时选择的。(动态绑定听起来好像十分的简单,但是到底是怎么完成的,如果引用的是一个网络上的类,又是怎样完成定位的)类型转换的时候影响了overload方法,而不会影响override方法。
final方法和性能:在C++中,方法默认的行为就像是隐藏变量,所以你必须显式声明这个方法为动态的,比如virtual关键字。但是在java中,默认的是动态。但是你能够使用final修饰符来声明一个实例方法不能够被overriden在一个子类中,这样它就不会从属于动态绑定。
在变量中,我们也会发现final关键字,用来表示他们是常量。当应用到一个方法时,final意味着它不允许override。final也可以用于类,表示类不能被继承。(刚才尝试使用C++来做个试验,发现自己这一年使用C#惯了,把我的老本行C++也忘记了许多,脑子里关于C++的完全是MFC或者是STL了,但是经过回忆,发现以前十分难理解的地方,豁然开朗了,看来理论+实践真的很有道理,人就是要不断的在这个理论+实践中循环,在这个循环中不断的总结,总结和归纳了,才是自己的了。其实小学的时候,我们语文老师就开始强调我们要善于总结,但是人小不懂,只清楚在文学的时候,要归纳总结段落大意。本科的时候有充裕的时间来想问题,才慢慢体会了,总结和归纳的重要性,不管做任何事情,你都要善于总结,其实人生就是一本书,你总结好了,你就会读懂它。)
在以前,动态方法绑定带来了性能的损失,有些人仍然倾向于使用final修饰符来保护。现在的java运行时消除了这些。它能够决定哪些方法不被override,然后把他们做成inline,把他们看成像是final,直到他们另外有必要改变。作为一个规则,你有必要使用final关键字,当它对你的程序结构有用时,而不是从性能上考虑。
编译优化:现在的javac是智能优化你的代码,比如内联和静态。还有允许你在Java代码中加入调试代码,而没有一点性能的损失。java没有预编译,但是你能够获得一些同样的效果来控制哪些代码被include,使用一个常变量,比如static final,加一个if。(这个的使用我还是没有多大的把握)
06-9-25:
方法选择重访:
异常和overridden方法:
特别的引用:this和super:简单讲了super和this的作用,强调super的作用,在overridden中。
类型转换:在Java中,类型转换是在编译时期和运行时。在编译时,javac将会阻止你执行一个不可能执行的转换,比如把date类型的转换成string的。运行时Java将会检查似是而非的转换,比如string到string。
尝试把一个对象转换到一个不兼容的类型,在运行时会抛出ClassCastException。同样继承层次的对象才能够相互转换。类型转换仅仅影响了对待引用的方式。他们从来不改变真正的对象的形式。你不能改变对象指向,你仅仅改变了编译器对待它的概念。
类型转换能够缩小或者使引用的类型向下。通常我们这么做当我们不得不检索一个对象从一个更加泛型的集合中,或者当这个对象是更加的派生。(就是说,在java中,我们可以隐式的把一个derived类赋给superclass,也可以显示的转换把一个superclass赋给derived类)如果你有一只猫的对象,你可以把它作为动物或者object,因为object是所有的java类的基类。使用instanceof可以检查一个对象是否是对象A(这个又是没有听说过的,有点像MFC中的IsKindOf和C#中的GetType方法,包括VB6.0都给出了这样的函数或者方法。)
但是转换能够影响编译器选择变量或者是overloaded的时间,而不是overridden方法的时间。(可能是我翻译水平不够的问题,这里的意思是,类型转换可以影响变量和overloaded的方法,但是不影响overridden方法)
类型转换的损失:在Java中应该尽量的避免类型转换,这使得代码可读性变差。Java5.0出现的泛型部分地解决了类型转换的问题。
06-9-26:
使用superclass构造函数:如果superclass含有默认的构造函数,subclass调用可以隐式(显示)调用superclass的默认构造函数;如果没有则要在subclass中显示的调用super(...)的含有参数的构造函数。
完全揭露:构造函数和初始化:
抽象方法和类:abstract修饰符用来声明一个方法仅仅是原型。你不能使用一个包含抽象方法的类;同样的也可以声明一个抽象类(这个与C++中的抽象类相似,但是表示的方法不一样,没有abstract修饰符,直接在声明后面加“=0”,表示抽象方法)抽象类提供了一个框架。比如java.io.InputStream类,有一个抽象的方法read()。
接口:
Java在抽象类的基础上扩展的概念。一个类可以使用implements实现需要的方法。不像抽象类,一个实现接口的类不需要继承任何特殊的继承层次或者任何一个实现。
接口类型就像是类这个类型。你能够声明一个接口类型的变量,你能够声明一个方法的参数是接口类型,而且你能够方法的返回值是接口。这些表示任何实现了接口的对象可以代替角色。(这个巴适,我之前看了一个Java的源代码,这些源代码使我非常的迷惑,我了解一点关于接口的知识,我脑袋中,就认为接口是不能被实例化的,也就是不能够声明一个接口类型的变量,但是这些源代码上却活生生的声明了接口变量,作为方法的函数和实例变量。)在这个意义上,接口是垂直于类的层次的。他们切断了对象是什么类型和对象能完成什么功能之间的界限。一个类能够实现多接口,在这个意义上,接口代替了Java对多继承的需要。
一个接口实质上像一个纯粹的抽象类。可以接收,但是没有必要在声明方法中,加入abstract修饰符。更重要的是,一个接口的方法总是被认为public的。
接口是定义对象的能力的,所以一般都把接口以他们的能力命名。Driveable,Runable啊,都是好的名字。任何一个实现了所有方法的类可以使用implements表示它实现了接口。