一、內部類的概述
1、內部類,就是在一個類的內部在定義一個類。
2、分類:靜態內部類、成員內部類、局部內部類、匿名內部類
3、內部類的簡單應用:
(1)新建一個外部類Outer,在Outer裏寫一個內部類Inter
public class Outer {
private int id=1001;
private String name="admin";
public void py()
{
System.out.println(id+"\t"+name);
}
public class Inter
{
public void play()
{
py(); //調用方法不可與本方法同名
}
}
}
(2)聲明內部類Inter方法一
public void test01()
{
Outer.Inter oi=new Outer().new Inter();
oi.play();
}
//輸出結果【1001 admin】
(3)聲明內部類Inter方法二
public void test02()
{
Outer o=new Outer();
Outer.Inter oi=o.new Inter();
oi.play();
}
//輸出結果【1001 admin】
二、內部類的實際應用
1、在User類中定義兩個內部類,分別是Teacher、Student,並添加帶參構造方法
public class User {
private int id;
private String name;
private String sex;
private String address;
private String birth;
private String phone;
public User(int id, String name, String sex, String address, String birth, String phone) {
this.id = id;
this.name = name;
this.sex = sex;
this.address = address;
this.birth = birth;
this.phone = phone;
}
public void play(){
System.out.println(id+"\t"+name+"\t"+sex+"\t"+address+"\t"+birth+"\t"+phone);
}
//內部類Teacher
public class Teacher
{
int teaAge;
public Teacher(int teaAge)
{
this.teaAge = teaAge;
}
public void show()
{
play(); //調用方法不可與本方法同名
System.out.println(teaAge);
}
}
//內部類Teacher
public class Student
{
int pop;
public Student(int pop) {
this.pop = pop;
}
public void show()
{
play();
System.out.println(pop);
}
}
}
2、調用內部類
public void test03()
{
User u=new User(1001,"張三","男","廣東廣州","1990-02-14","15018743146");
User.Teacher teacher=u.new Teacher(7);
teacher.show();
}
//輸出結果【1001 張三 男 廣東廣州 1990-02-14 15018743146 7】
三、靜態內部類
1、靜態內部類可以用public,protected,private,默認訪問權限修飾。
2、在靜態內部類中可以存在靜態成員和非靜態的成員,靜態內部類只能訪問外部類的靜態成員變量和方法,不能訪問外部類的非靜態成員變量和方法。
3、非靜態內部類中不能存在靜態成員,非靜態內部類中可以調用外部類的任何成員,不管是靜態的還是非靜態的。
4、代碼示例:
public class StaticOuter
{
@SuppressWarnings("unused")
private String sex;
public static String name = "chenssy";
/**
*靜態內部類可以用public,protected,private,默認訪問權限修飾
*/
static class InnerClass1
{
int inner_i = 100;
public static String name1 = "chenssy_static"; //在靜態內部類中可以存在靜態成員和非靜態的成員
public void display()
{
System.out.println("OutClass name :" + name); //靜態內部類只能訪問外部類的靜態成員變量和方法, 不能訪問外部類的非靜態成員變量和方法
}
}
/**
* 非靜態內部類
*/
class InnerClass2
{
public String name2 = "chenssy_inner"; //非靜態內部類中不能存在靜態成員
public void display(){
System.out.println("OuterClass name:" + name); //非靜態內部類中可以調用外部類的任何成員,不管是靜態的還是非靜態的
}
}
/**
* 外部類方法
*/
public void display()
{
System.out.println(InnerClass1.name1); //外部類可以直接訪問靜態內部類的靜態成員:[內部類.靜態成員]
new InnerClass1().display(); //靜態內部類可以直接創建實例不需要依賴於外部類, 外部類訪問內部類的非靜態成員,實例化內部類即可
StaticOuter.InnerClass2 inner2 = new StaticOuter().new InnerClass2(); //非靜態內部的創建需要依賴於外部類
System.out.println(inner2.name2); //訪問非靜態內部類的成員需要使用非靜態內部類的實例
inner2.display();
}
public static void main(String[] args)
{
StaticOuter outer = new StaticOuter();
outer.display();
}
/*
* 輸出結果:
* chenssy_static
OutClass name :chenssy
chenssy_inner
OuterClass name:chenssy
*/
}
四、成員內部類
1、成員內部類中不能存在任何static的變量,static方法和static代碼塊
2、成員內部類是依附於外部類的,所以只有先創建了外部類才能夠創建內部類。
3、代碼示例:
public class MemberOuter
{
private static int i = 1;
private int j = 10;
private int k = 20;
public static void outer_f1()
{
}
public void outer_f2()
{
}
class Inner
{
// static int inner_i = 100;
//成員內部類中不允許定義靜態成員
int j = 100; //內部類和外部類的變量可以同名
int inner_i = 1;
void inner_f1()
{
System.out.println(i); // 成員內部類中,可以訪問外部類的所有成員
System.out.println(j); //在內部類中訪問內部類自己的變量直接用變量名
System.out.println(this.j); //在內部類中訪問內部類自己的變量也可以用this.變量名
System.out.println(MemberOuter.this.j); //在內部類中訪問外部類中與內部類同名的實例變量用外部類名.this.變量名
System.out.println(k); //如果內部類中沒有與外部類同名的變量,則可以直接用變量名訪問外部類變量
outer_f1(); //成員內部類中,可以訪問外部類的所有成員
outer_f2(); //成員內部類中,可以訪問外部類的所有成員
}
}
//外部類的非靜態方法訪問成員內部類(和使用普通類沒什麼區別)
public void outer_f3()
{
Inner inner = new Inner();
inner.inner_f1();
}
// 外部類的靜態方法訪問成員內部類,與在外部類的外部訪問成員內部類一樣,應該具體的指出這個對象的類型:OuterClassName.InnerClassName
public static void outer_f4()
{
//step1 建立外部類對象
MemberOuter out = new MemberOuter();
//step2 根據外部類對象建立內部類對象
Inner inner = out.new Inner();
//step3 訪問內部類的方法
inner.inner_f1();
}
public static void main(String[] args) {
//outer_f4(); //該語句的輸出結果和下面三條語句的輸出結果一樣
//如果要直接創建內部類的對象,不能想當然地認爲只需加上外部類Outer的名字就可以按照通常的樣子生成內部類的對象,而是必須使用此外部類的一個對象來創建其內部類的一個對象
//Outer.Inner outin = out.new Inner(); //這是錯的
//因此,除非你已經有了外部類的一個對象,否則不可能生成內部類的對象。因爲此內部類的對象會悄悄地鏈接到創建它的外部類的對象。如果你用的是靜態的內部類,那就不需要對其外部類對象的引用。
MemberOuter out = new MemberOuter();
MemberOuter.Inner outin = out.new Inner();
outin.inner_f1();
}
/*
* 輸出結果:
* 1
100
100
10
20
*/
}
五、局部內部類
public class PartOuter
{
@SuppressWarnings("unused")
private void internalTracking(boolean b)
{
if(b)
{
class TrackingSlip
{
private String id;
TrackingSlip(String s)
{
id = s;
}
String getSlip()
{
return id;
}
}
TrackingSlip ts = new TrackingSlip("chenssy");
String string = ts.getSlip();
}
}
public void track(){
internalTracking(true);
}
public static void main(String[] args)
{
PartOuter parcel = new PartOuter();
parcel.track();
}
}
六、匿名內部類
1、匿名內部類就是沒有名字的內部類。
2、使用匿名內部類還有個前提條件:必須繼承一個父類或實現一個接口, 當然也僅能只繼承一個父類或者實現一個接口。
3、如果滿足下面的一些條件,使用匿名內部類是比較合適的:
(1)只用到類的一個實例。
(2)類在定義後馬上用到。
(3)類非常小(推薦是在4行代碼以下)
(4)給類命名並不會導致你的代碼更容易被理解。
4、代碼示例:
public class AnOuter
{
public InnerClass getInnerClass(final int num,String str2)
{
return new InnerClass()
{
int number = num + 3;
public int getNumber(){
return number;
}
}; /* 注意:分號不能省 */
}
public static void main(String[] args)
{
AnOuter out = new AnOuter();
InnerClass inner = out.getInnerClass(2, "chenssy");
System.out.println(inner.getNumber());
} //輸出結果【5】
}
interface InnerClass
{
int getNumber();
}