1.接口
首先接口不是類,而是對類的一組需求描述。下面是泛型類型的接口代碼
public interface Comparable<T>
{
int compareTo(T other);
}
接口中的所有方法自動屬於public,在接口中聲明方法,不必提關鍵字public。注意,接口中不能提供實例域和方法實現,這些必須由實現接口的那個類來完成。
這里簡單舉例說明下實例域的概念:
舉個例子:人類是一個類,張三就是人類的一個實例。
人類都有手、腳,可以理解為 人類的域。
張三的手、腳就是張三這個實例的自己的私有的域,比如張三有一個手指是斷的,不能說人類的手
這里接口和沒有實例域的抽象類類似,但它們還是有所區別。有如下區別:
1.接口是公開的,里面不能有私有的方法或變量,是用於讓別人使用的,而抽象類是可以有私有方法或私有變量的。
2.接口可以實現多重繼承,而一個類只能繼承一個超類,但可以通過繼承多個接口實現多重繼承。
3.接口可以多繼承,抽象類不行。
4.接口中基本數據類型為static 而抽類象不是的。
以下是實現接口方法的語句(注意:在現實接口時,必須把方法聲明為public,否則,編譯器將認為這個方法的訪問屬性是包可見性,即類的默認訪問屬性,之后編譯器就會給出試圖提供更弱的訪問權限的警告信息):
class Employee implements Comparable<Employee>
{
public int compareTo(Employee other)
{
return Double.compare(salary,other.salary);
}
}
我們再來看接口的一些特性:
1.接口不是類,所以不能用x=new Comparable(...);來實例化一個接口,但可以先聲明一個接口變量,再對其進行類的實例化。
Comparable x;
x=new Employee(...);
2.我們可以用一下語句來檢查對象是否實現了某個特定的接口:
if(anObject instanceof Comparable){...}
3.接口也可以擴展
public interface Moveable
{
void move(double x,double y);
}
public interface Powered extends Moveable
{
doble milePerGallon();
}
public interface Powered extends Moveable{
double milesPerGllon();
double SPEED_LIMIT=95;//a public static final constant,接口中的域將被自動設為public static final.
2.內部類
定義在另一個類中的類,稱為內部類。
1.內部類可以對同一個包中的其他類隱藏起來。 (一般的非內部類,是不允許有 private 與protected權限的,但內部類可以)
2.內部類方法可以訪問外圍類中定義所在作用域中的數據,包括私有的數據。
3.可以實現多重繼承
4.可以避免修改接口而實現同一個類中兩種同名方法的調用。
5.當想要定義一個回調函數且不想編寫大量代碼時,使用匿名內部類比較便捷。
內部類嵌套類的兩個重要作用是:命名控制和訪問控制
看下面這個C++嵌套類的例子:
Class LinkedList
{
public:
class Iterator
{
public:
void insret(int x);
int erase();
...
};
private:
class Link
{
public:
Link*next;
int data;
}
...
};
Iterator被嵌套在LinkedList類內部,我們可以用LinkedList::Iterator的方式命名來避免與其他名為Iterator的類重復。
即使Link的數據域被設計為公有的,它仍然安全,只能被LinkedList中的方法訪問。
注意,JAVA中的內部類還有另外一個功能,內部類的對象有一個隱式引用,通過這個指針可以訪問外圍類對象的全部狀態。請看下面的java內部類的例子:
public class TalkingClock
{
private int interval;
private boolean beep;
public TalkingClock(int interval,boolean beep){...}
public void start(){...}
public class TimePrinter implements ActionListerner
{
public void actionPerformed(ActionEvent event)
{
Date now=new Date();
System.out.println("At the tone,the time is"+now);
if(beep)Toolkit.getDefaultToolkit().beep();//我們把外圍類對象的引用稱為outer,所以該語句等價於if(outer.beep)Toolkit.getDefaultTookit().beep();
//使用外圍類引用的正規語法還要復雜一些。表達式為:OuterClass.this,所該語句可以改寫為if(TalkingClock.this.beep)Toolkit.getDefaultTookit().beep();
}
}
從上面的例子看出,內部類可以訪問自身的數據域,也可以訪問創建它的外圍類對象的數據域。注意可以用outerObject.new Inner(construction paramenters)
來編寫內部對象的構造器。同樣可以用OuterClass.InnerClass的語法來引用內部類。
我們繼續來看下面這個局部內部類
public void start()//我們把該語句改成public void start(int interval,final boolean beep), 這樣局部類不僅能訪問它們的外部類,還可以訪問局部變量,注意局部變量必須被
//聲明為final,局部變量的訪問非常容易,它減少了需要顯示編寫的實例域,從而使得內部類更加簡單。
{
class TimePrinter implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
Date now=new Date();
System.out.println("At the tone,the time is"+now);
if(beep) Toolkit.getDefaultTookit().beep();
}
}
ActionLister listener=new TimePrinter();
Time t=new Timer(interval,listener);
t.start();
}
注意局部類不能用public或者private訪問說明符進行聲明,它的作用域被限定在聲明這個局部類的塊中。因此,它有一個更大的優勢是,對外部世界完全的隱藏起來,
除start方法之外,沒有任何方法知道TimePrinter類的存在。
匿名內部類
創建這個類的一個對象,就不必命名了,我們稱為匿名內部類。
public void start(int interval,final boolean beep)
{
ActionListener listener=new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
Date now=new Date();
System.out.println("At the tone,the time is"+now);
if(beep)Toolkit.getDefaultToolkit().beep();
}
};
Timer t=new Timer(interval,listener);
t.start();
}
注意匿名類沒有類名,而構造器的名字必須域類名相同,所以匿名類沒有構造參數。
靜態內部類
如果我們僅僅想把一個類隱藏在另一個類中,而不需要引用外部對象,可以將內部類聲明為static,以便取消產生引用。