Java程序设计题

构造有限个数的有效三角形

/*创建一个三角形类,包含属性:private int a,b,c;分别代表三角形的三条边。设计是需要满足如下需求:  
a. 在创建对象输入三条边,三边取值必须合法(三边均为正值,且任意两边之和大于第三边),否则将无法创建对象;
b.为使类更易于维护,必须单独设计一个boolean limit(…)函数,实现对三条边的限制检查,符合创建条件则返回真,否则返回假。
c.该类有一个public boolean setEdges(int x, int y, int z)方法(注:此方法为非静态方法),将a/b/c的值替换成x/y/z,返回true。
但当x,y,z的值不满足三角形限制条件时,将不予替换,并返回false;
d. 三角形至多能创建3个。
设计该三角形类,并验证上述需求。 */
public class Triangle {
     
	private int a,b,c;
	static int total = 3,count = 0;
	private Triangle(int x,int y,int z){
     
		a = x;b = y;c = z;
		count++;
	}
	static boolean limit(int x,int y,int z) {
     
		if(x>0 && y>0 && z>0 && x+y>z && x+z>y && y+z>x) {
     
			return true;
		}
		return false;
	}
	public static Triangle setTri(int x,int y,int z) {
     
		if(limit(x,y,z) && count<total) {
     
			return new Triangle(x,y,z);
		}
		return null;
	}
	public boolean setEdges(int x,int y,int z) {
     
		if(limit(x,y,z)) {
     
			a = x;b = y;c = z;
			return true;
		}
		return false;
	}
	public String toString() {
     
		return "(" + a + "," +  b + "," + c + ")";
	}
}
class App1{
     
	public static void main(String[] args) {
     
		Triangle[] t = new Triangle[5];
		t[0] = Triangle.setTri(2, 2, 1);
		t[1] = Triangle.setTri(1, 2, 1);
		t[2] = Triangle.setTri(3, 4, 5);
		t[3] = Triangle.setTri(2, 4, 4);
		t[4] = Triangle.setTri(6, 8, 10);
		for(int i = 0; i<5; i++)
			System.out.println(t[i]);
	}
}

注:

  1. count++要放在构造函数中,只要调用了构造函数就会创建对象
  2. 类中的toString()方法必须用public修饰,不能改小权限,且该方法会被对象自动调用
  3. 静态方法只能使用类中的静态成员,所以limit()方法和total,count变量要为静态的

形状识别器

使用抽象类实现

/*实现智能识别器,可针对圆形、矩形、三角形、梯形不同形状,提供如下服务:
a. 识别形状的面积;
b. 输出形状属性信息:类型和各种参数,如:梯形,上底:20,下底:30,高:10)--- 考虑toString()*/
import static java.lang.Math.PI;
abstract class Shape {
     
	private String type;
	Shape(String t){
     
		type  = t;
	}
	String getType() {
     
		return type;
	}
	abstract double getArea();
}
class Circle extends Shape{
     
	private int  r;
	Circle(String s,int R){
     
		super(s);
		r = R;
	}
	double getArea() {
     
		return PI*r*r;
	}
	public String toString() {
     
		return "半径:" + r;
	}
}
class Rectangle extends Shape{
     
	private int w,h;
	Rectangle(String s,int x,int y){
     
		super(s);
		w = x;h = y;
	}
	double getArea() {
     
		return w*h;
	}
	public String toString() {
     
		return "宽:" + w + ",高:" + h;
	}
}
class Trigon extends Shape{
     
	private int  s,h;
	Trigon(String t,int x,int y){
     
		super(t);
		s = x;h = y;
	}
	double getArea() {
     
		return s*h/2;
	}
	public String toString() {
     
		return "底:" + s + ",高:" + h;
	}
}
class Trapezoidal extends Shape{
     
	private int  a,b,h;
	Trapezoidal(String s,int x,int y,int z){
     
		super(s);
		a = x;b = y;h = z;
	}
	double getArea() {
     
		return (a+b)*h/2;
	}
	public String toString() {
     
		return "上底:" + a + ",下底:" + b + ",高:" + h;
	}
}
class Recognizer{
     
	public static void identify(Shape s) {
     
		System.out.println(s.getType() + "," + s.toString() + ",面积:" + s.getArea());
	}
}
class App2{
     
	public static void main(String[] args) {
     
		Shape[] s = {
     new Circle("圆形", 2),
				new Rectangle("矩形", 3, 4),
				new Trigon("三角形", 4, 2),
				new Trapezoidal("梯形", 2, 4, 3)
		};
		for(int i = 0;i<4;i++)
			Recognizer.identify(s[i]);
	}
}

注:

  1. 私有属性可以通过类中的方法返回得到
  2. abstract类中不一定要有抽象方法,但抽象方法所属类一定是抽象类
  3. 抽象方法不能有方法体
  4. 该识别器基于超类编程,实现即插即用的功能,添加子类很方便

使用接口实现

/*【接口实现】实现智能识别器,可针对圆形、矩形、三角形、梯形不同形状,提供如下服务:
a. 识别形状的面积;
b. 输出形状属性信息:类型和各种参数,如:梯形,上底:20,下底:30,高:10)--- 考虑toString()*/
import static java.lang.Math.PI;
interface Shapein {
     
	public abstract String getType();
	public abstract double getArea();
}
class yx implements Shapein{
     
	private int  r;
	private String type;
	yx(String s,int R){
     
		r = R;
		type = s;
	}
	public String getType() {
     
		return type;
	}
	public double getArea() {
     
		return PI*r*r;
	}
	public String toString() {
     
		return "半径:" + r;
	}
}
class jx implements Shapein{
     
	private int w,h;
	private String type;
	jx(String s,int x,int y){
     
		w = x;h = y;
		type = s;
	}
	public String getType() {
     
		return type;
	}
	public double getArea() {
     
		return w*h;
	}
	public String toString() {
     
		return "宽:" + w + ",高:" + h;
	}
}
class sj implements Shapein{
     
	private int w,h;
	private String type;
	sj(String s,int x,int y){
     
		w = x;h = y;
		type = s;
	}
	public String getType() {
     
		return type;
	}
	public double getArea() {
     
		return w*h/2;
	}
	public String toString() {
     
		return "底:" + w + ",高:" + h;
	}
}
class tx implements Shapein{
     
	private int a,b,h;
	private String type;
	tx(String s,int x,int y,int z){
     
		a = x;b = y;h = z;
		type = s;
	}
	public String getType() {
     
		return type;
	}
	public double getArea() {
     
		return (a+b)*h/2;
	}
	public String toString() {
     
		return "上底:" + a + ",下底:" + b + ",高:" + h;
	}
}
class Identifier{
     
	public static void identify(Shapein s) {
     
		System.out.println(s.getType() + "," + s.toString() + ",面积:" + s.getArea());
	}
}
class App3{
     
	public static void main(String[] args) {
     
		Shapein[] s = {
     new yx("圆形", 2),
				new jx("矩形", 3, 4),
				new sj("三角形", 4, 2),
				new tx("梯形", 2, 4, 3)
		};
		for(int i = 0;i<4;i++)
			Identifier.identify(s[i]);
	}
}

注:

  1. 接口中只能定义常量,且常量都有public static final修饰,接口中的方法都有public abstract修饰
  2. 在main函数中,用的是接口引用指向实现类的对象,Java在利用接口变量调用其实现类的对象的方法时,该方法必须已经在接口中被声明,而且实现类的对象对该方法进行了重写。

兵种游戏设计

/*兵种包括轰炸机、直升机、重型坦克、轻型坦克、音波坦克、步兵、飞行兵
b.轰炸机、直升机、飞行兵属于空军;步兵、轻型坦克、重型坦克属于陆军,音波坦克属于水陆两栖;
c.轻型坦克、步兵只能攻击陆军,音波坦克只能攻击空军,轰炸机可攻击陆军、海军;重型坦克可攻击陆军、空军,直升机、飞行兵可攻击海军、陆军、空军;
并验证设计效果。(即向兵种变量填入海/陆/空军兵种,检测a.attack(b)的输出)*/
interface 陆军{
     }
interface 空军{
     }
interface 海军{
     }
interface 可攻击陆军{
     
	default void attack(陆军 x) {
     System.out.println("可攻击陆军");}
}
interface 可攻击空军{
     
	default void attack(空军 x) {
     System.out.println("可攻击空军");}
}
interface 可攻击海军{
     
	default void attack(海军 x) {
     System.out.println("可攻击海军");}
}
interface 可攻击陆军海军 extends 可攻击陆军,可攻击海军{
     }
interface 可攻击陆军空军 extends 可攻击陆军,可攻击空军{
     }
interface 可攻击陆军空军海军 extends 可攻击陆军,可攻击空军,可攻击海军{
     }
abstract class 兵种{
     
	private String type;
	public String getType() {
     return type;}
	兵种(String x){
     
		type = x;
	}
	public abstract void attack(兵种 x);
	public String attackinfo(兵种 x) {
     
		return getType() + "遇见" + x.getType() +":";
	}
}
class 轰炸机 extends 兵种 implements 空军,可攻击陆军海军{
     
	轰炸机(){
     
		super("轰炸机");
	}
	public void attack(兵种 x) {
     
		if(x instanceof 陆军) {
     
			System.out.print(attackinfo(x));
			attack((陆军)x);
		}else if(x instanceof 海军) {
     
			System.out.print(attackinfo(x));
			attack((海军)x);
		}else {
     
			System.out.println(attackinfo(x) + "不能攻击!");
		}
	}
}
class 直升机 extends 兵种 implements 空军,可攻击陆军空军海军{
     
	直升机(){
     
		super("直升机");
	}
	public void attack(兵种 x) {
     
		if(x instanceof 陆军) {
     
			System.out.print(attackinfo(x));
			attack((陆军)x);
		}else if(x instanceof 海军) {
     
			System.out.print(attackinfo(x));
			attack((海军)x);
		}else {
     
			System.out.print(attackinfo(x));
			attack((空军)x);
		}
	}
}
class 飞行兵 extends 兵种 implements 空军,可攻击陆军空军海军{
     
	飞行兵(){
     
		super("飞行兵");
	}
	public void attack(兵种 x) {
     
		if(x instanceof 陆军) {
     
			System.out.print(attackinfo(x));
			attack((陆军)x);
		}else if(x instanceof 海军) {
     
			System.out.print(attackinfo(x));
			attack((海军)x);
		}else {
     
			System.out.print(attackinfo(x));
			attack((空军)x);
		}
	}
}
class 重型坦克 extends 兵种 implements 陆军,可攻击陆军空军{
     
	重型坦克(){
     
		super("重型坦克");
	}
	public void attack(兵种 x) {
     
		if(x instanceof 陆军) {
     
			System.out.print(attackinfo(x));
			attack((陆军)x);
		}else if(x instanceof 空军) {
     
			System.out.print(attackinfo(x));
			attack((空军)x);
		}else {
     
			System.out.println(attackinfo(x) + "不能攻击!");
		}
	}
}
class 音波坦克 extends 兵种 implements 陆军,海军,可攻击空军{
     
	音波坦克(){
     
		super("音波坦克");
	}
	public void attack(兵种 x) {
     
		if(x instanceof 空军) {
     
			System.out.print(attackinfo(x));
			attack((空军)x);
		}else {
     
			System.out.println(attackinfo(x) + "不能攻击!");
		}
	}
}
class 轻型坦克 extends 兵种 implements 陆军,可攻击陆军{
     
	轻型坦克(){
     
		super("轻型坦克");
	}
	public void attack(兵种 x) {
     
		if(x instanceof 陆军) {
     
			System.out.print(attackinfo(x));
			attack((陆军)x);
		}else {
     
			System.out.println(attackinfo(x) + "不能攻击!");
		}
	}
}
class 步兵 extends 兵种 implements 陆军,可攻击陆军{
     
	步兵(){
     
		super("步兵");
	}
	public void attack(兵种 x) {
     
		if(x instanceof 陆军) {
     
			System.out.print(attackinfo(x));
			attack((陆军)x);
		}else {
     
			System.out.println(attackinfo(x) + "不能攻击!");
		}
	}
}
class App4{
     
	public static void main(String[] args) {
     
		兵种[] x = {
     
				new 轰炸机(),new 直升机(),new 重型坦克(),new 轻型坦克(),new 音波坦克(),new 飞行兵(),new 步兵()
		};
		for(int i = 0;i<x.length;i++) {
     
			x[i].attack(x[x.length-1-i]);
		}
	}
}

注:

  1. 陆军、海军和空军都是空接口,仅起到标签作用
  2. 接口中的attack()方法不是抽象方法,有缺省实现,子类可以不重写
  3. 通过instanceof来判断兵种的具体类型,并在attack()中进行强制类型转换

PCI

/*展示接口实现“功能扩展”
【需求】主板预留PCI插槽。不可能知道该插槽将插装什么硬件。
主板做的事情只能是:加电、启动、run、停止。主板类预留5个PCI插槽,如何实现?
提示:5个插槽,就是5个变量。
 * */
interface PCI {
     
	void start();
	void run();
	void stop();
}
class NetCard implements PCI{
     
	public void start() {
     System.out.print("\n网卡启动  ");}
	public void run() {
     System.out.print("网卡运行");}
	public void stop() {
     System.out.print("\n网卡停止");}
}
class SoundCard implements PCI{
     
	public void start() {
     System.out.print("\n声卡启动  ");}
	public void run() {
     System.out.print("声卡运行");}
	public void stop() {
     System.out.print("\n声卡停止");}
}
class DisplayCard implements PCI{
     
	public void start() {
     System.out.print("\n显卡启动  ");}
	public void run() {
     System.out.print("显卡运行");}
	public void stop() {
     System.out.print("\n显卡停止");}
}
class MainBoard{
     
	PCI[] pci = new PCI[5];
	public void add(PCI x) {
     
		for(int i = 0;i<pci.length;i++)
			if(pci[i] == null){
     
				pci[i] = x;
				return;
			}
		System.out.print("插槽已满!");
	}
	public void start() {
     
		for(int i = 0;i<pci.length;i++)
			if(pci[i] != null) {
     
				pci[i].start();
				pci[i].run();
			}
	}
	public void stop() {
     
		for(int i = 0;i<pci.length;i++)
			if(pci[i] != null) pci[i].stop();
	}
} 
class Computer{
     
	MainBoard mb = new MainBoard();//电脑中有一块主板,主板插装何种板卡通过参数传入
	Computer(PCI[] x){
     
		for(int i = 0;i<x.length;i++) {
     
			mb.add(x[i]);//依次将PCI板卡插入主板
		}
	}
	void start() {
     mb.start();}
	void stop() {
     mb.stop();}
}
class App5{
     
	public static void main(String[] args) {
     
		PCI[] pci = {
     new NetCard(),new SoundCard(),new DisplayCard()};
		Computer c = new Computer(pci);
		c.start();c.stop();
	}
}

互斥

/*线程类T定义方式为:class T implements Runnable{ int data; ...}
线程体实现依次输出data的1~10倍数据。
在main中,构造和启动线程的方式形如: T t=new T(2);  t.start(); 
构造data分别为2、3、5的线程,线程名分别为t2、t3、t5,要求:t2、t3、t5分3行输出,且输出结果不得交叉。
 * */
class D{
     
	int x;
}
class T implements Runnable {
     
	D d;
	int data;
	Thread t;
	T(int x,D y){
     
		data = x;
		d = y;
		t = new Thread(this);
	}
	public void run() {
     
		synchronized(d) {
     
			for(int i = 1;i<=10;i++) {
     
				System.out.print(data*i + " ");
			}
			System.out.println();
		}
	}
	void join() {
     
		try {
     t.join();}catch(Exception e) {
     ;}
	}
	void start() {
     
		t.start();
	}
}
class App6{
     
	public static void main(String[] args) {
     
		System.out.println("main线程开始");
		D d = new D();
		T t2 = new T(2,d);
		T t3 = new T(3,d);
		T t5 = new T(5,d);
		t2.start();t3.start();t5.start();
		t2.join();t3.join();t5.join();
		System.out.println("main线程结束");
	}
}

注:

  1. 类D仅用来充当对象锁和共享资源,所以不同线程传入的D要相同
  2. 该程序中join()用于让main线程在t2、t3和t5线程结束后结束
  3. t2、t3和t5并不是线程对象,但其内部包含线程对象

同步

/*线程类T定义方式为:class T implements Runnable{ int data; ...}
线程体实现依次输出data的1~10倍数据。
在main中,构造和启动线程的方式形如: T t=new T(2);  t.start(); 
构造data分别为2、3、5的线程,线程名分别为t2、t3、t5,要求:t2、t3、t5输出结果按2 3 5 4 6 10...特定顺序输出。
 * */
class Flag{
     
	private int flag = 0;
	void ChangeFlag(int x,int y) {
     
		while(flag!=x) try {
     wait();}catch(Exception e) {
     ;}
		flag = y;notifyAll();
	}
}
class Th implements Runnable{
     
	private Flag flag;
	int data,x,y;
	Thread t;
	Th(int h,int m,int n,Flag f){
     
		t = new Thread(this);
		data = h;flag = f;x = m;y = n;
	}
	public void run() {
     
		synchronized(flag) {
     
			for(int i = 1;i<=10;i++) {
     
				try {
     Thread.sleep(1000);}catch(Exception e) {
     }
				flag.ChangeFlag(x, y);
				System.out.print(data*i + " ");
			}
		}
	}
	void start() {
     t.start();}
}
class App7{
     
	public static void main(String[] args) {
     
		Flag f = new Flag();
		Th t2 = new Th(2,0,1,f);
		Th t3 = new Th(3,1,2,f);
		Th t5 = new Th(5,2,0,f);
		t2.start();t3.start();t5.start();
	}
}

注:

  1. Flag类用于状态标志不同线程的执行顺序,如果轮到t2执行,则将状态改为下一个执行线程的状态,并唤醒所有线程,否则等待
  2. 判断标志时不能用if,因为可能会存在伪唤醒,放在循环体中可避免这种情形
  3. 线程定义中的构造函数需要传入四个值:要进行操作的数据、当前状态、下一个状态、共享资源

委托事件处理模型

/*做一个简单的计算器,[1][+][2]=[3],[]为文本框,点击=按钮计算出结果,最后一个文本框不可点击(enable(false)),并借助标签显示出错信息
 * a.当操作数文本框/运算符文本框中的字符串,在剔除首尾空格后,若字符串长度为0,则抛出自定义异常NoneException,提示“操作数为空”/“运算符为空”
 * b.当运算符框中的字符串s剔除首尾空格(s.trim())后,若包含多个字符/不是+-* /等字符时抛出自定义异常OpCharException,提示“运算符过多”/“无法识别的运算符”
 * c.对Double.parseDouble(s),如果无法将s转换成正确的double值,若s是“1.2.3”、“a.b”、“a3b”或是转换后的数值越界时,将抛出非检查型异常NumberFormatException,
 * 提示“数据格式有错”;产生除零错时将抛出非检查型异常ArithmeticException,提示“除零错”
*/
import java.awt.*;import java.awt.event.*;import javax.swing.*;
class NoneException extends Exception{
     
	public NoneException(String msg){
     super(msg);}
}
class OpCharException extends Exception{
     
	public OpCharException(String msg){
     super(msg);}
}
public class GUI extends JFrame implements ActionListener {
     
	private JTextField op1,op2,opchar,result;//对应操作数1、2、操作符、运算结果
	private JButton bt_eq;//=按钮
	private JLabel t_la;//显示错误信息
	public GUI(){
     
		super("计算器");
		setSize(500,100);
		setLocation(500,500);
		setLayout(new FlowLayout());		
		op1 = new JTextField(5); add(op1);
		opchar = new JTextField(2); add(opchar);
		op2 = new JTextField(5); add(op2);
		bt_eq = new JButton("="); add(bt_eq);
		result = new JTextField(5);
		result.setEnabled(false);
		add(result);
		t_la = new JLabel(" ");
		add(t_la);
		setVisible(true);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置点击关闭按钮
		bt_eq.addActionListener(this);
	}
	private double getDouble(JTextField jf,int num) throws NoneException{
     
		//检测jf是否为合法的操作数
		String s = jf.getText().trim();double val;
		if(s.length() == 0) throw new NoneException("第"+ num + "个操作数为空");
		try {
     
			val = Double.parseDouble(s);
		}catch(NumberFormatException e) {
     
			throw new NumberFormatException("第"+ num + "个操作数格式有错");
		}
		return val;
	}
	private char getOpChar(JTextField jf) throws NoneException,OpCharException{
     
		//检测jf是否为合法的运算符
		String s = jf.getText().trim();
		if(s.length()==0) throw new NoneException("运算符为空");
		if(s.length()>1) throw new OpCharException("运算符过多");
		if("+-*/".indexOf(s)<0) throw new OpCharException("无法识别的运算符");
		return s.charAt(0);//返回字符串第0位置的字符
	}
	private double compute(double a,double b,char op) {
     
		//进行运算
		if(b==0 && op == '/') throw new ArithmeticException("除零错");
		if(op == '+') return a+b;
		if(op == '-') return a-b;
		if(op == '*') return a*b;
		if(op == '/') return a/b;
		return -1;//实际上为通过编译而设置
	}
	public void actionPerformed(ActionEvent e) {
     
		double x,y;
		char z;
//		if(e.getCommand() == bt_eq) {
     
		if(e.getActionCommand().equals("=")) {
     //确定事件源的两种写法
			try {
     
				x = getDouble(op1,1);y = getDouble(op2,2);z = getOpChar(opchar);
				result.setText(compute(x,y,z)+"");
			}
			catch(Exception c) {
     
				result.setText(" ");
				t_la.setText(c.getMessage());
			}
		}
	}
}
class App8{
     
	public static void main(String[] args) {
     new GUI();}
}

注:

  1. 自定义异常类必须是Throwable类的子类,一般以Exception作为超类,且可以通过super()将出错信息传给超类,Exception类也可以通过getMessage()方法显示出错信息
  2. 委托事件处理模型:
    • 处理者(GUI对象)要实现ActionListener接口
    • 类中要重写接口中的actionPerformed()方法,方法中的参数为ActionEvent,在该方法中执行处理过程
    • 将事件源(bt_eq按钮)与处理者相关联(通过addActionListener()方法)
  3. 将处理过程分成多个部分,使处理过程更加清晰
  4. “±* /”.indexOf(s)返回的是指定子字符串s在字符串"±*/"中第一次出现处的索引

复制文件

逐个字符读/写文件

public class FileCopy {
     
	public static void main(String[] args) {
     
		File inF = new File("a.txt");//关联当前文件夹中的文件a.txt,作为读出源头
		File outF = new File("b.txt");//关联当前文件夹中的文件b.txt,作为写入目标
		try {
     
			int ch;
			FileReader in = new FileReader(inF);//建立阅读器对象in
			FileWriter out = new FileWriter(outF);
			System.out.println("文件开始复制");
			while((ch = in.read())!=-1)
				out.write(ch);//从流in中读取字符ch并写入流out
			in.close();out.close();//关闭流,释放相关资源
			System.out.println("文件复制结束");
		}catch(FileNotFoundException e) {
     
			System.out.println("文件未找到!\n" + e);
		}catch(IOException e) {
     
			System.out.println("File read error!\n" + e);
		}
	}
}

注:

  1. a.txt要和src放在同一目录下,否则会找不到文件,当然也可以用绝对路径

按字符流整体读/写文件

public class FileCopy {
     
	public static void main(String[] args) {
     
		File inF = new File("a.txt");
		File outF = new File("c.txt");
		char[] ca = new char[(int)inF.length()];
		try {
     
			FileReader in = new FileReader(inF);
			FileWriter out = new FileWriter(outF);
			System.out.println("文件开始复制");
			in.read(ca);out.write(ca);
			in.close();out.close();
			System.out.println("文件复制结束");
		}catch(FileNotFoundException e) {
     
			System.out.println("文件未找到!\n" + e);
		}catch(IOException e) {
     
			System.out.println("File read error!\n" + e);
		}
	}
}

基于缓冲区读/写文件

public class FileCopy {
     
	public static void main(String[] args) {
     
		String s;
		File inF = new File("a.txt");
		File outF = new File("d.txt");
		try {
     
			FileReader in = new FileReader(inF);
			FileWriter out = new FileWriter(outF);
			BufferedReader br = new BufferedReader(in);
			BufferedWriter bw = new BufferedWriter(out);
			System.out.println("文件开始复制");
			while((s = br.readLine()) !=null) {
     //读取一行,并赋值给字符串s
				bw.write(s,0,s.length());//将s中从0至s.length()的所有字符串写入bw
				bw.newLine();//添加行分隔符
			}
			br.close();bw.close();
			System.out.println("文件复制结束");
		}catch(FileNotFoundException e) {
     
			System.out.println("文件未找到!\n" + e);
		}catch(IOException e) {
     
			System.out.println("File read error!\n" + e);
		}
	}
}

防止出现乱码

class Utf_8_to_GBK {
     
	public static void main(String args[] ){
     
 		BufferedReader br=null; 
 		BufferedWriter bw=null; 
 		String s;
		try{
       //按UTF-8格式读,按GBK格式写
			br=new BufferedReader(new InputStreamReader(new FileInputStream("a.txt"), "UTF-8")); 
			bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("e.txt"), "GBK")); 
			System.out.println("文件开始复制");
			while((s=br.readLine())!=null){
     
				bw.write(s,0,s.length());
				bw.newLine(); 
			}
			br.close(); bw.close();
			System.out.println("文件复制结束");
 		}
 		catch(UnsupportedEncodingException e){
      System.out.println("不支持的编码格式!\n"+e); }
 		catch(FileNotFoundException e){
      System.out.println("文件没找到!\n"+e); }
 		catch(IOException e){
      System.out.println("File read error!\n"+e); }
	}
}

序列化与反序列化

import java.io.*;
class C{
     
	public int x;
}
class B{
     
	public int x;
	public C c;
	public B(int n,C c1) {
     x = n;c = c1;}
}
class A implements Serializable{
     
	int x; 
	transient B b;//b引用对象将不被序列化
}
class ReadObject{
     
	public static void main(String[] args) {
     
		C c = new C();A a =new A();a.x = 10;a.b = new B(5,c);
		System.out.println("序列化前 a.b.x=" + a.b.x);
		A new_a = null;
		try {
     
			FileOutputStream fo = new FileOutputStream("serialObj.bat");
			ObjectOutputStream obj_o = new ObjectOutputStream(fo);
			obj_o.writeObject(a);obj_o.close();
			FileInputStream fi = new FileInputStream("serialObj.bat");
			ObjectInputStream obj_i = new ObjectInputStream(fi);
			new_a = (A)obj_i.readObject();obj_i.close();
		}catch(Exception e) {
     e.printStackTrace();}
		System.out.print("恢复对象 new_a.b.x=" + new_a.b.x);
	}
}

注:

  1. 本例将产生空指针异常,因为未对B对象序列化,在恢复时就没有创建相应的对象,当引用该属性域时会出错
  2. transient是成员修饰符,不能修饰类

你可能感兴趣的:(java,java)