摘要:內部類的使用場景上面介紹了中種內部類的定義,接著我們介紹這些內部類的一些使用場景。成員內部類的使用場景普通內部類可以訪問外部類的所有成員和方法,因此當類需要使用類,同時需要訪問的成員方法時,可以將作為的成員內部類。
文章出自:安卓進階學習指南
主要貢獻者:Cloud9527
Alex_趙
Struggle
shixinzhang
讀完本文你將了解: [TOC]
通過反編譯介紹四種內部類
結合實戰(zhàn)介紹內部類的使用場景
背景介紹大家好,這篇文章是 《安卓進階技能樹計劃》 的第一部分 《Java 基礎系列》 的第三篇。
我們做這個活動,除了要保證知識點的全面、完整,還想要讓每一篇文章都有自己的思考,盡可能的將知識點與實踐結合,努力讓讀者讀了有所收獲。每位小伙伴都有工作在身,每個知識點都需要經過思考、學習、寫作、提交、審核、修改、編輯、發(fā)布等多個過程,所以整體下來時間就會慢一些,這里先向各位道歉。
《Java 基礎系列》初步整理大概有 12 篇,主要內容為:
抽象類和接口 (完成)
內部類
修飾符
裝箱拆箱
注解
反射
泛型
異常 (完成)
集合
IO
字符串
其他
這一篇我們來聊聊內部類。
“內部類”聽起來是非常普遍的東西,有些朋友會覺得:這個太基礎了吧,有啥好說的,你又來糊弄我。
既然你這么自信,那就來試兩道筆試題吧!
第一道:要求使用已知的變量,在三個輸出方法中填入合適的代碼,在控制臺輸出30,20,10。
class Outer { public int num = 10; class Inner { public int num = 20; public void show() { int num = 30; System.out.println(?); //填入合適的代碼 System.out.println(??); System.out.println(???); } } } class InnerClassTest { public static void main(String[] args) { Outer.Inner oi = new Outer().new Inner(); oi.show(); } }
接招,第二題:補齊代碼 ,要求在控制臺輸出”HelloWorld
interface Inter { void show(); } class Outer { //補齊代碼 } class OuterDemo { public static void main(String[] args) { Outer.method().show(); } }
題目來自:https://www.cnblogs.com/zhang...
先思考幾秒,看看這些題你能否應付得來。
在面試中常常遇到這樣的筆試題,咋一看這題很簡單,還是會有很多人答不好。根本原因是很多人對“內部類”的理解僅限于名稱。
“內部類、靜態(tài)內部類、匿名內部類”是什么大家都清楚。但是當轉換一下思維,不僅僅為了完成功能,而是要保證整個項目架構的穩(wěn)定靈活可擴展性,你會如何選擇呢?
這篇文章我們努力回答這些問題,也希望你可以說出你的答案。
四種內部類介紹定義在一個類中或者方法中的類稱作為內部類。
內部類又可以細分為這 4 種:
成員內部類
局部內部類
匿名內部類
靜態(tài)內部類
1.成員內部類成員內部類就是最普通的內部類,它定義在一個類的內部中,就如同一個成員變量一樣。如下面的形式:
public class OutClass2 { private int i = 1; public static String str = "outclass"; class InnerClass { // 成員內部類 private int i = 2; public void innerMethod() { int i = 3; System.out.println("i=" + i); System.out.println("i=" + this.i); System.out.println("i=" + OutClass2.this.i); System.out.println("str=" + str); } } } public class TestClass { public static void main(String[] args) { //先創(chuàng)建外部類對象 OutClass2 outClass = new OutClass2(); //創(chuàng)建內部類對象 OutClass2.InnerClass in = outClass.new InnerClass(); //內部類對象調用自己的方法 in.innerMethod(); } }
因為內部類依附于外部類存在,所以需要外部類的實例來創(chuàng)建內部類:
outClass.new InnerClass()
注意不是直接 new outClass.InnerClass() 。
成員內部類可以無條件的訪問外部類的成員屬性和成員方法(包括 private 和 static 類型的成員),這是因為在內部類中,隱式地持有了外部類的引用。
我們編譯上述的代碼,可以看到,會生成兩個 class 文件:
這個 OutClass2$InnerClass.class 就是內部類對應的字節(jié)碼文件,我們使用 AS 打開,會自動進行反編譯:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.example.simon.androidlife.innerclass; import com.example.simon.androidlife.innerclass.OutClass2; class OutClass2$InnerClass { private int i; OutClass2$InnerClass(OutClass2 var1) { this.this$0 = var1; this.i = 2; } public void innerMethod() { byte var1 = 3; System.out.println("i=" + var1); System.out.println("i=" + this.i); System.out.println("i=" + OutClass2.access$000(this.this$0)); System.out.println("str=" + OutClass2.str); } }
可以看到,在內部類 OutClass2$InnerClass 的字節(jié)碼中,編譯器為我們生成了一個參數(shù)為外部類對象的構造方法,這也解釋了內部類為什么可以直接訪問外部類的內容,因為持有外部類的引用!
在這個不完整的反編譯字節(jié)碼中,我們可以看到,編譯器會為內部類創(chuàng)建一個叫做 this$0 的對象,它是外部類的引用。
innerMethod() 中的 OutClass2.access$000(this.this$0)) 是什么意思呢?
為了幫助內部類訪問外部類的數(shù)據,編譯器會生成這個 access$ 方法,參數(shù)是外部類的引用,如果外部類有 N 個成員,編譯器會生成多個 access 方法,$ 符號后面的數(shù)字會會隨著不同的聲明順序而改變,可以理解為一種橋接方法。
對比內部類的 innerMethod() 的 java 代碼和字節(jié)碼我們可以得出這些結論:
在內部類中,直接使用變量名,會按照從方法中的局部變量、到內部類的變量、到外部類的變量的順序訪問
也就是說,如果在外部類、內部類、方法中有重名的變量/方法,編譯器會把方法中直接訪問變量的名稱修改為方法的名稱
如果想在方法中強制訪問內部類的成員變量/方法,可以使用 this.i,這里的 this 表示當前的內部類對象
如果想在方法中強制訪問外部類的成員變量/方法,可以使用 OutClass.this.i,這里的 OutClass.this 表示當前外部類對象
成員內部類就如同外部類的成員一樣,同樣可以被public、protected、private、缺省(default)這些修飾符來修飾。
但是有一個限制是:成員內部類不能創(chuàng)建靜態(tài)變量/方法。如果我們嘗試創(chuàng)建,編譯器會直接 say no。
為什么會這樣呢?
Stackoverflow 有一個回答很好:
“if you’re going to have a static method, the whole inner class has to be static. Without doing that, you couldn’t guarantee that the inner class existed when you attempted to call the static method. ”
我們知道要使用一個類的靜態(tài)成員,需要先把這個類加載到虛擬機中,而成員內部類是需要由外部類對象 new 一個實例才可以使用,這就無法做到靜態(tài)成員的要求。
2.靜態(tài)內部類說完成員內部類我們來看看靜態(tài)內部類。
使用 static 關鍵字修飾的內部類就是靜態(tài)內部類,靜態(tài)內部類和外部類沒有任何關系,可以看作是和外部類平級的類。
我們來反編譯個靜態(tài)內部類看看。
java 代碼:
public class Outclass3 { private String name; private int age; public static class InnerStaticClass { private String name; public String getName() { return name; } public int getAge() { return new Outclass3().age; } } }
編譯后的靜態(tài)內部類:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.example.simon.androidlife.innerclass; import com.example.simon.androidlife.innerclass.Outclass3; public class Outclass3$InnerStaticClass { private String name; public Outclass3$InnerStaticClass() { } public String getName() { return this.name; } public int getAge() { return Outclass3.access$000(new Outclass3()); } }
可以看到,靜態(tài)內部類很干凈,沒有持有外部類的引用,我們要訪問外部類的成員只能 new 一個外部類的對象。
否則只能訪問外部類的靜態(tài)屬性和靜態(tài)方法,同理外部類只能訪問內部類的靜態(tài)屬性和靜態(tài)方法。
3.局部內部類局部內部類是指在代碼塊或者方法中創(chuàng)建的類。
它和成員內部類的區(qū)別就是:局部內部類的作用域只能在其所在的代碼塊或者方法內,在其它地方是無法創(chuàng)建該類的對象。
public class OutClass4 { private String className = "OutClass"; { class PartClassOne { // 局部內部類 private void method() { System.out.println("PartClassOne " + className); } } new PartClassOne().method(); } public void testMethod() { class PartClassTwo { // 局部類內部類 private void method() { System.out.println("PartClassTwo " + className); } } new PartClassTwo().method(); } }
上面的代碼中我們分別在代碼塊和方法中創(chuàng)建了兩個局部內部類,來看看編譯后的它是怎么樣的:
首先可以看到會創(chuàng)建兩個 class 類,打開看下:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.example.simon.androidlife.innerclass; import com.example.simon.androidlife.innerclass.OutClass4; class OutClass4$1PartClassOne { OutClass4$1PartClassOne(OutClass4 var1) { this.this$0 = var1; } private void method() { System.out.println("PartClassOne " + OutClass4.access$000(this.this$0)); } } package com.example.simon.androidlife.innerclass; import com.example.simon.androidlife.innerclass.OutClass4; class OutClass4$1PartClassTwo { OutClass4$1PartClassTwo(OutClass4 var1) { this.this$0 = var1; } private void method() { System.out.println("PartClassTwo " + OutClass4.access$000(this.this$0)); } }
可以看到生成的這兩個字節(jié)碼和成員內部類生成的很相似,都持有了外部類的引用。
不過可惜的是出了它們聲明的作用域,就再也無法訪問它們,可以把局部內部類理解為作用域很小的成員內部類。
4.匿名內部類先讓我們來看一段最常見的代碼
Car jeep=new Car();
在Java中操縱的標識符實際是指向一個對象的引用,也就是說 jeep 是一個指向 Car 類對象的引用,而右面的 new Car() 才是真正創(chuàng)建對象的語句。
這可以將 jeep 抽象的理解為 Car 類對象的“名字”,而匿名內部類顧名思義可以抽象的理解為沒有“名字”的內部類:
button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub } });
上面代碼是 Android 中最常見的設置 button 的點擊事件,其中 new OnClickListener() {…} 就是一個匿名內部類,在這里沒有創(chuàng)建類對象的引用,而是直接創(chuàng)建的類對象。大部分匿名類用于接口回調。
由于 javac 無法編譯 android 代碼,我們寫個這樣的匿名內部類代碼來嘗試看看編譯后的結果。
public class OutClass5 { private OnClickListener mClickListener; private OutClass5 mOutClass5; interface OnClickListener { void onClick(); } public OutClass5 setClickListener(final OnClickListener clickListener) { mClickListener = clickListener; return this; } public OutClass5 setOutClass5(final OutClass5 outClass5) { mOutClass5 = outClass5; return this; } public void setClickInfo(final String info, int type) { setClickListener(new OnClickListener() { @Override public void onClick() { System.out.println("click " + info); } }); setClickListener(new OnClickListener() { @Override public void onClick() { System.out.println("click2 " + info); } }); } }
上面的代碼中,我們創(chuàng)建了一個內部接口,然后在 setDefaultClicker() 中創(chuàng)建了兩個匿名內部類,編譯后的結果:
可以看到生成了三個額外的類,OutClass5$OnClickListener 是生成的成員內部類字節(jié)碼,而 OutClass5$1 和 OutClass5$2 則是兩個實現(xiàn) OnClickListener 的子類:
class OutClass5$1 implements OnClickListener { OutClass5$1(OutClass5 var1, String var2) { this.this$0 = var1; this.val$info = var2; } public void onClick() { System.out.println("click " + this.val$info); } } class OutClass5$2 implements OnClickListener { OutClass5$2(OutClass5 var1, String var2) { this.this$0 = var1; this.val$info = var2; } public void onClick() { System.out.println("click2 " + this.val$info); } }
從反編譯的代碼可以看出:創(chuàng)建的每個匿名內部類編譯器都對應生成一個實現(xiàn)接口的子類,同時創(chuàng)建一個構造函數(shù),構造函數(shù)的參數(shù)是外部類的引用,以及匿名函數(shù)中訪問的參數(shù)。
現(xiàn)在我們知道了:匿名內部類也持有外部類的引用。
同時也理解了為什么匿名內部類不能有構造方法,只能有初始化代碼塊。 因為編譯器會幫我們生成一個構造方法然后調用。
此外還可以看出,匿名內部類中使用到的參數(shù)是需要聲明為 final 的,否則編譯器會報錯。
可能有朋友會提問了:參數(shù)為什么需要是 final 的?
我們知道在 Java 中實際只有一種傳遞方式:即引用傳遞。一個對象引用被傳遞給方法時,方法中會創(chuàng)建一份本地臨時引用,它和參數(shù)指向同一個對象,但卻是不同的,所以你在方法內部修改參數(shù)的內容,在方法外部是不會感知到的。
而匿名內部類是創(chuàng)建一個對象并返回,這個對象的方法被調用的時機不確定,方法中有修改參數(shù)的可能,如果在匿名內部類中修改了參數(shù),外部類中的參數(shù)是否需要同步修改呢?
因此,Java 為了避免這種問題,限制匿名內部類訪問的變量需要使用 final 修飾,這樣可以保證訪問的變量不可變。
內部類的使用場景上面介紹了 Java 中 4 種內部類的定義,接著我們介紹這些內部類的一些使用場景。
1.成員內部類的使用場景普通內部類可以訪問外部類的所有成員和方法,因此當類 A 需要使用類 B ,同時 B 需要訪問 A 的成員/方法時,可以將 B 作為 A 的成員內部類。
比如安卓開發(fā)中常見的在一個 Activity 中有一個 ListView,我們需要創(chuàng)建一個特定業(yè)務的 adapter,在這個 adapter 中需要傳入數(shù)據,你可以另建一個類,但如果只有當前類需要使用到,完全可以將它創(chuàng)建在 Activity 中:
public class VideoListActivity extends AppCompatActivity{ private ListView mVideoListView; private BaseAdapter mListAdapter; private ListmVideoInfoData; @Override protected void onCreate(@Nullable final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video_list); mVideoListView = (ListView) findViewById(R.id.video_list); mVideoInfoData = Collections.EMPTY_LIST; mListAdapter = new VideoListAdapter(); mVideoListView.setAdapter(mListAdapter); } //這里的 private 內部類說明這個 adapter 只能在當前類中使用 private class VideoListAdapter extends BaseAdapter { @Override public int getCount() { return mVideoInfoData.size(); //訪問外部類數(shù)據 } @Override public Object getItem(final int position) { return mVideoInfoData.get(position); //訪問外部類數(shù)據 } @Override public long getItemId(final int position) { return 0; } @Override public View getView(final int position, final View convertView, final ViewGroup parent) { return null; } } }
這是一種簡單的使用場景。
在 Java 中普通類(非內部類)是不可以設為 private 或者 protected,只能設置成 public default。
而內部類則可以,因此我們可以利用 private 內部類禁止其他類訪問該內部類,從而做到將具體的實現(xiàn)細節(jié)完全隱藏。
比如我們有一個 Activity 既可以用作登錄也可以用作注冊,我們可以這樣寫:
public class MultiplexViewActivity extends AppCompatActivity { public static final String DATA_VIEW_TYPE = "view_type"; public static final int TYPE_LOGIN = 1; public static final int TYPE_REGISTER = 2; private TextView mTitleTv; private ViewController mViewController; @Override protected void onCreate(@Nullable final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_multiplex_view); int type = getIntent().getIntExtra(DATA_VIEW_TYPE, TYPE_LOGIN); mViewController = getViewController(type); initView(); } //外界只能拿到基類,具體實現(xiàn)隱藏 public ViewController getViewController(final int type) { switch (type) { case TYPE_REGISTER: return new RegisterViewController(); case TYPE_LOGIN: default: return new LoginViewController(); } } private void initView() { mTitleTv = (TextView) findViewById(R.id.multiplex_title_tv); mViewController.initUi(); } /** * 定義操作規(guī)范 */ private interface ViewController { void initUi(); void loadData(); } private class LoginViewController implements ViewController { @Override public void initUi() { mTitleTv.setText("登錄"); //顯示登錄需要的布局 } @Override public void loadData() { //加載登錄需要的數(shù)據 } } private class RegisterViewController implements ViewController { @Override public void initUi() { mTitleTv.setText("注冊"); //顯示注冊需要的布局 } @Override public void loadData() { //加載注冊需要的數(shù)據 } } }
解釋一下上面的代碼,由于要復用這個布局,所以先定義一個布局控制接口 ViewController,再創(chuàng)建兩個內部類實現(xiàn)接口,分別負責登錄和注冊的布局控制和數(shù)據加載。
然后提供一個方法根據參數(shù)獲取具體的控制器實現(xiàn) getViewController(final int type),這個方法可以是 public 的,外界即使拿到這個 activity 實例,也只能獲取到布局控制器基類,具體的實現(xiàn)被隱藏了,這在后期修改某一個頁面時,不用擔心會對其他地方造成影響。
有朋友可能會說了:“這 2 個內部類也可以定義成普通類呀”。
確實普通類也同樣能滿足需求,但是我們希望這 2 個類只是在這個公共支付信息頁面才用到,在外界看來是不可見或不可用的狀態(tài),這個時候內部類就能滿足我們的需求。
2.靜態(tài)內部類的使用場景這樣的場景在 簡單工廠模式、迭代器設計模式、命令設計模式都有用到,有興趣的朋友可以去了解下。
靜態(tài)內部類只能訪問外部類的靜態(tài)變量和方法,但相對普通內部類的功能更為完整,因為它可以定義靜態(tài)變量/方法。
當類 A 需要使用類 B,而 B 不需要直接訪問外部類 A 的成員變量和方法時,可以將 B 作為 A 的靜態(tài)內部類。
比較常見的一種使用場景是:在基類 A 里持有靜態(tài)內部類 B 的引用,然后在 A 的子類里創(chuàng)建特定業(yè)務的 B 的子類,這樣就結合多態(tài)和靜態(tài)內部類的優(yōu)勢,既能拓展,又能限制范圍。
我們經常使用的 LayoutParams 就是靜態(tài)內部類,由于不同的布局中參數(shù)不一樣,Android SDK 提供了很多種 LayoutParams:
ViewGroup.LayoutParams
WindowManager.LayoutParams 繼承上一層
RelativeLayout.LayoutParams
...
public interface WindowManager extends ViewManager { //... public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable { //... } }
在 View 的 setLayoutParams 中的參數(shù)類型是最上層的 ViewGroup.LayoutParams params,這樣子類就可以傳入符合自己特性的 LayoutParams 實現(xiàn):
public void setLayoutParams(ViewGroup.LayoutParams params) { if (params == null) { throw new NullPointerException("Layout parameters cannot be null"); } mLayoutParams = params; resolveLayoutParams(); if (mParent instanceof ViewGroup) { ((ViewGroup) mParent).onSetLayoutParams(this, params); } requestLayout(); }
靜態(tài)內部類的另一種使用場景是:實現(xiàn)單例模式。
記得有一年去點評面試,面試官讓我寫個靜態(tài)內部類實現(xiàn)的單例模式,我寫的過程中不確定靜態(tài)內部類是否可以有靜態(tài)成員,基礎有多差可想而知。
先來看一下如何實現(xiàn):
public class LocationManager{ private static class ClassHolder { private static final LocationManager instance = new LocationManager(); } public static LocationManager getInstance() { return ClassHolder.instance; } }
我們知道靜態(tài)內部類功能和普通類一致,所以有 static 成員不足為奇。現(xiàn)在的問題是,為什么這種單例模式比較好?
原因有兩點:
懶加載:類加載時不會創(chuàng)建實例,只有當 getInstance() 方法被調用時才去加載靜態(tài)內部類以及其中持有的 LocationManager 實例
線程安全:JVM 加載類時,可以確保 instance 變量只能初始化一次
3.匿名內部類的使用場景Android 開發(fā)中設置一個按鈕的點擊事件很簡單,直接 new 一個 View.OnClickListener 然后實現(xiàn)方法即可:
mButton2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //... } });
結合前面談到的,編譯器會為每個匿名內部類創(chuàng)建一個 Class 文件。個人覺得在安卓開發(fā)中,有多個按鈕需要設置點擊事件時,讓當前類實現(xiàn) OnClickListener 接口然后在 onClick() 中根據 id 判斷事件,比創(chuàng)建一大堆匿名內部類要好些,你覺得呢?
之所以這樣寫,是因為我們不需要持有這個 new View.OnClickListener 的引用,只要創(chuàng)建了對象即可。
所以使用場景可以是:一個方法的返回值是接口,然后根據不同參數(shù)返回不同的實現(xiàn),我們不需要保存引用,直接 new 一個接口實現(xiàn)即可。
來看一個有趣的例子:
public class GirlFriendMaker { public interface GirlFriend { void sayHi(); } public static GirlFriend giveMeAGirlFriend(final String name) { return new GirlFriend() { //匿名內部類 @Override public void sayHi() { Log.i("來自女朋友的問候", "Hello I"m " + name); } }; } }4.局部內部類
局部內部類只用于當前方法或者代碼塊中創(chuàng)建、使用,一次性產品,使用場景比較少。
內存泄漏經過前面的介紹我們知道,四種內部類中除了靜態(tài)內部類,只要訪問外部類的成員/方法,就會持有外部類的引用。
當內部類持有外部類的引用,同時生命周期比外部類要長(比如執(zhí)行耗時任務、被其他長生命周期對象持有),就會導致外部類該被回收時無法被回收,也就是內存泄漏問題。
一個 Android 開發(fā)中常見的內部類導致內存泄露的例子:
public class MainActivity extends AppCompatActivity { public final int LOGIN_SUCCESS = 1; private Context mContext; private boolean isLongTimeNoMsg; @SuppressWarnings("HandlerLeak") private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { isLongTimeNoMsg = false; switch (msg.what) { case LOGIN_SUCCESS: {/ break; } //... } }
這個 Handler 持有外部類的引用,它發(fā)送的 runnable 對象,會被進一步包裝為 message 對象,放入消息隊列,在被執(zhí)行、回收之前會一致持有引用,導致無法釋放。
解決辦法就是使用弱引用或者干脆將 Handler 設計為靜態(tài)內部類。
總結總的來說,內部類一般用于兩個場景:
需要用一個類來解決一個復雜的問題,但是又不希望這個類是公共的
需要實現(xiàn)一個接口,但不需要持有它的引用
本篇文章介紹了 Java 開發(fā)中四種內部類的概念、反編譯后的格式以及使用場景。相信看完這篇文章,你對開頭的兩道題已經有了答案。
基礎就是這樣,不論你走的多遠,都需要及時回顧、彌補,等工作中需要用到才補,會錯失很多機會。
這個系列的目的是幫助大家系統(tǒng)、完整的打好基礎、逐漸深入學習,如果你對這些已經很熟了,請不要吝嗇你的評價,多多指出問題,我們一起做的更好!
文章同步發(fā)送于微信公眾號:安卓進化論,歡迎關注,第一時間獲取新文章。
參考資料《Java編程思想》
http://blog.csdn.net/qq734227...
http://www.cnblogs.com/latter...
https://www.javaworld.com/art...
https://www.cnblogs.com/zhang...
http://www.jianshu.com/p/6a36...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70698.html
摘要:里,有兩種方法獲得一定范圍內的數(shù)字返回一個列表,還有返回一個迭代器。在引用計數(shù)的基礎上,還可以通過標記清除解決容器對象可能產生的循環(huán)引用的問題。列舉常見的內置函數(shù)的作用,過濾函數(shù),循環(huán)函數(shù)累積函數(shù)一行代碼實現(xiàn)乘法表。 showImg(https://segmentfault.com/img/remote/1460000019294205); 1、為什么學習Python? 人生苦短?人間...
摘要:百度網盤提取碼一面試題熟練掌握是很關鍵的,大公司不僅僅要求你會使用幾個,更多的是要你熟悉源碼實現(xiàn)原理,甚至要你知道有哪些不足,怎么改進,還有一些有關的一些算法,設計模式等等。 ??百度網盤??提取碼:u6C4?一、java面試題熟練掌握java是很關鍵的,大公司不僅僅要求你會使用幾個api,更多的是要你熟悉源碼實現(xiàn)原理,甚...
摘要:與都繼承自類,在中也是使用字符數(shù)組保存字符串,,這兩種對象都是可變的。采用字節(jié)碼的好處語言通過字節(jié)碼的方式,在一定程度上解決了傳統(tǒng)解釋型語言執(zhí)行效率低的問題,同時又保留了解釋型語言可移植的特點。 String和StringBuffer、StringBuilder的區(qū)別是什么?String為什么是不可變的? String和StringBuffer、StringBuilder的區(qū)別 可變性...
閱讀 3200·2021-11-25 09:43
閱讀 3206·2021-11-23 09:51
閱讀 3518·2019-08-30 13:08
閱讀 1568·2019-08-29 12:48
閱讀 3594·2019-08-29 12:26
閱讀 396·2019-08-28 18:16
閱讀 2561·2019-08-26 13:45
閱讀 2428·2019-08-26 12:15