Java學習筆記08 複習

2020-08-08 23:49:15


二進制 ob
八進制 0
十六進制 0x
原碼 反碼 二補數
正數的原碼 反碼 二補數 都相同
負數的反碼 除符號位之外 按位元取反
負數的二補數 反碼加一
在計算機中的運算都是二補數運算
正數的二補數按位元取反(包括符號位)再加一---->負數
負數也同樣

變數的作用就是用來接受、操作、儲存、傳遞對應的數據
int a = 5; 5這個值通過操作傳遞給了a,a接受了5這一個值並儲存5這個值在變數a中
其中賦值 =左邊爲變數,右邊爲具體的數據,就是將等號右邊的東西傳給左邊

基本數據型別
byte    1位元組
short   2位元組
int     4位元組  
long    8位元組

float   4位元組
double  8位元組

char    2位元組
boolean 1位元組
跳脫字元 用於特殊字元
型別之間的轉換 小型別轉大型別可以自動轉換 大型別轉小型別需要強轉---手動轉換,但強轉可能會引發精度丟失的問題

在Java中的的浮點型別float和double不能進行精確的運算,雖然在大多情況是正常的,但偶爾也會出現問題
在Java中要保證執行結果的精度,可以使用BigDecimal類

變數
變數一定要先宣告,在複製,在使用
成員變數可以不用賦值,因爲系統會自動分配一個預設值
Java是強型別程式語言,要求數據的型別與變數的型別保持一致

物件
Java是物件導向的程式語言
物件:
屬性表示物件本身的一些特點
方法表示物件本身的一些行爲

類是抽象的,而物件是具體的
狗是一個類,具體到某一隻狗(小白) 那麼小白就是物件

參照數據型別變數
類型別 介面型別 陣列型別

我們寫的每一個類都是一種型別,這種型別就是參照型別
jdk中也會自帶一些類,這些型別也是參照型別

基本數據型別只能接收基本數據型別數據,相對來說是比較簡單的數據,沒有屬性,也沒有方法
參照數據型別只能接受物件,一般來說,物件是比較複雜的數據,可以具有屬性和方法
基本型別變數和參照型別的變數核心區別:是否可以指向物件

區域性變數:定義在方法之中,區域性變數沒有預設值
成員變數:定義在方法之中
- byte型別,預設值爲0
- short型別,預設值爲0
- int型別,預設值爲0
- long型別,預設值爲0L
- float型別,預設值爲0.0F
- double型別,預設值爲0.0D
- boolean型別,預設值false
- char型別,預設值是'\u0000'
- 參照型別,預設值是null
操作符
賦值操作符
= 賦值
*= 左邊變數與右邊數據相乘並把結果賦值個左邊變數
%= 求餘數
/= 求商
+= 求和
-= 求差
int a = 5/2.0
在這裏結果不爲2.5 而是爲2 這裏是5/2.0=2.5這個結果賦值給了a 但a不是浮點數型別而是整型 就會浮點型轉整型,系統就會預設去掉小數部分
a++ 先執行在自增一
++a 先自增一在執行
如果沒有執行 那麼a++與++a作用相同
a-- --a類似

比較操作符
> >= <= < 
instanceof 判斷物件是否屬於指定型別 語句 stu instanceof Student
但這個物件要被建立出來
Student stu; 這個不是建立物件 只是定義了一個型別類Student的變數,名爲stu

相等操作符
== 是否相等 != 是否不相等
算術操作符
+ - * / % 
移位元運算符
>> 算術右位移運算
注意,這個操作的本質就是除以2^n^,這個n就是我們右移的位數。
注意,除以2^n之後,只保留整數部分
注意,正數右移之後,最左邊空出的位置,都要補0
注意,負數右移之後,最左邊空出的位置,都要補1
例如,16 >> 3  結果是2  ,相當於 16 /2^3  = 2

<< 算術左位移運算
注意,這個操作的本質就是除以2^n^,這個n就是我們右移的位數。
注意,除以2^n之後,只保留整數部分
注意,不論正負數左移以後,最右邊空出的位置都要補0
注意,當左移之後,得到的數位已經超出當前型別所能表示的最大值的時候,這個值最終會被限定到這個當前型別中,所以最終顯示的值會和我們邏輯上算出的值有所不同。
例如:直接使用2進製表示數位
int a = 0b01000000000000000000000000000000;
int result = a<<2; //其實這個結果已經超出了int能表示的最大值
System.out.println(result);    //結果是0

特殊情況:
int a = 0b00000000000000000000000000000001;
System.out.println(a<<32);    //結果是1 相當於1<<0
System.out.println(a<<33);    //結果是2 相當於1<<1
System.out.println(a<<34);    //結果是4 相當於1<<2
原因:
        如果移動的位數超過了該型別的最大位數,那麼編譯器會對移動的位數取模/取餘。如果對int型移動33位,實際上只移動了33%32=1位。如果對int型移動32位元,實際上只移動了32%32=0位

>>> 邏輯右移位運算,也叫做【不帶】符號的右移運算
注意,這個操作的本質就是除以2^n^,這個n就是我們右移的位數
注意,除以2^n^之後,只保留整數部分
注意,正數和負數右移之後,最左邊空出的位置,都要補0

例如:
12>>>1  結果是 6
-12>>>1 結果是 2147483642

注意:在操作的時候,java操作的都是計算機中的二補數

正數的原碼、反碼、二補數都是一樣的
例如:數位1的原碼0000 0001,反碼0000 0001,二補數0000 0001

負數的原碼、反碼、二補數有所不同
例如:數位-1
原碼:1000 0001
反碼:1111 1110  除了符號位之外,其他按位元取反
二補數:1111 1111  反碼基礎上加1

位運算子
& 與運算 有0則0
| 或運算 有1則1
^ 互斥或運算 相同則0 不同則1
~ 取反運算
9取反=-10
0 1001
 1 0110
-0 0001
---------
 1 0101
 1 1010
邏輯運算子
短路與(邏輯與) && 
&& 與 & 的區別 ,在一個長表達式中包含多個表達式 當進行短路與判斷時
&會把每一個表達式都進行判斷 而&&則是遇到一個表達式結果爲false時候 後面其他的表達式不再進行判斷
整個表達式就結束了
不論時&& 還是& 有false的時候 表達時結果就爲false
短路或(邏輯或)||
||與|的區別與上訴類似,區別就在於或運算是有true的時候,整個表達式的結果就爲true

條件運算子(三目運算子)
語法:
boolean表達式?表達式1(boolean表達式爲true結果爲表達時1):表達式2(boolean表達式爲false結果爲表達式2)

String +兩邊 一邊是字串 一邊是數據 那+的意思就是拼接
String str = 1+1+"s"+2+5 = 2s25
String str = 1+1+'a'+"s"+2+5 = 99225
String str = 1+1+"S"+'a'+2+5 = 2Sa25

流程控制
if語句
if(表達式){

}else{

}

if(){

}elseif{

}else{

}
不論是那種方式 都會只執行其中一個花括號中的程式碼
當然可以再if語句中巢狀if語句

switch語句
switch語句與if語句類似
目前switch預設只支援byte,short, int ,char, String(jdk1.8)
int a = 1;
switch(a){
    case 0:{
        
    }
    case 1:{

    }
    case 2:{

    }
    .......
    default:{

    }
}

switch(a){
    case 0:{
        break;       
    }
    case 1:{
        break;
    }
    case 2:{
        break;
    }
    .......
    default:{
        
    }
}
這兩種方式不同之處就在於break,這要涉及到穿透概念
當沒有break的時候,如果有一個case滿足了switch()中的內容,那麼首先這個相對於的語句會執行
接着,這個case後面所有的執行語句都會執行,而跳過後面case的判斷,不論後面case是否滿足switch
在這兩種方法中還有一個default語句,這是再其他case都不滿足時候會執行的語句,也可以省略不寫

for回圈
for(初始變數值;判斷表達式;變數執行語句){
    執行語句
}
例如:
for(int i=0;i<10;i++){
    System.out.println("hello world");
}
當然,初始變數值可以寫在for回圈之外,變數執行語句可以寫在花括號中

int i = 0;
for(;i<10;){
    System.out.println("hello world");
    i++;
}
這是一個死回圈程式碼,for的小括號中,只有倆個分號
for(;;){
    System.out.println("hello world");
}
當for回圈中只有一行執行語句時候,花括號可以不寫,但不建議

while語句
while(判斷表達式){
    執行語句
}

do-while語句
do{
    執行語句
}while(判斷表達式);

while於do-while的區別在於,do-while語句至少會執行一次,大體上與for回圈型別

巢狀回圈
在一個回圈中可以巢狀另一個回圈
    for(){
        while(){
            do{

            }while();
        }
    }

break語句
break的意思是退出,結束當前的回圈或switch程式碼

continue語句
continue的意思是結束本次回圈,讓回圈直接進入一次執行

break與continue
例如
for(int i = 0;i<3;i++){
    if(i=0){
        break;
    }
}
當i=0時,結束for回圈,後面的i=1,1=2的語句不在執行
for(int i = 0;i<3;i++){
    if(i=0){
       continue;
    }
}
當i=0時,不執行i=0的執行程式碼,直接跳過i=0,直接執行下一個i=1的執行程式碼
預設情況下,在巢狀回圈中,break和continue只能預設對當前回圈其作用。

label
label用於結束指定一個for回圈
test1:for(int i=0;i<3;i++){//外層回圈
    test2:for(int j=0;j<5;j++){//內層回圈
        if(j==2){
            break test1;
        }
        System.out.println("i="+i+",j="+j);
    }
    System.out.println("----------------------");
}
其中test1,test2,test3就是label標籤
那麼會直接結束test1的for回圈(包括for回圈中其他回圈)
結束多層回圈可以使用label標籤,也可以使用return

Jvm記憶體的分配
虛擬機器棧:
儲存區域性變數
棧採用的是先進後出的規則
棧所佔的記憶體空間小
棧中的變數,變數的作用結束以後彈棧
堆:
存放物件範例,成員變數也屬於物件
堆佔據jvm記憶體中最大的一塊
堆裏面的記憶體需要通過Jvm中的垃圾回收機制 機製去回收
方法區:
儲存已被載入器載入的型別資訊、常數、靜態變數,即時編譯器編譯後的程式碼快取等數據
本地方法棧:
本地方法棧與虛擬機器棧作用型別,區別在於虛擬機器棧爲虛擬機器執行Java方法服務,而本地方法棧爲虛擬機器使用到的本地方法服務
暫存器:
程式計數器佔據很小的一塊記憶體空間,它可以看作當前執行緒所執行的位元組碼的行號治時期,位元組碼直譯器工作時就是通過該百年計數器的值來選取下一條需要執行的位元組碼指令,它時程式控制流的治時期,分支,回圈,挑戰,例外處理,執行緒恢復等功能都需要以來這個計算器來完成
簡單而言控製程式流程
jvm記憶體分配的方式
指針碰撞
空閒列表

陣列的概述
陣列是一組數據的集合,陣列中的每一個數據稱爲元素
在Java中,陣列也是物件。陣列中的元素可以是任意型別(基本型別或參照類型別),但同一個數組裏只能存放型別相同的元素
陣列是儲存同一種數據型別多個元素的結合,也可以看成是一個容器
陣列即可以儲存基本數據型別,也可以儲存參照數據型別
Java是強型別語言,所以陣列中的元素必須是對應陣列型別
陣列型別
任意型別 + [] = 相應的陣列型別
例如:
int [] ----->int[]
陣列中可以存放一組數據,要求這一組數據的型別都是一樣的(或者是相容的,相容就代表可以自動轉換)

陣列變數
在原有的陣列型別中宣告這個陣列型別的變數
int[] a; int[] a;
這兩種方式都是正確的變數宣告方式 建議使用第一種
陣列型別的變數,也是參照型別變數,簡稱參照,它是可以執行物件的

陣列物件
使用new關鍵字,來建立陣列物件,中括號中的數位代表陣列的長度(容量)
int[] a = new int[4];
陣列物件,在記憶體中,就是一塊連續的記憶體空間,在這一個連續的空間中可以存放多個型別相同的數據
注意:在堆中劃分物件空間記憶體,其對應的地址是存放在相對應的虛擬機器棧空間中的變數上,可以通過存取棧空間中的變數中的地址存取堆空間中存放的物件
陣列物件中只有一個屬性length,表示陣列的長度
陣列物件中的方法,只有從父類別型Object中繼承過來的方法
除此之外,陣列物件中就沒有其他的屬性和方法了

陣列長度
陣列物件的長度
陣列長度,是指一個數組物件中,最多可以存放多少個同以型別的數據
陣列長度,必須在建立陣列物件的時候明確指定
陣列長度,一旦確定,就無法在改變
陣列長度,可以爲0,但是不能爲負數

陣列下標
陣列物件在jvm的堆空間中是一款連續的記憶體空間,並允許使用下標,設定或獲取每一個空間的值·
陣列的下標區間[0,陣列長度-1]
可以通過陣列下標對陣列中對應位置進行賦值或者是去取值

陣列的地址
[(一個[對應一維陣列,有多少個[就是幾維陣列)I(這裏代表數據型別,不同的型別陣列對應不同的字母,對應的數據型別的英文字母第一個並大寫)雜湊碼(16進位制)
[Iafffff
預設值
一個數組物件在建立的時候,需要指明陣列長度,並且陣列中的每一個元素位置上,都已經有一個相對應的預設值,預設值與陣列的型別相關
//byte、short、int、long型別陣列中的預設值爲 0
//例如,
int[] a = new int[4];//預設4個數據全是0

//float、double型別陣列中的預設值爲 0.0
//例如,
double[] d = new double[4];//預設4個數據全是0.0

//boolean型別陣列中的預設值爲 false
//例如,
boolean[] d = new boolean[4];//預設4個數據全是false

//char型別陣列中的預設值爲 '\u0000'
//例如,
char[] d = new char[4];//預設4個數據全是'\u0000'

//參照型別陣列中的預設值爲 null
//例如,
String[] d = new String[4];//預設4個數據全是null

陣列的初始化
陣列建立時會在jvm中開闢連續的記憶體空間,併爲每個陣列元素賦值
陣列物件的初始化形式
動態初始化
只指定長度,沒有給陣列賦值,都是預設值
int[] arr = new int[4];
靜態初始化
給出初始化的值,長度由系統決定
int[] arr = new int[]{1,2,3,4}
int[] arr = {1,2,3,4}
int arr;
arr = new int[]{1,2,3,4};
錯誤的初始化方式
int[] arr = new int[4]{1,2,3,4}
int[] arr;
arr = {1,2,3,4}

陣列的拷貝
陣列物件在建立之時就已經確定了長度,並且時不能進行修改,但是可以通過賦值陣列的內容變通實現改變陣列長度
深拷貝 建立一個新的陣列來接收被拷貝的陣列
淺拷貝 定義一個數組變數指向被拷貝的記憶體地址
拷貝的三種方式
        int[] arr = {12,12};
        int[] arrcopy =new int[arr.length*2];

        System.arraycopy(arr, 0, arrcopy, 0,arr.length);

        arr=Arrays.copyOf(arr,arr.length*2);

        int[] arr01 =new int[arr.length*2];
        for(int i = 0;i<arr01.length;++i) {
            if(arr.length>i) {
                arr01[i]=arr[i];
            }else {
                arr01[i]=0;
            }

        }
        arr=arr01;
        
陣列的遍歷
將陣列中的元素逐個存取並取出來操作
可以使用三種基本回圈來實現,
也可以使用增強for回圈來實現(不需要下標)
增強for回圈:
 int[] arr = {1,4,4,5};
 for(int ar : arr) {
     System.out.println(ar);
 }
 陣列中常見的問題
 ArrayIndexOutOfBoundsException:陣列索引越界異常(訪問了不存在的索引)
 NullPointerException:空指針異常