2005年11月05日

初始化和清除
   构造函数负责初始化,分配空间。
   构建器,无返回值,可过载overloading

方法过载overloading(根据参数不同而区分)不能根据返回值
   相同名字的方法。

主类型的过载: 若我们的数据类型小于方法中的自变量,就会向上cast,转换。 如果是大于的话,需要强制转换(信息可能丢失)
 默认构造器:创建一个空对象。如果定义一个构建器,那么就不会使用默认的构建器。

“this”关键字,表示调用它的对象的句柄。//当前对象的句柄

在构建器中调用构建器。使用“this”关键字。例如:

public class Moop{
            int lit;
            int pak;
       public Moop(int x){
                lit = x;
            }
       public Moop(int x,int y){
               this(x);                  //在构建器中调用了构建器。this表示当前对象句柄。
               pak = y;
            }
}
“static”关键字,static定义的方法没有this句柄
注意:我们不可以从一个static方法内部发出对非static方法的调用,除非将以个句柄传到static方法内部。
清除:收尾和垃圾收集
         垃圾收集器只知道释放new分配的内存。当需要释放一些特殊内存的时候,Java提供了一个名为finalize ()的方法。可以在我们的类中定义它。
 finalize()工作原理:当垃圾收集器准备好释放对象空间,它首先调用finalize()方法,并且需要在下一次垃圾收集的过程中才真正回收对象内存。
三个重点:
    1、垃圾收集并不等于“破坏”(释放)Java对象并非肯定最为对象被收集。
  2、我们的对象可能不会当作垃圾被收集掉。
  3、垃圾收集只和内存有关。
什么时候用finalize()呢?答案是最好不用。似乎finalize()没有多少用途,只是在一些特殊的地方。非Java对象调用。

C++ 中的所有对象都必须“破坏”,而Java中大多时候由垃圾收集器来完成。finalize()最有用的地方就是观察垃圾收集过程。
例:

 //:Garbage.java
 //Demonstrate of the garbage
 //Collector and finalization

class Chair{
    static boolean gcrun = false;
    static boolean f = false;
    static int created = 0;
    static int finalized = 0;
    int i;
    Chair(){
        i = ++created ;
        if(created == 47)
           System.out.println("Created 47");
          }

 protected void finalize(){
          if(!gcrun){
             gcrun = false;
             System.out.println(Beginning to finalize after "+created+" Chairs have been created");
                    }
          if(i == 47){
             System.out.println(‘Finalizeing Chair #47,"+"Setting flag to stop Chair creation");
             f = true;
                     }
          finalized++;
          if(finalized >= crated)
              System.out.println("All" + finalized + "finalized");
       }

}

public class Garbage{
    public static void main(String[] args){
                if(args.length == 0){
                      System.out.println("Usage:\n"+
                                          "Java Garbage before\n or:\n"+
                                          "Java Garbage after");
                      return;
                                     }
                      while(!Chair.f){
                               new Chair();
                               new String("TO take up space");
                               }
                       System.out.println("After all Chairs have been created:\n"+ "total created = "+Chair.created+
                                           ", toatl finalized = " +Chair.finalized);
                      if(args[0].equals("before")){
                                System.out.println("gc():");
                                System.gc();
                                System.out.,println("runFinalization():");
                                System.runFinalization();
                                System.out.println("bye");
                                }
                       if(args[0].equals("after")){
                                 System.runFinalizerOnExit(true);
              }
}          

   System.runFinalization()( 收尾)与垃圾收集是否运行无关。Sun公司文档称应该先运行收尾模块,然后再释放存储空间,然而这里若先调用System.runFinalization(),再调用 System.gc(),则收尾模块根本不会运行。(可以自己试一下,我还没有试)

成员初始化:
      若程序员没有初始化,那编译器会为他们赋一个值:
Data Type                          Inital value
boolean                            false
char                                          (Null,不显示)
byte                               0
short                              0
int                                0
long                               0
float                              0.0
double                             0.0

规定初始化:在定义同时赋初值(C++ 中不能这样做)可以用new,方法(带返回值)来初始化

构建器初始化:在用此初始化之前定义的数据成员已经被编译器赋给默认值,所以在构建器中没有强迫我们初始化。

静态数据的初始化:static的初始化只有在必要的时候才会进行。初始化时首先是static

对象的创建过程:以名为Dog的类为例
  1.类型为Dog的一个对象首次创建时,或Dog类的static方法/static字段首次访问时,Java解释器必须找到Dog.class(在环境变量中设置搜索路径)
    2.找到Dog.class后(它会创建一个class对象) 它的所有static初始化模块都会运行.因此,static初始化仅发生一次,即在class对象首次装载时。
    3.创建一个new Dog()时,Dog对象分配足够的内存存储空间。
    4.这种存储空间会清为零,将Dog中所有基本类型设为他们的默认值。
    5.进行字段定义时发生的初始化都会执行。
    6.执行构建器。

明确进行静态初始化
     例:
       class Spoon{
          static int i;
     static{                      //静态初始化开始
          i = 47;
           }
     }

数组初始化: Java中的数组大小在编译的时候才决定,在运行的时候才创建。在编译的时候进行边界检查。牺牲性能换来安全。
 
         int[] a1 = {1,2,3,4,5};
         int[] a2 ;
          a2 = a1; //复制一个句柄。
   对于非基本数据类型的数组初始化:使用new
       Integer[] a = new Integer[] {            //java1.1以后版本支持
                            new Integer(1);
                            new Integer(2);
                         };

          Integer[] a = {             //java 1.0 版本支持(唯一)
                         new Integer(1);
                         new Integer(2);
                        }

未知参数数量大小,及类型:变参表
              //:VarArgs.java
                            //Using the Java1.1 array syntax to create
                            //varivale argument lists
                            class A{int i;}
                           
                            public class VarArgs{
                                  static void f(Object[] x){
                                    for(int i = 0 ; i < x.length ; i++)
                                           System.out.println(x[i]);           //每一个Object都有一个toString(),自动转换
                                          }
                    public static void main(String[] args){
                                      f(new Object[]{                  //不同的类型
                                                 new Integer(47),new VarArgs(),
                                                 new Float(3.14),new Double(11.11)});
                                      f(new Object[]{"one","two","three"});
                                      f(new Object[]{new A(),new A(),new A()});
                                   }
              }
              
多维数组初始化:
                 int[][] a1 = {
                              {1,2,3},
                              {4,5,6},
                              };

                  Integer[][] a2 = {
                           {new Integer(1),new Integer(2)},
                           {new Integer(3),new Integer(4)},
                           {new Integer(5),new Integer(6)},
                           }

                 int[][][[] a3 = new int[pRand(7)][][];             //pRand(int)是一个随机方法
                        for(int i = 0; i < a3.length;i++){
                            a3[i] = new int[pRand{5)][];
                            for(int j = 0 ;j<a3[i].length;j++)
                                 a3[i][j] = new int[pRand(5)];
                            }

2005年11月01日

今天的东西也很基础,不过不要紧,慢慢来。

Java运算符: 一个运算符可能改变运算对象的值。这也叫“副作用”(Side Effect)。所以用的时候要小心。

优先级: 一般优先级很难记住,所以必要的时候用"()"来确定。这个还有个助记的东西:

"Ulcer Addicts Really Like C A lot"溃疡患者特别喜欢维生素C

 助记词  运算符类型  运算符
 Ulcer  Unary  + – ++ – [[rest...]]
 Addicts  Arithmetic(and Shift) * / % + – << >>
 Really  Relational  > < >= <= == !=
 Like  Logical (and bitwise)  && || & | ^
 C  Conditional(ternary)  A>B?X:Y
 A lot  Assignment  =(and Compound assignment like *=)

老外真有意思。

赋值:

          注意:对象赋值。例如:A=B(A、B为句柄);此时A、B都将指向B原先指向的对象。此时A将成为B的别名。无论A或者B对对象的改变都是一样的。当对象作为参数传递时也是传递句柄,所以往往会改变对象本身。

算数运算符:没有什么好讲的。

关系运算符:当两个对象相比较时,请看
      Integer n1 = new Integer(48);

     Integer n2 = new Integer(48);

System.out.println(n1==n2);    //ture of false?句柄比较,false

System.out.println(n1.equals(n2));      //true of false ?对象比较,true

逻辑运算符:

“短路”,当出现false的时候,不需要判断下面的,就可以知道表达式的值。减少运算量。

按位运算符:

 & 与

|  或

~ 非

^ 异或

<<将运算符左边的运算对象向左移动运算符右侧指定的位数(在低位补0)。

>>则将运算符左边的运算对象向右移动运算符右侧指定的位数。“有符号”右移位运算符使用了“符号扩展”:若值为正,则在高位插入0;若值为负,则在高位插入1

>>>(java特有)无符号”右移位运算符(>>>),它使用了“零扩展”:无论正负,都在高位插入0

若对char,byte或者short进行移位处理,那么在移位进行之前,它们会自动转换成一个int。只有右侧的5个低位才会用到。这样可防止我们在一个int数里移动不切实际的位数。

移位符号可以和赋值“=”一起用。<<=或者>>=,先移位,后赋值。

三元if-else表达式:不多说了。

逗号只在for语句里面使用

造型运算(Cast)(类型转换)作用是“与一个模型匹配”。

例:

                  int   i = 200;

                  long  lo = (long)i;

                  long l2 = (long)200;

两种: NarrowingConversion(缩小)—————〉编译器会警告,要求强迫转换。主要是信息可能丢失。

             Widening Conversion (放大)编译器可以自动转换 。

中断和继续

         //:BreakAndContinue.java
//Demonstrates break and continue keywords
public class BreakAndContinue{
          public static void main(String[] args){
              for(int i =0;i<100;i ++){
                     if(i==74)break;//out of for loop
                     if(i%9!=0)continue; //Next iterator;
                        System.out.println(i);
                      }
                      int i = 0;
                      //an "infinite loop "
                          while(true){
                            i++;
                            int j = i*27;
                            if(j==1269)break;//out of loop
                            if(i%10 != 0)continue;//top of loop
                            System.out.println(i);
                                  }
                         }
 }///:`

规则:

1、简单的一个continue会退回内层循环的开头,并继续执行。

2、带有标签的continue会到达标签的位置,并重新进入接在那个标签后面的循环。

3、break会中断当前循环,并移离当前标签的末尾。

4、带标签的break会中断当前循环,并移离由那个标签指示的循环末尾。

goto:java中没有使用的保留字。

在Java中唯一用的标签的地方就是拥有套嵌的循环。

字面值:前缀与后缀

char c =0xffff    //max char hex value
byte b = 0×7f    //max byte hex value
short s = 0×7fff  //max short hex value

int i1 = 0×2f    //Hexadecimal lowercase
int i2 = 0X2F      //Hexadecimal uppercase
int i3 = 0177    //octal (leading zero)

long n1 = 200L
long n2 = 200l

float f1 = 1F
float f2 = 1f
float f3 = 12e-45f  //10 to the power

指数表示 默认为double,上面的表示为1*10^(-45),注意需要强制转换float f3 = (float)12e-45f

double d1=1d;
double d2=1D;
double d3=47e47d //10 to the power
表示47*10^(47),可以不要后缀。

"e"表示"Exponential"指数,幂数。

最后以Java中没有sizeof来结束吧。Java不需要sizeof(),因为她无论在那里都是一样的。与平台无关。

真罗嗦,我说我呢。