最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?NIO?Buffer實(shí)現(xiàn)原理詳解

 更新時(shí)間:2021年11月30日 09:19:39   作者:興趣使然的草帽路飛  
本篇文章主要對(duì)NIO核心三件套:緩沖區(qū)(Buffer)、選擇器?(Selector)和通道(Channel),其中之一的緩沖區(qū)Buffer實(shí)現(xiàn)原理的學(xué)習(xí)總結(jié)。感興趣的小伙伴可以了解一下

1、Buffer的繼承體系

如上圖所示,對(duì)于Java中的所有基本類型,都會(huì)有一個(gè)具體的Buffer類型與之對(duì)應(yīng),一般我們最經(jīng)常使用的是ByteBuffer。

2、Buffer的操作API使用案例

舉一個(gè)IntBuffer的使用案例:

/**
 * @author csp
 * @date 2021-11-26 3:51 下午
 */
public class IntBufferDemo {
    public static void main(String[] args) {
        // 分配新的int緩沖區(qū),參數(shù)為緩沖區(qū)容量。
        // 新緩沖區(qū)的當(dāng)前位置為0,其界限(限制位置)為其容量。它具有一個(gè)底層實(shí)現(xiàn)數(shù)組,其數(shù)組偏移量為0。
        IntBuffer buffer = IntBuffer.allocate(8);

        for (int i = 0; i < buffer.capacity(); i++) {
            int j = 2 * (i + 1);
            // 將給定整數(shù)寫(xiě)入此緩沖區(qū)的當(dāng)前位置,當(dāng)前位置遞增。
            buffer.put(j);
        }

        // 重設(shè)此緩沖區(qū),將限制位置設(shè)置為當(dāng)前位置,然后將當(dāng)前位置設(shè)置為0。
        buffer.flip();

        // 查看在當(dāng)前位置和限制位置之間是否有元素:
        while (buffer.hasRemaining()){
            // 讀取此緩沖區(qū)當(dāng)前位置的整數(shù),然后當(dāng)前位置遞增。
            int j = buffer.get();
            System.out.print(j + " ");
        }
    }
}

運(yùn)行結(jié)果:

2 4 6 8 10 12 14 16

從該案例中可以看出,其實(shí)本質(zhì)上這里就是把IntBuffer看作成一個(gè)數(shù)組容器使用,可以通過(guò)get方法向容器中讀取數(shù)據(jù)(put方法向容器中寫(xiě)入數(shù)據(jù))。

3、Buffer的基本原理

Buffer緩沖區(qū)本質(zhì)上就是一個(gè)特殊類型的數(shù)組對(duì)象,與普通數(shù)組不同的地方在于,其內(nèi)置了一些機(jī)制,能夠跟蹤和記錄緩沖區(qū)的狀態(tài)變化情況,如果我們使用get()方法從緩沖區(qū)獲取數(shù)據(jù)或者使用put()方法把數(shù)據(jù)寫(xiě)入緩沖區(qū),都會(huì)引起緩沖區(qū)狀態(tài)的變化。

Buffer內(nèi)置數(shù)組實(shí)現(xiàn)狀態(tài)變化與追蹤的原理,本質(zhì)上是通過(guò)三個(gè)字段變量實(shí)現(xiàn)的:

  • position:指定下一個(gè)將要被寫(xiě)入或者讀取的元素索引,它的值由get()/put()方法自動(dòng)更新,在新創(chuàng)建一個(gè)Buffer對(duì)象時(shí),position被初始化為0。
  • limit:指定還有多少數(shù)據(jù)需要取出(在從緩沖區(qū)寫(xiě)入通道時(shí)),或者還有多少空間可以放入數(shù)據(jù)(在從通道讀入緩沖區(qū)時(shí))。
  • capacity:指定了可以存儲(chǔ)在緩沖區(qū)中的最大數(shù)據(jù)容量,實(shí)際上,它指定了底層數(shù)組的大小,或者至少是指定了準(zhǔn)許我們 使用的底層數(shù)組的容量。

源碼如下:

public abstract class Buffer {
    // 三個(gè)字段屬性之間的數(shù)值關(guān)系:0 <= position <= limit <= capacity
    private int position = 0;
    private int limit;
    private int capacity;
    ...
}

如果我們創(chuàng)建一個(gè)新的容量大小為10的ByteBuffer對(duì)象,在初始化的時(shí)候,position設(shè)置為0,limit和 capacity設(shè)置為10,在以后使用ByteBuffer對(duì)象過(guò)程中,capacity的值不會(huì)再發(fā)生變化,而其他兩個(gè)將會(huì)隨著使用而變化。

我們來(lái)看一個(gè)例子:

準(zhǔn)備一個(gè)txt文檔,存放在項(xiàng)目目錄下,文檔中輸入以下內(nèi)容:

Java

我們用一段代碼來(lái)驗(yàn)證position、limit和capacity這三個(gè)值的變 化過(guò)程,代碼如下:

/**
 * @author csp
 * @date 2021-11-26 4:09 下午
 */
public class BufferDemo {

    public static void main(String[] args) throws IOException {
        FileInputStream fileInputStream = new FileInputStream("/Users/csp/IdeaProjects/netty-study/test.txt");

        // 創(chuàng)建文件的操作管道
        FileChannel channel = fileInputStream.getChannel();

        // 分配一個(gè)容量為10的緩沖區(qū)(本質(zhì)上就是一個(gè)容量為10的byte數(shù)組)
        ByteBuffer buffer = ByteBuffer.allocate(10);

        output("初始化", buffer);
        channel.read(buffer);// 從管道將數(shù)據(jù)讀取到buffer容器中
        output("調(diào)用read()", buffer);

        // 準(zhǔn)備操作之前,先鎖定操作范圍:
        buffer.flip();
        output("調(diào)用flip()", buffer);

        // 判斷有沒(méi)有可讀數(shù)據(jù)
        while (buffer.remaining() > 0){
            byte b = buffer.get();
        }
        output("調(diào)用get()", buffer);

        // 可以理解為解鎖
        buffer.clear();
        output("調(diào)用clear()", buffer);

        // 最后把管道關(guān)閉
        fileInputStream.close();
    }

    /**
     * 將緩沖區(qū)里的實(shí)時(shí)狀態(tài)打印出來(lái)
     *
     * @param step
     * @param buffer
     */
    public static void output(String step, Buffer buffer) {
        System.out.println(step + " : ");
        // 容量(數(shù)組大小):
        System.out.print("capacity" + buffer.capacity() + " , ");
        // 當(dāng)前操作數(shù)據(jù)所在的位置,也可以叫做游標(biāo):
        System.out.print("position" + buffer.position() + " , ");
        // 鎖定值,flip,數(shù)據(jù)操作范圍索引只能在 position - limit 之間:
        System.out.println("limit" + buffer.limit());
        System.out.println();
    }
}

輸出結(jié)果如下:

初始化 :?

capacity10 , position0 , limit10

調(diào)用read() :?

capacity10 , position4 , limit10

調(diào)用flip() :?

capacity10 , position0 , limit4

調(diào)用get() :?

capacity10 , position4 , limit4

調(diào)用clear() :?

capacity10 , position0 , limit10

下面我們來(lái)對(duì)上面代碼的執(zhí)行結(jié)果進(jìn)行圖解分析(圍繞position、limit、capacity三個(gè)字段值):

// 分配一個(gè)容量為10的緩沖區(qū)(本質(zhì)上就是一個(gè)容量為10的byte數(shù)組)
ByteBuffer buffer = ByteBuffer.allocate(10);

// 從管道將數(shù)據(jù)讀取到buffer容器中 
channel.read(buffer);
output("調(diào)用read()", buffer);

首先從通道中讀取一些數(shù)據(jù)到緩沖區(qū)中(注意從通道讀取數(shù)據(jù),相當(dāng)于往緩沖區(qū)寫(xiě)入數(shù)據(jù))。如果讀取4個(gè)字節(jié)的數(shù)據(jù),則此時(shí) position的值為4,即下一個(gè)將要被寫(xiě)入的字節(jié)索引為4,而limit仍然是10,如下圖所示。

// 準(zhǔn)備操作之前,先鎖定操作范圍:
buffer.flip();
output("調(diào)用flip()", buffer);

下一步把讀取的數(shù)據(jù)寫(xiě)入輸出通道,相當(dāng)于從緩沖區(qū)中讀取數(shù)據(jù),在此之前,必須調(diào)用flip()方法。該方法將會(huì)完成以下兩件事情:

  • 一是把limit設(shè)置為當(dāng)前的position值。
  • 二是把position設(shè)置為 0。

由于position被設(shè)置為0,所以可以保證在下一步輸出時(shí)讀取的是緩沖區(qū)的第一個(gè)字節(jié),而limit被設(shè)置為當(dāng)前的position,可以保證讀取的數(shù)據(jù)正好是之前寫(xiě)入緩沖區(qū)的數(shù)據(jù),如下圖所示。

// 判斷有沒(méi)有可讀數(shù)據(jù)
while (buffer.remaining() > 0){
    byte b = buffer.get();
}
output("調(diào)用get()", buffer);

調(diào)用get()方法從緩沖區(qū)中讀取數(shù)據(jù)寫(xiě)入輸出通道,這會(huì)導(dǎo)致 position的增加而limit保持不變,但position不會(huì)超過(guò)limit的值, 所以在讀取之前寫(xiě)入緩沖區(qū)的4字節(jié)之后,position和limit的值都為 4,如下圖所示。

// 可以理解為解鎖
buffer.clear();
output("調(diào)用clear()", buffer);

// 最后把管道關(guān)閉
fileInputStream.close();

在從緩沖區(qū)中讀取數(shù)據(jù)完畢后,limit的值仍然保持在調(diào)用flip()方法時(shí)的值,調(diào)用clear()方法能夠把所有的狀態(tài)變化設(shè)置為初始化時(shí)的值,最后關(guān)閉流,如下圖所示。

通過(guò)上述案例,更能突出Buffer是一個(gè)特殊的數(shù)組容器,與普通數(shù)組區(qū)別就在于其內(nèi)置三個(gè) “指針變量”:position、limit、capacity 用于跟蹤和記錄緩沖區(qū)的狀態(tài)變化情況!

4、allocate方法初始化一個(gè)指定容量大小的緩沖區(qū)

在創(chuàng)建一個(gè)緩沖區(qū)對(duì)象時(shí),會(huì)調(diào)用靜態(tài)方法allocate()來(lái)指定緩沖區(qū)的容量,其實(shí)調(diào)用allocate()方法相當(dāng)于創(chuàng)建了一個(gè)指定大小的數(shù)組,并把它包裝為緩沖區(qū)對(duì)象。

allocate()源碼如下:

// 位于ByteBuffer下
public static ByteBuffer allocate(int capacity) {
    if (capacity < 0)
        throw new IllegalArgumentException();
    // 新建一個(gè)ByteBuffer數(shù)組對(duì)象,容量為:capacity,limit參數(shù)值為:capacity
    return new HeapByteBuffer(capacity, capacity);
}

// 位于HeapByteBuffer下,父類為:ByteBuffer
HeapByteBuffer(int cap, int lim) {
    super(-1, 0, lim, cap, new byte[cap], 0);// 調(diào)用ByteBuffer的有參構(gòu)造函數(shù)
}

// 位于ByteBuffer下,父類為:Buffer
ByteBuffer(int mark, int pos, int lim, int cap,
                 byte[] hb, int offset){
    super(mark, pos, lim, cap);// 調(diào)用 Buffer構(gòu)造函數(shù)
    this.hb = hb;// final byte[] hb; 不可變的byte數(shù)組
    this.offset = offset;// 偏移量
}

// Buffer構(gòu)造函數(shù)
Buffer(int mark, int pos, int lim, int cap) {
    if (cap < 0)
        throw new IllegalArgumentException("Negative capacity: " + cap);
    this.capacity = cap;// 數(shù)組容量
    limit(lim);// 數(shù)組的了limit
    position(pos);// 數(shù)組的positio
    if (mark >= 0) {
        if (mark > pos)
            throw new IllegalArgumentException("mark > position: ("
                                               + mark + " > " + pos + ")");
        this.mark = mark;
    }
}

本質(zhì)上等同于如下代碼:

// 初始化一個(gè)byte數(shù)組
byte[] bytes = new byte[10];
// 將該數(shù)組包裝給ByteBuffer
ByteBuffer buffer = ByteBuffer.wrap(bytes);

5、slice方法緩沖區(qū)分片

Java NIO中,可以根據(jù)先用的緩沖區(qū)Buffer對(duì)象創(chuàng)建一個(gè)子緩沖區(qū)。即,在現(xiàn)有緩沖區(qū)上切出一片作為一個(gè)新的緩沖區(qū),但現(xiàn)有的緩沖區(qū)與創(chuàng)建的子緩沖區(qū)在底層數(shù)組層面上是數(shù)據(jù)共享的。

示例代碼如下所示:

/**
 * @author csp
 * @date 2021-11-28 6:20 下午
 */
public class BufferSlice {
    public static void main(String[] args) {
        ByteBuffer buffer = ByteBuffer.allocate(10);

        // 向緩沖區(qū)中put數(shù)據(jù): 0~9
        for (int i = 0; i < buffer.capacity(); i++) {
            buffer.put((byte) i);
        }

        // 創(chuàng)建子緩沖區(qū):即從數(shù)組下標(biāo)為3的位置到下標(biāo)為7的位置
        buffer.position(3);
        buffer.limit(7);
        ByteBuffer slice = buffer.slice();

        // 改變子緩沖區(qū)的內(nèi)容
        for (int i = 0; i < slice.capacity(); i++) {
            byte b = slice.get(i);
            b *= 10;
            slice.put(i, b);
        }

        // position和limit恢復(fù)到初始位置:
        buffer.position(0);
        buffer.limit(buffer.capacity());

        // 輸出buffer容器中的內(nèi)容:
        while (buffer.hasRemaining()) {
            System.out.println(buffer.get());
        }
    }
}

在該示例中,分配了一個(gè)容量大小為10的緩沖區(qū),并在其中放入 了數(shù)據(jù)0~9,而在該緩沖區(qū)基礎(chǔ)上又創(chuàng)建了一個(gè)子緩沖區(qū),并改變子緩沖區(qū)中的內(nèi)容,從最后輸出的結(jié)果來(lái)看,只有子緩沖區(qū)“可見(jiàn)的” 那部分?jǐn)?shù)據(jù)發(fā)生了變化,并且說(shuō)明子緩沖區(qū)與原緩沖區(qū)是數(shù)據(jù)共享 的,輸出結(jié)果如下所示:

0

1

2

30

40

50

60

7

8

9

6、只讀緩沖區(qū)

只讀緩沖區(qū),顧名思義就是只可以從緩沖區(qū)中讀取數(shù)據(jù),而不可以向其中寫(xiě)入數(shù)據(jù)。

將現(xiàn)有緩沖區(qū)讓其調(diào)用asReadOnlyBuffer()方法,使其轉(zhuǎn)換成只讀緩沖區(qū)。這個(gè)方法返回一個(gè)與原緩沖區(qū)完全相同的緩沖區(qū),并與原緩沖區(qū)共享數(shù)據(jù),只不過(guò)它是只讀的。如果原緩沖區(qū)的 內(nèi)容發(fā)生了變化,只讀緩沖區(qū)的內(nèi)容也隨之發(fā)生變化。

示例代碼如下所示:

/**
 * @author csp
 * @date 2021-11-28 6:33 下午
 */
public class ReadOnlyBuffer {
    public static void main(String[] args) {
        // 初始化一個(gè)容量為10的緩沖區(qū)
        ByteBuffer buffer = ByteBuffer.allocate(10);

        // 向緩沖區(qū)中put數(shù)據(jù): 0~9
        for (int i = 0; i < buffer.capacity(); i++) {
            buffer.put((byte) i);
        }

        // 將該緩沖區(qū)轉(zhuǎn)變?yōu)橹蛔x緩沖區(qū)
        ByteBuffer readOnlyBuffer = buffer.asReadOnlyBuffer();

        // 由于buffer和readOnlyBuffer本質(zhì)上共享一個(gè)byte[]數(shù)組對(duì)象,
        // 所以,改變buffer緩沖區(qū)的內(nèi)容時(shí),會(huì)導(dǎo)致只讀緩沖區(qū)readOnlyBuffer的內(nèi)容也隨著改變。
        for (int i = 0; i < buffer.capacity(); i++) {
            byte b = buffer.get(i);
            b *= 10;
            buffer.put(i, b);
        }

        // position和limit恢復(fù)到初始位置:
        readOnlyBuffer.position(0);
        readOnlyBuffer.limit(buffer.capacity());

        // 輸出readOnlyBuffer容器中的內(nèi)容:
        while (readOnlyBuffer.hasRemaining()) {
            System.out.println(readOnlyBuffer.get());
        }
    }
}

輸出結(jié)果如下:

0

10

20

30

40

50

60

70

80

90

如果嘗試修改只讀緩沖區(qū)的內(nèi)容,則會(huì)報(bào) ReadOnlyBufferException異常。只可以把常規(guī)緩沖區(qū)轉(zhuǎn)換為只讀緩沖區(qū),而不能將只讀緩沖區(qū)轉(zhuǎn)換為 可寫(xiě)的緩沖區(qū)。

7、直接緩沖區(qū)

參考文章:Java NIO學(xué)習(xí)篇之直接緩沖區(qū)和非直接緩沖區(qū)

對(duì)于直接緩沖區(qū)的定義,《深入理解Java虛擬機(jī)》這本書(shū)是這樣介紹的:

  • Java NIO字節(jié)緩沖區(qū)(ByteBuffer)要么是直接的,要么是非直接的。如果為直接字節(jié)緩沖區(qū),則java虛擬機(jī)會(huì)盡最大努力直接在此緩沖區(qū)上執(zhí)行本機(jī)的IO操作,也就是說(shuō),在每次調(diào)用基礎(chǔ)操作系統(tǒng)的一個(gè)本機(jī)IO操作前后,虛擬機(jī)都會(huì)盡量避免將內(nèi)核緩沖區(qū)內(nèi)容復(fù)制到用戶進(jìn)程緩沖區(qū)中,或者反過(guò)來(lái),盡量避免從用戶進(jìn)程緩沖區(qū)復(fù)制到內(nèi)核緩沖區(qū)中。
  • 直接緩沖區(qū)可以通過(guò)調(diào)用該緩沖區(qū)類的allocateDirect(int capacity) 方法創(chuàng)建,此方法返回的緩沖區(qū)進(jìn)行分配和取消分配所需的成本要高于非直接緩沖區(qū)。直接緩沖區(qū)的內(nèi)容駐留在垃圾回收堆之外,因此他們對(duì)應(yīng)用程序內(nèi)存(JVM內(nèi)存)需求不大。所以建議直接緩沖區(qū)要分配給那些大型,持久(就是緩沖區(qū)的數(shù)據(jù)會(huì)被重復(fù)利用)的緩沖區(qū),一般情況下,最好僅在直接緩沖區(qū)能在程序性能帶來(lái)非常明顯的好處時(shí)才分配它們。
  • 直接緩沖區(qū)還可以通過(guò)FileCHannel的map()方法將文件區(qū)域映射到內(nèi)存中來(lái)創(chuàng)建,該方法返回MappedByteBuffer。Java平臺(tái)的實(shí)現(xiàn)有助于通過(guò)JNI本地代碼創(chuàng)建直接字節(jié)緩沖區(qū),如果以上這些緩沖區(qū)中某個(gè)緩沖區(qū)實(shí)例指向的是不可訪問(wèn)的內(nèi)存區(qū)域,則試圖方法該區(qū)域不會(huì)更改緩沖區(qū)的內(nèi)容,并且會(huì)在訪問(wèn)期間或者稍后的某個(gè)時(shí)間導(dǎo)致報(bào)出不確定性異常。
  • 字節(jié)緩沖區(qū)是直接緩沖區(qū)還是非直接緩沖區(qū)可以通過(guò)調(diào)用其isDIrect()方法來(lái)判斷。

案例代碼:

/**
 * @author csp
 * @date 2021-11-28 7:07 下午
 */
public class DirectBuffer {
    public static void main(String[] args) throws IOException {
        // 從磁盤(pán)中讀取test.txt文件內(nèi)容
        FileInputStream fileInputStream = new FileInputStream("/Users/csp/IdeaProjects/netty-study/test.txt");
        // 創(chuàng)建文件的操作管道
        FileChannel inputStreamChannel = fileInputStream.getChannel();

        // 把讀取的內(nèi)容寫(xiě)入到新的文件中
        FileOutputStream fileOutputStream = new FileOutputStream("/Users/csp/IdeaProjects/netty-study/test2.txt");
        FileChannel outputStreamChannel = fileOutputStream.getChannel();
        
        // 創(chuàng)建直接緩沖區(qū)
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);
        
        while (true){
            byteBuffer.clear();

            int read = inputStreamChannel.read(byteBuffer);
            
            if (read == -1){
                break;
            }
            
            byteBuffer.flip();
            
            outputStreamChannel.write(byteBuffer);
        }
    }
}

要分配 直接緩沖區(qū),需要調(diào)用allocateDirect()方法,而不是allocate()方 法,使用方式與普通緩沖區(qū)并無(wú)區(qū)別。

8、內(nèi)存映射

內(nèi)存映射是一種讀和寫(xiě)文件數(shù)據(jù)的方法,可以比常規(guī)的基于流或者基于通道的I/O快得多。內(nèi)存映射文件I/O通過(guò)使文件中的數(shù)據(jù)表現(xiàn)為內(nèi)存數(shù)組的內(nèi)容來(lái)完成,這初聽(tīng)起來(lái)似乎不過(guò)就是將整個(gè)文件讀到內(nèi)存中,但事實(shí)上并不是這樣的。一般來(lái)說(shuō),只有文件中實(shí)際讀取或 寫(xiě)入的部分才會(huì)映射到內(nèi)存中。來(lái)看下面的示例代碼:

/**
 * @author csp
 * @date 2021-11-28 7:16 下午
 */
public class MapperBuffer {
    static private final int start = 0;
    static private final int size = 10;

    public static void main(String[] args) throws IOException {
        RandomAccessFile randomAccessFile = new RandomAccessFile("/Users/csp/IdeaProjects/netty-study/test.txt", "rw");

        FileChannel channel = randomAccessFile.getChannel();

        // 把緩沖區(qū)跟文件系統(tǒng)進(jìn)行一個(gè)映射關(guān)聯(lián),只要操作緩沖區(qū)里面的內(nèi)容,文件內(nèi)容也會(huì)隨之改變
        MappedByteBuffer mappedByteBuffer = channel.map(FileChannel.MapMode.READ_WRITE, start, size);

        mappedByteBuffer.put(4, (byte) 97);// a
        mappedByteBuffer.put(5, (byte) 122);// z

        randomAccessFile.close();
    }
}

原來(lái)test.txt文件內(nèi)容為:

Java

執(zhí)行完上述代碼之后,test.txt文件內(nèi)容更新為:

Javaaz?

以上就是Java NIO Buffer實(shí)現(xiàn)原理詳解的詳細(xì)內(nèi)容,更多關(guān)于Java NIO Buffer的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • maven模塊化開(kāi)發(fā)部署實(shí)現(xiàn)方案

    maven模塊化開(kāi)發(fā)部署實(shí)現(xiàn)方案

    有些用戶有定制化需求,需要添加新的模塊功能,因此需要平臺(tái)主體功能迭代的同時(shí),非主體功能和定制化功能插件化,本文給大家介紹maven模塊化開(kāi)發(fā)部署實(shí)現(xiàn)方案,感興趣的朋友一起看看吧
    2024-01-01
  • JAVA中JNI的簡(jiǎn)單使用分享

    JAVA中JNI的簡(jiǎn)單使用分享

    這篇文章介紹了JAVA中JNI的簡(jiǎn)單使用,有需要的朋友可以參考一下
    2013-10-10
  • MyBatis方法重載的陷阱及解決方案

    MyBatis方法重載的陷阱及解決方案

    在使用 MyBatis 進(jìn)行開(kāi)發(fā)時(shí),尤其是使用注解模式(如 @Select、@Insert 等)時(shí),開(kāi)發(fā)者常常會(huì)遇到這樣一個(gè)問(wèn)題:為什么我的方法重載不能正常工作?這篇文章將深入探討 MyBatis 的這個(gè)特性及如何規(guī)避相關(guān)的坑,需要的朋友可以參考下
    2024-09-09
  • 深度剖析Java中的內(nèi)存原型及工作原理

    深度剖析Java中的內(nèi)存原型及工作原理

    這篇文章主要介紹了深度剖析Java中的內(nèi)存原型及工作原理,本文講解了java虛擬機(jī)內(nèi)存原型、常量池、Java內(nèi)存分配中的棧、Java內(nèi)存分配中的堆等內(nèi)容,需要的朋友可以參考下
    2015-01-01
  • 整理java讀書(shū)筆記十五之java中的內(nèi)部類

    整理java讀書(shū)筆記十五之java中的內(nèi)部類

    內(nèi)部類是指在一個(gè)外部類的內(nèi)部再定義一個(gè)類。類名不需要和文件夾相同。本文給大家分享java讀書(shū)筆記十五之java中的內(nèi)部類,對(duì)java讀書(shū)筆記相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧
    2015-12-12
  • Java 中HashCode作用_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java 中HashCode作用_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了Java 中HashCode作用以及hashcode對(duì)于一個(gè)對(duì)象的重要性,對(duì)java中hashcode的作用相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧
    2017-05-05
  • 使用SpringBoot和JPA實(shí)現(xiàn)批量處理新增、修改

    使用SpringBoot和JPA實(shí)現(xiàn)批量處理新增、修改

    最近項(xiàng)目需要在JPA中使用ID進(jìn)行批量更新,所以下面這篇文章主要給大家介紹了關(guān)于使用SpringBoot和JPA實(shí)現(xiàn)批量處理新增、修改的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • Spring?Security認(rèn)證的完整流程記錄

    Spring?Security認(rèn)證的完整流程記錄

    相信大伙對(duì)Spring Security這個(gè)框架又愛(ài)又恨,愛(ài)它的強(qiáng)大,恨它的繁瑣,下面這篇文章主要給大家介紹了關(guān)于Spring?Security認(rèn)證流程的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-01-01
  • java編程多線程并發(fā)處理實(shí)例解析

    java編程多線程并發(fā)處理實(shí)例解析

    這篇文章主要介紹了java編程多線程并發(fā)處理實(shí)例解析,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • 淺談Java安全之C3P0鏈利用與分析

    淺談Java安全之C3P0鏈利用與分析

    本文主要介紹了淺談Java安全之C3P0鏈利用與分析,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01

最新評(píng)論

会同县| 夹江县| 山东省| 泰顺县| 满洲里市| 靖远县| 枝江市| 富蕴县| 东辽县| 山东省| 张家港市| 广德县| 东阳市| 济宁市| 伊川县| 南雄市| 和平县| 兴安县| 海丰县| 金坛市| 泰和县| 通化市| 什邡市| 长宁县| 福贡县| 平乐县| 巴彦淖尔市| 麻城市| 鄄城县| 龙游县| 忻城县| 尤溪县| 揭阳市| 大庆市| 元朗区| 双牌县| 阿瓦提县| 临邑县| 东城区| 宝兴县| 嫩江县|