java一些基本概念的复习

1. static
static public int test(){}和public static int test(){}没有区别
用Static:不用实例化对象,直接使用类名+方法名就可以调用这个方法
不用Static:需要创建一个实例,通过该实例才能调用这个方法

参考网址:http://caterpillar.onlyfun.net/Gossip/JavaGossip-V1/AboutStaticMember.htm
對於每一個基於相同類別所產生的物件而言,其擁有各自的資料成員,然而在某些時候,您會想要這些物件擁有相同的資料成員,其資料是共享的。
舉個例子來說,在Ball類別中,您會使用到圓周率的這個資料,對於任一個球而言,圓周率都是一樣的,您並不需要讓不同的球物件擁有各自的資料成員來記錄圓周率,而這個記錄的值卻是相同,這只會增加記憶體的消耗而已。
您可以將資料成員宣告為"static",被宣告為"static"的資料成員,它是屬於類別所擁有,而不是個別的物件,您可以將"static"視為個別物件所擁有、共享的資料成員。

要宣告static變數,您只要在宣告資料成員時加上"static"關鍵字就可以了,例如:

public class Ball {
    // ....
    public static double PI = 3.14159; // 宣告static資料
 
    public Ball() {
        // ..
    }
 
    public Ball(double radius, String name) {
        //...
    }
 
    public double getVolumn() {
      // ......
    }
}

由於static成員屬於類別所擁有,所以在不使用物件名稱的情況下,您也可以使用類別名稱加上 . 運算子來存取static資料成員,例如:

System.out.println("PI = " + Ball.PI);

static變數同樣遵守public、protected與 private的存取限制,所以若您要在類別之外直接存取static變數,必須注意它的權限(例如必須設定為public成員)。

雖然您也可以在宣告物件之後,使用 . 運算子來存取static資料成員,但是這並不被鼓勵,通常建議使用類別名稱加上 . 運算子來存取,一方面也可以避免與非static成員混淆。

與靜態資料成員類似的,您也可以宣告方法成員為static方法,又稱靜態方法,被宣告為靜態的方法通常是為了提供工具,例如在Ball類別上增加一個角度轉徑度的方法toRadius():

public class Ball {
    ...
    public static double toRadius(double angle) {
         return 3.14159 / 180 * angle;
    }
}

與靜態資料成員一樣的,您可以透過類別名稱使用'.'運算子來存取static方法(當然要注意權限設定,例如設定為public),例如:

System.out.println("角度90等於徑度" + Ball.toRadius(90));

靜態資料與靜態方法的作用通常是為了提供共享的資料或工具方法,例如將數學常用常數或計算公式,以static宣告並撰寫,之後您可以把這個類別當作工具,透過類別名稱來管理與取用這些靜態資料或方法,例如像J2SE 所提供的Math類別上,就有Math.PI這個靜態常數,以及Math.Exp()、Math.Log()、Math.Sin()等靜態方法可以直接使用,另外還有像Integer.parseInt()、Integer. MAX_VALUE等也都是靜態方法與靜態資料成員的實際例子。

由於static成員是屬於類別而不是物件,所以當您呼叫static方法時,並不會傳入物件的位置參考,所以static方法中不會有 this參考,由於沒有this參考,所以在Java的static方法成員中不允許使用非static成員,因為程式沒有this來參考至物件位址,也就無法辨別要存取哪一個物件的成員,事實上,如果您在static方法中使用非static資料成員,在編譯時就會出現以下的錯誤訊息:
non-static variable test cannot be referenced from a static context

或者是在static函式中呼叫非static函式,在編譯時就會出現以下的錯誤訊息:
non-static method showMe() cannot be referenced from a static context

Java在使用到類別時才會加以載入程式中,如果您要使用一個static資料或方法,而在載入一個類別時,您希望先進行一些初始化動作,您可以使用static定義一個區塊,並在當中撰寫初始化資源的動作,例如:

public class Ball {
    public static int[] arr = new int[10];
    static {
        // 一些初始化程式碼
    }

    ....
}

像上面這樣一個類別,在第一次呼叫而被載入時,static區塊中的程式碼就會被執行,且只會執行一次,要注意的是,static屬性成員必須撰寫在 static區塊之前,而如果在static區塊中發生了例外,則最後會被包裝為 java.lang.ExceptionInInitializerError。
-------------------------------------------------------------------------------------------------------
2. 接口(interface)和抽象类(abstract)
抽象类可以有自己的数据成员和抽象方法,或实现了的方法,如:

abstract   class   A   {
      int   i;
      abstract   void   do();
      int   getI()   {
          return   i;
      }
}

继承抽象类的类可以实现抽象类中的抽象方法,也可以不实现。

接口比抽象类更抽象,不能有数据成员,所有的方法都是抽象方法,
implements接口的类必须实现所有的抽象方法。

==================================参考网址:http://www.cnblogs.com/danica/archive/2011/07/05/2098626.html
abstract(抽象)修饰符,可以修饰类和方法

1,abstract修饰类,会使这个类成为一个抽象类,这个类将不能生成对象实例,但可以做为对象变量声明的类型,也就是编译时类型,抽象类就像当于一类的半成品,需要子类继承并覆盖其中的抽象方法。
2,abstract修饰方法,会使这个方法变成抽象方法,也就是只有声明(定义)而没有实现,实现部分以";"代替。需要子类继承实现(覆盖)。

注意:有抽象方法的类一定是抽象类。但是抽象类中不一定都是抽象方法,也可以全是具体方法。
abstract修饰符在修饰类时必须放在类名前。
abstract修饰方法就是要求其子类覆盖(实现)这个方法。调用时可以以多态方式调用子类覆盖(实现)后的方法,也就是说抽象方法必须在其子类中实现,除非子类本身也是抽象类。

注意:父类是抽象类,其中有抽象方法,那么子类继承父类,并把父类中的所有抽象方法都实现(覆盖)了,子类才有创建对象的实例的能力,否则子类也必须是抽象类。抽象类中可以有构造方法,是子类在构造子类对象时需要调用的父类(抽象类)的构造方法。
举个简单的例子下面有一个抽象类

abstract class E{
public abstract void show();//public abstract 可以省略
}

然后其它类如果继承它通常为了实现它里面的方法

class F extends E{
     void show(){
    //写具体实现的代码
}
}

最后再主方法里面定义一个父类引用指向子类对象,就会发生多态现象,比如
E e=new F();
e.show();
实际调用了子类里面的show()方法

==================================对于多态的理解
继承,是对有着共同特性的多类事物,进行再抽象成一个类。这个类就是多类事物的父类。父类的意义在于可以抽取多类事物的共性。
多态,把子类对象主观的看作是其父类型的对象,那么父类型就可以是很多种类型。

例如父类Person(人)  子类 Students(学生) 子类Teacher(教师)
父类中有抽象方法 void work();子类分别实现
Person p1 = new Student();
Person p2 = new Teacher();
p1.work();
p2.work();
------------------------------
父类:ABC
子类:Abc,Abcd
ABC obj1 = new Abc();
ABC obj2 = new Abcd();
如果ABC是abstract的有一个show();子类实现了show()
那么obj1.show()就是第一个子类的show();
obj2.show()就是第2个子类的show();
多态我的理解就是在运行时期表示的多种形态(不准就这意思)
比如说我现在想写一个test 方法这个方法要调用子类的show方法
那么我可以这么定义
void test(ABC temp)
{
  temp.show();
}

这样我如果想运行第一个子类的show()
ABC obj1 = new Abc();
test(obj1);
如果想运行第2个
ABC obj2 = new Abc();
test(obj2);
这样那个抽象类就类似一个接口,我可以用这个接口来生产东西
比如说过一阵我又想写一个新的类继承它,那么
class Abcde extends ABC
{
  void show()
  {...
  }
}
ABC obj3 = new Abcde();
test(obj3);
这样我只写了一个类,声明了一个对象而没有改变原来的代码,直接调用我新写的类即可,完成了代码的重用
以后我再想写新的类只需再这么做而不必改动原来的代码,这个接口就好像能预测将来发生的事,将来完成的东西只要满足这个接口都可以调用这个函数而不必重新写
-------------------------------------------------------------------------------------------------------
3. java作用域public ,private ,protected 及不寫時的區別
参考网址:http://www.wretch.cc/blog/forkome/9008256

在说明这四个关键字之前,我想就class之间的关系做一个简单的定义,对于继承自己的class,base class可以认为他们都是自己的子女,而对于和自己一个目录下的classes,认为都是自己的朋友。
1、public:public表明該數據成員、成員函數是對所有用戶開放,所有用戶都可以直接進行調用
2、private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用,私有财产神圣不可侵犯嘛,即便是子女,朋友,都不可以使用。
3、protected:protected对于子女、朋友来说,就是public的,可以自由使用,没有任何限制,而对于其他的外部class,protected就变成private。

作用域   當前類 同一package 子孫類 其他package
public     √    √     √    √
protected  √    √     √    ×
friendly     √       √     ×    ×
private    √    ×     ×    ×

不寫時默認為friendly
-------------------------------------------------------------------------------------------------------
4.  final 
成員 (member) 宣告時若使用關鍵字 final 修飾,表示該成員為常數 (constant) ,屬性 (field) 或區域變數 (local variable) 都不能重新給值,
而方法 (method) 繼承 (inherit) 後不可被改寫 (overload)

参考网址:http://www.chinaitpower.com/A200507/2005-07-24/165848.html
final在Java中并不常用,然而它却为我们提供了诸如在C语言中定义常量的功能,不仅如此,final还可以让你控制你的成员、方法或者是一个类是否可被覆写或继承等功能,这些特点使final在Java中拥有了一个不可或缺的地位,也是学习Java时必须要知道和掌握的关键字之一。
final成员
当你在类中定义变量时,在其前面加上final关键字,那便是说,这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可再变。其初始化可以在两个地方,一是其定义处,也就是说在final变量定义时直接给其赋值,二是在构造函数中。这两个地方只能选其一,要么在定义时给值,要么在构造函数中给值,不能同时既在定义时给了值,又在构造函数中给另外的值。下面这段代码演示了这一点:

  import java.util.List;
   import java.util.ArrayList;
   import java.util.LinkedList;
   public class Bat{
       final PI=3.14;          //在定义时便给址值
       final int i;            //因为要在构造函数中进行初始化,所以此处便不可再给值
       final List list;        //此变量也与上面的一样
       Bat(){
           i=100;
           list=new LinkedList();
       }
       Bat(int ii,List l){
           i=ii;
           list=l;
       }
       public static void main(String[] args){
           Bat b=new Bat();
           b.list.add(new Bat());
           //b.i=25;
           //b.list=new ArrayList();
           System.out.println("I="+b.i+" List Type:"+b.list.getClass());
           b=new Bat(23,new ArrayList());
           b.list.add(new Bat());
           System.out.println("I="+b.i+" List Type:"+b.list.getClass());
       }
   } 

此程序很简单的演示了final的常规用法。在这里使用在构造函数中进行初始化的方法,这使你有了一点灵活性。如Bat的两个重载构造函数所示,第一个缺省构造函数会为你提供默认的值,重载的那个构造函数会根据你所提供的值或类型为final变量初始化。然而有时你并不需要这种灵活性,你只需要在定义时便给定其值并永不变化,这时就不要再用这种方法。在main方法中有两行语句注释掉了,如果你去掉注释,程序便无法通过编译,这便是说,不论是i的值或是list的类型,一旦初始化,确实无法再更改。然而b可以通过重新初始化来指定i的值或list的类型,输出结果中显示了这一点:
I=100 List Type:class java.util.LinkedList
I=23 List Type:class java.util.ArrayList
还有一种用法是定义方法中的参数为final,对于基本类型的变量,这样做并没有什么实际意义,因为基本类型的变量在调用方法时是传值的,也就是说你可以在方法中更改这个参数变量而不会影响到调用语句,然而对于对象变量,却显得很实用,因为对象变量在传递时是传递其引用,这样你在方法中对对象变量的修改也会影响到调用语句中的对象变量,当你在方法中不需要改变作为参数的对象变量时,明确使用final进行声明,会防止你无意的修改而影响到调用方法。
另外方法中的内部类在用到方法中的参变量时,此参变也必须声明为final才可使用,如下代码所示:

public class INClass{
      void innerClass(final String str){
           class IClass{
               IClass(){
                   System.out.println(str);
               }
           }
           IClass ic=new IClass();
       }
     public static void main(String[] args){
         INClass inc=new INClass();
         inc.innerClass("Hello");
     }
   } 

final方法
将方法声明为final,那就说明你已经知道这个方法提供的功能已经满足你要求,不需要进行扩展,并且也不允许任何从此类继承的类来覆写这个方法,但是继承仍然可以继承这个方法,也就是说可以直接使用。另外有一种被称为 inline的机制,它会使你在调用final方法时,直接将方法主体插入到调用处,而不是进行例行的方法调用,例如保存断点,压栈等,这样可能会使你的程序效率有所提高,然而当你的方法主体非常庞大时,或你在多处调用此方法,那么你的调用主体代码便会迅速膨胀,可能反而会影响效率,所以你要慎用 final进行方法定义。

final类
当你将final用于类身上时,你就需要仔细考虑,因为一个final类是无法被任何人继承的,那也就意味着此类在一个继承树中是一个叶子类,并且此类的设计已被认为很完美而不需要进行修改或扩展。对于final类中的成员,你可以定义其为final,也可以不是final。而对于方法,由于所属类为final的关系,自然也就成了final型的。你也可以明确的给final类中的方法加上一个final,但这显然没有意义。
下面的程序演示了final方法和final类的用法:

final class final{
       final String str="final Data";
       public String str1="non final data";
       final public void print(){
           System.out.println("final method.");
       }
       public void what(){
           System.out.println(str+"\n"+str1);
       }
   }
   public class FinalDemo {   //extends final 无法继承
       public static void main(String[] args){
           final f=new final();
           f.what();
           f.print();
       }
   } 

从程序中可以看出,final类与普通类的使用几乎没有差别,只是它失去了被继承的特性。final方法与非final方法的区别也很难从程序行看出,只是记住慎用。
final在设计模式中的应用
在设计模式中有一种模式叫做不变模式,在Java中通过final关键字可以很容易的实现这个模式,在讲解final成员时用到的程序Bat.java就是一个不变模式的例子。如果你对此感兴趣,可以参考阎宏博士编写的《Java与模式》一书中的讲解。

到此为止,this,static,supert和final的使用已经说完了,如果你对这四个关键字已经能够大致说出它们的区别与用法,那便说明你基本已经掌握。然而,世界上的任何东西都不是完美无缺的,Java提供这四个关键字,给程序员的编程带来了很大的便利,但并不是说要让你到处使用,一旦达到滥用的程序,便适得其反,所以在使用时请一定要认真考虑。

posted @ 2012-05-24 13:37  日光之下无新事  阅读(228)  评论(0编辑  收藏  举报