Java基礎(chǔ)字符編碼與內(nèi)存流詳細(xì)解讀
1、字符編碼
1.1 常用字符編碼
在計(jì)算機(jī)的世界之中,所有的顯示文字都是按照其指定的數(shù)字編碼進(jìn)行保存的,如果沒(méi)有正確的解碼,那么就坑你產(chǎn)生亂碼,如果要想清楚解決亂碼問(wèn)題,就要了解經(jīng)常見(jiàn)到一些常見(jiàn)的編碼:
GBK/GBK2312:表示國(guó)標(biāo)中文編碼,其中GBK是包含簡(jiǎn)體中文和繁體中文,而GB2312只有簡(jiǎn)體;
ISO 8859-1:是一種國(guó)際通用編碼,可以表示任何文字,但是對(duì)于中國(guó)文字需要進(jìn)行轉(zhuǎn)碼;
UNICODE:使用十六進(jìn)制完成的編碼,可以準(zhǔn)確的表示出任何的語(yǔ)言文字;
UTF-8:部分編碼使用UNICODE,而一些編碼繼續(xù)使用像ISO 8859-1,類(lèi)型的編碼,適合于網(wǎng)絡(luò)傳輸,在以后的所有的項(xiàng)目開(kāi)發(fā)之中,都必須采用此編碼??墒强紤]到日后學(xué)習(xí)的方便,幾乎都會(huì)使用命令行進(jìn)行操作,所以命令行只支持GBK編碼,UTF不支持,一旦程序設(shè)置了UTF編碼,那么通過(guò)命令行查看就是亂碼。
在開(kāi)發(fā)之中經(jīng)常會(huì)遇見(jiàn)亂碼的問(wèn)題,所謂的亂碼的核心在于編碼和解碼不統(tǒng)一。如果要想正確的避免項(xiàng)目之中出現(xiàn)的亂碼,那么首先就應(yīng)該知道環(huán)境之中所支持的編碼是什么。
1.2 亂碼產(chǎn)生分析
讀取Java運(yùn)行屬性
package com.day15.demo;
public class ListDemo {
public static void main(String[] args) {
System.getProperties().list(System.out);
}
}
這個(gè)時(shí)候顯示出來(lái)的信息是很多的,這里面有專(zhuān)門(mén)的編碼選項(xiàng)“file.encoding=GBK”,也就是說(shuō)如果沒(méi)有任何的意外,所有的文字編碼都是GBK。
改變編碼
package com.day15.demo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class ListDemo {
public static void main(String[] args) throws Exception{
OutputStream out = new FileOutputStream(new File("f:" + File.separator + "test" + File.separator + "hello.txt"),true);
out.write("世界和平".getBytes());
out.close();
}
}
2、內(nèi)存流基本操作
在講解之前首先來(lái)思考一個(gè)問(wèn)題:就是如果現(xiàn)在某個(gè)操作必須發(fā)生IO,但有不希望有一些臨時(shí)文件產(chǎn)生的話(huà),那么現(xiàn)在肯定無(wú)法使用之前的文件操作流,所以為了解決這樣的問(wèn)題,提供了內(nèi)存操作流,即:以?xún)?nèi)存進(jìn)行操作的終端,以發(fā)生IO操作關(guān)系。

對(duì)于內(nèi)存操作流也分為兩組:
**字節(jié)內(nèi)存操作流:**內(nèi)存輸入流(ByteArrayInputStream)內(nèi)存輸出流(ByteArrayOutputStream)
**字符內(nèi)存操作流:**內(nèi)存輸入流(CharArrayReader)內(nèi)存輸出流(CharArrayWriter)

ByteArrayInputStream ByteArrayOutputStreamjava.lang.Object java.io.InputStream java.io.ByteArrayInputStreamjava.lang.Object java.io.OutputStream java.io.ByteArrayOutputStreampublic ByteArrayInputStream(byte[] buf)public ByteArrayOutputStream()
輸出流

輸入流

通過(guò)內(nèi)存實(shí)現(xiàn)大小寫(xiě)轉(zhuǎn)換的操作
package com.day15.demo;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;
public class MemoryDemo {
public static void main(String[] args) throws Exception{
String str = "Hello,World!";
InputStream in = new ByteArrayInputStream(str.getBytes());
OutputStream out = new ByteOutputStream();
int temp = 0;
while((temp = in.read())!=-1){
out.write(Character.toUpperCase(temp));
}
in.close();
out.close();
System.out.println(out.toString());
}
}
此過(guò)程我們發(fā)現(xiàn)沒(méi)有文件的產(chǎn)生,而此過(guò)程只不過(guò)是產(chǎn)生了臨時(shí)文件。
3、打印流
如果說(shuō)想在要想輸出數(shù)據(jù),肯定使用OuputStream或者是Writer,那么請(qǐng)問(wèn),這兩個(gè)操作類(lèi)在執(zhí)行輸出的時(shí)候你認(rèn)為它好用嗎?
打印流主要解決的就是OutputStream缺陷,屬于OutputStream加強(qiáng)版,如果現(xiàn)在操作不是二進(jìn)制的數(shù)據(jù),只是通過(guò)程序向終端目標(biāo)輸出信息。OutputStream并不方便。
缺點(diǎn)一:所有的數(shù)據(jù)必須變?yōu)樽止?jié)數(shù)組
缺點(diǎn)二:只支持String類(lèi)型,輸出int、double就不方便
如果現(xiàn)在要想輸出字符串,使用Writer可以直接輸出,而使用OutputStream還需要將字符串變?yōu)樽止?jié)數(shù)組,那么如果現(xiàn)在要想輸出數(shù)字(int型或double型),還需要將這些數(shù)據(jù)先變?yōu)樽址笤僮優(yōu)樽止?jié)數(shù)組輸出,多以,如果用戶(hù)直接調(diào)用OutputStream或Writer輸出的時(shí)候本身并不方便,所以在這個(gè)時(shí)候可以想辦法將OutputStream或Writer變得加強(qiáng)一些,定義一個(gè)專(zhuān)門(mén)的工具類(lèi):PrintUtil.java。
編寫(xiě)一個(gè)輸出功能類(lèi)PrintUtil類(lèi)
package com.day15.demo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
class PrintUtil{
OutputStream out;
public PrintUtil(OutputStream out){
this.out=out;
}
public void print(String str) throws Exception{
this.out.write(str.getBytes());
}
public void println(String str) throws Exception{
this.print(str.concat("\r\n"));
}
public void print(int num) throws Exception{
this.print(String.valueOf(num));
}
public void println(int num) throws Exception{
this.println(String.valueOf(num));
}
}
public class PintUtilDemo {
public static void main(String[] args) throws Exception {
PrintUtil printUtil = new PrintUtil(new FileOutputStream(new File("f:" + File.separator + "test" + File.separator + "test.txt")));
printUtil.println("姓名:" + "張麻子");
printUtil.print("年齡");
printUtil.print(19);
}
}
以后使用PrintWriter的使用率挺高,但是這兩者的使用形式相同的。首先觀察這兩個(gè)類(lèi)的繼承結(jié)構(gòu)和構(gòu)造方法:
首先來(lái)觀察一下PrintStream,PrintWriter的繼承結(jié)構(gòu)和構(gòu)造方法:
| PrintStream | PrintWriter |
| java.lang.Object java.io.OutputStream java.io.FilterOutputStream java.io.PrintStream |
java.lang.Object java.io.Writer java.io.PrintWriter |
| public PrintStream(OuputStream out) | public PrintWriter(Writer out) |

看見(jiàn)以上的結(jié)構(gòu),可能第一反應(yīng)就屬于代理設(shè)計(jì)模式,但它并不是代理,代理設(shè)計(jì)模式的特點(diǎn):以接口為使用原則,用戶(hù)調(diào)用代理主題方法的時(shí)候依然是接口之中定義的方法。而此時(shí)PrintStream類(lèi)調(diào)用的絕對(duì)不是OutputStream類(lèi)之中定義的一系列write()方法。雖然PrintStream在外表操作上產(chǎn)生了變化,但實(shí)際上依然執(zhí)行的是OutputStream累哦所定義的操作,所以本質(zhì)沒(méi)有發(fā)生變化,只是提供了一些更加方便的功能支持,多以這種設(shè)計(jì)模式上講稱(chēng)為裝飾設(shè)計(jì)模式。
3.1 格式化文本信息
在JDK1.5之后,打印流也進(jìn)行了更新,增加了一個(gè)新的方法,格式化輸出:格式化輸出:public PrintStream printf(String format,Object… args)
當(dāng)看到此方法名稱(chēng)的時(shí)候首先想到的是C語(yǔ)言中的輸出,而現(xiàn)在Java也具備了同樣的功能,而輸出的時(shí)候可以使用一些標(biāo)記表示要輸出的內(nèi)容,例如:字符串(%s),數(shù)字(%d)小數(shù)(%m.nf),字符(%c)等。
觀察格式化輸出
package com.day15.demo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
public class PrintWriterDemo {
public static void main(String[] args) throws Exception{
PrintWriter pu = new PrintWriter(new FileOutputStream(new File("f:" + File.separator + "test" + File.separator + "test.txt")),true);
String name = "張麻子";
int age=23;
double score=8123219.127456;
pu.printf("姓名:%s 年齡:%d 成績(jī):%7.2f",name,age,score);
}
}
而在JDK1.5之后增加字符串格式化操作類(lèi)不光有PrintStream,還有String類(lèi),String類(lèi)也提供了一個(gè)格式化字符串的操作方法:public static String format(String format,Object… args)
格式化字符串
package com.day15.demo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
public class PrintWriterDemo {
public static void main(String[] args) throws Exception{
PrintWriter pu = new PrintWriter(new FileOutputStream(new File("f:" + File.separator + "test" + File.separator + "test.txt")),true);
String name = "張麻子";
int age=23;
double score=8123219.127456;
String str = String.format("姓名:%s 年齡:%d 成績(jī):%7.2f",name,age,score);
System.out.println(str);
}
}
雖然格式化字符串可以執(zhí)行準(zhǔn)確的四舍五入操作,但是這種處理完的數(shù)據(jù)都是String型,而實(shí)際工作中,如果要四舍五入,肯定還是要編寫(xiě)B(tài)igDecimal類(lèi)完成。
以后只要是程序輸出數(shù)據(jù)的操作,都使用PrintStream類(lèi)。
4、 System類(lèi)
在我們學(xué)習(xí)完了PrintWriter、PrintStream之后我們會(huì)發(fā)現(xiàn)里面的方法都很熟悉,例如print()、println()輸出就利用我們的IO流模式完成的。在System類(lèi)中實(shí)際上定義有三個(gè)操作的常量。

| public static final PrintStream out | 標(biāo)準(zhǔn)輸出 |
| public static final PrintStream err | 錯(cuò)誤輸出 |
| public static final InputStream in | 標(biāo)準(zhǔn)輸出 |
4.1 系統(tǒng)輸出
系統(tǒng)輸出我們發(fā)現(xiàn)一共有兩個(gè)常量:out、err,而且這兩個(gè)常量所表示的都是PrintSream的對(duì)象。從
Java設(shè)計(jì)的本質(zhì)上來(lái)講這樣的輸出有以下設(shè)計(jì)的目的。out是希望輸出的用戶(hù)可以看見(jiàn)的內(nèi)容
,err是希望輸出用戶(hù)不能夠看見(jiàn)的內(nèi)容。
package com.day15.demo;
public class PrintDemo {
public static void main(String[] args) throws Exception{
try{
Integer.valueOf("abc");
}catch(Exception e){
System.err.println(e);
System.out.println(e);
}
}
}
/*
java.lang.NumberFormatException: For input string: "abc"
java.lang.NumberFormatException: For input string: "abc"
*/
4.2 系統(tǒng)輸出
系統(tǒng)輸出是將所有的信息輸出到指定的輸出設(shè)備上——顯示器。而System.out本身是屬于PrintStream對(duì)象,而PrintStream是OutputStream子類(lèi),所以現(xiàn)在實(shí)際上可以利用System.out為OutputStream類(lèi)執(zhí)行實(shí)例化操作。
package com.day15.demo;
import java.io.OutputStream;
public class PrintDemo {
public static void main(String[] args) throws Exception {
String str ="hello,world";
OutputStream output = System.out;//System.out為OutputStream實(shí)例化
output.write(str.getBytes());
}
}
本程序沒(méi)有任何的意義,而講解的主要目的就希望可以理解:OutputStream會(huì)根據(jù)實(shí)例化它的子類(lèi)或?qū)ο蟮牟煌?,輸出的位置也不同?/p>
4.3 系統(tǒng)輸入
系統(tǒng)輸入針對(duì)于標(biāo)準(zhǔn)的輸入設(shè)備——鍵盤(pán),也就是俗稱(chēng)的鍵盤(pán)輸入數(shù)據(jù),但是System.in返回的是InputStream型的數(shù)據(jù),所以下面編寫(xiě)一個(gè)操作由鍵盤(pán)輸入數(shù)據(jù)。
package com.day15.demo;
import java.io.IOException;
import java.io.InputStream;
public class inDemo {
public static void main(String[] args) throws Exception {
InputStream input = System.in;
System.out.println("請(qǐng)輸入!");
byte data[] = new byte[1024];
int len = input.read(data);
System.out.println(new String(data,0,len));
}
}
除了實(shí)例化InputStream類(lèi)的對(duì)象不同之外,其他的地方和之前文件輸入數(shù)據(jù)沒(méi)有任何區(qū)別,但是這個(gè)程序本身有問(wèn)題,已經(jīng)開(kāi)辟的空間大小是1024,如果輸入的數(shù)據(jù)超過(guò)1024呢?發(fā)現(xiàn)只會(huì)接收滿(mǎn)足指定長(zhǎng)度的數(shù)據(jù),程序有bug,那么最好的解決方法是不設(shè)置長(zhǎng)度,輸入一個(gè)讀取一個(gè),一直到用戶(hù)不輸入為止。
package com.day15.demo;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class inDemo {
public static void main(String[] args) throws Exception {
InputStream input = System.in;//為父類(lèi)實(shí)例化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte data[] = new byte[10];//開(kāi)辟一個(gè)空間
System.out.println("請(qǐng)輸入!");
int temp = 0;
while((temp = input.read(data))!=-1){//數(shù)據(jù)讀取到字節(jié)數(shù)
//這里面要用戶(hù)自己來(lái)處理?yè)Q行問(wèn)題
bos.write(data,0,temp);//保存在內(nèi)存輸出流
if(temp < data.length){
break;
}
}
System.out.println(new String(bos.toByteArray()));
}
}
簡(jiǎn)化操作,但是中文無(wú)法識(shí)別
package com.day15.demo;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class inDemo {
public static void main(String[] args) throws Exception {
InputStream input = System.in;//為父類(lèi)實(shí)例化
StringBuffer buf = new StringBuffer();
System.out.println("請(qǐng)輸入!");
int temp = 0;
while((temp = input.read())!=-1){//數(shù)據(jù)讀取到字節(jié)數(shù)
//這里面要用戶(hù)自己來(lái)處理?yè)Q行問(wèn)題
if(temp == '\n'){
break;
}
buf.append((char)temp);
}
System.out.println(buf);
}
}
通過(guò)以上比較可以感受到System.in的支持度原本不高,對(duì)于英文的操作是支持,但是對(duì)于中文是不太友好的,對(duì)于中文的輸出還必須借助內(nèi)存流來(lái)實(shí)現(xiàn)的。
5、BufferedReader類(lèi)
BufferedReader屬于一個(gè)緩沖的輸入流,而且是一個(gè)字符流的操作對(duì)象。但是必須清楚一點(diǎn)就是對(duì)于我們的緩存流定義有兩類(lèi):字節(jié)緩沖流( BufferedInputStream )、字節(jié)緩沖流( BufferedReader )。
如果說(shuō)想在把所有的輸入數(shù)據(jù)放在一起了,一次性讀取出來(lái),那么這個(gè)時(shí)候肯定就能夠避免中文問(wèn)題了,而這一操作就必須依靠緩沖區(qū)操作流完成。對(duì)于緩沖區(qū)的讀取在IO包中定義了兩種類(lèi):BufferedInputStream,BufferedReader,但是考慮到本次操作有中文的問(wèn)題,肯定使用BufferedReader類(lèi)完成操作。下面就需要觀察一下BufferedReader類(lèi)的繼承結(jié)構(gòu),構(gòu)造方法,操作方法:
| 繼承結(jié)構(gòu): | java.lang.Object java.io.Reader java.io.BuffereedReader |
| 構(gòu)造方法: | public BuffereedReader(Reader in) |
| 讀取操作: | public String readLine() throws IOException |
之所以選擇BufferReader類(lèi)操作提供的readLine()方法,這個(gè)方法可以讀取一行數(shù)據(jù)以回車(chē)為準(zhǔn)。

使用BufferedReader進(jìn)行數(shù)據(jù)讀取
package com.day15.demo;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class BufferReaderDemo {
public static void main(String[] args) throws Exception{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
System.out.println("請(qǐng)輸入");
//默認(rèn)的換行模式是BufferReader最大的缺點(diǎn)
String str = bufr.readLine();//接受輸入信息,默認(rèn)使用回車(chē)換行
System.out.println(str);
}
}
對(duì)輸入的數(shù)據(jù)進(jìn)行驗(yàn)證,判斷是否是數(shù)字
package com.day15.demo;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class BufferReaderDemo {
public static void main(String[] args) throws Exception{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
System.out.println("請(qǐng)輸入年齡");
//默認(rèn)的換行模式是BufferReader最大的缺點(diǎn)
String str = bufr.readLine();//接受輸入信息,默認(rèn)使用回車(chē)換行
if(str.matches("\\d{1,3}"))
System.out.println(str);
else
System.out.println("輸入數(shù)據(jù)有誤!");
}
}
6、Scanner
這個(gè)類(lèi)是作為了一個(gè)工具類(lèi)出現(xiàn)的,在Scanner之中定義兩個(gè)如下的一些方法:
| public Scanner(InputStream sourse); | 構(gòu)造方法 |
| public Boolean hasNextXxx(); | 判斷是否有數(shù)據(jù) |
| public 數(shù)據(jù)類(lèi)型 nextXxx(); | 取得數(shù)據(jù) |
| public Scanner useDelimiter(String partern); | 定義分隔符 |
以后調(diào)用的時(shí)候在執(zhí)行nextXxx()之前一定要首先使用hasNextXxx()判斷是否有指定格式的數(shù)據(jù)出現(xiàn)。
通過(guò)Scanner類(lèi)進(jìn)行數(shù)據(jù)的輸入
package com.day15.demo;
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("請(qǐng)輸入數(shù)據(jù):");
if(sc.hasNext()){//現(xiàn)在有輸入的內(nèi)容,不能判斷空字符串
System.out.println(sc.next());
}
sc.close();
}
}
使用Scanner類(lèi)判斷輸入數(shù)據(jù)是否是int型數(shù)據(jù)
package com.day15.demo;
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
System.out.println("請(qǐng)輸入數(shù)據(jù):");
Scanner sca=new Scanner(System.in);
if(sca.hasNextInt()){
int date=sca.nextInt();
System.out.println("輸入的數(shù)據(jù)是:"+date);
}else{
System.out.println("輸入的不是數(shù)字");
}
}
}
在Scaner類(lèi)之中,useDelimiter()方法的輸入針對(duì)于字符串,但是其他的數(shù)據(jù)類(lèi)型并不方便使用。
使用Scanner類(lèi)判斷用戶(hù)輸入的是不是生日
package com.day15.demo;
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("請(qǐng)輸入生日:");
if(sc.hasNext("\\d{4}-\\d{2}-\\d{2}")){//現(xiàn)在有輸入的內(nèi)容,不能判斷空字符串
String bir = sc.next("\\d{4}-\\d{2}-\\d{2}");
System.out.println(bir);
}
sc.close();
}
}
Scanner讀取文件內(nèi)容
package com.day15.demo;
import java.io.File;
import java.io.FileInputStream;
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) throws Exception{
Scanner sc = new Scanner(new FileInputStream(new File("f:" + File.separator + "test" + File.separator + "hello.txt")));
sc.useDelimiter("\n");
if(sc.hasNext()){//現(xiàn)在有輸入的內(nèi)容,不能判斷空字符串
System.out.println(sc.next());
}
sc.close();
}
}
除了二進(jìn)制文件拷貝處理之外,只要針對(duì)于程序的信息輸出都使用打印流,對(duì)于信息的輸入都是Scanner。
7、對(duì)象序列化
所有的項(xiàng)目都一定有序列化的概念。
7.1 對(duì)象序列化的概念
所謂的對(duì)象序列化是指在內(nèi)存中保存的對(duì)象變?yōu)槎M(jìn)制流的形式進(jìn)行傳輸,或者將其保存在文本中。但是我們并不意味著所有對(duì)象都可以被序列化,嚴(yán)格來(lái)講,我們需要被實(shí)例化的類(lèi)對(duì)象往往需要傳輸使用,同時(shí)這個(gè)類(lèi) 必須實(shí)現(xiàn)java.io.Serializable接口。但是這個(gè)接口沒(méi)有任何方法定義,所以只是一個(gè)標(biāo)識(shí)。
package com.day15.demo;
import java.io.Serializable;
class Person implements Serializable{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class SerializableDemo {
}
序列化對(duì)象是所需要保存的就是對(duì)象中的屬性所以默認(rèn)情況下對(duì)象的屬性將被轉(zhuǎn)為二進(jìn)制數(shù)據(jù)流存儲(chǔ)。
7.2 實(shí)現(xiàn)序列化和反序列化
如果要想進(jìn)行對(duì)象的序列化和反序列話(huà)的手工操作,在java之中提提供了兩個(gè)操作類(lèi):ObjectOutputStream,ObjectInputStream,而這兩個(gè)類(lèi)的繼承結(jié)構(gòu),構(gòu)造方法,操作方法定義如下:
| ObjectOutputStream | ObjectInputStream |
| java.lang.Object java.io.OutputStream java.io.ObjectOutputStream |
java.lang.Object java.io.InputStream java.io.ObjectInputStream |
| public ObjectOutputStream(OutputStream out) throws IOException |
public ObjectInputStream(InputStream in) throws IOException |
| public final void writeObject(Object obj) throws IOException |
public final Object readObject() throws IOException,ClassNotFoundException |


實(shí)現(xiàn)對(duì)象的序列化操作
package com.day15.demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;
class Person implements Serializable{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
public class SerializableDemo{
public static final File FILE = new File("F:" + File.separator + "test" + File.separator + "person.txt");
public static void ser(Object o) throws Exception {
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(FILE));
outputStream.writeObject(o);
outputStream.close();
}
public static void dser() throws Exception {
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(FILE));
System.out.println(inputStream.readObject());
inputStream.close();
}
public static void main(String[] args) throws Exception{
//序列化
//ser(new Person("張麻子",20));
//反序列化
dser();
}
}
如果出現(xiàn)com.day15.demo.Person@6d311334這個(gè)情況的主要原因是因?yàn)閷?shí)體類(lèi)沒(méi)有進(jìn)行toString()方法的重寫(xiě)。
7.3 transient關(guān)鍵字(了解)
實(shí)際上序列化的處理在Java.io有兩類(lèi),Serializable是使用最多的序列化接口,這種操作采用自動(dòng)化的模式完成,默認(rèn)情況下所有的屬性都會(huì)進(jìn)行序列化。有一個(gè)Externalizable接口需要用戶(hù)手動(dòng)序列化處理。
由于默認(rèn)情況Serializable會(huì)將對(duì)象中的所有屬性進(jìn)行保存,但是如果現(xiàn)在有某些屬性不希望被保存了,那么可以使用transient關(guān)鍵字。
使用transient
package com.day15.demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;
class Person implements Serializable{
private transient String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
public class SerializableDemo{
public static final File FILE = new File("F:" + File.separator + "test" + File.separator + "person.txt");
public static void ser(Object o) throws Exception {
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(FILE));
outputStream.writeObject(o);
outputStream.close();
}
public static void dser() throws Exception {
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(FILE));
System.out.println(inputStream.readObject());
inputStream.close();
}
public static void main(String[] args) throws Exception{
ser(new Person("張麻子",20));
dser();
}
}
/*
Person [name=null, age=20]
*/
發(fā)現(xiàn)此處name沒(méi)有進(jìn)行序列化操作。使用序列化往往在簡(jiǎn)單java類(lèi)上使用,其他類(lèi)上使用序列化的使用很少,但是在簡(jiǎn)單java類(lèi)中基本上不去使用transient。
到此這篇關(guān)于Day15基礎(chǔ)不牢地動(dòng)山搖-Java基礎(chǔ)的文章就介紹到這了,更多相關(guān)Java基礎(chǔ)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot分頁(yè)的實(shí)現(xiàn)與long型id精度丟失問(wèn)題的解決方案介紹
在以后的開(kāi)發(fā)中,當(dāng)全局唯一id的生成策略生成很長(zhǎng)的Long型數(shù)值id之后會(huì)超過(guò)JS對(duì)Long型數(shù)據(jù)處理的能力范圍,可能發(fā)生精度丟失而造成后端方法失效,我們要學(xué)會(huì)解決。分頁(yè)功能雖然簡(jiǎn)單但是非常重要,對(duì)于剛接觸項(xiàng)目的人一定要重點(diǎn)注意2022-10-10
MyBatis動(dòng)態(tài)SQL實(shí)現(xiàn)配置過(guò)程解析
這篇文章主要介紹了MyBatis動(dòng)態(tài)SQL實(shí)現(xiàn)配置過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
Java中關(guān)于優(yōu)先隊(duì)列PriorityQueue的使用及相關(guān)方法
這篇文章主要介紹了Java中關(guān)于優(yōu)先隊(duì)列PriorityQueue的使用及相關(guān)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
基于Spring AOP實(shí)現(xiàn)日志自動(dòng)打印功能
這篇文章主要介紹了基于Spring AOP實(shí)現(xiàn)日志自動(dòng)打印功能,文中通過(guò)代碼示例講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2025-01-01
Java中final關(guān)鍵字的使用與注意總結(jié)
這篇文章主要給大家介紹了關(guān)于Java中final關(guān)鍵字的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
Java中JSONObject和Map<String,?Object>的轉(zhuǎn)換方法
平時(shí)對(duì)接口時(shí),經(jīng)常遇到j(luò)son字符串和map對(duì)象之間的交互,這篇文章主要給大家介紹了關(guān)于Java中JSONObject和Map<String,?Object>的轉(zhuǎn)換方法,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07
java基于JSON實(shí)現(xiàn)前后端交互(附代碼)
本文主要介紹了java基于JSON實(shí)現(xiàn)前后端交互,通過(guò)實(shí)際代碼示例展示了如何前后端JSON交互,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01
java中BeanUtils.copyProperties的用法(超詳細(xì))
本文介紹了BeanUtils.copyProperties()方法的使用,包括其功能、用法、注意事項(xiàng)和示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08

