12.16 對象序列化
12.16.1 基本概念與Serializable接口
對象序列化就是把一個對象變為二進制的資料流的一種方法。通過對象序列化可以友善地實作對象的傳輸或存儲。
*****如果一個類得對象想被序列化,則對象所在的類必須實作java.io.Serializable接口。 此接口定義格式如下:*****
public interface Serializable{}
接口Serializable中,并沒有定義任何方法。是以此接口隻是一個辨別接口。表示一個類具備了被序列化的能力!!!
範例:定義可序列化的類
package org.forfan06.serializabledemo;
import java.io.Serializable;
public class Person implements Serializable{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:" + this.name + "; 年齡:" + this.age;
}
}
上面的Person類實作了序列化接口Serializable, 是以此類的對象是可以經過二進制資料流進行傳輸的。而如果要完成對象的輸入或輸出,還必須依靠對象輸出流(ObjectOutputStream類)和對象輸入流(ObjectInputStream類)。
使用對象輸出流(ObjectOutputStream類)輸出序列化對象的過程稱為序列化,而使用對象輸入流(ObjectInputStream)讀入對象的過程稱為反序列化。
- 對象序列化和對象反序列化操作時的版本相容型問題
在對象進行序列化或反序列化操作時,要考慮到JDK版本的問題。如果序列化的JDK版本和反序列化的JDK版本不統一則有可能造成異常, 是以在序列化操作中引入了一個serialVersionUID常量, 可以通過此常量來驗證版本的一緻性。
在進行反序列化時,JVM會把傳來的位元組流中的serialVersionUID與本地相應實體(類)的serialVersionUID進行比較。如果相同就認為是一緻的,可以進行反序列化;否則就會出現序列化版本不一緻的異常。
當實作java.io.Serializable接口的實體(類)沒有顯式地定義一個名為serialVersionUID、類型為long的變量時,Java序列化機制在編譯時會自動生成一個此版本的serialVersionUID。
當然,如果不希望通過編譯來自動生成,也可以直接顯式地定義一個名為serialVersionUID、類型為long的變量,隻要不修改這個變量值的序列化實體,都可以互相進行串行化和反串行化。
===可以在上面程式Person類中加入以下的常量即可:
private static final long serialVersionUID = 1L;
serialVersionUID具體内容由使用者指定!!!
12.16.2 對象輸出流 ObjectOutputStream
一個對象如果要進行輸出,則必須使用ObjectOutputStream類(對象輸出流)。 ObjectOutputStream類得定義如下:
public class ObjectOutputStream extends OutputStream implement ObjectOutput, ObjectStreamConstants
ObjectOutputStream類屬于OutputStream類的子類;ObjectOutputStream類的常用方法有:

ObjectOutputStream類的使用形式和PrintStream類非常相似,在執行個體化時也需要傳入一個OutputStream的子類對象,然後根據傳入的OutputStream子類對象的不同,輸出的位置也不同!!!
範例:将Person類的對象儲存在檔案中
package org.forfan06.serializabledemo;
import java.io.Serializable;
public class Person implements Serializable{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:" + this.name + "; 年齡:" + this.age;
}
}
package org.forfan06.serializabledemo;
import java.io.File;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class SerializableDemo01{
public static void main(String args[]) throws Exception{
File f = new File("E:" + File.separator + "test.txt");
ObjectOutputStream oos = null;
OutputStream out = new FileOutputStream(f);
oos = new ObjectOutputStream(out);
oo.writeObject(new Person("forfan06", 28));
oos.close();
}
}
上面demo将内容儲存到檔案中,但是儲存的内容全是二進制資料。儲存的檔案本身不可以直接修改,因為會破壞其儲存格式!!!!!
Q:到底序列化了哪些内容呢??? 一個對象被序列化後,到底哪些内容被儲存下來,是屬性還是方法???
- 隻有屬性被序列化了!!!在面對對象基礎部分曾經提到,每個對象都具備相同的方法,但是每個對象的屬性不一定相同,也就是說, 對象儲存的隻有屬性資訊,那麼在序列化操作時也同樣的是這個道理,隻有屬性被序列化了!!!!!!!!!!
12.16.3 對象輸入流 ObjectInputStream
使用ObjectInputStream類可以直接把被序列化好的對象反序列化。
ObjectInputStream類得定義格式如下:
public class ObjectInputStream extend InputStream implements ObjectInput, ObjectStreamConstants
ObjectInputStream類是InputStream類的一個子類, 與PrintStream類得使用類似。ObjectInputStream類同樣需要接收InputStream類的執行個體對象才可以執行個體化。
ObjectInputStream類的主要操作方法如下:
下面通過對象輸入流将SerializableDemo01中儲存在檔案中的對象讀取出來,此過程也稱為反序列化。
範例:對象的反序列化操作, 從檔案中把Person對象反序列化
package org.forfan06.serializabledemo;
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class SerializableDemo02{
public static void main(String args[]) throws Exception{
File f = new File("E:" + File.separator + "test.txt");
ObjectInputStream ois = null;
InputStream input = new FileInputStream(f); //檔案輸入流
ois = new ObjectInputStream(input);
Object obj = ois.readObject(); //讀取對象
ois.close();
System.out.println(obj);
}
}
運作結果:
姓名: forfan06; 年齡:28
解析:從程式結果可以發現,實作了Serializable接口的類,對象中的所有屬性都被序列化。
*****如果使用者想根據自己的需要選擇被序列化的屬性,則可以使用另外一種序列化接口 ---> Externalizable接口*****
問題: 可不可以讓所有的類都實作Serializable接口?? 一個類如果實作了Serializable接口後可以直接序列化,而且此接口中沒有任何的方法,也不會讓實作此接口的類增加不必要的操作,那麼所有的類都實作此接口的話不是更好嗎???這樣也可以增加類得一個功能。
Answer:
- 肯定不可以讓所有的淚都實作Serializable接口。 在目前已知的JDK版本中,java.io.Serializable接口中都沒有定義任何方法。如果所有的類都實作此接口在文法上并沒有任何的問題,但是,如果在以後的JDK版本中修改了此接口,而且有增加了許多方法呢??那麼以往的系統中所有的類就都被修改,這樣肯定會很麻煩的。。。是以最好在隻有需要被序列化對象的類實作Serializable接口。
12.16.4 Externalizable接口
被Serializable接口聲明的類的對象,其内容都将被序列化;但是,如果使用者希望自己指定被序列化的内容,則可以讓一個類實作Externalizable接口。
Externalizable接口的定義如下:
public interface Externalizable extend Serializable{
public void writeExternal(ObjectOutput out) throws IOException;
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}
Externalizable接口繼承了Serializable接口。是Serializable接口的子接口!! 在此接口中定義了兩個方法,這兩個方法的作用如下:
- writeExternal(ObjectOutput out): 在此方法中指定要儲存的屬性資訊,對象序列化時調用!
- readExternal(ObjectInput in): 在此方法中讀取被儲存的資訊,對象反序列化時調用。
writeExternal(ObjectOutput out)和readExternal(ObjectInput in)方法的參數類型是ObjectOutput和ObjectInput。 這兩個接口的定義如下:
---------> ObjectOutput接口定義:
public interface ObjectOutput extends DataOutput
---------> ObjectInput接口定義:
public interface ObjectInput extends DataInput
上面兩個接口分别繼承DataOutput和DataInput, 這樣在這兩個方法中就可以像DataOutputStream和DataInputStream那樣直接輸出和讀取各種類型的資料!!!
如果一個類要使用 Externalizable接口實作序列化時, 在此類中必須存在一個無參構造方法, 因為在反序列化時會預設調用無參構造執行個體化對象!!如果沒有此無參構造方法,則運作時将會出現異常, 這點的實作機制與Serializable接口是不同的!!
範例: 修改Person類并實作Externalizable接口
package org.forfan06.serializabledemo;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectInput;
public class Person implements Externalizable{
private String name;
private int age;
public Person(){ //必須定義無參構造方法
}
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:" + this.name + "; 年齡:" + this.age;
}
//覆寫接口Externalizable中定義的兩個抽象方法
public void writeExternal(ObjectOutput out) throws IOException{
out.writeObject(this.name);
out.writeInt(this.age);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException{
this.name = (String) in.readObject();
this.age = in.readInt();
}
}
以上程式,Person類實作了Externalizable接口,這樣使用者在類中有選擇地儲存需要的屬性或其他的具體資料。 在這裡,我們将全部屬性都儲存下來了!
注意: out.writeObject(this.name); --> 是因為ObjectOutput類中定義了writeObject(Object obj), 其子接口ObjectOutputStream類中writeObject(Object obj)是實作了此方法
ObjectOutput類中自己定義了以下方法:
close()、flush()、write(byte[] b)、write(byte[] b, int off, int len)、write(int b)、writeObject(Object obj)。他們都是抽象方法!!!!!!
另外,ObjectOutput類也從java.io.DataOutput中繼承了以下方法:
Methods inherited from interface java.io.DataOutput |
---|
|
範例: 序列化和反序列化Person對象。
(1)Person類的定義:
package org.forfan06.serializabledemo;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectInput;
public class Person implements Externalizable{
private String name;
private int age;
public Person(){ //必須定義無參構造方法
}
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:" + this.name + "; 年齡:" + this.age;
}
//覆寫接口Externalizable中定義的兩個抽象方法
public void writeExternal(ObjectOutput out) throws IOException{
out.writeObject(this.name);
out.writeInt(this.age);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException{
this.name = (String) in.readObject();
this.age = in.readInt();
}
}
(2)序列化和反序列化Person類對象
/*
*對象的序列化、反序列化操作!!!!
*/
package org.forfan06.serializabledemo;
import java.io.File;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerializableDemo03{
public static void main(String args[]) throws Exception{
ser(); //序列化
dser(); //反序列化
}
//對象的序列化
public static void ser() throws IOException{
File f = new File("E:" + File.separator + "test.txt");
ObjectOutputStream oos = null;
OutputStream out = new FileOutputStream(f); //檔案輸入流
oos = new ObjectOutputStream(out); //執行個體化對象輸出流
oos.writeObject(new Person("forfan", 28)); //儲存對象到檔案
oos.close(); //關閉輸出流
}
//對象的反序列化
public static void dser() throws IOException, ClassNotFoundException{
File f = new File("E:" + File.separator + "test.txt");
ObjectInputStream ois = null;
InputStream input = new FileInputStream(f); //檔案輸入流
ois = new ObjectInputStream(input); //為對象輸入流執行個體化
Object obj = ois.readObject(); //讀取對象
ois.close(); //關閉輸入流
System.out.println(obj);
}
}
使用Externalizable接口實作序列化明顯要比使用Serializable接口實作序列化要麻煩很多。兩者的實作方式還有以下差別:
一般的開發中,因為Serializable接口的使用較為友善,是以出現比較多。
12.16.5 transient關鍵字
Serializable接口實作的操作實際上是将一個對象中的全部屬性進行序列化;當然,也可以使用Externalizable接口以實作部分屬性的序列化,但是這樣操作比較複雜。
當使用Serializable接口實作序列化操作時,如果一個對象中的某個/些屬性不希望被序列化時,可以使用關鍵字transient來修飾(進行聲明), 例如:
範例:Person類中的name屬性不希望被序列化
package org.forfan06.serializabledemo;
import java.io.Serializable;
public 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 toString(){
return "姓名: " + this.name + ";年齡 : " + this.age;
}
}
範例:重新儲存、再讀取對象
package org.forfan06.serializabledemo;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
public class SerializableDemo04{
public static void main(String args[]) throws Exception{
ser();
dser();
}
public static void ser() throws Exception{
File f = new File("E:" + File.separator + "test.txt");
ObjectOutputStream oos = null;
OutputStream out = new FileOutputStream(f);
oos = new ObjectOutputStream(out);
oos.writeObject(new Person("forfan06", 28));
oos.close();
}
public static void dser() throws Exception{
File f = new File("E:" + File.separator + "test.txt");
ObjectInputStream ois = null;
InputStream input = new FileInputStream(f);
ois = new ObjectInputStream(input);
Object obj = ois.readObject();
ois.close();
System.out.println(obj);
}
}
運作結果:
姓名:null; 年齡:28
以上程式中的姓名為null,表示内容沒有被序列化儲存下來。這樣在對象反序列化後,輸出時姓名就是預設值null。
12.16.6 序列化一組對象
對象輸出時,隻提供了一個對象的輸出操作(writeObject(Object obj)),并沒有提供多個對象的輸出。
如果要同時序列化多個對象,可以使用對象數組進行操作。因為數組也是屬于引用資料類型,是以可以直接使用Object類型進行接收的!!!
範例:序列化多個Person對象
(1)Person類的定義:
package org.forfan06.serializabledemo;
import java.io.Serializable;
public class Person implements Serializable{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:" + this.name + "; 年齡:" + this.age;
}
}
(2)測試類
package org.forfan06.serializabledemo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
public class SerializableDemo05{
public static void main(String args[]) throws Exception{
Person per[] = {new Person("forfan06", 28), new Person("eric", 31), new Person("linda", 17)};
ser(per);
Object obj[] = dser();
for(int i = 0; i < obj.length; i++){
Person p = (Person) obj[i];
System.out.println(p);
}
}
public static void ser(Object obj[]) throws Exception{
File f = new File("E:" + File.separator + "test.txt");
ObjectOutputStream oos = null;
OutputStream out = new FileOutputStream(f);
oos = new ObjectOutputStream(out);
oos.writeObject(obj);
oos.close();
}
public static Object[] dser() throws Exception{
File f = new File("E:" + File.separator + "test.txt");
ObjectInputStream ois = null;
InputStream input = new FileInputStream(f);
ois = new ObjectInputStream(input);
Object obj[] = (Object[]) ois.readObject();
ois.close();
return obj;
}
}
以上程式中,使用對象數組可以儲存多個對象;但是,數組本身存在長度的限制,為了解決數組中的長度問題,可以使用動态對象數組(類集)完成。
12.17 執行個體操作 -- 單人資訊關系程式
将前面的菜單程式進行擴充,要求增加時可以增加一個人的完整資訊,人的資訊包括姓名和年齡。儲存後也可以修改、删除、查詢此資訊
可以使用對象序列化儲存。此時程式可以使用前面講解過的InputData、Person、Operate、Menu幾個類。 需要增加檔案操作類,專門負責儲存和讀取檔案的内容,并修改Operate類,為其增加具體的操作。
(1)增加檔案操作類FileOperate
package org.forfan06.execdemo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class FileOperate{
private File file = null;
public FileOperate(String pathName){
this.file = new File(pathName);
}
public boolean save(Object obj) throws Exception{
ObjectOutputStream oos = null;
boolean flag = false;
try{
oos = new ObjectOutputStream(new FileOutputStream(this.file));
oos.writeObject(obj);
flag = true;
}catch (Exception e){
e.printStackTrace();
}finally{
if(oos != null){
oos.close();
}
}
return flag;
}
public Object load() throws Exception{
Object obj = null;
ObjectInputStream ois = null;
try
{
ois = new ObjectInputStream(new FileInputStream(this.file));
obj = ois.readObject();
}catch (Exception e){
throw e;
}finally{
if (ois != null){
ois.close();
}
}
return obj;
}
}
以上程式中的FileOperate類的功能就是向程式中寫入對象和 讀取對象,在操作時隻需要傳入一個路徑即可!
(2)修改Person類,增加setter和 getter方法
package org.forfan06.execdemo;
import java.io.Serializable;
public class Person implements Serializable{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String toString(){
return "姓名:" + this.name + ";年齡:" + this.age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
}
需要在增加、修改、删除、顯示的地方編寫具體的代碼,但是在修改時應該先查詢出來,顯示已有的内容。
(3)修改操作類
package org.forfan06.execdemo;
import java.io.File;
public class Operate{
public static void add(){
InputData input = new InputData();
FileOperate fo = new FileOperate("E:" + File.separator + "test.per");
String name = input.getString("請輸入姓名: ");
int age = input.getInt("請輸入年齡: ", "輸入錯誤!年齡必須是數字!");
Person per = new Person(name, age);
try{
fo.save(per);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("資訊增加成功");
}
public static void delete(){
FileOperate fo = new FileOperate("E:" + File.separator + "test.per");
try{
fo.save(null);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("資訊删除成功 !");
}
public static void update(){
InputData input = new InputData();
FileOperate fo = new FileOperate("E:" + File.separator + "test.per");
Person per = null;
try{
per = (Person) fo.load();
}catch(Exception e){
e.printStackTrace();
}
String name = input.getString("請輸入新的姓名 (原姓名: " + per.getName() + "):");
int age = input.getInt("請輸入新的年齡( 原 年齡:" + per.getAge() + "):", "年齡必須是數字");
per = new Person(name, age);
try{
fo.save(per);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("資訊更新成功!");
}
public static void find(){
FileOperate fo = new FileOperate("E:" + File.separator + "test.per");
Person per = null;
try{
per = (Person)fo.load();
}catch(Exception e){
e.printStackTrace();
}
System.out.println(per);
}
}
(4)專門處理輸入資料的類 InputData類!
package org.forfan06.execdemo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.util.Date;
import java.text.SimpleDateFormat;
public class InputData{
private BufferedReader buf = null;
public InputData(){
this.buf = new BufferedReader(new InputStreamReader(System.in));
}
public String getString(String info){
String temp = null;
System.out.println(info);
try{
temp = this.buf.readLine();
}catch(IOException e){
e.printStackTrace();
}
return temp;
}
public int getInt(String info, String err){
int temp = 0;
String str = null;
boolean flag = true;
while(flag){
//str = this.buf.readLine(); should add a try...catch if use this statement,
str = this.getString(info);
if(str.matches("^\\d+$")){
temp = Integer.parseInt(str);
flag = false;
}else{
System.out.println(err);
}
}
return temp;
}
public float getFloat(String info, String err){
float temp = 0;
String str = null;
boolean flag = true;
while(flag){
//str = this.buf.readLine(); should add a try...catch if use this statement,
str = this.getString(info);
if(str.matches("^\\d+.?\\d+$")){
temp = Float.parseFloat(str);
flag = false;
}else{
System.out.println(err);
}
}
return temp;
}
public Date getDate(String info, String err){
Date d = null;
String str = null;
boolean flag = true;
while(flag){
//str = this.buf.readLine(); should add a try...catch if use this statement,
str = this.getString(info);
if(str.matches("^\\d{4}-\\d{2}-\\d{2}$")){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try{
d = sdf.parse(str);
}catch(ParseException e){
e.printStackTrace();
}
flag = false;
}else{
System.out.println(err);
}
}
return d;
}
}
(5)界面類Menu
package org.forfan06.execdemo;
public class MyMenu{
public MyMenu(){
while(true){
this.show();
}
}
public void show(){
System.out.println("=====Xxx系統=====");
System.out.println("[1]、增加資料");
System.out.println("[2]、删除資料");
System.out.println("[3]、修改資料");
System.out.println("[4]、檢視資料");
System.out.println("[0]、系統退出\n");
InputData input = new InputData();
int i = input.getInt("請選擇: ", "請輸入正确的選項!");
switch (i){
case 1:{
Operate.add();
break;
}
case 2:{
Operate.delete();
break;
}
case 3:{
Operate.update();
break;
}
case 4:{
Operate.find();
break;
}
case 0:{
System.exit(1);
break;
}
default:{
System.out.println("請輸入正确的操作!");
}
}
}
}
(6)測試類ExecDemo05
package org.forfan06.execdemo;
public class ExecDemo05{
public static void main(String args[]) throws Exception{
new MyMenu();
}
}
12.18 本章要點
- 本章所講解到的操作類。它們之間的繼承關系
- 在Java中使用File類表示檔案本身,可以直接使用此類完成檔案的各種操作。如建立、删除等
- RandomAccessFile類可以從指定的位置開始讀取資訊,但是要求檔案愛你中各個資料的儲存長度必須固定。
- 輸入/輸出流主要分為位元組流(OutputStream類、InputStream類)和字元流(Writer類、Reader類)兩種。但是在傳輸中以位元組流操作較多; 字元流在操作時使用到緩沖區,而位元組流沒有用到緩沖區。
- 位元組流或字元流都是以抽象類的形式定義的,根據其使用的子類不同,輸入/輸出的位置也不同。
- 在IO包中可以使用OutputStreamWriter類和InputStreamReader類,來完成字元流與位元組流之間的轉換操作!!!!
- 使用ByteArrayInputStream類和ByteArrayOutputStream類可以對記憶體進行輸入/輸出操作。
- 線上程之間進行輸入/輸出通信,主要使用PipedOutputStream類和PipedInputStream類
- 在IO中輸出時最好使用列印流(PrintStream類、PrintWrite類),這樣可以友善地輸出各種類型的資料
- System類提供了3個支援IO操作的常量: out、err、in。 (1)System.out 對應顯示器的标準輸出 (2)System.err 對應錯誤列印,一般此資訊不希望被使用者看到 (3)System.in 對應标準的鍵盤輸入。 *****在程式操作中,根據setOut()方法可以修改System.out的輸出位置; 使用setErr()方法修改System.err的輸出位置; 使用setIn()方法修改System.in的輸入位置*****
- BufferedReader可以直接從緩沖區中讀取資料。 标準的鍵盤輸入!!!!!!!!!!!!!!!!!!!!!!!!!
- 使用Scanner類可以友善地進行輸入流操作
- 資料操作流提供了與平台無關的資料操作,主要使用DataOutputStream類和DataInputStream類
- 使用合并流(SequenceInputStream類)可以将兩個檔案的内容進行合并處理
- 如果資料量過大,則可以使用壓縮流壓縮資料。在Java中支援ZIP、JAR、GZIP3種壓縮格式
- 使用回退流可以将不需要的資料回退到資料緩沖區中以待重新讀取
- 造成字元亂碼的根本原因在于程式編碼與本地編碼的不統一
- 對象序列化可以将記憶體中的對象轉化為二進制資料。 但是,對象所在的類必須實作Serializable接口。一個類中的屬性如果使用transient關鍵字聲明(修飾),表明此屬性的内容将不會被序列化
- 對象的輸入/輸出主要使用ObjectInputStream類、ObjectOutputStream類來完成
12.19 習題
- 編寫Java程式,輸入3個整數,并求出3個整數的最大值和最小值
- 從鍵盤輸入檔案的内容和要儲存的檔案名稱,然後根據輸入的名稱建立檔案,并将内容儲存到檔案中
- 從鍵盤傳入多個字元串到程式中,并将它們按照逆序輸出到螢幕上
- 從鍵盤輸入以下的資料: “TOM:89 | JERRY: 90 | TONY:95”, 資料格式為“姓名:成績 | 姓名:成績 | 姓名:成績” ,對輸入的内容按年齡進行排序,并将排序結果按照成績由高到低排序
- 将第4題中的内容進行擴充,可以将全部輸入的資訊儲存在檔案中,還可以添加資訊,并可以顯示全部的資料
- 編寫程式,程式運作後,根據螢幕提示輸入一個數字字元串,輸入後統計有多少個偶數數字和奇數數字
- 完成系統登入程式,從指令行輸入使用者名和密碼,如果沒有輸入使用者名和密碼,則提示輸入使用者名和密碼;如果輸入了使用者名但是沒有輸入密碼,則提示使用者輸入密碼;然後判斷使用者名是否是csdn,密碼是否是hello;如果正确,則提示登入成功;如果錯誤,則顯示登入失敗的資訊,使用者再次輸入使用者名和密碼,連續3次輸入錯誤後系統退出
- 完成檔案複制操作,在程式運作後提示輸入源檔案路徑,然後再輸入目标檔案路徑
- 編寫程式,程式運作時輸入目錄名稱,并把該目錄下的所有檔案名字尾改為.txt
- 編寫一個投票程式,具體如下:
(1)功能描述
- 有一個班采用民主投票方式推選班長,班長候選人共4位,每個人姓名及代号分别為: “張三 1; 李四 2; 王五 3; 趙六 4”。 程式操作員将每張選票上鎖天的代号(1、2、3或4)循環輸入電腦,輸入數字0結束輸入,然後将所有候選人的得票情況顯示出來,并顯示最終當選者的資訊
(2)具體要求
- 要求面對對象方法,編寫學生類Student,将候選人姓名、代号和票數儲存到類Student中,并實作相應的getXXX和setXXX方法
- 輸入資料前,顯示出各位候選人的代碼及姓名(提示,建立一個候選人類型數組)
- 循環執行接收鍵盤輸入的班長候選人代号,知道輸入的數字為0,結束選票的輸入工作
- 在接收每次輸入的選票後,要求驗證該選票是否有效!也就是,如果輸入的數不是0、1、2、3、4這5個數字之一,或者輸入的是一串字母,應顯示出錯誤提示資訊“此選票無效,請輸入正确的候選人代号!” 并繼續等待輸入
- 輸入結束後,顯示所有候選人的得票情況。
- 輸出最終當選者的相關資訊