內(nèi)部類
內(nèi)部類:一個(gè)類定義在另外一個(gè)類的內(nèi)部,那么該類就稱作為內(nèi)部類。
內(nèi)部類的class文件名: 外部類$內(nèi)部類. 好處:便于區(qū)分該class文件是屬于哪個(gè)外部類的。
內(nèi)部類的類別:
一 :成員內(nèi)部類
成員內(nèi)部類的訪問方式:
- 在外部類提供一個(gè)方法創(chuàng)建內(nèi)部類的對(duì)象進(jìn)行訪問。
- 在其他類直接創(chuàng)建內(nèi)部類的對(duì)象。 格式:
外部類.內(nèi)部類 變量名 = new 外部類().new 內(nèi)部類();
注意: 如果是一個(gè)靜態(tài)內(nèi)部類,那么在其他類創(chuàng)建 的格式:
外部類.內(nèi)部類 變量名 = new 外部類.內(nèi)部類();
內(nèi)部類的應(yīng)用場(chǎng)景:
我們?cè)诿枋鯝事物的時(shí)候,發(fā)現(xiàn)描述的A事物內(nèi)部還存在另外一個(gè)比較復(fù)雜的事物B時(shí)候,而且這個(gè)比較復(fù)雜事物B還需要訪問A事物的屬性等數(shù)據(jù),那么這時(shí)候我們就可以使用內(nèi)部類描述B事物。
比如: 人--->心臟
class 人{(lán)
血
氧氣
等....
class 心臟{
}
}
內(nèi)部類的好處:內(nèi)部類可以直接訪問外部類的所有成員。
內(nèi)部類要注意的細(xì)節(jié):
- 如果外部類與內(nèi)部類存在同名的成員變量時(shí),在內(nèi)部類中默認(rèn)情況下是訪問內(nèi)部類的成員變量。
可以通過"外部類.this.成員變量名" 指定訪問外部類的 成員。 - 私有的成員內(nèi)部類只能在外部類提供一個(gè)方法創(chuàng)建內(nèi)部類的對(duì)象進(jìn)行訪問,不能在其他類創(chuàng)建對(duì)象了。
- 成員內(nèi)部類一旦出現(xiàn)了靜態(tài)的成員,那么該類也必須 使用static修飾。
//外部類
class Outer{
//成員變量
int x = 100;
//成員內(nèi)部類
static class Inner{
static int i = 10;
public void print(){
System.out.println("這個(gè)是成員內(nèi)部類的print方法!"+i);
}
}
//在外部的方法中創(chuàng)建了內(nèi)部類的對(duì)象,然后調(diào)用內(nèi)部 方法。
public void instance(){
Inner inner = new Inner();
inner.print();
}
}
//其他類
class Demo4
{
public static void main(String[] args)
{
/*
System.out.println(Outer.Inner.i); //訪問靜態(tài)內(nèi)部類的靜態(tài)變量
//內(nèi)部類的兩種創(chuàng)建方式
Outer outer = new Outer();
outer.instance();
Outer.Inner inner = new Outer().new Inner();
inner.print();
*/
//靜態(tài)內(nèi)部類的創(chuàng)建方式
Outer.Inner inner = new Outer.Inner();
inner.print();
}
}
二:局部?jī)?nèi)部類
/*
局部?jī)?nèi)部類: 在一個(gè)類 的方法內(nèi)部定義另外一個(gè)類,那么另外一個(gè)類就稱作為局部?jī)?nèi)部類。
局部?jī)?nèi)部類要注意的細(xì)節(jié):
1. 如果局部 內(nèi)部類訪問了一個(gè)局部變量,那么該局部變量必須使用final修飾、
*/
class Outer{
String name= "外部類的name";
public void test(){
//局部變量
final int y =100; // y 什么時(shí)候從內(nèi)存中消失? 方法執(zhí)行完畢之后y消失。
//局部?jī)?nèi)部類
class Inner{ /*
當(dāng)test方法執(zhí)行完畢之后,那么y馬上從內(nèi)存中消失,而Inner對(duì)象在方法
執(zhí)行完畢的時(shí)候還沒有從內(nèi)存中消失,而inner對(duì)象的print方法還在訪問著
y變量,這時(shí)候的y變量已經(jīng)消失了,那么就給人感覺y的生命變量已經(jīng)被延長(zhǎng)了
.
解決方案: 如果一個(gè)局部?jī)?nèi)部類訪問一個(gè)局部變量的時(shí)候,那么就讓該局部?jī)?nèi)部類
訪問這個(gè)局部 變量 的復(fù)制品。
*/
int x = 10;
public void print(){
System.out.println("這個(gè)是局部?jī)?nèi)部類的print方法.."+y);
}
}
Inner inner = new Inner(); //這個(gè)inner對(duì)象什么時(shí)候消失? Inner對(duì)象的生命周期比局部變量y的生命周期要長(zhǎng)。
inner.print();
}
}
class Demo5
{
public static void main(String[] args)
{
Outer outer = new Outer();
outer.test();
}
}
三:匿名內(nèi)部類
/*
匿名內(nèi)部類:沒有類名的類就稱作為匿名內(nèi)部類。
匿名內(nèi)部類的好處:簡(jiǎn)化書寫。
匿名內(nèi)部類的使用前提:必須存在繼承或者實(shí)現(xiàn)關(guān)系才能使用。
匿名內(nèi)部類一般是用于實(shí)參。
*/
abstract class Animal{
public abstract Animal run();
public abstract void sleep();
}
class Outer{
public void print(){
//需求: 在方法內(nèi)部定義一個(gè)類繼承Animal類,然后調(diào)用run方法與sleep()。
/*
//局部?jī)?nèi)部類
class Dog extends Animal{
public void run(){
System.out.println("狗在跑..");
}
public void sleep(){
System.out.println("狗趴在睜開眼睛睡..");
}
}
//創(chuàng)建對(duì)象
Dog d = new Dog();
d.run();
d.sleep();
*/
//匿名內(nèi)部類 :匿名內(nèi)部類只是沒有類名,其他的一概成員都是具備的。
// 匿名內(nèi)部類與Animal是繼承 的關(guān)系。 目前是創(chuàng)建Animal子類的對(duì)象.
Animal a = new Animal(){ //多態(tài)
//匿名內(nèi)部的成員
public Animal run(){
System.out.println("狗在跑..");
return this;
}
public void sleep(){
System.out.println("狗趴在睜開眼睛睡..");
}
//特有的方法
public void bite(){
System.out.println("狗在咬人..");
}
};//.run()/.sleep()/.bite() 可以通過這種方式調(diào)用成員方法和自已特有方法
//a.bite(); 不能這樣調(diào)用子類的特有方法
a.run();
a.sleep();
}
}
class Demo6
{
public static void main(String[] args)
{
Outer outer = new Outer();
outer.print();
}
}
匿名內(nèi)部類應(yīng)用場(chǎng)景
/*
匿名內(nèi)部類的應(yīng)用場(chǎng)景:
在主方法中需要使用Dao這個(gè)接口的一個(gè)方法,那么沒有必要為了一個(gè)方法去實(shí)現(xiàn)一個(gè)接口
所以可以使用匿名的內(nèi)部類
*/
//實(shí)現(xiàn)關(guān)系下匿名內(nèi)部類
interface Dao{
public void add();
}
class Outer{
public void print(){
//創(chuàng)建一個(gè)匿名內(nèi)部類的對(duì)象
new Dao(){
public void add(){
System.out.println("添加成功");
}
}.add();
}
}
class Demo7
{
public static void main(String[] args)
{
test(new Dao(){
public void add(){
System.out.println("添加員工成功");
}
});
}
//調(diào)用這個(gè)方法...
public static void test(Dao d){ //形參類型是一個(gè)接口引用..
d.add();
}
}