有多少人喜歡使用內(nèi)部類(lèi)漫蛔,我就問(wèn)你累不累。閑話(huà)不多說(shuō)旧蛾。
在Java中莽龟,可以將一個(gè)類(lèi)定義在另一個(gè)類(lèi)里面或者一個(gè)方法里面,這樣的類(lèi)稱(chēng)為內(nèi)部類(lèi)锨天。內(nèi)部類(lèi)分為:成員內(nèi)部類(lèi)毯盈,局部?jī)?nèi)部類(lèi),匿名內(nèi)部類(lèi)病袄,靜態(tài)內(nèi)部類(lèi)搂赋。
1.成員內(nèi)部類(lèi)。
public class A
{
private String aa;
class B
{
private String aa;
public String getAa()
{
return aa;
}
public void setAa(String aa)
{
this.aa = aa;
}
public void print()
{
System.out.println(aa);
System.out.println(A.this.aa);
}
}
public String getAa()
{
return aa;
}
public void setAa(String aa)
{
this.aa = aa;
}
public static void main(String[] args)
{
A test = new A();
test.aa = "hello world";
B b = test.new B();
b.aa = "hello java";
b.print();
}
}
hello java
hello world
類(lèi)B像是類(lèi)A的一個(gè)成員益缠,類(lèi)B稱(chēng)為外部類(lèi)脑奠。成員內(nèi)部類(lèi)可以無(wú)條件訪(fǎng)問(wèn)外部類(lèi)的所有成員屬性和成員方法(包括private成員和靜態(tài)成員)
不過(guò)需要注意的是,當(dāng)成員內(nèi)部類(lèi)擁有和外部類(lèi)同名的成員變量或者方法時(shí)幅慌,會(huì)發(fā)生隱藏現(xiàn)象宋欺,即默認(rèn)情況下訪(fǎng)問(wèn)的是成員內(nèi)部類(lèi)的成員。如果要訪(fǎng)問(wèn)外部類(lèi)的同名成員胰伍,需要用下面的形式訪(fǎng)問(wèn)齿诞。
外部類(lèi).this.成員變量
外部類(lèi).this.成員方法
2.局部?jī)?nèi)部類(lèi)
局部?jī)?nèi)部類(lèi)是定義在一個(gè)方法或者一個(gè)作用域里面的類(lèi),它和成員內(nèi)部類(lèi)的區(qū)別在于局部?jī)?nèi)部類(lèi)的訪(fǎng)問(wèn)僅限于方法內(nèi)或者該作用域內(nèi)骂租。
略:貌似沒(méi)有看到別人這樣寫(xiě)過(guò)代碼
3.匿名內(nèi)部類(lèi)
匿名內(nèi)部類(lèi)是你通向大神的道路上的一座大山掌挚。因?yàn)椴皇撬腥硕寄芨愣ǖ摹_@個(gè)匿名內(nèi)部類(lèi)在異步回調(diào)機(jī)制中使用的非常多菩咨,與js的回調(diào)函數(shù)有很多相似的地方吠式。
我們知道Node.js中大部分請(qǐng)求響應(yīng)都是異步回調(diào)方式完成的,在編寫(xiě)監(jiān)聽(tīng)事件的代碼使用匿名內(nèi)部類(lèi)不但方便抽米,而且代碼比較容易維護(hù)特占。
public MQPushConsumer start() throws InterruptedException,
MQClientException
{
DefaultMQPushConsumer pushConsumer = new DefaultMQPushConsumer(
getConsumerGroup());
pushConsumer.setNamesrvAddr(getNameSrvAddr());
pushConsumer.subscribe(getTopic(), getSubExpression());
pushConsumer
.setConsumeMessageBatchMaxSize(getConsumeMessageBatchMaxSize());
pushConsumer
.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
pushConsumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(
List<MessageExt> msgs, ConsumeConcurrentlyContext context)
{
try
{
processMsg(msgs);
}
catch (Exception e)
{
logger.info("end consume::" + msgs.toString());
logger.error(e);
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
logger.info("Consumer Started.");
return pushConsumer;
}
這一段代碼是RocketMQ消費(fèi)端監(jiān)聽(tīng)是否有消息過(guò)來(lái)的代碼。這里面就是用了匿名內(nèi)部類(lèi)云茸。
注意:匿名內(nèi)部?jī)?nèi)是不能有訪(fǎng)問(wèn)修飾符合static修飾符的是目。
匿名內(nèi)部類(lèi)是唯一一種沒(méi)有構(gòu)造器的類(lèi),因?yàn)闆](méi)有構(gòu)造器則使用范圍就變得很窄标捺,大部分匿名內(nèi)部類(lèi)都用于接口回調(diào)(所謂的回調(diào)就是把內(nèi)部類(lèi)比作一個(gè)電話(huà)號(hào)碼懊纳,這個(gè)電話(huà)號(hào)碼是你給別人的揉抵,只有別人能夠打,你自己不能用自己的手機(jī)打嗤疯,其他的號(hào)碼你還是可以打的)冤今。匿名內(nèi)部類(lèi)在編譯的時(shí)候由系統(tǒng)自動(dòng)起名為Outter$1.class。一般來(lái)說(shuō)茂缚,匿名內(nèi)部類(lèi)用于繼承其他類(lèi)或是實(shí)現(xiàn)接口戏罢,并不需要增加額外的方法,只是對(duì)繼承方法的實(shí)現(xiàn)或是重寫(xiě)脚囊。
4.靜態(tài)內(nèi)部類(lèi)
靜態(tài)內(nèi)部類(lèi)也是定義在另一個(gè)類(lèi)里面的類(lèi)龟糕,只不過(guò)在類(lèi)的前面多了一個(gè)關(guān)鍵字static。靜態(tài)內(nèi)部類(lèi)是不需要依賴(lài)于外部類(lèi)的悔耘,這點(diǎn)和類(lèi)的靜態(tài)成員屬性有點(diǎn)類(lèi)似讲岁,并且它不能使用外部類(lèi)的非static成員變量或者方法,這點(diǎn)很好理解衬以,因?yàn)樵跊](méi)有外部類(lèi)的對(duì)象的情況下催首,可以創(chuàng)建靜態(tài)內(nèi)部類(lèi)的對(duì)象,如果允許訪(fǎng)問(wèn)外部類(lèi)的非static成員就會(huì)產(chǎn)生矛盾泄鹏,因?yàn)橥獠款?lèi)的非static成員必須依附于具體的對(duì)象