java基礎之內部類詳解
說到Java的內部類,相信會有人跟我一樣剛瞭解時有點難以理解,(本人通過一番學習也僅僅只是略知一二,但從未使用過。。。)再此總結了下個人學習所得。
內部類定義
內部類就是在一個類的內部定義的類,內部類也是一個獨立的類,在編譯時會產生相應的class檔案。如下例:
class Outer{
class Inter{}
}
這就是一個基本的內部類,它在編譯時會產生兩個.class檔案,Outer.class和Outer$Inter.class,內部類的.class檔案命名為:外部類$內部類.class
內部類的種類
java內部類分為: 成員內部類、靜態巢狀類、方法內部類、匿名內部類 。
-
成員內部類
成員內部類的意思和成員變數類似,即直接在一個類中定義的類。那麼內部類該如何訪問呢?內部類除了可以在外部類中產生例項化物件,也可以在外部類的外部來例項化。如下例:
public class test { public static void main(String[] args) { outer o=new outer() outer.inter i=o.new inter(); i.print(); } } class outer{ //成員內部類 private class inter{ public void print(){ System.out.print("inter"); } } }
在上述程式碼中,想要使用inter內部類中的print方法怎麼辦呢?我們可以通過上面的
outer o=new outer() outer.inter i=o.new inter(); i.print();
這種方式來建立內部類的物件用於訪問內部類中的方法和變數。但通常情況下,我們並不建議這樣來例項化內部類的物件。我們可以採用在外部類封裝一個方法,用於訪問內部類,並向外部類提供內部類介面,如下例:
public class test { public static void main(String[] args) { //在外部建立成員內部類的例項(通常不建議如此例項內部類物件) //outer o=new outer() //outer.inter i=o.new inter(); //i.print(); outer o=new outer(); o.interPrint(); } } class outer{ //建議在外部類定義一個方法,用於訪問內部類,並向外部提供內部類介面 public void interPrint(){ inter i=new inter(); i.print(); } //成員內部類 private class inter{ public void print(){ System.out.print("inter"); } } }
我們在outer外部類中定義一個方法,實現內部類的訪問,這樣就可以在其他類中直接例項化外部類物件用於訪問內部類即可,並且內部類可以加上private修飾符,使其他類無法訪問該內部類 。
-
方法內部類
內部類可以作為一個類的成員外,還可以把類放在方法內定義。格式如下:
class Outer{
public void thing(){
class Inter{
public void print(){}
}
}
}
但是注意,方法內部類只能在定義該內部類的方法內例項化,不可以在此方法外對其例項化,並且方法內部類物件不能使用該內部類所在方法的非final區域性變數。
class Outer{
public void thing(){
class Inter{
public void print(){
System.out.print("方法內部類");
}
}
Inter inter=new Inter();
inter.print();
}
只能通過上面的方式來訪問該內部類。
-
靜態巢狀類
在一個類內部定義一個靜態巢狀類,靜態的含義是該內部類可以像其他靜態成員一樣,沒有外部類物件時,也能夠訪問它,靜態巢狀類僅能訪問外部類的靜態成員和方法。
class Out{
static class in{
}
}
public class Test{
public static void main(String[] args) {
Out.in n=new Out.in();
}
}
-
匿名內部類
匿名內部類顧名思義就是沒有名字的內部類。匿名內部類有三種情況:繼承式的匿名內部類,介面式的匿名內部類,引數式的匿名內部類。
1.繼承式匿名內部類
public class Test{
public static void main(String[] args) {
Out.in n=new Out.in();
test1 t1=new test1();
t1.print();
}
}
class test1 {
public void print() {
test2 t2 = new test2() {
@Override
public void thing() {
System.out.print("繼承式");
}
};
t2.thing();
}
}
abstract class test2{
public abstract void thing();
}
在test1中對於test2的例項化時使用了匿名的內部類。即
test2 t2 = new test2() { @Override public void thing() { System.out.print("繼承式"); } };
2.介面式匿名內部類
class Test{
public static void main(String[] args) {
test1 t1=new test1();
t1.print2();
}
}
class test1 {
public void print(){
test3 t3=new test3(){
@Override
public void thing1() {
System.out.print("介面式");
}
};
t3.thing1();
}
}
interface test3{
void thing1();
}
3.引數式匿名內部類
public class Test{
public static void main(String[] args) {
test1 t1=new test1();
t1.print3(new test3() {
@Override
public void thing1() {
System.out.print("引數式");
}
});
}
}
class test1 {
public void print3(test3 t3){
t3.thing1();
}
}
interface test3{
void thing1();
}
在使用匿名內部類時要注意以下幾個原則:
- 不能有構造方法,只能有一個例項
- 不能定義任何靜態成員,靜態方法
- 不能是public、protected、private、static
- 一定是在new的後面,用其隱含實現一個介面或實現一個類
- 匿名內部類為區域性的,所以區域性類的所有限制都對其生效
為什麼要使用內部類呢?
典型的情況是,內部類繼承自某個類或實現某個介面,內部類的程式碼操作建立其他外圍類的物件。所以你可以認為內部類提供了某種進入其外圍類的視窗。使用內部類最吸引人的原因是:
每個內部類都能獨立地繼承自一個(介面的)實現,所以無論外圍類是否已經繼承了某個(介面的)實現,對於內部類都沒有影響。如果沒有內部類提供的可以繼承多個具體的或抽象的類的能力,一些設計與程式設計問題就很難解決。從這個角度看,內部類使得多重繼承的解決方案變得完整。介面解決了部分問題,而內部類有效地實現了“多重繼承”。
以上就是本菜鳥在學習內部類時所瞭解到的淺薄知識,由於水平有限,可能對於其認知有限,希望大家多多糾正和指導!!