相信不少的Android開發者和我同樣,當初學習Android開發時,對Java的學習並非很是深刻;大體瞭解了類和對象是怎麼回事,對多線程及網絡編程有了一個簡單的瞭解以後,便投入到了Android開發中;感受當時瞭解的東西就夠用了,一些比較偏的點,遇到了在網上找一下就能解決問題了,總的來講不影響平常工做。javascript
可是,隨着時間的流逝,慢慢感受本身遇到了瓶頸,基礎的東西都會了;嘗試去學習一些進階的東西,卻發現很是的難;因爲不瞭解註解和反射,第一次使用Retrofit框架的時候,徹底就是一臉懵逼,搞不懂@是幹什麼用的;嘗試去解讀Glide的源碼,因爲缺少對泛型及設計模式的瞭解,連Glide底層的網絡請求時在哪裏實現都找不到;基礎不牢,寫代碼老是挖坑……。java
總之應了那句話,出來混老是要還的。想在這條道上長遠的走下去,曾經欠下的東西都得補回來。因此,這段時間對惡補了一寫Java基礎,總結了一些以前理解有誤差或錯誤的點,在這裏權當筆記記錄一下,以後又新的心得體會會持續更新。編程
類型 | 位數 | 值域 |
---|---|---|
boolean | JVM 決定 | true/false |
char | 16bit | 0~65535 |
byte | 8bit | -128~127 |
short | 16bit | -32768~32767 |
int | 32bit | -2147483648~2147483648 |
long | 64bit | 很大 |
float | 32bit | 範圍可變 |
double | 64bit | 範圍可變 |
People man=new People();
People women=new People();
People boy=man;複製代碼
man,women,boy應該稱爲引用變量,它保存的是存取對象的方法;引用變量並非對象的容器,而是相似指向對象的指針。設計模式
以上賦值代碼表達的意思,一個People類型的變量man引用到堆上建立的一個People對象。網絡
== 兩個引用變量是否引用到堆上的同一個對象。或者是基礎數據類型(int,long等)的變量是否相等。
equals 兩個對象的內容是否同樣多線程
以前寫代碼的時候,就關於變量賦值產生過一個很經(di)典(ji)的bug。這裏來分享一下。背景很簡單,就是作RecyclerView的下拉刷新,代碼以下,很簡單。框架
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {
private List<String> datas = new ArrayList<>();
private MyAdaptetr mMyAdaptetr;
SwipeRefreshLayout mSwipeRefreshLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeLayout);
mSwipeRefreshLayout.setOnRefreshListener(this);
RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
datas = getData();
mMyAdaptetr = new MyAdaptetr(datas);
mRecyclerView.setAdapter(mMyAdaptetr);
}
private List<String> getData() {
List<String> datas = new ArrayList<>();
for (int i = 0; i < 100; i++) {
datas.add("item " + i);
}
return datas;
}
@Override
public void onRefresh() {
datas.clear();
datas = getData();
mMyAdaptetr.notifyDataSetChanged();
mSwipeRefreshLayout.setRefreshing(false);
}
}
private class MyAdaptetr extends RecyclerView.Adapter<MyAdaptetr.MyHolder> {
private List<String> datas;
public MyAdaptetr(List<String> datas) {
this.datas = datas;
}
@Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new MyHolder(mView);
}
@Override
public void onBindViewHolder(MyHolder holder, int position) {
holder.text.setText(datas.get(position));
}
@Override
public int getItemCount() {
return datas.size();
}
class MyHolder extends RecyclerView.ViewHolder {
TextView text;
public MyHolder(View itemView) {
super(itemView);
text = (TextView) itemView.findViewById(R.id.text);
}
}
}複製代碼
實際場景代碼要比這複雜不少,這裏爲了說明問題,寫了一個簡易的demo,但所要表達的問題一致,onRefresh裏的代碼是有問題的,你發現了嗎?dom
乍一看,這代碼貌似沒問題,可是執行下拉刷新後,列表直接被清空了,一條數據都顯示不出來。記得當初爲了找緣由,對MyAdapter各類修改,甚至懷疑本身是否是發現了一個Android系統的bug。徹底沒有去考慮datas=getData()這行代碼的意義。直到後來打斷點發現,mMyAdaptetr.notifyDataSetChanged() 執行後,再次去Adapter的onBindViewHolder方法中查看時,竟然發現的列表的size變成了0。這下但是徹底懵逼了。
後來作了以下修改,問題得以解決:ide
@Override
public void onRefresh() {
datas.clear();
//datas = getData();
datas.addAll(getData());
mMyAdaptetr.notifyDataSetChanged();
mSwipeRefreshLayout.setRefreshing(false);
}複製代碼
當時,雖然把問題解決了,可是很是的不理解。爲何第一執行datas=getData()時就能夠,第二次執行就不行了呢?datas=getData() 和 datas.addAll(getData())有區別嗎?不都是把新建的列表賦給datas嗎?函數
結合上面關於引用變量的賦值解釋,這個問題就很容易理解了。
而當咱們建立MyAdapter對象時,因爲MyAdapter只會執行一次
public MyAdaptetr(List<String> datas) {
this.datas = datas;
}複製代碼
所以,MyAdapter內部的datas指向的永遠都是咱們第一次建立的那塊存儲區域。
到這裏,咱們就很容易理解這個bug的本質了。
"=", 不是的賦值這麼簡單 !
應用變量的類型能夠是實際對象類型的父類
//Man 繼承自People類
People mPeople=new Man();複製代碼
方法的覆蓋,參數,返回值類型,均不能改變,存取權限不能下降
方法的重載,參數不一樣,返回值類型,存取權限能夠改變,與多態無關。
People mPeople=new People();
Object o=mPeople;
int code=o.hashCode();
o.toString();
o.eat();複製代碼
編譯器是根據引用類型來判斷有哪些method能夠調用,而不是根據引用所指向的對象類型來判斷。所以,上述o.eat()將 沒法執行,即使People類這個方法,可是對於Object來講是未知的。
this 關鍵字是類內部當中對本身的一個引用,能夠方便類中方法訪問本身的屬性
要從子類調用父類的方法可使用super關鍵字來引用
super.onResume()複製代碼
使用this()來從某個構造函數調用同一個類的另一個構造函數。this()只能用在構造函數中,而且必須是第一行被執行的語句。
super() 用來調用父類的構造函數,必須是第一個被執行的語句,所以,super()和this() 不能共存。
之後自定義View的時候,構造函數該怎麼寫,終於有譜了。
被abstract標記的類稱爲抽象類,沒法被實例化;
抽象類任然能夠做爲引用變量的類型。
被abstract標記的方法被聲明時沒有內容,以分號結束;非抽象子類必須實現此方法。
若是有一個類當中有任意一個抽象的方法,那麼這個類也必須是抽象的;固然這個抽象類當中,同時能夠包括其餘非抽象的方法。
若是要限制一個類被實例化,除了使用abstract標記爲抽象類以外,還能夠將其構造函數標記爲private。
被static標記的方法,靜態方法,能夠不須要具體的對象,可直接由類調用。
靜態方法不能調用非靜態的變量,由於他沒法得知是那個實例變量。同理可得,靜態方法不>能調用非靜態的方法。
靜態變量是共享的,同一類的全部實例共享一份靜態變量,它會在該類的任何靜態方法 執行以前就初始化,沒有被賦值時,會被設定爲該變量所屬的默認值。
Math.random();
Math.min(1,2);複製代碼
所以,帶有靜態方法的類,通常來講能夠是抽象的,沒必要要被初始化;但不是必須的。
static final double PI=3.1415925複製代碼
final 類型的靜態變量爲常量
final 類型的變量一旦被賦值就不能再更改
final 類型的方法不能被覆蓋
final 類型的類不能被繼承
防止兩個線程同時進入同一對象的同一個方法
public class TestSync implements Runnable {
private static final int COUNT = 500000;
private int count;
@Override
public void run() {
for (int i = 0; i < COUNT; i++) {
increment();
System.err.println("count=" + count);
}
}
private synchronized void increment() {
count = count + 1;
}
public static void main(String[] args) {
TestSync mRunnable = new TestSync();
Thread a = new Thread(mRunnable);
Thread b = new Thread(mRunnable);
a.start();
b.start();
}
}複製代碼
上面的代碼中,當a,b 兩個線程同時開始執行run方法時,在缺乏synchronized的狀況下,兩個線程將由虛擬機的調度器控制執行,所以當a線程完成count+1時,還沒來得及賦值操做,就被切換到了b線程,b線程再次執行count+1操做時,就會丟掉a完成的工做,最終會致使結果不正確,兩個線程內各自經歷COUNT次循環後,並無使最終的值達到COUNT*2 的結果。
只有increment()方法被synchronized修飾後,就能夠保證在每次在a線程完整了執行完了increment方法後,b線程才能夠執行該方法,反之亦然。這樣就能夠保證最終的執行結果的正確性
須要注意的是,synchronized(鎖)並非加在方法上,而是配在對象上。某個對象都有一把「鎖」和一把「鑰匙」存在,大部分時候並無實際意義,只有對方法使用synchronized(同步化)以後,鎖纔會變得有意義。當同時有多個線程須要執行同步化方法時,只有取得當前對象鎖的鑰匙的線程才能進入該同步化方法。其餘線程只有在得到鑰匙的線程完整的執行完畢同步化方法時,纔會得到鑰匙從而進入同步化方法,不然,就只能等待。所以,使用synchronized會消耗額外的資源,會使方法執行變慢,所以要謹慎使用。同時,使用不當會致使死鎖問題的產生。
當對象有多個同步化的方法時,鎖和鑰匙仍是隻有一把。得到鑰匙的某個線程進入到該對象的同步化方式時,其餘線程也沒法進入該對象其餘的同步化方法。此時,惟一能作的事情就是等待。
未完待續。。。。
Google I/O 大會以後Kotlin很火,那麼咱們是否意味着在Android開發中他會取代Java呢?
Google’s Java-centric Android mobile development platform is adding the Kotlin language as an officially supported development language, and will include it in the Android Studio 3.0 IDE.
這段話應該說的很清楚了。