1.java异常机制
Java异常(Exception)又称例外,是一种运行时错误。Java异常机制就是对于Java异常的处理方法,使用Java异常机制能提升程序的容错性,从而使程序更加健壮与安全。
异常的分类:
1.异常的继承结构:基类为Throwable,Error和Exception继承Throwable,RuntimeException和IOException等继承Exception.
2. Error和RuntimeException及其子类称为未检查异常(unchecked),其它异常称为已检查异常(checked)。
Error类描述了Java运行系统中的内部错误以及资源耗尽的情形。应用程序不应该抛出这种类型的对象(一般是由虚拟机抛出)。如果出现这种错误,除了尽力使程序安全退出外,在其他方面是无能为力的。
RuntimeException包括错误的类型转换、数组越界访问和试图访问空指针等等。处理RuntimeException的原则是:如果出现RuntimeException,那么一定是程序员的错误。例如,可以通过检查数组下标和数组边界来避免数组越界访问异常。
JAVA中常见的几种异常:算术异常类(ArithmeticException),空指针异常类(NullPointerException),输入输出异常类(IOException),数组下标越界异常类(ArrayIndexOutOfBoundsException)、类型转换异常类(ClassCastException),数字格式异常(NumberFormatException)等。
Java中常有如下三种异常处理方法:
1.使用try-catch-finally语句。try语句块放置可能发生异常的代码,catch语句块捕获这些代码产生的异常,finally语句块无论程序是否有异常发生,都会执行。
2.使用throws关键字抛出异常。若某个方法可能发生异常,但不想在当前方法中处理这个异常,那就可以利用throws关键字在该方法抛出异常,然后在调用该方法的代码中捕获该异常进行处理。
3.自定义异常类与throw关键字
关于自定义异常类的使用,分为如下几个步骤:
1)创建自定义异常类,利用继承思想
2)在方法中通过throw关键字抛出异常对象
3)若在当前抛出异常的方法中处理,使用第一种方法,否则使用第二种方法。
**throw和throws的区别
区别一:
throw 是语句抛出一个异常;throws 是方法抛出一个异常;
throw语法:throw <异常对象>
在方法声明中,添加throws子句表示该方法将抛出异常。
throws语法:[<修饰符>]<返回值类型><方法名>([<参数列表>])[throws<异常类>]
其中:异常类可以声明多个,用逗号分割。
区别二:
throws可以单独使用,但throw不能;
区别三:
throw要么和try-catch-finally语句配套使用,要么与throws配套使用。但throws可以单独使用,然后再由处理异常的方法捕获。
throws E1,E2,E3 只是告诉程序这个方法可能会抛出这些个异常,方法的调用者可能要处理这些异常。而这些异常E1,E2,E3可能是该函数体产生的。 而throw是明确之处这个地方要抛出这个异常。 void doA() throws Exception1, Exception3 { try { ……
} catch(Exception1 e) { throw e;
} catch(Exception2 e) {
System.out.println("出错了"); }
if (a != b)
throw new Exception3("自定义异常"); }
2.实现五子棋进度的保存
感谢队友王小二的大力支持~~
保存进度,其实就是把我们所画的图形存到文件中。因此,我们需要一个文件打开和一个文件写入的方法,当然要实现保存,必须将保存与一个按钮,及其监听器相互绑定起来。
下面又是代码时间~~这次让我们先从主函数开始
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class Chesstry extends JPanel {
String fileName = "F:/五子棋.txt";
Test test = new Test();
private int Longer;
List<Chess> list = new ArrayList();
Graphics g;
ChessListener cl;
public static void main(String[] args) {
// 实例化一个面板对象
Chesstry cb = new Chesstry();
cb.Beautiful();
}
// 写一个设置棋盘的方法
public void Beautiful() {
JFrame jf = new JFrame();
jf.setSize(600, 620);
jf.setTitle("五子棋");
jf.setLocationRelativeTo(null);
JPanel eastJpanel = new JPanel();
// 设置东边的布局的颜色
eastJpanel.setBackground(new Color(227, 160, 200));
// 设置东边的大小
eastJpanel.setPreferredSize(new Dimension(100, 0));
jf.add(eastJpanel, BorderLayout.EAST);
// 在东边添加两个按钮
JButton jb1 = new JButton("开始");
JButton jb2 = new JButton("退出");
JButton jb3 = new JButton("黑子先手");
JButton jb4 = new JButton("白子先手");
JButton jb5 = new JButton("保存");
JButton jb6 = new JButton("打开");
// 将按钮加到面板上
eastJpanel.add(jb1);
eastJpanel.add(jb2);
eastJpanel.add(jb3);
eastJpanel.add(jb4);
eastJpanel.add(jb5);
eastJpanel.add(jb6);
// 给按钮添加监听器
//匿名内部类
jb1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("开始")) {
test.setB1("1");
System.out.println(" " + test.getB1());
}
}
});
jb2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("退出")) {
int i = JOptionPane.showConfirmDialog(null, "请点击关闭按钮退出程序");
if (i == 0) {
System.exit(0);
}
}
}
});
jb3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("黑子先手")) {
test.setB3("1");
}
}
});
jb4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("白子先手")) {
test.setB3("-1");
}
}
});
jb5.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("保存"))
;
try {
// 调用写入方法
write(fileName);
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
jb6.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("打开")) {
try {
// 调用读取文件的方法
open(fileName);
} catch (IOException e1) {
e1.printStackTrace();
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
}
}
});
// 设置棋盘的颜色
this.setBackground(Color.PINK);
jf.add(this, BorderLayout.CENTER);
jf.setVisible(true);
g = jf.getGraphics();
// 获取绘画的图形
Graphics g = this.getGraphics();
// 实例化一个ChessLIstener类的监听对象
// ChessListener cl = new ChessListener(g,b1, b2,b3,b4);
ButtonListener c2 = new ButtonListener(jb3, jb4);
// 给事件源棋盘面板添加鼠标监听器方法,绑定事件处理类的对象
cl = new ChessListener(g, test, list);
this.addMouseListener(cl);
// 绘制棋盘
jf.setDefaultCloseOperation(3);
}
// 重绘操作,重写重绘方法
public void paint(Graphics g) {
super.paint(g);
drawChessTable(g);
}
// 绘制棋盘
private void drawChessTable(Graphics g) {
for (int i = 0; i < Config.ROW; i++) {
g.drawLine(i * Config.SIZE + Config.X, Config.Y, i * Config.SIZE
+ Config.X, Config.Y + (Config.COLUMN - 1) * Config.SIZE);
}
for (int i = 0; i < Config.COLUMN; i++) {
g.drawLine(Config.X, i * Config.SIZE + Config.Y, Config.X
+ (Config.ROW - 1) * Config.SIZE, i * Config.SIZE
+ Config.Y);
}
}
//写一个写入方法,将数据保存到文件里面
public boolean write(String fileName) throws IOException {
this.list = cl.list;
//写入对象
FileOutputStream fos = new FileOutputStream(fileName);
ObjectOutputStream out = new ObjectOutputStream(fos);
// 写入队列的长度
DataOutputStream dos = new DataOutputStream(fos);
//writeInt方法,将棋子个数写入文件中
dos.writeInt(list.size());
for (int i = 0; i < list.size(); i++) {
Chess chess = list.get(i);
out.writeObject(chess);
// System.out.println("aaaaaaaaaaa");
out.flush();
}
//写完文件后关闭文件
dos.close();
out.close();
return true;
}
//定义一个打开文件的方法
public boolean open(String fileName) throws IOException,ClassNotFoundException {
// for (int i = 0; i < list.size(); i++) {
FileInputStream fis = new FileInputStream(fileName);
ObjectInputStream input = new ObjectInputStream(fis);
//首先读取原来队列的长度,即对象的个数
DataInputStream dis = new DataInputStream(fis);
int listSize = dis.readInt();
for (int i = 0; i <listSize; i++) {
//强制转型,读出对象
Chess chess = (Chess) input.readObject();
//判断并设置画布的颜色
if(chess.getColor()==1){
g.setColor(Color.black);
}else{
g.setColor(Color.WHITE);
}
System.out.println(chess.getI()+"ppppppppppppppp"+ chess.getJ());
g.fillOval(chess.getI()+Config.CHESS_SIZE /4, chess.getJ()+Config.CHESS_SIZE ,
Config.SIZE, Config.SIZE);
// chess = (Chess) input.readObject();
}
//数据读取完毕,关闭文件
dis.close();
input.close();
return true;
}
}
接下来是棋子监听器
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JOptionPane;
public class ChessListener extends MouseAdapter {
private Graphics g;
private int b3=0;// 判断黑白棋的依据
private Win win = new Win();
List<Chess> list;
int longer = 0;
int count = 0;// 保证黑白子交替出现
int flag = 0;
Test test;
public ChessListener(Graphics g, Test test, List<Chess> list) {
// TODO Auto-generated constructor stub
this.g = g;
this.test = test;
this.list = list;
System.out.println(test.getB1() + "b2::::::::" + test.getB2());
}
public void mouseReleased(MouseEvent e) {
// System.out.println("222222222222 here b1 is: "+test.getB1());
if (test.getB1().equals("1")) {
int x1 = e.getX();// 得到坐标
int y1 = e.getY();
// System.out.println(x1+" "+y1);
for (int i = 0; i < Config.ROW; i++) {
for (int j = 0; j < Config.COLUMN; j++) {
// 判断此点是否已经被落子
if (Config.array[i][j] == 0) {
// 得到当前的坐标
int x = Config.X + Config.CHESS_SIZE * i
- Config.CHESS_SIZE / 2;
int y = Config.Y + Config.CHESS_SIZE * j
- Config.CHESS_SIZE / 2;
if (x1 > (Config.X + Config.CHESS_SIZE * i - Config.CHESS_SIZE / 3)
// 如果在三分之一范围内就落子
&& x1 < (Config.X + Config.CHESS_SIZE * i + Config.CHESS_SIZE / 3)
&& y1 > (Config.Y + Config.CHESS_SIZE * j - Config.CHESS_SIZE / 3)
&& y1 < (Config.Y + Config.CHESS_SIZE * j + Config.CHESS_SIZE / 3)) {
// 下黑子
if (count == 0) {
g.setColor(Color.black);
count++;
b3 = 1;
} else {
// 下白子
g.setColor(Color.WHITE);
count--;
b3 = -1;
}
g.fillOval(x, y, Config.CHESS_SIZE,
Config.CHESS_SIZE);
Chess chess = new Chess(x, y, b3);// 实例化一个棋子对象,存储当前的坐标及颜色
System.out.println(x+"oooooo"+y);
// 将该棋子对象存到队列里面去
list.add(chess);
Config.array[i][j] = b3;
if (win.validater(i, j)) {
if (b3 == 1) {
JOptionPane.showMessageDialog(null,
"恭喜,黑棋胜利!");
test.setB1("0");
for (int i1 = 0; i1 < Config.ROW; i1++) {
for (int j1 = 0; j1 < Config.COLUMN; j1++) {
Config.array[i1][j1] = 0;
}
}
} else {
JOptionPane.showMessageDialog(null,
"恭喜,白棋胜利!");
test.setB1("0");
for (int i1 = 0; i1 < Config.ROW; i1++) {
for (int j1 = 0; j1 < Config.COLUMN; j1++) {
// Config.array[i][j]=0;
Config.array[i1][j1] = 0;
}
}
}
}
}
}
}
}
}
}
}
按钮监听器
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
public class ButtonListener extends MouseAdapter{
private JButton jb3,jb4;
private Component a;
public ButtonListener(JButton jb3,JButton jb4){
this.jb3 = jb3;
this.jb4 = jb4;
}
}
/**
* 五子棋配置信息的接口
*
*/
public interface Config {
int X = 20;
int Y = 20;
int ROW = 16;
int COLUMN = 16;
int SIZE = 30;
int CHESS_SIZE = 30;
int array[][] = new int[ROW][COLUMN];
}
反序列化棋子
//实例化一个棋子类可以用来反序列化棋子
import java.io.Serializable;
public class Chess implements Serializable {
private int i;
private int j;
private int Color;
public Chess(int i ,int j,int Color){
this.i=i;
this.j=j;
this.Color=Color;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public int getJ() {
return j;
}
public void setJ(int j) {
this.j = j;
}
public int getColor() {
return Color;
}
public void setColor(int color) {
Color = color;
}
}
测试类
//用于测试按钮监听器是否奏效的测试类
public class Test {
String b1="0", b2="0",b3="0",b4="0";
public String getB1() {
return b1;
}
public String getB2() {
return b2;
}
public String getB3() {
return b3;
}
public void setB1(String b1) {
this.b1 = b1;
}
public void setB2(String b2) {
this.b2 = b2;
}
public void setB3(String b3) {
this.b3 = b3;
}
}
备注:关于文件写入与输出的类
第一,ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久存储。
第二,类 DataOutputStream
数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。
看一下效果图