Think in java 学习手记(二)

来源:互联网 发布:怎么作图软件下载 编辑:程序博客网 时间:2024/05/01 11:48

    可怜我的五一长假了……

 

Chap 5 隐藏实现

1*.java文件中具有两个以上类时的处理

       当一个java文件(又称编译单元)包含两个以上类时,只能有一个类有public 类,其余类全部默认为非public的,其实也就相当于public的辅助类,仅仅为该public 服务。

2、将域名作为包名的作法是非常好的创意,这可以确保包名不重复。这是一个相当重要的命名原则,试想你的程序要与世界上其它任何别的公司开发的程序进行整合时,要避免不重名是多么麻烦的事。

3、如何找到某个类?

       1)一般的类:通过设置CLASSPATH来解决。如某个包:com.p9.doc。该包存放在D:/Tomcat/com/p9/doc中,则设置CLASSPATH D:/TOMCAT 。查找该包时,就会先找到D:/TOMCAT,然后再结合包名,就可以找到了。

       2)对Jar文件:必须在CLASSPATH中包含完整的名字。如classpath=d:/t1/t2.jar。这很容易解释,t2.jar将全部解压到t2目录下去。

       3)如果你不把”.”放进CLASSPATH,则java不会查找本目录。这相当重要。

4、关于package权限

       又称友元权限(friendly)。当一个包有多个类时,可以不给这个类赋权限符号,这时这个类就是package权限,即包中所有其它类都可以访问该类,而包外的类均不能访问。

       可以说,没有package权限,包存在的意义就不大。正因为有了这个权限,包才形成一个有机的整体。

       对于同一个目录里面的所有文件,尽管没有声明所属的包,但系统会认为它们处在当前目录的默认包中。

       要注意:protected也包含了package权限。

5、关于构造函数

       以前想当然地认为所有构造函数都是public的,错了错了,哈哈。

6、代码风格

       不同的权限按顺序归类存放是合适的:public protected package private 。这样便于阅读。

7、类的权限

       类只能是public package 的。当你不想让别人访问你的类时,可以将构造函数做成private的。但可以在这个类里面用静态方法来调用构造函数。想一想设计模式。

Chap 6

1、关于同一个包中,有多个类都具有main方法的情况

       实际上这种情况也是推荐的。Main方法的目的就是用于调试。

2、两个构造函数的互调用

       设有两个构造函数A()和Aint I),且后者要调用前者,则不能直接写A(),而要写this();

3、关于super的用途

public class StackTest extends A2{

 

       /**

        * @param args

        */

       public StackTest(){

              //super(  );

              System.out.println( "A3" );

       }

       public static void main(String[] args) {

              //A.main();

              new StackTest();

       }

}

 

class A1{

       A1(){

              System.out.println( "A1" );

       }

}

 

class A2 extends A1{

       A2(){

              System.out.println( "A2" );

       }

}

       上面这段简单代码中,继承层次分别为StackTestàA2àA1。这时,在执行new StackTest()时,其执行顺序依次是:先执行A1.A1(),再执行A2.A2(),最后执行StackTest()。即先执行父类的构造函数,再执行子类的构造函数。

       而假设取消StackTest()super()前面的注释,则直接执行父类的构造函数,再执行以后的语句。注意Super()只能放在程序体首行。

       这样,通过这两种方式,最后得到的结果是一样的。

       **那么,super又有什么用途呢?

       假设A2只有一个构造函数:A2(int I),那么StackTest()就会出错,要求明确调用A2的构造函数。所以这里就要用到super(1)或其它了。

       **换句话说,super主要针对父类带参构造函数。

4、关于final

       primitive类型,final表示值不可变;

       对类类型,final表示reference不可变,但值当然是可以变的了。

       看起来,后者并无多大用处。

       还有一种空白final,也就是先定义final,再赋值。例如:先定义final int I ;再I = 3

       可以在方法的参数表中指定final。例如with(final int I)。在方法中不能改变I,即只读参数。当然,这也没什么实际用途。   

       方法本身也可以是final的,这样派生类就不能覆盖这个方法了。Final方法本身据说还可以提高效率,但这点提升是微不足道的。

       如果把类声明为final的,则表明你不希望别人继承这个类。

       不要随便将类声明为final的。以jdk1.0/1.1Vector为例,有很多final方法。具有讽刺意味的是,看起来逻辑上与Vector并无关系的Stack类偏偏就继承了Vector类。而同样是集合类的Hashtable,则没有一个final方法,并且命名要简洁得多。所以作者说这些类是一群毫不相干的人设计的。

 

Chap 7 多态性

1、如何理解Random的调用方式?

       Random的调用一般是这样的:

       Random r = new Random();    I = r.nextInt(3);

       这典型地不同于其它过程化的语言,这些语言一般是用函数I = random(3)直接实现。

       作为面向对象的语言,为了让一切对象化,很自然地,Random就成了对象。这时,为了便于理解,我们可以将Random看作一个无限长的stream,每次调用nextInt时光标就移到下一位置。这种理解是比较曲折,但这是面向对象的代价吧。

2、关于扩展接口

       这是多态中不太好理解的一个地方。

       假设基类为:

              abstract class Shape{

              void draw(){}

              void erase(){}

       }其有两个接口。

       而派生类为:

              class Square extends Shape{

              void draw(){

                     System.out.println( "Square.draw()" );

              }

              void erase(){

                     System.out.println( "Square.erase()" );

              }

              void tt(){

                     System.out.println( "tt" );

              }

       }其有三个接口, 最后一个是扩展接口。

       假设main中是这样定义的:

       Shape square = new Square();

       则下面这句调用是合法的:

       square.draw(); 将调用Squaredraw().

       而下面这句调用是非法的:

       square.tt();因为这是扩展接口,而Shape类型不能找到扩展接口。

3、多态性的关键:上传与下传

       上传:

       A是父类,A1是子类,如下语句实现上传:A  a1 = new  A1()

       下传:

       接上,如下语句实现下传:(A1) a1,即将类型强制转换回子类。要调用非扩展接口,则必须下传。
复用类