1. 程式人生 > >Java core 基礎概念

Java core 基礎概念

JAVA學習中記錄的一些筆記,不斷更新

目錄

1.識別符號

2.變數

5.語句

8.陣列

16.繼承

20.介面

21.多型

24.異常

25.包

29.集合

1.識別符號

包名:xxxyyyzzz

類名介面名:XxxYyyZzz

變數名函式名:xxxYyyZzz

常量名:XXX_YYY_ZZZ

2.變數

基本資料型別:資料型,字元型,布林型(棧記憶體)

引用資料型別:類,介面,陣列(棧記憶體引用堆記憶體)

當資料不確定時,且需要對資料進行儲存時,定義變數

3.邏輯運算子

&和&&:

&:無論左邊是true還是false,右邊都運算

&&:當左邊為false時,右邊不運算

|和||

|:兩邊都參與運算

||:當左邊為true時,右邊不運算

4.位運算子(高效運算)

左移<<:乘2的移動位數次冪

右移>>:除2的移動位數次冪

>>:最高位補什麼由原有資料的最高位值而定

        如果最高位0,右移後,用0補空位

        如果最高位1,右移後,用1補空位

>>>:無論最高位是什麼,右移後,都用0補

異或^:A^B^B=A(加密解密,資料交換)

5.語句

switch:判斷的具體數值不多,且符合byte,short,int,char,String(1.7)型別

if:對區間判斷,對結果為Boolean型別判斷

for:變數有作用域,迴圈增量定義在for中,且只在for中有效,for執行完畢後,該增量在記憶體中消失。for(;;){}-->(無限迴圈)

while,dowhile:運算結果用於迴圈外,while(true){}-->(無限迴圈)

break:跳出,應用於選擇結構和迴圈結構

continue:繼續,應用於迴圈結構,結束本次迴圈繼續下次迴圈

6.函式(方法)

過載(overload):同一個類中,同名且引數個數或引數型別不同,與返回值型別無關。當定義的功能相同,但參與運算的位置內容不同,定義一個函式名稱以表示該功能,通過引數列表的不同來區分多個同名函式。

主函式(main 不是關鍵字):是一個特殊的函式,作為程式入口,可以被JVM呼叫

public static void main(String[] args)args==arguments(n.引數)

public:代表該函式訪問許可權最大

static:代表主函式隨著類的載入就已經存在了

void:主函式沒有具體的返回值

String [] args:函式的引數,引數型別是一個字串陣列,傳入的是new String[0] 空陣列

                        javac mainDemo

                        java mainDemo haha hehe heihei

                        System.out.println(args[0]);--->haha

7.記憶體結構

棧記憶體:用於儲存區域性變數,當資料使用後,所佔空間會自動釋放

堆記憶體:陣列和物件,通過new建立的例項都存放在堆記憶體中,每一個實體都有記憶體地址值,實體中的變數都有預設初始化值,實體不在被使用,會在不確定的時間內被垃圾回收器回收。

               [I@xxxxxx:一維陣列,integer型別元素,記憶體地址(雜湊值,十六進位制)

方法區:

本地方法區:

暫存器:

8.陣列

排序:Arrays.sort(arr);

選擇排序:內迴圈結束一次,最值出現在頭角標位上

public static void selectSort(int []arr)
{
    for(int x=0;x<arr.length;x++)
    {
       for(int y=x+1;y<arr.length;y++)
       {
           if(arr[x]>arr[y])
           {
               int temp=arr[x];
               arr[x]=arr[y];
               arr[y]=temp;                
           }
       }
    }
}

氣泡排序:

public static void bubbleSort(int []arr)
{
    for(int x=0;x<arr.length-1;x++)
    {
       for(int y=0;y<arr.length-x-1;y++)//-x:讓每一次比較的元素減少  -1:避免角標越界
       {
           if(arr[y]>arr[y+1])
           {
               int temp=arr[y];
               arr[y]=arr[y+1];
               arr[y+1]=temp;                
           }
       }
    }
 }

9.面向物件

封裝,繼承,多型

具體物件就是java在堆記憶體用new建立實體

屬性就是類中變數,行為就是類中函式(成員變數和成員方法)

類型別變數指向堆記憶體中的物件

成員變數和區域性變數 作用範圍

成員變數作用於整個類中,存放於堆記憶體,因為物件的存在,才在記憶體中存在

區域性變數作用於函式中,或者語句中,存放於棧記憶體中

10.匿名物件

當對物件的方法(非屬性變數,呼叫完即在記憶體中成為垃圾,等待回收)只調用一次時,可簡化為匿名物件

可以將匿名物件作為實際引數進行傳遞

Car c=new Car();
show(c);

show(new Car());

11.訪問控制修飾符

用於控制被修飾變數、方法、類的可見範圍.
public 的訪問級別是最高的,其次是 protected、預設和 private.
成員變數和成員方法可以處於4個訪問級別中的一個:公開、受保護、預設或私有.
存在繼承關係時,父類不可以是 private,因為子類無法繼承
頂層類可以處於公開或預設級別,頂層類不能被 protected 和 private 修飾. (外部類)
區域性變數不能被訪問控制修飾符修飾

private:私有,用於修飾類中成員(成員變數和成員方法),私有隻在本類中有效,物件不能直接訪問,提供get,set方法進行訪問。僅僅是封裝的一種表現形式

預設許可權(不寫default):介於私有和共有之間

public:

protected:

12.建構函式

預設建構函式(系統自帶): 類名(){}  預設建構函式的許可權隨著類的變化而變化

自定義建構函式後,預設建構函式消失

物件一建立,就會呼叫與之對應的建構函式,可以用於給物件進行初始化,只執行一次

構造程式碼塊 {}

作用:給物件進行初始化 物件一建立就執行,而且優先於建構函式執行

構造程式碼塊是給所有物件進行統一初始化(定義不同物件共性的初始化內容)

建構函式是給對應的物件初始化

13.this關鍵字

代表對本類物件的引用

預設被省略

用於區分區域性變數和成員變數同名的情況

代表它所在函式所屬物件的引用

當定義類中功能(方法)時,該函式內部要用到呼叫該函式的物件時,這時用this來表示這個物件

但凡本類功能內部使用了本類物件,都用this表示

this語句:只能用於在建構函式間進行互相呼叫,this語句只能定義在建構函式第一行,因為初始化要先執行

Person()
{
    this.name="xixi";
}
Person(String name)
{
    this();
    this.name=name;
}
Person(String name,int age)
{
    this(name);
    //this.name=name;
    this.age=age;
}

14.static關鍵字

靜態 用於修飾成員(成員變數,成員函式),成員被靜態修飾後,成員不存在於堆記憶體中,而存在於方法區(共享區,資料區),在記憶體中只有一個副本

被修飾的成員:隨著類的載入而載入,優先於物件存在,被所有物件所共享,共享資料 (country=“CN”(類變數))

                        可以直接被類名呼叫(類名.靜態成員),因為靜態成員存在時,物件可能不存在。

注意事項:靜態方法只能訪問靜態成員,非靜態方法既可以訪問靜態也可以訪問非靜態,

                 靜態方法中不可以寫this,super關鍵字,主函式是靜態的

利處:對物件的共享資料進行單獨空間儲存,節省空間,沒有必要每個物件都儲存一份。

弊處:生命週期過長,訪問出現侷限性

用處:當物件中出現共享資料(值)時,該資料被靜態修飾,物件特有資料定義成非靜態。

           當功能內部沒有訪問到非靜態資料時,該功能可以定義成靜態方法

應用:每一個應用程式中都有共性的功能,可以將這些功能進行抽取,獨立封裝,以便複用。

           工具類(ArrayTool等)不需要物件,可將類中方法定義成靜態的,直接通過類名呼叫。因為不需要建立物件,可將建構函式私有化強制不能建立物件。

靜態程式碼塊: static{ 語句 }  隨著類的載入而執行,只執行一次。用於給類進行初始化。

15.物件的初始化過程

class Person
{
    private String name="xixi";
    private int age;
    private static String country="CN";
    Person (String name,int age)
    {
        this.name=name;
        this.age=age;
    }
    {
        System.out.println(name+"--"+age);
    }
    public void setName(String name)
    {
        this.name=name;
    }
    public void speak()
    {
        System.out.println(this.name+"--"+this.age);
    }
    public static void showcountry()
    {
        System.out.println("country="+country);
    } 
 }
class PersonDemo
{
    public static void main(String []args)
    {
        Person p=new Person("heihei",10);
    }
}

Person p=new Person("heihei",10);

1.因為new用到了Person.class,所以會先找到Person.class檔案並載入到記憶體中(Person p=null 這種情況類不載入(new時會用到建構函式))

2.執行該類中的static程式碼塊,如果有的話,給Person.class進行初始化。

3.在堆記憶體中開闢空間,分配記憶體地址。

4.在堆記憶體中建立物件的特有屬性,並進行預設初始化。

5.對屬性進行顯示初始化。

6.對物件進行構造程式碼塊初始化。

7.對物件進行對應的建構函式初始化。

8.將記憶體地址賦給棧記憶體中的p變數。

16.繼承

特性:單繼承(多繼承安全隱患),支援多層繼承

聚集 :has a

聚合:球隊球員

組合:人體器官

提高程式碼的複用性,讓類與類之間產生了關係,有了這個關係,才有了多型的特性。所屬關係 :is a

如何使用一個繼承體系中的功能:先查閱體系父類的描述,因為父類中定義的是該體系中共性功能,通過了解共性功能。就可以知道該體系的基本功能。在具體呼叫時,要建立最子類的物件,因為有可能父類不能建立物件(抽象類),建立子類物件可以使用更多功能。

當子類繼承父類,沿襲了父類的功能,到子類中,但是子類雖具備該功能,但是功能的內容卻和父類不一致,這時,沒有必要定義新功能,而是使用覆蓋,保留父類的功能定義,並重寫功能內容。

子類覆蓋父類,必須保證子類許可權大於等於父類許可權,才可以覆蓋,否則編譯失敗。(方法非屬性)靜態只能覆蓋靜態。

如果子類和父類中有同名屬性,父類引用指向子類物件的時候,通過父類引用訪問那個同名屬性時,訪問的是父類中的那個,不是子類中的那個,因為父類引用是看不到子類中的屬性的,這和方法不同,父類引用呼叫子類方法時有個優先順序的問題,this優先於super,即,如果子類中重寫了父類的方法,那麼呼叫的就是子類中的,如果沒有重寫,就呼叫的是父類中的。

public class tt 
{
   
    public static void main(String[] args) throws Exception{
       A b=new B(); //父類引用指向子類物件
       b.show();//輸出bbbb
       System.out.print(b.num);//輸出111
       int x=b.getnum();
       System.out.print(x);//輸出333
       b.ss();//輸出AAAA
    }
}
class A
{
	public int num=111;
	public void show()
	{
		System.out.print("aaaa");
	}
	public int getnum() {
		
		return num;
	}
	public void ss()
	{
		System.out.print("AAAA");
	}

}
class B extends A
{
	public int num=333;
	public int getnum()
	{
		return num;
	}
	public void show()
	{
		System.out.print("bbbb");
	}
}

17.super關鍵字

代表對父類物件的引用

在對子類物件進行初始化時,父類的建構函式也會執行,那是因為子類的建構函式預設第一行有一條隱式語句 super();

super():會訪問父類中空引數的建構函式,而且子類中所有的建構函式預設第一行都是super();

因為父類中的資料子類可以直接獲取,所以子類物件在建立時,需要先檢視父類時如何對這些資料進行初始化的。所以子類在物件初始化時,要先訪問一下父類中的建構函式。如果要訪問父類中指定的建構函式,可以通過手動定義super語句的方法來指定。當然,子類的建構函式第一行也可以手動指定this語句來訪問本類中的建構函式,子類中至少會有一個建構函式會訪問父類中的建構函式。

18.final關鍵字

final可以修飾類,方法,變數。

final修飾的類不可以被繼承。

final修飾的方法不可以被覆蓋。

final修飾的變數是一個常量,只能被賦值一次。

內部類只能訪問被final修飾的區域性變數。

19.abstract關鍵字

當多個類中出現相同功能,但是功能主體不同。這時可以進行向上抽取,這時,只抽取功能定義,而不抽取功能主體。

抽象類的特點:抽象方法一定在抽象類中,抽象方法和抽象類都必須被abstract關鍵字修飾,抽象類不可以用new建立物件,因為呼叫抽象方法沒意義。抽象類中的方法要被使用必須由子類複寫其所有的抽象方法後,建立子類物件呼叫。如果子類只覆蓋了部分抽象方法,那麼該子類還是一個抽象類。

抽象類中可以不定義抽象方法,這樣做僅僅是不讓該類建立物件。

20.介面

可以認為是一個特殊的抽象類,當抽象類中的方法都是抽象的,那麼該類可以通過介面的形式來表示

不可以建立物件,因為有抽象方法,需要被子類實現,子類對介面中的抽象方法全都覆蓋後,子類才可以例項化,否則子類是一個抽象類。

一個類可以實現多個介面也是對多繼承不支援的轉換形式

class用於定義類

interface用於定義介面

介面定義時,格式特點:

介面中常見定義:常量,抽象方法

介面中的成員都有固定修飾符(自動+):常量:public static final

                                                方法:public abstract

介面中的成員都是public

類與類 繼承 extends

類與介面 實現 implements

介面與介面 繼承 extends(介面可以多繼承)

21.多型

可以理解為事物存在的多種體現形態

貓 x=new 貓();

動物 x=new 貓();//型別提升,向上轉型

體現:父類引用指向了自己的子類物件,父類引用也可以接收自己的子類物件

前提:類與類之間必須有關係,要麼繼承,要麼實現

好處:提高程式的擴充套件性

弊端:只能使用父類的引用訪問父類中的成員。

          如果子類和父類中有同名屬性,父類引用指向子類物件的時候,通過父類引用訪問那個同名屬性時,訪問的是父類中的那個,不是子類中的那個,因為父類引用是看不到子類中的屬性的,這和方法不同,父類引用呼叫子類方法時有個優先順序的問題,this優先於super,即,如果子類中重寫了父類的方法,那麼呼叫的就是子類中的,如果沒有重寫,就呼叫的是父類中的。

//如果想要呼叫子類的特有方法,就強制將父類的引用,轉成子類型別
Animal a=new Cat();//向上轉型
a.eat();
Cat c=(Cat)a;//向下轉型
c.catchMouse();


//能轉換的是父類引用指向自己的子類物件時,該引用可以被提升,也可以被強制轉換
//多型自始至終都是子類物件在做著變化

Animal a=new Animal();
Cat c=(Cat)a;//這是不允許的

a instanceof Cat//判斷a是否是Cat型別(判斷所屬型別)

在多型中成員函式(非靜態)的特點:

在編譯時期,參閱引用型變數所屬的類中是否有呼叫的方法,如果有,編譯通過,否則編譯失敗

在執行時期,參閱物件所屬的類中是否有呼叫的方法

簡單總結:非靜態成員函式在多型呼叫時,編譯看左邊,執行看右邊

                 靜態成員函式,無論編譯和執行,都參考左邊

                 成員變數,無論編譯和執行,都參考左邊(引用型變數所屬的類)

22.內部類

定義原則:當描述事物時,事物的內部還有事物,該事物用內部類來描述。因為內部事物在使用外部事物的內容。

內部類可以直接訪問外部類中的成員,包括私有(因為內部類有預設引用 外部類.this)

外部類要訪問內部類,必須建立內部類物件

其他類直接訪問內部類: Outer.Inner in= new Outer().new Inner();

外部類與內部類出現同名變數時,內部類想要訪問外部類變數:Outer.this.xxx;

內部類在成員位置上,就可以被成員修飾符所修飾

內部類定義在區域性時,不可以被成員修飾符修飾

訪問區域性變數時,區域性變數必須被final修飾

private :將內部類在外部類中進行封裝

static:內部類具有靜態特性(靜態內部類),只能直接訪問外部類中的靜態成員

當內部類中定義了靜態成員,該內部類必須是靜態的

當外部類中的靜態方法訪問內部類時,內部類也必須是靜態的

其他類訪問靜態內部類的非靜態成員  new Outer.Inner().function();

其他類訪問靜態內部類的靜態成員  Outer.Inner().function();

23.匿名內部類

匿名內部類其實就是內部類的簡寫格式。是一個匿名子類物件

前提:內部類必須是繼承一個類或者實現介面

匿名內部類中定義的方法最好不要超過三個

abstract class AbsDemo
{
    abstract void show();
}
class Outer
{
    int x=3;
    /*
    class Inner extends AbsDemo
    {
        void show()
        {
            System.out.println(x);
        }
    }
    */
    public void function
    {
        //new Inner().show();

        new AbsDemo()//建立的是AbsDemo的子類,因為show方法被重寫了
        {
            void show()
            {
                System.out.println(x);
            }
        }.show();
    }
}
interface Inter
{
    void method();
}
class Test
{
    public static Inter function()//1
    {
        return new Inter()
        {
            public void method()
            {
                System.out.println("haha");
            }
        };
    }
}
class TestDemo
{
    public static void main(String []args)
    {
        Test.function().method();//1
        

        show(new Inter()
        {
            public void method()
            {
                System.out.println("haha");
            }
        });//2
    }
    public static void show(Inter in)//2
    {
        in.method();
    }
}

24.異常

程式在執行時出現的不正常情況

異常由來:問題也是現實生活中一個具體的事物,也可以通過JAVA的類的形式進行描述,並封裝成物件

                   其實就是java對不正常情況進行描述後的物件體現

問題劃分:嚴重的 java通過Error類進行描述(一般不編寫針對性的程式碼對其進行處理)

                 非嚴重的 java通過Exception類進行描述(可以使用針對性的處理方式進行處理)

向上抽取 父類 Throwable

異常的處理:

try{  需要被檢測的程式碼 }

catch( 異常類 變數 ){  處理異常的程式碼(處理方式) }      (Exception e = new XXXException())

finally{  一定會執行的語句 通常用於關閉資源(IO流 SQL連線)  }

宣告異常:throws Exception 必須有try catch迴應,否則編譯失敗,除非一直拋,直到拋給JVM處理。

宣告異常時,簡易宣告更具體的異常 如除零 ArithmeticException

對方宣告幾個異常,就對應有幾個catch塊,不要定義多於的catch塊。

如果多個catch塊中的異常出現繼承關係,父類異常catch塊放在最下面。

建議在進行catch處理時,一定要定義具體處理方式,不要簡單定義一句e.printStackTrace語句。

自定義異常

因為專案中會出現特有的問題。而這些問題並未被java所描述並封裝成物件。 所以對於這些特有的問題可以按照java的對問題封裝的思想,將特有的問題,進行自定義的異常封裝。

當在函式內部出現了throw丟擲異常物件,那麼就必須要給對應的處理動作,要麼在內部try catch 要麼在函式上宣告讓呼叫者處理。

一般情況下,函式內出現異常,函式上需要宣告。

如何定義異常資訊:因為父類已經把異常資訊的操作都完成了,所以子類只要在構造時,把異常資訊傳遞給父類通過super語句。那麼就可以直接通過getMessage方法獲取自定義的異常資訊。

自定義異常,必須是自定義類繼承Exception

異常體系有一個特點,因為異常類和異常物件都被丟擲,他們都具備可拋性,這個可拋性是throwable這個體系中的獨有特點。

只有這個體系中的類和物件才可以被throw和throws操作。

throw和throws的區別:

throws使用在函式上                                                    throw使用在函式內

throws後面跟的是異常類,可以跟多個,用逗號隔開     throw後面跟的是異常物件

class FuShuException extends Exception
{
    private int value;
    FuShuException()
    {
        super();
    }
    FuShuException(String message,int value)
    {
        super(message);
        this.value=value;
    }
    public int getValue()
    {
        return value;
    }

}
class Demo 
{
    int div(int a,int b)throws FuShuException
    {
        if(b<0)
            throw new FuShuException("出現了除負數異常!!!",b);//手動通過throw關鍵字丟擲自定義異常
        return a/b;
    }
}
class Test
{
    public static void main(String []args)
    {
        Demo d=new Demo();
        try
        {
            int x=d.div(4,-9);
            System.out.println(x);
        }
        catch(FuShuException e)
        {
            System.out.println(e.toString());
            System.out.println("錯誤的負數是"+e.getValue());
        }
    }
}

 

特殊異常:RuntimeException

Exception中有一個特殊的子類異常RuntimeException執行時異常

如果在函式內中丟擲異常,函式可以不用宣告,編譯一樣通過。

如果在函式上聲明瞭該異常,呼叫者可以不進行處理,編譯一樣通過。

之所以不用函式宣告,是因為不需要讓呼叫者處理,當該異常發生,希望程式停止,因為在執行時,出現了無法繼續運算的情況,希望停止程式後,對程式碼進行修正。

自定義異常時,如果該異常的發生,無法在繼續進行運算,就讓自定義異常繼承RuntimeException.

異常分兩種

編譯時被檢測的異常

編譯時不被檢測的異常(RuntimeException及其子類)

異常在子父類覆蓋中的體現:

1 子類在覆蓋父類方法時,如果父類的方法丟擲異常,那麼子類的覆蓋方法,只能丟擲父類的異常或者該異常的子類,或者不拋(自己捕獲異常並解決)

2 如果父類方法丟擲多個異常,那麼子類在覆蓋該方法時,只能丟擲父類異常的子集

3 如果父類或者介面的方法中沒有異常丟擲,那麼子類在覆蓋方法時,也不可以丟擲異常(如果子類方法發生了異常,就必須進行try處理,絕對不能拋)

總結

Ps:截圖為畢向東老師Java基礎視訊。

25.包

對類檔案進行分類管理,給類提供多層名稱空間,寫在程式檔案的第一行,類名的全稱是 包名.類名,包也是一種封裝形式。

編譯:javac -d . PakeageDemo.java(-d 引數 包資料夾地址 (.為當前地址))

執行:java pack.PakeageDemo

總結:包與包之間進行訪問,被訪問的包中的類以及類中的成員,需要被public修飾

不同包中的子類還可以直接訪問父類中被protected許可權修飾的成員

import:為了簡化類名的書寫,使用此關鍵字

//如果不import的話  pack.packzi.DemoB a=new pack.packzi.DemoB();

建議不寫萬用字元* 需要使用哪個類。就匯入哪個。

c:\myclass

c:\myclass\pack\DemoA.class

c:\myclass\pack\packzi\DemoB.class

import pack.*;               匯入的是pack中的所有類,不包括packzi中的類

import pack.packzi.*;    匯入的是packzi中的所有類

定包名不要重複,可以使用url來定義

import cn.itcast.demo

26.多執行緒

一個程式至少有一個程序,一個程序至少有一個執行緒

程序:是一個正在執行中的程式。每一個程序都有一個執行順序,該順序是一個執行路徑,或者叫一個控制單元。

執行緒:就是程序中的一個獨立的控制單元,執行緒在控制著程序的執行。

一個程序中至少有一個執行緒。

Javac 編譯時 會啟動javac.exe 編譯完成後關閉

Java VM 啟動的時候會有一個程序java.exe

該程序至少有一個執行緒負責java程式的執行,而且這個執行緒執行的程式碼存在於main方法中,該執行緒稱之為主執行緒。

JVM不止啟動一個執行緒,還有負責垃圾回收機制的執行緒。

建立執行緒的第一種方式:繼承Thread類

定義類繼承Thread 重寫Thread類中的run方法,呼叫執行緒的start方法(start方法啟動執行緒並呼叫run方法)。

class Demo extends Thread
{
        Demo(String name)
        {
            super(name);//自定義執行緒名稱
        }
        public void run()
        {
            System.out.print(this.getName());  
           // System.out.print(Thread.currentThread().getName());  Thread.currentThread() 獲取當前執行緒的引用 建議使用這種方法
       }
}
main()
{
    Demo d=new Demo("xixi");//建立執行緒
    d.start();//啟動執行緒 並呼叫run方法 則d這個執行緒和主執行緒就在“同時”執行(併發),出現隨機性,CPU執行誰,誰執行。
    //d.run(); 如果直接呼叫run方法,而沒有啟動執行緒,run()中的程式碼執行完畢後主函式才會繼續執行。
}

執行緒有預設名字 格式:Thread-編號 編號從0開始。

自定義執行緒名字 :建構函式或者setName()方法

多執行緒具有隨機性,誰搶到誰執行。

執行緒的幾種狀態:

建立執行緒的第二種方式:實現Runnable介面

定義類實現Runnable介面,覆蓋Runnable介面中的run方法,通過Thread類建立執行緒物件,將Runnable介面的子類物件作為

實際引數傳遞給Thread類的建構函式,呼叫Thread類的start方法開啟執行緒並呼叫Runnable介面子類的run方法。

繼承方式和實現方式:建議使用實現方式,避免了單繼承的侷限性。

區別:繼承---執行緒程式碼存放在Thread子類run方法中。

          實現---執行緒程式碼存放在介面子類run方法中。

多執行緒安全問題:  當多條語句在操作同一個執行緒共享資料時,一個執行緒對多條語句只執行了一部分,還沒有執行完,另一個執行緒參與進來執行時,導致共享資料的錯誤。

Java解決多執行緒的安全問題的方法:同步程式碼塊/同步函式

 Object obj=new Object();

 synchronized(物件){}

哪些程式碼需要放進同步程式碼塊中:

    明確哪些程式碼是多執行緒執行程式碼

    明確共享資料

    明確多執行緒執行程式碼中哪些語句是操作共享資料的

同步函式使用的鎖是this

靜態同步函式,使用的鎖是該方法所在類的位元組碼檔案物件  類名.class(靜態方法中不可以定義this 靜態進記憶體 記憶體中沒有本類物件 但是一定有該類對應的位元組碼檔案物件 所以該物件的型別是Class)

同步程式碼塊

同步函式

同步函式

物件如同鎖,持有鎖的執行緒可以在同步中執行,沒有持有鎖的執行緒即使獲取了cpu的執行權,也進不去,因為沒有獲取鎖

同步的前提:必須要有兩個或者兩個以上的執行緒,必須是多個執行緒使用一個鎖

雖然同步程式碼塊解決了多執行緒的安全問題,但多個執行緒都需要判斷鎖,較為消耗資源。

死鎖:同步中含有同步

賣票:

public class TicketSale {

	public static void main(String[] args) {
		Ticket t1=new Ticket();
		Ticket t2=new Ticket();
		Ticket t3=new Ticket();
		Ticket t4=new Ticket();
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}

}
class Ticket extends Thread
{
	private static int tick=100;
	public void run()
	{
		while(tick>0)
		{
		    System.out.println(currentThread().getName()+"----"+tick--);
		}
	}
}
public class TicketSale {

	public static void main(String[] args) {
		Ticket t=new Ticket();
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
		new Thread(t).start();
	}

}
class Ticket implements Runnable
{
	private int tick=100;
        Object obj=new Object();
        public void run()
	{
		while(true)
		{
                     synchronized(obj)
                     {
                         if(tick>0)
                         {
                            System.out.println(Thread.currentThread().getName()+"----"+tick--);	
                         }
                     }	
		}
	}
}

多執行緒通訊: 多個執行緒在操作同一個資源,但是操作的動作不同

wait() nitify() notifyAll()

都是用在同步中,因為要對持有監視器(鎖)的執行緒操作。只有同步才具有鎖。

為什麼這些方法定義在Object類:因為這些方法在操作同步中執行緒時,都必須要標識他們所操作執行緒只有的鎖,只有同一個鎖上的被等待執行緒,才可以被同一個鎖上的notify喚醒,不可以對不同鎖中的執行緒進行喚醒。

而鎖可以是任意物件,所以可以被任意物件呼叫的方法定義在Object類中

優化:

生產者消費者:

多個生產者多個消費者

1.在判斷flag時,用While不用if(每次被喚醒應重新判斷flag 可能會導致生產兩個 消費一個等不匹配情況,)

2.應使用notifyAll();(用notify可能導致所有執行緒都wait()。)

JDK1.5 提供了多執行緒升級方案

將同步Synchronized替換成顯式Lock操作,將Object中的wait,notify,notifyALL替換成了Condition物件,該物件可以Lock鎖進行獲取,可以實現本方執行緒只喚醒對方執行緒的操作。

相關介面:Condition Lock

執行緒停止:

守護執行緒(後臺執行緒):噹噹前執行緒都為守護執行緒時,自動結束。

Join:等待執行緒結束

27.String

字串特點:一旦被初始化,就不可以被改變。存在於常量池。

String使用private final char value[ ]實現字串的儲存,也就是說String建立物件之後不能夠再次修改此物件中儲存的字串內容

String s="abc";//s1是一個類型別變數,"abc"是一個物件

s="123"; //此時"abc"這個物件的內容並沒有改變,只是s這個引用指向了另一個物件,即"123"


String類中重寫了equals方法用於比較兩個字串的內容是否相等。(Java中也有其他類對equals進行了重寫)

           一般情況     String類重寫
==     比較記憶體地址     ------
equals    比較記憶體地址    比較內容
public class sss {
	public static void main(String []args)
	{
		String s1="aaa";
                String s2="aaa";
                String s3=new String("aaa");
                //s1和s3的區別
                  s1在記憶體中有一個物件
                  s2在記憶體中有兩個物件
                System.out.println(s1==s2);//true  指向的是同一個物件
                System.out.println(s1==s3); //false  不是一個物件 記憶體地址不同
                System.out.println(s1.equals(s3));//true   不是一個物件,但內容相同
         }
}

字串常用操作方法:

1.字串去頭尾空格:

2.字串反轉(或部分反轉):

3.字串個數

4.獲取最大相同字串

StringBuffer:

StringBuilder:單執行緒使用StringBuilder可提高效率

28.包裝類

自動裝箱拆箱:

29.集合

集合用來儲存物件(記憶體地址),長度是可變的,可以儲存不同型別物件。

Collection---List Set

List--- ArrayList LinkedList Vector

Set--- HashSet TreeSet

Iterator介面 迭代器:

30.List集合

元素是有序的,可以重複,集合有角標。

ArrayList:

LinkedList:

封裝LinkedList到自己的類中:

佇列/堆疊

Vector:

31.Set集合

元素無序(存入和取出的順序不一定一致),且元素不能重複。

HashSet:

底層資料結構為雜湊表,集合中元素的存的順序為元素雜湊值大小順序。如果雜湊值相同,在判斷是否是同一物件(equals()),不是則順延存入。

例子:

TreeSet

可以對Set集合中的元素進行排序,按ASCII順序。 底層資料結構為二叉樹

(1)物件類中自帶比較

存物件時,需要實現Comparable介面中的唯一一個函式 compareTo()方法,並定義返回的int型,

返回負數,零,正數 分別代表 曉宇 等於 大於。等於時物件相等,不存入。主要條件相同時,判斷次要條件。

如果想要實現按存入順序取出的話,compareTo方法就一直返回正數。取出時預設從小到大取。

(2)TreeSet建構函式中傳入比較器

定義自定義比較器類實現Comparator

物件和容器都有排序時,以容器的排序為主。

32.集合泛型

集合中使用泛型來約束集合中要儲存的類型別

當類中要操作的引用資料型別不確定的時候,定義泛型類。(靜態方法不能訪問類上定義的型別,因為靜態方法存在時,類還不存在)

方法也可以定義泛型。泛型放在返回值前面

介面也可以定義泛型

泛型限定

33.Map

HashMap

keySet:取出所有鍵存到Set中

entrySet:取出每一條資料對映關係存到Set中

相關推薦

Java core 基礎概念

JAVA學習中記錄的一些筆記,不斷更新 目錄 1.識別符號 2.變數 5.語句 8.陣列 16.繼承 20.介面 21.多型 24.異常 25.包 29.集合

[18/11/7] Java基礎概念

java語言的優勢是跨平臺 ,計算機界的英語,是IT行業的第一大語言                   特點是多執行緒 分散式 健壯性 面向物件 java和JavaScript的關係 雷鋒和雷峰塔的關係 或卡巴斯基

Java註解基礎概念總結

註解的概念 註解(Annotation),也叫元資料(Metadata),是Java5的新特性,JDK5引入了Metadata很容易的就能夠呼叫Annotations。註解與類、介面、列舉在同一個層次,並可以應用於包、型別、構造方法、方法、成員變數、引數、本地變數的宣告中,用來對這些元素進行說明註釋。 註

RabbitMQ訊息佇列入門篇(環境配置+Java例項+基礎概念

一、訊息佇列使用場景或者其好處 訊息佇列一般是在專案中,將一些無需即時返回且耗時的操作提取出來,進行了非同步處理,而這種非同步處理的方式大大的節省了伺服器的請求響應時間,從而提高了系統的吞吐量。 在專案啟動之初來預測將來專案會碰到什麼需求,是極其困難的。訊息

Java面試基礎概念總結

前段時間由於忙於修改論文,就好久沒更新部落格,現在準備重新開始記錄自己的屌絲人生。哈哈 面向物件軟體開發的優點有哪些? 答:開發模組化,更易維護和修改;程式碼之間可以複用;增強程式碼的可靠性、靈活

JAVA一些基礎概念

JRE為Java Runtime Environment的簡稱,Java Runtime Environment(包括Java Plug-in)是Sun的產品,包括兩部分:Java Runtime Environment和Java Plug-in。JavaRuntimeEnvironment(JRE)是可

java 基礎概念 -- 數組與內存控制

nbsp 堆內存 數組元素 art pan popu ace article pac 問題1: Java在聲明數組的過程中,是怎樣分配內存的? 在棧內存中 建一個數組變量,再在堆內存中 建一個 數組對象。至於詳細的內存分配細節,還得看 該初始化是 數組動態初始化 還是

粵嵌java培訓第一天筆記-java基礎概念

ont 類型 運算符 按位或 次循環 規則 是否 支持 har 一、二進制數   1、最高位為0,表示正數;最高位為1,表示負數。   2、相應的負數與正數之間進行轉換方式:通過補碼方式進行轉換,即:取反再加1。     例如:0000 0001 表示 +1;通過對 000

Java基礎概念收集

安全性 當前 javaweb query fig 響應 請求 私有 引用 Javaweb階段 Ajax你以前用過麽?簡單介紹一下 AJAX = 異步 JavaScript 和 XML。 AJAX 是一種用於創建快速動態網頁的技術。 通過在後臺與服務器進行少量數據交換,AJA

java基礎概念

ipc javaee 目錄 基本數據類型 字符串 註釋 單行 公司 開發工具 一、Java語言從何而來?發展平臺版本   Java語言最初是屬於SUN公司的產品,始於1994年   Java語言之父:詹姆斯高斯林   Java語言平臺版本: JavaSE:

Java反射之基礎概念

ide 包名 void java 類名 super 運行 生成 over 0.實例準備 package com.blueStarWei.invoke; public class Student { private String name; pu

菠菜源碼搭建與java基礎概念

意義 硬件 protect str 數值類型 cto 尋找 nta java基礎 1.java jvm的功能:通過 ClassLoader 尋找和裝載 class 文件?? ??? ??? ?? 解釋字節碼成為指令並執行,提供 class 文件的運行環境?? ??? ???

h--5--菠菜源碼下載java基礎概念

應用程序 虛擬 clas 不同 world 空間 ase 即時編譯 rac 1.第一個應用程序:Hello World!package my.xkyy.lsc;public class HelloWorld {public static void main(String[]

Java 多執行緒設計模式之基礎概念

順序、併發與並行 順序 用於表示多個操作“依次處理”。比如把十個操作交給一個人來處理時,這個人要一個一個地按順序來處理 並行 用於標識多個操作“同時處理”。比如十個操作分給兩個人處理時,這兩個人就會並行來處理。 併發 相對於順序和並行來說比較抽象,用於表示“將一個

Java面試題:面向物件,類載入器,JDBC, Spring 基礎概念

    1. 為什麼說Java是一門平臺無關語言? 平臺無關實際的含義是“一次編寫到處執行”。Java 能夠做到是因為它的位元組碼(byte code)可以執行在任何作業系統上,與底層系統無關。 2. 為什麼 Java 不是100%面向物件? Java

Java併發程式設計1.1—基礎概念

併發程式設計1.1—基礎概念 1.CPU核心數和執行緒數的關係和區別 簡單的說: CPU核心數:執行緒數=1:1 ;使用了超執行緒技術後—> 1:2。 詳細解釋: CPU核心數指物理上,也就是硬體上存在著幾個核心。比如,雙核就是包括2個相對獨立的CPU核

Java NIO筆記之IO基礎概念

1.緩衝區 緩衝區是所有IO的基礎,”輸入/輸出”就是將資料移進或移除緩衝區。程序IO操作的執行也是向作業系統傳送請求,讓它要麼將緩衝區的資料排幹(寫),要麼將緩衝區的填滿資料(讀)。 圖 1-1 簡單描述了資料從外部磁碟向執行中的程序的記憶體區

java基礎概念finalize、final和finaly的區別

final: 1.應用於基本型別變數時,該變數的值無法改變 2.應用於引用變數時,該引用變數不能只想堆上的任何其他物件 3.應用於方法時,該方法不能被重寫 4.應用於類時,該類不能被繼承finally

Java基礎概念之JSE JME JEE JDK JRE JVM

JSE. JME,JEE,JDK,JRE SE:stands for "Standard Edition" EE:stands for "Enterprise Edition" JDK: stands for “Java Development Kit" JRE: stan

黑馬程式設計師--Java學習日記之基礎知識(思維導圖&基礎概念)

------- android培訓、java培訓、期待與您交流! ---------- 什麼是常量      在程式執行的過程中其值不可以發生改變  Java中常量的分類