Java Basics Part 20/20 - Inner Classes
目錄
嵌套類
在 Java 中,在類中可以編寫另外一個類。類中的類就叫做嵌套類(nested class),包含內部類的類就叫做外部類(outer class)。
語法
編寫內部類的語法如下:
class Outer_Demo{
class Nested_Demo{
}
}
嵌套類分成兩種形式:
- 非靜態內部類:這些是類的非靜態成員
- 靜態內部類:這些是類的靜態成員。
非靜態內部類
內部類是 Java 安全機制的一種。Java 的類不可以有 private 這種訪問級別,但是如果一個類中存在內部類,那麼內部類就可以使 private 的了。
根據內部類定義的位置,可以分爲三類:
- 內部類
- 方法內部類
- 匿名內部類
內部類
創建一個內部類是很easy的,只需要在類中編寫另外一個類即可,但是與普通的類不同,內部類可以是 private 的,一旦將內部類聲明爲 private,那麼在外部類類外部就無法訪問這個內部類了。
例如下面這個程序,將內部類定義成 private 的,通過方法訪問這個 private 的內部類:
class Outer_Demo{
int num;
//inner class
private class Inner_Demo{
public void print(){
System.out.println("This is an inner class");
}
}
//Accessing he inner class from the method within
void display_Inner(){
Inner_Demo inner = new Inner_Demo();
inner.print();
}
}
public class My_class{
public static void main(String args[]){
//Instantiating the outer class
Outer_Demo outer = new Outer_Demo();
//Accessing the display_Inner() method.
outer.display_Inner();
}
}
// output
This is an inner class.
訪問私有成員
內部類還可以用來訪問外部類的私有成員。在內部類中,定義一個方法 getValue() 來返回外部類的私有成員,然後第三方的類就可以使用 內部類的 getValue() 方法來訪問外部類的私有成員了。
爲了實例化內部類,要先實例化外部類,然後使用外部類對象的引用來實例化內部類。
Outer_Demo outer=new Outer_Demo();
Outer_Demo.Inner_Demo inner=outer.new Inner_Demo();
下面這個例子表明演示了怎樣通過內部類來訪問外部類的私有成員:
class Outer_Demo {
//private variable of the outer class
private int num= 175;
//inner class
public class Inner_Demo{
public int getNum(){
System.out.println("This is the getnum method of the inner class");
return num;
}
}
}
public class My_class2{
public static void main(String args[]){
//Instantiating the outer class
Outer_Demo outer=new Outer_Demo();
//Instantiating the inner class
Outer_Demo.Inner_Demo inner=outer.new Inner_Demo();
System.out.println(inner.getNum());
}
}
// output
The value of num in the class Test is: 175
方法內部類
在 Java 中,我們甚至可以在方法中編寫一個類,那麼這個類就變成了一個局部類型,就像局部變量一樣,這個類的作用範圍就是在方法中。
一個方法內部類只能在定義它的方法中實例化。舉例:
public class Outerclass{
//instance method of the outer class
void my_Method(){
int num = 23;
//method-local inner class
class MethodInner_Demo{
public void print(){
System.out.println("This is method inner class "+num);
}
}//end of inner class
//Accessing the inner class
MethodInner_Demo inner = new MethodInner_Demo();
inner.print();
}
public static void main(String args[]){
Outerclass outer = new Outerclass();
outer.my_Method();
}
}
// output
This is method inner class 23
匿名內部類
顧名思義,沒有名字的類就是匿名內部類,匿名內部類的聲明和實例化是同時進行的。一般情況下,當需要重寫一個類或者接口的方法時,需要用到匿名內部類。
AnonymousInner an_inner = new AnonymousInner(){
public void my_method(){
........
........
}
};
下面的例子演示了怎樣使用匿名內部類來重寫一個類的方法:
abstract class AnonymousInner{
public abstract void mymethod();
}
public class Outer_class {
public static void main(String args[]){
AnonymousInner inner = new AnonymousInner(){
public void mymethod(){
System.out.println("This is an example of anonymous inner class");
}
};
inner.mymethod();
}
}
// output
This is an example of anonymous inner class
同樣,可以使用匿名內部類來重寫一個接口實現類的方法。
使用匿名內部類作爲參數
一般情況下,如果一個方法接收一個接口/抽象類/具體類的對象作爲參數,那麼我們就可以實現接口,繼承抽象類,然後把對象傳遞給方法。但是如果它是一個類,那麼我們可以直接傳遞給方法。
針對以上三種情況,均可以傳遞匿名內部類給方法。下面是語法:
obj.my_Method(new My_Class(){
public void Do(){
.....
.....
}
});
使用如下:
//interface
interface Message{
String greet();
}
public class My_class {
//method which accepts the object of interface Message
public void displayMessage(Message m){
System.out.println(m.greet() +", This is an example of anonymous inner class as an argument");
}
public static void main(String args[]){
//Instantiating the class
My_class obj = new My_class();
//Passing an anonymous inner class as an argument
obj.displayMessage(new Message(){
public String greet(){
return "Hello";
}
});
}
}
// output
Hello This is an example of anonymous inner class as an argument
靜態嵌套類
靜態內部類就相當於外部類的靜態成員。與使用一般靜態成員一樣,不用實例化外部類就可以訪問。同樣,靜態嵌套類不可以訪問外部類的實例變量和實例方法。靜態嵌套類的語法如下:
class MyOuter {
static class Nested_Demo{
}
}
實例化一個靜態嵌套類與實例化內部類有點不同,如下:
public class Outer{
static class Nested_Demo{
public void my_method(){
System.out.println("This is my nested class");
}
}
public static void main(String args[]){
Outer.Nested_Demo nested = new Outer.Nested_Demo();
nested.my_method();
}
}
// output
This is my nested class