當前位置:首頁 » 存儲配置 » java類的存儲

java類的存儲

發布時間: 2023-05-03 22:04:43

『壹』 在java類中如何實現信息的存儲


package com.ctx0331;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
* 實現文件的讀取和寫入
*
* @author Administrator
*
*/
public class FileUtil {

public static void main(String[] args) throws IOException {

byte[] datafile = loadFileData("./tempdata/abc.txt");
System.out.println(new String(datafile));

String str = "寫入文件";
String outpath = "./tempdata/out.txt";
saveDataToFile(outpath, str.getBytes());
}

/**
* 讀取指定路徑的文件內容
*
* @param fileName
* @return data
* @throws IOException
*/
public static byte[] loadFileData(String fileName) throws IOException {
byte[] data = new byte[1024];// 用於存儲讀取的文件內容
File file = new File(fileName);
if (file.exists()) {
FileInputStream fis = new FileInputStream(file);
fis.read(data);
fis.close();
} else {
System.out.println("文件不存在");
}
return data;
}

/**
* 向指定路徑的文件寫入data中的內容
*
* @param fileName
* @param data
* @throws IOException
*/
public static void saveDataToFile(String fileName, byte[] data)
throws IOException {
File file = new File(fileName);
if (!file.exists()) {// 文件不存在就創建
file.createNewFile();
}
FileOutputStream fos = new FileOutputStream(file);
fos.write(data);
fos.close();
}
}

『貳』 java中一個類的方法是怎麼存儲的

java內存分析:
都是將內存分為三塊
第一塊內存區域是:棧
第二塊內存區域是:堆
第三塊內存區域是:方法區
棧空間里裝的都是局部變數
堆空間里裝的都是new出來的東西,特殊的對象 (非static修飾的全局變數是特殊的對象,在堆內存區域內)
方法區里裝的都是基本類型常量和字元串常量、static修飾的全局變數、代碼

『叄』 JAVA中類中的方法存儲在什麼地方

類的實例方法在內存中是只有一份,不過肯定不會是第一個對象中,如果是第一個對象的話,那麼當第一個對象被銷毀的時候,那麼後面的對象就永遠無法調用了...
類的實例方法存在一個專門的區叫方法區,事實上類剛裝載的時候就被裝載好了,不過它們在"睡眠",只是這些方法必須當有對象產生的時候才會"蘇醒".(比如,一個輸出類的成員變數的方法,如果連對象都沒有,何來的輸出成員變數).所以,方法在裝載的時候就有了,但是不可用,因為它沒有指象任何一個對象。

『肆』 深入Java對象及元素的存儲區域


在JAVA平台上開發應用程序的時候,有一個很大的特點就是其是在應用程序運行的時候才建立對象。換句話說,在程序運行的時候,才會最終確定對象的歸屬,即對象應該存儲在什麼地方。由於存儲在不同的區域,其在性能上會有所不同。為此作為Java程序開發人員需要了解各個存儲區域的特點以及對性能的影響。然後再根據需要來調整應用程序的區域分配。總的來說,在操作系統中有五個地方可以用來保存應用程序運行中的數據。這類區域的特點以及對性能的影響分析如下。
存儲區域一:寄存器
雖然同在內存中,但是不同的區域由於用途不同,其性能也有所不同。如就拿Java應用程序來說,寄存器由於其處於處理器的內部,為此這個區域存取數據最快。跟內存中的其他存儲區域有著天壤之別。那麼我們把所有對象都放到這個區域內,不就可以提高Java應用程序的性能了嗎?理論上是如此,但是在現實中是行不通的。因為這個寄存器的數量是非常有限的。在內存中的寄存器區域是由編譯器根據需要來分配的。我們程序開發人員不能夠通過代碼來控制這個寄存器的分配。所以說,這第一個存儲區域寄存器,我們只能夠看看,而不能夠對其產生任何的影響。
存儲區域二:堆棧
對象的創建有兩種方式,一是在應用程序開發的過程中就創建對象;二是在程序運行的過程中要用到對象的時候再來創建對象。前者比後者性能要高,而後者比前者要靈活。這主要是因為前者創建對象的時候,就是這個堆棧中創建的。雖然其創建的對象沒有保存在寄存器中,但是通過這個對象的推棧指針可以直接從處理器哪裡獲得相關的支持。如堆棧指針往上移動的時候,則釋放原有對象佔用的內存;如堆棧指針向下移動時,則為對象分配新的內存。所以,如果把對象存放在這個堆棧中,雖然性能沒有像存放在寄存器中那麼理想,但是仍然比存儲在其他地方要好的多。
由於Java程序是在程序運行過程中才根據需要來創建對象。為此對象就不能夠保存在這個堆棧中。不過Java應用程序也不能夠白白的浪費這個寶貴的空間。為此雖然Java對象本身沒有保存在這個堆棧中(不是不保存而是這里沒有他的容身之地),但是還是應該把一些可以放的內容放到這個堆棧中,以提高應用程序的性能。如可以把一些對象引用存放在這個堆棧中。
另外對於一些基本的數據類型對象,Java程序也往往把他們放置在堆棧中,以提高數據處理的性能。如一些整數型、字元型的數據對象,這些對象有些共同的特點,如對象比較小、是Java程序提供的標准對象等等。對於這些對象由於每個應用程序基本上都需要用到,而且我們程序開發人員只能夠引用這些對象,而不能夠對其進行更改弊衡胡。為此Java程序在處理的時候,往往一開始就創建了對象(即直接在堆棧中創建對象並保存),而不像其他對象一樣,在需要的時候才創建。只所以在堆棧中創建這些對象,還有一個重要的原因。因為如果在堆棧中創建對象的話,Java編輯器必須知道存儲在堆棧內所有數據的確切大小和生命周期。為了得到這些信息,必須產生相關的代碼來獲得這些信息,以便其操作堆棧指針。普通的對象大小、生命周期等等難以預先獲得,為此在堆棧中創建普通的對象,對於Java應用程序來說並不是很合適。相反,這些Java編譯器預定義的對象大小並不會隨著機器硬體架構的變化和用戶需求的變化而變化;而且這些對象往往從始之終都會存在的,所以也不存在生命周期的問題。所以把這些對象放置在堆棧中是合理的,也是可實現的。如此處理,不僅不會影響到對象的靈活性,而且還可以提供比較好的性能。
存儲區域三:堆
堆雖然跟堆棧一樣,都是隨機訪問存儲器中的區域,但是兩者有很大的不同。因為在堆中,沒有堆棧指針,為此也就無法直接從處理器那邊獲得支持。為此其性能跟堆棧比起來,就有一定的差距。通常情況下,除上面所說的一些預定義對象之外,其他的對象都是保存在這個堆中的。或者說,利用new關鍵字創建的對象都是保存在堆中的。保存在堆中其好處也是顯而易見的。如Java編譯器不需要知道從堆里需要分配多少存儲區域,也不必知道存儲的數據在堆里會存活多長時間。所以在攔磨堆里分配存儲有很大的靈活性。當需要對象時,我們可以使用New關鍵字建立一個對象。然後系統會自動給這個對象在堆中分配一個區域讓其作為歸宿。不過其最大的不足之處,就是在堆中創建租攔對象與分配存儲區域,要比在堆棧中慢許多。魚與熊掌不能兼得呀。
存儲區域四:靜態存儲區域與常量存儲區域
在Java對象中有一些特殊的元素。如有些元素是比較特別的(如利用關鍵字Static定義的變數)。這些變數對於其他對象來說,可能就是靜態的。為了更好的管理這些變數,Java在內存中專門劃分了一個靜態存儲區域來管理這些元素。這里的靜態存儲區域就是指在固定的位置存放應用程序運行時一直存在的數據。這里需要明確的一點就是,Java對象是不保存在這個地方的,而只是把對象中的一些特殊元素放置這里。由於位置固定,所以下次調用的時候就省去了查找的麻煩。為此其對於提供應用程序的性能是有利的。作為我們程序開發人員來說,在書寫代碼的時候,就需要靈活應用Static這個關鍵字。筆者的意見是,能用則用;不能用的時候也要想著法兒用。特別是有些元素用不用Static關鍵字時對於程序功能沒有影響,此時我們要理直氣壯的在元素前面加上Static關鍵字。
在Java對象中還有一類特殊的元素,我們叫做常量。由於常量的值是穩定不變的,如圓周率。為此把他們放在代碼的內部是可行的。不過有些時候,在進行一些嵌入式系統開發的時候,我們往往不這么做。而是會把常量元素跟代碼分開來保存。如我們會根據情況把常量的值存放在一些只讀存儲器中。這主要是為了一些特殊的功能考慮的。如出於版權控制的需要。如在列印機上為了保護原裝耗材的版權,往往把常量跟代碼分開存放。
存儲區域五:非RAM存儲
有時候,有些程序運行所需要的數據我們還會放置在其他地方。如在一些系統中需要用到流對象,這個對象的數據並沒有保存在上面所談到的任何一個存儲區域,這個對象直接被轉為為位元組流,發送到其他的主機上去了。另外有一種叫做持久化的對象,其是被存儲在硬碟中的。這些對象平時在應用程序開發過程中用到的並不是很多,大家只需要了解有這些對象的存在即可。等到需要用到的時候,再去深入研究也不遲。
從上面的分析中我們可以看到,對象的歸屬我們程序開發人員很難控制。寄存器是編譯器來管理的。而堆與堆棧又基本上受到開發平台的限制,我們程序人員也沒有這個能耐來干涉他們。其實我們主要能夠調整與控制的就是第四個存儲區域,即靜態存儲與常量存儲。筆者的建議是,對於非嵌入式程序,能夠利用靜態存儲來實現的,就盡量採用靜態存儲。而對於常量來說,需要根據需要實現的功能來判斷是否需要把常量存儲在只讀存儲器中。有時候對於版權的保護等等需要用到這個只讀存儲器。

『伍』 Java資料庫程序中的存儲過程設計

本文闡述了怎麼使用DBMS存儲過程 闡述了使用存儲過程的基本的和高級特性 比如返回ResultSet 本文假設你對DBMS和JDBC已經非常熟悉 也假設你能夠毫無障礙地閱讀其它語言寫成的代碼(即不是Java的語言) 但是 並不要求你有任何存儲過程的編程經歷

存儲過程是指保存在數據豎拿庫並在資料庫端執行的程序 你可以使用特殊的語法在Java類中調用存儲過程 在調用時 存儲過程的名稱及指定的參數通過JDBC連接發送給DBMS 執行存儲過程並通過連接(如果有)返回結果

使用存儲過程擁有和使用基於EJB或CORBA這樣的應用伺服器一樣的好處 區別是存儲過程可以從很多流行的DBMS中免費使用 而應用伺服器大都非常昂貴 這並不只是許可證費用的問題 使用應用伺服器所需要花費的管理 編寫代碼的費用 以及客戶程序所增加的復雜性 都可以通過DBMS中的存儲過程所整個地替代

你可以使用Java Python Perl或C編寫存儲過程 但是通常使用你的DBMS所指定的特定語言 Oracle使用PL/sql PostgreSQL使用pl/pgsql DB 使用Proceral SQL 這些語言都非常相似 在它們之間移植存儲過程並不比在Sun的EJB規范不同實現版本之間移植Session Bean困難 並且 存儲過程是為嵌入SQL所設計 這使得它們比Java或C等語言更加友好地方式表達資料庫的機制

因為存儲過程運行在DBMS自身 這可以幫助減少應用程序中的等待時間 不是在Java代碼中執行 個或 個SQL語句 而只需要在伺服器端執行 個存儲過程 網路上的數據往返次數的減少可以戲劇性地優化性能

使用存儲過程

簡單的老的JDBC通過CallableStatement類支持存儲過程的調用 該類實際上是PreparedStatement的一個子類 假設我們有一個poets資料庫 資料庫中有一個設置詩人逝世年齡的存儲過程 下面是對老酒鬼Dylan Thomas(old soak Dylan Thomas 不指定是否有關典故跡灶 文化 請批評指正 譯注)進行調用的詳細代碼

try{int age = ;String poetName = dylan thomas ;CallableStatement proc = connection prepareCall( { call set_death_age(? ?) } );proc setString( poetName);proc setInt( age);cs execute();}catch (SQLException e){// }

傳給prepareCall方法的字串是存儲過程調用的書寫規范 它指定了存儲過程的名稱 ?代表了你需要指定的參數

和JDBC集成是存儲過程的一個很大的便利 為了從應用中調用存儲過程 不需要存根(stub)類或者配置文件 除了你的DBMS的JDBC驅動程序外什麼也不需要

當這段代碼執行時 資料庫的存儲過程就被調用 我們沒有去獲取結果 因為該存儲過程並不返回結果 執行成功或失敗將通過例外得知 失敗可能意味著調用存儲姿纖扮過程時的失敗(比如提供的一個參數的類型不正確) 或者一個應用程序的失敗(比如拋出一個例外指示在poets資料庫中並不存在 Dylan Thomas )

結合SQL操作與存儲過程

映射Java對象到SQL表中的行相當簡單 但是通常需要執行幾個SQL語句 可能是一個SELECT查找ID 然後一個INSERT插入指定ID的數據 在高度規格化(符合更高的範式 譯注)的資料庫模式中 可能需要多個表的更新 因此需要更多的語句 Java代碼會很快地膨脹 每一個語句的網路開銷也迅速增加

將這些SQL語句轉移到一個存儲過程中將大大簡化代碼 僅涉及一次網路調用 所有關聯的SQL操作都可以在資料庫內部發生 並且 存儲過程語言 例如PL/SQL 允許使用SQL語法 這比Java代碼更加自然 下面是我們早期的存儲過程 使用Oracle的PL/SQL語言編寫

create procere set_death_age(poet VARCHAR poet_age NUMBER)poet_id NUMBER;beginSELECT id INTO poet_id FROM poets WHERE name = poet;INSERT INTO deaths (mort_id age) VALUES (poet_id poet_age);end set_death_age;

很獨特?不 我打賭你一定期待看到一個poets表上的UPDATE 這也暗示了使用存儲過程實現是多麼容易的一件事情 set_death_age幾乎可以肯定是一個很爛的實現 我們應該在poets表中添加一列來存儲逝世年齡 Java代碼中並不關心資料庫模式是怎麼實現的 因為它僅調用存儲過程 我們以後可以改變資料庫模式以提高性能 但是我們不必修改我們代碼

下面是調用上面存儲過程的Java代碼

public static void setDeathAge(Poet dyingBard int age)throws SQLException{Connection con = null;CallableStatement proc = null;

try{con = connectionPool getConnection();proc = con prepareCall( { call set_death_age(? ?) } );proc setString( dyingBard getName());proc setInt( age);proc execute();}finally{try{proc close();}catch (SQLException e) {}con close();}}

為了確保可維護性 建議使用像這兒這樣的static方法 這也使得調用存儲過程的代碼集中在一個簡單的模版代碼中 如果你用到許多存儲過程 就會發現僅需要拷貝 粘貼就可以創建新的方法 因為代碼的模版化 甚至也可以通過腳本自動生產調用存儲過程的代碼

Functions

存儲過程可以有返回值 所以CallableStatement類有類似getResultSet這樣的方法來獲取返回值 當存儲過程返回一個值時 你必須使用registerOutParameter方法告訴JDBC驅動器該值的SQL類型是什麼 你也必須調整存儲過程調用來指示該過程返回一個值

下面接著上面的例子 這次我們查詢Dylan Thomas逝世時的年齡 這次的存儲過程使用PostgreSQL的pl/pgsql

create function snuffed_it_when (VARCHAR) returns integer declarepoet_id NUMBER;poet_age NUMBER;begin first get the id associated with the poet SELECT id INTO poet_id FROM poets WHERE name = $ ; get and return the age SELECT age INTO poet_age FROM deaths WHERE mort_id = poet_id;return age;end; language pl/pgsql ;

另外 注意pl/pgsql參數名通過Unix和DOS腳本的$n語法引用 同時 也注意嵌入的注釋 這是和Java代碼相比的另一個優越性 在Java中寫這樣的注釋當然是可以的 但是看起來很凌亂 並且和SQL語句脫節 必須嵌入到Java String中

下面是調用這個存儲過程的Java代碼

connection setAutoCommit(false);CallableStatement proc =connection prepareCall( { ? = call snuffed_it_when(?) } );proc registerOutParameter( Types INTEGER);proc setString( poetName);cs execute();int age = proc getInt( );

如果指定了錯誤的返回值類型會怎樣?那麼 當調用存儲過程時將拋出一個RuntimeException 正如你在ResultSet操作中使用了一個錯誤的類型所碰到的一樣

復雜的返回值

關於存儲過程的知識 很多人好像就熟悉我們所討論的這些 如果這是存儲過程的全部功能 那麼存儲過程就不是其它遠程執行機制的替換方案了 存儲過程的功能比這強大得多

當你執行一個SQL查詢時 DBMS創建一個叫做cursor(游標)的資料庫對象 用於在返回結果中迭代每一行 ResultSet是當前時間點的游標的一個表示 這就是為什麼沒有緩存或者特定資料庫的支持 你只能在ResultSet中向前移動

某些DBMS允許從存儲過程中返回遊標的一個引用 JDBC並不支持這個功能 但是Oracle PostgreSQL和DB 的JDBC驅動器都支持在ResultSet上打開到游標的指針(pointer)

設想列出所有沒有活到退休年齡的詩人 下面是完成這個功能的存儲過程 返回一個打開的游標 同樣也使用PostgreSQL的pl/pgsql語言

create procere list_early_deaths () return refcursor as declaretoesup refcursor;beginopen toesup forSELECT poets name deaths ageFROM poets deaths all entries in deaths are for poets but the table might bee generic WHERE poets id = deaths mort_idAND deaths age < ;return toesup;end; language plpgsql ;

下面是調用該存儲過程的Java方法 將結果輸出到PrintWriter

PrintWriter:

static void sendEarlyDeaths(PrintWriter out){Connection con = null;CallableStatement toesUp = null;try{con = ConnectionPool getConnection();

// PostgreSQL needs a transaction to do this con setAutoCommit(false);

// Setup the call CallableStatement toesUp= connection prepareCall( { ? = call list_early_deaths () } );toesUp registerOutParameter( Types OTHER);getResults execute();

ResultSet rs = (ResultSet) getResults getObject( );while (rs next()){String name = rs getString( );int age = rs getInt( );out println(name + was + age + years old );}rs close();}catch (SQLException e){// We should protect these calls toesUp close();con close();}}

因為JDBC並不直接支持從存儲過程中返回遊標 我們使用Types OTHER來指示存儲過程的返回類型 然後調用getObject()方法並對返回值進行強制類型轉換

這個調用存儲過程的Java方法是mapping的一個好例子 Mapping是對一個集上的操作進行抽象的方法 不是在這個過程上返回一個集 我們可以把操作傳送進去執行 本例中 操作就是把ResultSet列印到一個輸出流 這是一個值得舉例的很常用的例子 下面是調用同一個存儲過程的另外一個方法實現

public class ProcessPoetDeaths{public abstract void sendDeath(String name int age);}

static void mapEarlyDeaths(ProcessPoetDeaths mapper){Connection con = null;CallableStatement toesUp = null;try{con = ConnectionPool getConnection();con setAutoCommit(false);

CallableStatement toesUp= connection prepareCall( { ? = call list_early_deaths () } );toesUp registerOutParameter( Types OTHER);getResults execute();

ResultSet rs = (ResultSet) getResults getObject( );while (rs next()){String name = rs getString( );int age = rs getInt( );mapper sendDeath(name age);}rs close();}catch (SQLException e){// We should protect these calls toesUp close();con close();}}

這允許在ResultSet數據上執行任意的處理 而不需要改變或者復制獲取ResultSet的方法

static void sendEarlyDeaths(final PrintWriter out){ProcessPoetDeaths myMapper = new ProcessPoetDeaths(){public void sendDeath(String name int age){out println(name + was + age + years old );}};mapEarlyDeaths(myMapper);}

這個方法使用ProcessPoetDeaths的一個匿名實例調用mapEarlyDeaths 該實例擁有sendDeath方法的一個實現 和我們上面的例子一樣的方式把結果寫入到輸出流 當然 這個技巧並不是存儲過程特有的 但是和存儲過程中返回的ResultSet結合使用 是一個非常強大的工具

結論

存儲過程可以幫助你在代碼中分離邏輯 這基本上總是有益的 這個分離的好處有

快速創建應用 使用和應用一起改變和改善的資料庫模式

資料庫模式可以在以後改變而不影響Java對象 當我們完成應用後 可以重新設計更好的模式

存儲過程通過更好的SQL嵌入使得復雜的SQL更容易理解

編寫存儲過程比在Java中編寫嵌入的SQL擁有更好的工具——大部分編輯器都提供語法高亮!

存儲過程可以在任何SQL命令行中測試 這使得調試更加容易

並不是所有的資料庫都支持存儲過程 但是存在許多很棒的實現 包括免費/開源的和非免費的 所以移植並不是一個問題 Oracle PostgreSQL和DB 都有類似的存儲過程語言 並且有在線的社區很好地支持

存儲過程工具很多 有像TOAD或TORA這樣的編輯器 調試器和IDE 提供了編寫 維護PL/SQL或pl/pgsql的強大的環境

lishixin/Article/program/Java/hx/201311/25906

熱點內容
h板電影種子ftp 發布:2025-02-11 09:06:10 瀏覽:738
c語言數據類型定義 發布:2025-02-11 09:00:38 瀏覽:237
一個小時如何選擇伺服器 發布:2025-02-11 08:58:14 瀏覽:442
網易我的世界伺服器推薦國服 發布:2025-02-11 08:56:34 瀏覽:241
電視父母鎖屏密碼應該會是什麼 發布:2025-02-11 08:36:42 瀏覽:892
梅花適合用哪些植物進行配置 發布:2025-02-11 08:30:54 瀏覽:252
安卓手機如何像蘋果一樣彈窗 發布:2025-02-11 08:26:33 瀏覽:912
壓縮文件掃碼 發布:2025-02-11 08:20:55 瀏覽:258
小米5安卓70怎麼分屏 發布:2025-02-11 08:00:58 瀏覽:140
訪問二維碼 發布:2025-02-11 08:00:11 瀏覽:883