接口中的內(nèi)部類
??在我們實(shí)際開發(fā)過程中,如果想要?jiǎng)?chuàng)建某些公共代碼,使得他們可以被某個(gè)接口的所有不同實(shí)現(xiàn)所共用,那么接口內(nèi)部的嵌套類會(huì)顯得很方便.也就是說在接口中可以含有內(nèi)部類.在這里,向大家展示接口中放置普通成員內(nèi)部類和抽象成員內(nèi)部類的情況.
?
1.首先創(chuàng)建接口,接口中定義了普通內(nèi)部類InnerClass和抽象內(nèi)部類AbInnerClass
package com.diandian.inter;
// 接口IOuterInterface
public interface IOuterInterface{
int TEMP = 100; // 常量
void abMethod();// 抽象方法
public default void deMethod(){ // jdk1.8后可添加
System.out.println("接口中默認(rèn)方法");
}
public static void stMethod() {
System.out.println("接口中靜態(tài)方法");
}
// 普通內(nèi)部類
public class InnerClass{
public void show(){
System.out.println("接口中可定義普通成員內(nèi)部類");
}
}
// 抽象內(nèi)部類
public abstract class AbInnerClass{
public abstract void abInfo();
public void info(){
System.out.println("接口中可定義抽象成員內(nèi)部類");
}
}
}
2.普通成員內(nèi)部類的實(shí)例化
// 創(chuàng)建接口的實(shí)現(xiàn)類ClassDemo
package com.diandian.inter;
// 實(shí)現(xiàn)類ClassDemo
public class ClassDemo implements IOuterInterface{
@Override
public void abMethod(){
System.out.println("實(shí)現(xiàn)類");
}
// 獲取接口中內(nèi)部類方法
public InnerClass getInner(){
return new InnerClass();
}
}
// 獲取普通內(nèi)部類對(duì)象,調(diào)用方法
package com.diandian.test;
import com.diandian.inter.ClassDemo;
import com.diandian.inter.IOuterInterface;
import.com.diandian.inter.IOuterInterface.InnerClass;
// 測(cè)試類:普通成員內(nèi)部類
public class Test{
public static void main(String[] args){
/**第一種實(shí)例化對(duì)象方式:
通過接口名.類名 進(jìn)行實(shí)例化
*/
IOuterInterface.InnerClass inner = new IOuterInterface.InnerClass();
inner.show();
/**第二種實(shí)例化對(duì)象方式:
通過在實(shí)現(xiàn)類中創(chuàng)建接口中內(nèi)部類獲取方法
用實(shí)現(xiàn)對(duì)象調(diào)用獲取方法
*/
ClassDemo demo = new ClassDemo();
demo.getInner().show();
/**第三種實(shí)例化對(duì)象方式:
將內(nèi)部類導(dǎo)入后,直接實(shí)例化
*/
InnerClass innerTwo = new InnerClass();
innerTwo.show();
}
}
運(yùn)行結(jié)果:
接口中可定義普通成員內(nèi)部類
接口中可定義普通成員內(nèi)部類
接口中可定義普通成員內(nèi)部類
3.抽象成員內(nèi)部類的實(shí)例化
// 創(chuàng)建接口的實(shí)現(xiàn)類AbClassDemo
package com.diandian.inter;
// 實(shí)現(xiàn)類AbClassDemo
public class AbClassDemo implements IOuterInterface{
@Override
public void abMethod(){
}
// 繼承抽象類AbInnerClass
public class AbDemo extends AbInnerClass{
@Override
public void abInfo(){
System.out.println("重寫接口中抽象內(nèi)部類中的抽象方法");
}
}
}
獲取抽象內(nèi)部類對(duì)象,調(diào)用方法
package com.diandian.test;
import com.diandian.inter.AbClassDemo;
import com.diandian.inter.IOuterInterface;
// 測(cè)試類:抽象成員內(nèi)部類
public class TestOne{
public static void main(String[] args){
/*第一種實(shí)例化對(duì)象方式:
通過接口名.類名 進(jìn)行實(shí)例化
但是對(duì)于抽象類而言,不能直接實(shí)例化,所以這里可使用匿名內(nèi)部類的方式
*/
IOuterInterface.AbInnerClass abInner = new IOuterInterface.AbInnerClass(){
public void abInfo(){
System.out.println("重寫抽象類中的抽象方法");
}
};
abInner.abInfo();
abInner.info();
System.out.println("=====================");
/*第二種實(shí)例化方法:
在實(shí)現(xiàn)類中定義內(nèi)部類繼承接口中的抽象內(nèi)部類
*/
IOuterInterface.AbInnerClass abInnerOne = new AbClassDemo().new AbDemo();
abInnerOne.abInfo();
abInnerOne.info();
}
}
運(yùn)行結(jié)果:
重寫抽象類中的抽象方法
接口中可定義抽象成員內(nèi)部類
========================
重寫接口中抽象類中的抽象方法
接口中可以定義抽象成員內(nèi)部類
匿名內(nèi)部類
概念
匿名內(nèi)部類也及時(shí)沒有名字的內(nèi)部類
正因?yàn)闆]有名字,所以匿名內(nèi)部類只能使用一次,它通常用來簡(jiǎn)化代碼編寫但使用匿名內(nèi)部類還有個(gè)前提條件:必須繼承一個(gè)父類或者一個(gè)接口
注意事項(xiàng):
- 編譯后的文件名:外部類$數(shù)字.class
- 無法使用publick,private,abstract,static修飾,匿名內(nèi)部類不能出現(xiàn)抽象方法
- 無法編寫構(gòu)造方法,但可以添加構(gòu)造代碼塊
- 不能出現(xiàn)靜態(tài)成員
- 匿名內(nèi)部類可實(shí)現(xiàn)接口也可以繼承類,但是不可兼得
- 匿名內(nèi)部類不能是抽象類的,它必須要實(shí)現(xiàn)繼承的類或者實(shí)現(xiàn)接口的所有抽象方法
?
匿名內(nèi)部類初始化
??我們一般都是利用構(gòu)造器來完成某個(gè)實(shí)例的初始化工作,但是匿名內(nèi)部類是沒有構(gòu)造器的,那怎么來初始化匿名內(nèi)部類呢?使用構(gòu)造代碼塊!利用構(gòu)造代碼塊能夠達(dá)到為匿名內(nèi)部類創(chuàng)建一個(gè)構(gòu)造器的效果.
實(shí)例:
先定義一個(gè)接口,然后定義該接口的匿名內(nèi)部類.
public interface InnerClass{
public String getName();
public int getAge();
}
public class OutClass{
public InnerClass getInnerClass(final int age,final String name){
return new InnerClass(){
int age_;
String name_;
// 構(gòu)造代碼塊完成初始化工作
{
if(0 < age && age < 200){
age_ = age;
name_ = name;
}
}
public String getName(){
return age_;
}
};
}
public static void main(String[] args){
OutClass out = new OutClass();
InnerClass inner_1 = out.getInnerClass(201,"chenssy");
System.out.println(inner_1.getName());
InnerClass inner_2 = out.getInnerClass(23,"chenssy");
System.out.println(inner_2.getName());
}
}
實(shí)例
匿名內(nèi)部類可以有不同的表現(xiàn)形式,下面用實(shí)例向大家展示一下:
繼承式的匿名內(nèi)部類:
abstract class Car{
public abstract void drive();
}
class Test{
public static void main(String[] args){
Car car = new Car(){
public void drive(){
System.out.println("Driving another car!");
}
};
car.drive();
}
}
輸出結(jié)果:
Driving another Car!
引用變量不是應(yīng)用Car對(duì)象,而是Car匿名子類的對(duì)象
??建立匿名內(nèi)部類的關(guān)鍵點(diǎn)事重寫父類的一個(gè)或多個(gè)方法.再?gòu)?qiáng)調(diào)一下,是重寫的方法,而不是創(chuàng)建新的方法.因?yàn)橛酶割惖囊貌豢赡苷{(diào)用父類本身沒有的方法,創(chuàng)建新的方法時(shí)多余的.
?
接口式的匿名內(nèi)部類:
interface Vehicle{
public void drive();
}
class Test{
public static void main(String[] args){
Vehicle vehicle = new Vehicle(){
public void drive(){
System.out.println("Driving a car!");
}
}
vehicle.drive();
}
}
輸出結(jié)果:
Driving a car!
上面的代碼很怪,好像是在實(shí)例化一個(gè)接口.事實(shí)并非如此,接口式的匿名內(nèi)部類是實(shí)現(xiàn)了一個(gè)接口的匿名類.而且只能實(shí)現(xiàn)一個(gè)接口.
//參數(shù)是的匿名內(nèi)部類:
abstract class Bar{
void doStuff(Foo f){}
}
class BarOne extends Bar{
void doStuff(Foo f){}
}
interface Foo{
void foo();
}
class Test{
static void go(){
Bar b = new BarOne();
b.doStuff(new Foo(){
public void foo(){
System.out.println("foofy");
}
})
}
}
?由上面的三個(gè)例子可以看出,只要一個(gè)類是抽象的或是一個(gè)接口,那么其子類中的方法都可以使用匿名內(nèi)部類來實(shí)現(xiàn).最常用的情況就是多線程的實(shí)現(xiàn)上,因?yàn)橐獙?shí)現(xiàn)多線程必須繼承Thread類或是實(shí)現(xiàn)Runnable接口
Thread類的匿名內(nèi)部類實(shí)現(xiàn):
public class Demo{
public static void main(String[] args){
Thread t = new Thread(){
public void run(){
for(int i = 1; i <= 5; i++){
System.out.print(i +" ");
}
}
};
t.start();
}
}
Runnable接口的匿名內(nèi)部類實(shí)現(xiàn):
public class Demo{
public static void main(String[] args){
Runnable r = new Runnable(){
public void run(){
for(int i = 1; i <= 5; i++){
System.out.print(i + " ");
}
}
};
Thread t = new Thread(r);
t.start();
}
}