2010年11月3日
#
知识点一:分类
IO中按照数据流的方向不同可以分为输入流和输出流(以程序的角度来考虑)
按照数据单位的不同可以分为字节流和字符流。
按照功能的不同可以分为节点流和处理流。
知识点二: 四大等级结构
java语言的i/o库提供了四大等级结构:InputStream,OutputStream,Reader,Writer四个系列的类。InputStream和OutputStream处理8位字节流数据, Reader和Writer处理16位的字符流数据。InputStream和Reader处理输入, OutputStream和Writer处理输出。大家一定要到J2SE文档中看看这四大等级结构的类继承体系。
除了这四大系列类,i/o库还提供了少数的辅助类,其中比较重要的是InputStreamReader和OutputStreamWriter。InputStreamReader把InputStream适配为Reader, OutputStreamWriter把OutputStream适配为Writer;这样就架起了字节流处理类和字符流处理类间的桥梁。
您使用I/O库时,只要按以上的规则,到相应的类体系中寻找您需要的类即可
下面我就会对I/O 进行不定期更新:
1 FileOutputStream 文件字节流
Public class FileInputStream extends InputStream
{
/* File Descriptor - handle to the open file */
private FileDescriptor fd;
public FileInputStream(FileDescriptor fdObj)
{
SecurityManager security = System.getSecurityManager();
if (fdObj == null) {
throw new NullPointerException();
}
if (security != null) {
security.checkRead(fdObj);
}
fd = fdObj;
}
//其他代码
}
可见,FileInputStream继承了InputStream,组合了FileDescriptor,采用的是对象Adapter模式。我们学习i/o库时,主要应该掌握这四个对象Adapter模式的适配源: ByteArrayInputStream的适配源是Byte数组, FileInputStream的适配源是File对象, PipedInputStream的适配源是PipedOutputStream对象, StringBufferInputStream的适配源是String对象
线程间通信:一个线程向数据存储空间添加数据(唐老鸭),另一个线程从数据存储空间取出数据(米琪)。
程序有两种以外需要考虑:
1、 假设唐老鸭线程刚向数据存储空间添加了一辆车的名字。还没有加入这辆车的颜色,CPU就切换到了米琪线程,唐老鸭线程将把这辆车的名字和上辆车的颜色联系到了一起。
2 、唐老鸭了若干次的数据。米琪才开始取数据,或者是,米琪取完了一个数据后,还没等到唐老鸭放入新的数据,又重复取出已取过的数据。
可能出现的问题:
1唐老鸭比米琪快时,米琪会漏掉一些数据没有取到。
2、 米琪比唐老鸭快时,米琪取相同的数据。
多个线程共享同一资源的时候,必须进行同步,采用同步方法,解决第一个问题。
线程的等待和唤醒机制:
wait():告诉当前线程放弃监视器并进入睡眠状态,直到其他线程进入同一监视器并调用notify为止。
notify():唤醒同一对象监视器中调用wait的第一个线程。
程序中采用线程的等待和唤醒机制,当发现米琪没有取走内容时,唐老鸭应该等待,当米琪把内容取走之后,唐老鸭才可以放。这样解决了第二个问题。
代码如下:
package Killva.IOchaper4.o3;
class Animal{
private String name ="唐老鸭";
private String sex= "公";
private boolean flag=false;
public synchronized void set(String name, String sex){//生产者
//如果flag的值不是true则要等待
if(!flag){
//等待
try{
wait();
}catch(Exception e){}
}
//如果向下继续执行了,则表示可以设置, flag =true
this.name=name;
this.sex=sex;
//修改设置的标志
flag = false;
//唤醒其他线程
notify();
}
//设置一个输出的方法
public synchronized void get(){
//如果flag的值为true的时候,表示要等待
if(flag){
try{
wait();
}catch(Exception e){}
}
//如果向下执行了,就表示允许
System.out.println(this.name+"-->"+this.sex);
//改变标签
flag =true;
notify();
}
}
class Pro implements Runnable{
Animal per =null;
public Pro(Animal p){
this.per=p;
}
public void run() {
int i =0;
while (true){
if(i==0){
per.set("米琪", "母");
i=1;
}else{
per.set("唐老鸭", "公");
i=0;
}
}
}
}
class Cus implements Runnable{
Animal per =null;
public Cus(Animal p){
this.per=p;
}
public void run() {
while(true){
per.get();
}
}
}
public class Demo01 {
//主方法
public static void main(String[] args){
Animal per =new Animal();
Pro p =new Pro(per);
Cus c =new Cus(per);
new Thread(p).start();
new Thread(c).start();
}
}
运行结果:
感谢阅读 !!!欢迎交流!!! QQ:237333696
所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。
下面是我忍为比较重要的API:
1、. Accept方法用于产生"阻塞",直到接受到一个连接,并且返回一个客户端的Socket对象实例。"阻塞"是一个术语,它使程序运行暂时"停留"在这个地方,直到一个会话产生,然后程序继续;通常"阻塞"是由循环产生的。
2、. getInputStream方法获得网络连接输入,同时返回一个InputStream对象实例,。
3、. getOutputStream方法连接的另一端将得到输入,同时返回一个OutputStream对象实例。
注意:其中getInputStream和getOutputStream方法均会产生一个IOException,它必须被捕获,因为它们返回的流对象,通常都会被另一个流对象使用。
写代码时一般先写server端.
//Server
package Killva.NetWorkchaper1.o3;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class TestTCPServer {
public static void main(String args[])throws IOException{
ServerSocket ss =new ServerSocket(9999);
while(true){
System.out.println("--------服务端已近启动------------");
Socket s =ss.accept();
DataOutputStream dos =new DataOutputStream(s.getOutputStream());
System.out.println("客户端["+s.getInetAddress().getHostAddress()+
" :"+s.getPort()+
"]已近链接!");
dos.writeUTF("服务器端写入客户端的数据:客户端("+
s.getInetAddress().getHostAddress()+
" :"+s.getPort()+
"]已经链接上服务器端["+
s.getLocalAddress().getHostName()+
":"+s.getLocalPort()+
"]!");
dos.flush();
dos.close();
s.close();
}
}
}
Client端
package Killva.NetWorkchaper1.o3;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
public class TestTCPCLient {
public static void main(String[] args) throws IOException{
System.out.println("-------------client端-----------");
for(long i=0;i<10;i++){
Socket s =new Socket("192.168.1.*",9999);//IP是用你所在的局域网来测试
DataInputStream dis = new DataInputStream(s.getInputStream());
System.out.println(""+dis.readUTF());
dis.close();
s.close();
}
}
}
运行结果真确时服务器端和客户端能连接
感谢阅读!!!!
创建线程有两种方法:继承Thread类和实现Runnable接口。
方法一:继承 Thread 类,覆盖方法 run(),我们在创建的 Thread 类的子类中重写 run() ,加入线程所要执行的代码即可。
a.每个线程都是通过某个特定Thread对象所对应的方法run()l来完成其操作的,方法run()成为线程体。
b.如果想要启动多线程,则肯定调用start()方法,start方法可以调用被子类覆写过的run方法
c.不过这种这种实现方式会受到单继承的局限
下面是一个例子:
public class MyThread extends Thread {
int count= 1, number;
public MyThread(int num) {
number = num;
System.out.println("创建线程 " + number);
}
public void run() {
while(true) {
System.out.println("线程 " + number + ":计数 " + count);
if(++count== 6) return;
}
}
public static void main(String args[]) {
for(int i = 0; i < 5; i++) new MyThread(i+1).start();
}
}
方法二:实现 Runnable 接口
Runnable 接口只有一个方法 run(),我们声明自己的类实现 Runnable 接口并提供这一方法,将我们的线程代码写入其中,就完成了这一部分的任务。
但是 Runnable 接口并没有任何对线程的支持,我们还必须创建 Thread 类的实例,这一点通过 Thread 类的构造函数public Thread(Runnable target);来实现。
该实现方式有以下好处:
① 适合多个相干同程序代码的线程去处理同一资源的情况。
② 可以避免由于Java单继承特性带来的局限。
③ 有利于程序的健壮性,代码能够被多个线程共享。
下面是一个例子:
public class MyThread implements Runnable {
int count= 1, number;
public MyThread(int num) {
number = num;
System.out.println("创建线程 " + number);
}
public void run() {
while(true) {
System.out.println("线程 " + number + ":计数 " + count);
if(++count== 6) return;
}
}
public static void main(String args[]) {
for(int i = 0; i < 5; i++) new Thread(new MyThread(i+1)).start();
}
}
两种方法各有千秋,可以灵活运用。
Java把内存划分成两种:一种是栈内存,一种是堆内存。
在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。
当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。
堆内存用来存放由new建立的对象和数组。
在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。
在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。
引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中运用栈中的引用变量来访问堆中的数组或对象。
具体的说:
栈与堆都是Java用来在Ram中存放数据的地点。与C++不同,Java自动管理栈和堆,程序员不能直接地配置栈或堆。
Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等 指令建立,它们不须要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时 动态分配内存的,Java的垃圾收集器会自动收走这些不再运用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。
栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本 类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。
栈有一个很主要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:
int a = 3;
int b = 3;
编译器先处理int a = 3;首先它会在栈中建立一个变量为a的引用,然后查找栈中能不能有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在建立完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。这时,如果再令a=4;那么编译器 会重新搜索栈中能不能有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改动不会影响到b的值。要留心这 种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。
String是一个特殊的包装类数据。可以用:
String str = new String("abc");
String str = "abc";
两种的形式来建立,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会建立一个新的对象。
而第二种是先在栈中建立一个对String类的对象引用变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向“abc”,如果已经有“abc” 则直接令str指向“abc”。
比较类里面的数值能不能相等时,用equals()要领;当测试两个包装类的引用能不能指向同一个对象时,用==,下面用例子说明上面的理论。
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true可以看出str1和str2是指向同一个对象的。
String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1==str2); // false用new的方式是生成不同的对象。每一次生成一个。
因此用第二种方式建立多个“abc”字符串,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定能不能有必要建立新对象。而对于String str = new String("abc");的代码,则一概在堆中建立新对象,而不管其字符串值能不能相等,能不能有必要建立新对象,从而加重了程序的负担。
另一方面, 要留心 : 我们在运用诸如String str = "abc";的格式定义类时,总是想当然地认为,建立了String类的对象str。担心陷阱!对象可能并没有被建立!而可能只是指向一个先前已经建立的 对象。只有通过new()要领才能保证每次都建立一个新的对象。 由于String类的immutable性质,当String变量须要经常变换其值时,应该考虑运用 StringBuffer类,以提高程序效率。
java中内存分配策略及堆和栈的比较
2.1 内存分配策略按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的.静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求程序代码中不允 许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序不能计算准确的存储空间需求.栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的.和静态存储分配相反,在栈式存储方案中,程序对数据区的需求在编译时是完全未知 的,只有到运行的时候才能够知道,但是规定在运行中进入一个程序模块时,必须知道该程序模块所需的数据区大小才能够为其分配内存.和我们在数据结构所熟知 的栈一样,栈式存储分配按照先进后出的原则执行 分配。
静态存储分配要求在编译时能知道所有变量的存储要求,栈式存储分配要求在流程的入口处必须知道所有的存储要求,而堆式存储分配则专门负责在编译时或运行时 模块入口处都不能确定存储要求的数据结构的内存分配,比如可变长度串和对象实例.堆由大片的可运用 块或空闲块组成,堆中的内存可以按照任意顺序分配和释 放.
2.2 堆和栈的比较
上面的定义从编译原理的教材中总结而来,除静态存储分配之外,都显得很呆板和难以理解,下面撇开静态存储分配,集中比较堆和栈:从堆和栈的功能和作用来通俗的比较,堆主要用来存放对象的,栈主要是用来执行程序的.而这种不同又主要是由于堆和栈的特点决定的:在编程中,例如C/C++中,所有的要领调用都是通过栈来执行 的,所有的局部变量,形式参数都是从栈中分配内存空间的。实际上也不是什么分配,只是从栈顶 向上用就行,就好像工厂中的传送带(conveyor belt)一样,Stack Pointer会自动指引你到放东西的位置,你所要做的只是把东西放下来就行.退出函数的时候,修改栈指针就可以把栈中的内容销毁.这样的模式速度最快, 当然要用来运行程序了.须要留心的是,在分配的时候,比如为一个即将要调用的程序模块分配数据区时,应事先知道这个数据区的大小,也就说是虽然分配是在程 序运行时执行 的,但是分配的大小多少是确定的,不变的,而这个"大小多少"是在编译时确定的,不是在运行时.堆是使用程序在运行的时候请求操作系统分配给自己内存,由于从操作系统管理的内存分配,所以在分配和销毁时都要占用时间,因此用堆的效率非常低.但是堆的 优点在于,编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间,因此,用堆保存数据时会得到更大的灵活性。事实上,面 向对象的多态性,堆内存分配是必不可少的,因为多态变量所需的存储空间只有在运行时建立了对象之后才能确定.在C++中,要求建立一个对象时,只需用 new命令编制有关的代码即可。执行这些代码时,会在堆里自动执行 数据的保存.当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会花 掉更长的时间!这也正是导致我们刚才所说的效率低的原由 ,看来列宁同志说的好,人的优点往往也是人的缺点,人的缺点往往也是人的优点.
2.3 JVM中的堆和栈JVM是基于堆栈的虚拟机.JVM为每个新建立的线程都分配一个堆栈.也就是说,对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只执行 两种操作:以帧为单位的压栈和出栈操作。
我们知道,某个线程正在执行的要领称为此线程的当前要领 .我们可能不知道,当前要领运用的帧称为当前帧。当线程激活一个Java要领 ,JVM就会在线程的 Java堆栈里新压入一个帧。这个帧自然成为了当前帧.在此要领执行期间,这个帧将用来保存参数,局部变量,中间计算流程和其他数据.这个帧在这里和编译 原理中的活动纪录的概念是差不多的.从Java的这种分配机制来看,堆栈又可以这样理解:堆栈(Stack)是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有先进后出的特征。
每一个Java使用都唯一对应一个JVM实例,每一个实例唯一对应一个堆。使用程序在运行中所建立的所有类实例或数组都放在这个堆中,并由使用所有的线程 共享.跟C/C++不同,Java中分配堆内存是自动原始化的。Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也 就是说在建立一个对象时从两个地点都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。
要求:
1、完成一个对水果仓库管理的简单系.。
2、完成,增加、查询、修改简单的操作。
分析:
1、首先我们要有进行分成分析 表层----操作层----底层;
2、表层有什么 :可供操作的选项即(增、查、改);
3、操作层有什么:完成不同的操作(读文件和写文件);
4、底层有什么:完成数据的写出和读入;
步骤:
先完成如下javaproject的创建:
//下面为每个类中的具体内容(按我做改程序的顺须写的)
//Fruit
package VO;
import java.io.Serializable;
@SuppressWarnings("serial")
public class Fruit implements Serializable {
//属性
private String name;
private String area;
private float kg;
//构造方法
public Fruit(){}
public Fruit(String name,String area,float kg){
this.name =name;
this.area =area;
this.kg =kg;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getArea() {
return area;
}
public void setArea(String area) {
this.area = area;
}
public float getKg() {
return kg;
}
public void setKg(float kg) {
this.kg = kg;
}
public String toString (){
return "水果名:"+this.name +" 源产地:"+this.area+" 现重量:"+this.kg ;
}
}
//主方法
package Main;
import Menu.Menu;
public class Main {
//主方法
public static void main(String[] args){
System.out.println("简单的水果仓库管理系统");
//调用Menu方法
new Menu();
}
}
//Menu
package Menu;
import OP.FruitOperate;
import Util.InputDate;
public class Menu {
InputDate input= null;
public Menu(){
this.input=new InputDate();
//循环出现菜单
while (true){
this.show();
}
}
//需要定义的菜单内容
private void show() {
System.out.println("\t\t\t1、增加水果库存");
System.out.println("\t\t\t2、浏览库存信息");
System.out.println("\t\t\t3、修改库存信息");
System.out.println("\t\t\t4、注销管理系统");
System.out.print("\n\n请选择您要使用的操作:");
int temp = input.getInt();
switch(temp){
case 1:{ // 增加水果库存
new FruitOperate().add(); //业务处理层
break;
}
case 2:{ // 浏览库存信息
new FruitOperate().show();
break;
}
case 3:{ // 修改库存信息
new FruitOperate().update();
break;
}
case 4:{ //注销管理系统
System.out.println("注销中******************");
System.out.println("注销成功!");
System.exit(1);
}
default:{ //错误信息提示
System.out.println("请选择正确的操作范围如下:");
break;
}
}
}
}
//对度入数据的相关操作
package Util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class InputDate {
private BufferedReader buf =null;
public InputDate(){
buf = new BufferedReader(new InputStreamReader(System.in));
};
public String getString(){
String str = null;
try {
str = buf.readLine();
} catch (IOException e) {}
return str;
}
public int getInt(){
int temp = 0;
//如果输入的不是数字,告诉用户输入错了~
//可以使用正则验证
String str = null;
boolean flag = true;
while(flag){
//输入数据
str = this.getString();
if (!(str.matches("\\d+"))){
//如果输入的不是一个数字,则必须重新输入
System.out.print("输入的内容必须是上面操作代号的范围,请重新输入:");
}else{
//输入的是一个正确的数字,则可以进行转换
temp = Integer.parseInt(str);
//表示退出循环
flag = false;
}
}
return temp;
}
public float getFloat() {
float f = 0.0f;
//如果输入的不是数字,提示告诉用户输入错了~
//可以使用正则验证
String str = null;
boolean flag = true;
while(flag){
//输入数据
str = this.getString();
if (!(str.matches("\\d+?.\\d{1,2}"))){
//如果输入的不是一个数字,则必须重新输入
System.out.print("输入的内容必须是小数(小数点后两位),请重新输入:");
}else{
//输入的是一个正确的数字,则可以进行转换
f = Float.parseFloat(str);
//表示退出循环
flag = false;
}
}
return f;
}
}
///实现管理的方法类
package OP;
import Util.FileOperate;
import Util.InputDate;
import VO.Fruit;
public class FruitOperate {
private InputDate input = null;
public FruitOperate(){
this.input = new InputDate();
}
//完成具体的Fruit对象操作
public void add(){
//要使用输入数据的类
String name = null;
String area = null;
float kg = 0.0f;
System.out.print("输入水果名:");
name = this.input.getString();
System.out.print("输入源产地:");
area = this.input.getString();
System.out.print("输入入库量:");
kg = this.input.getFloat();
//生成Fruit对象,把对象保存在文件中
Fruit f = new Fruit(name,area,kg);
try{
new FileOperate().save(f); //io操作层
System.out.println("数据保存成功!");
}catch(Exception e){
System.out.println("数据保存失败!");
}
}
public void show(){
//从文件中把内容读进来
Fruit f = null;
try{
f = (Fruit) new FileOperate().read();
}catch(Exception e){
System.out.println("内容显示失败,请确定数据是否存在!");
}
if(f != null){
System.out.println(f);
}
}
public void update(){
//先将之前的信息查出来
Fruit f = null;
try{
f = (Fruit) new FileOperate().read();
}catch(Exception e){
System.out.println("内容显示失败,请确定数据是否存在!");
}
if(f != null){
String name = null;
String area = null;
float kg =0.0f;
System.out.print("请输入新的水果名(原水果名:"+f.getName()+")");
name = this.input.getString();
System.out.print("请输入新的源产地(原源产地:"+f.getArea()+")");
area = this.input.getString();
System.out.print("请输入新的库总量(原库总量:"+f.getKg()+")");
kg = this.input.getFloat();
//信息重新设置
f.setName(name);
f.setArea(area);
f.setKg(kg);
try{
new FileOperate().save(f);
System.out.println("数据更新成功!");
}catch(Exception e){
System.out.println("数据更新失败!");
}
}
}
}
//底层操作 文件的读入和读出
package Util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class FileOperate {
public static final String FILENAME = "E:\\fruit.txt";
//把对象保存在文件之中
public void save(Object obj){
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(new FileOutputStream(new File(FILENAME)));
//写入对象
out.writeObject(obj);
}catch(Exception e){
try {
throw e;
} catch (Exception e1) {}
}finally {
try {
out.close();
}catch(Exception e){}
}
}
//把对象从文件之中读出来
public Object read() throws Exception{
Object obj = null;
ObjectInputStream input =null;
try {
input = new ObjectInputStream(new FileInputStream(new File(FILENAME)));
obj = input.readObject();
} catch (Exception e) {
throw e;
}finally{
try{
input.close();
}catch(Exception e){}
}
return obj;
}
}
运行结果如下:
这篇文章只是一个原理 ,感谢阅读 希望能够提供宝贵意见!QQ:237333696
该程序是很简单 只是把我上一个程序可视化希望能给初学java的人提供帮助!!!
//stock
package StockUI;
public class Stock {
private int id; //
private String name; //
private int price; //
private int flag; //
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getFlag() {
return flag;
}
public void setFlag(int flag) {
this.flag = flag;
}
}
//服务器端
package StockUI;
import java.util.Random;
public class StockServer {
public static void main(String[] args){
Stock sk[] = getStock();
for(int i=0;i<sk.length;i++){
if(sk[i] != null){
System.out.println("name = " + sk[i].getPrice());
}
}
}
public static Stock[] getStock(){
Stock stock[] = new Stock[3];
//#####################################################
Stock sk = new Stock();
sk.setId(1);
sk.setName("ibm");
Random rd = new Random();
sk.setPrice(rd.nextInt(100));
sk.setFlag(1);
stock[0] = sk;
//#######################################################
Stock sk1 = new Stock();
sk1.setId(2);
sk1.setName("sun");
sk1.setPrice(rd.nextInt(100));
sk1.setFlag(1);
stock[1] = sk1;
//######################################################
Stock sk2 = new Stock();
sk2.setId(3);
sk2.setName("oracle");
sk2.setPrice(rd.nextInt(100));
sk2.setFlag(1);
stock[2] = sk2;
return stock;
}
}
package StockUI;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
public class StockUI {
private TableEditor editor = null;
private Table table = null;
public static void main(String[] args) {
new StockUI();
}
private StockUI() {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
shell.setText("大智慧股票模拟系统");
createTable(shell,display);
shell.pack(); //窗口变大
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
/**
* 创建表格
*
* @param shell
*/
private void createTable(final Shell shell,final Display display) {
table = new Table(shell, SWT.MULTI | SWT.FULL_SELECTION);
editor = new TableEditor(table);
editor.horizontalAlignment = SWT.LEFT;
editor.grabHorizontal = true;
table.setHeaderVisible(true);
table.setLinesVisible(true);
TableColumn col1 = new TableColumn(table, SWT.LEFT);
col1.setText("股票代码");
col1.setWidth(100);
TableColumn col2 = new TableColumn(table, SWT.LEFT);
col2.setText("公司名");
col2.setWidth(100);
TableColumn col5 = new TableColumn(table, SWT.LEFT);
col5.setText("现价");
col5.setWidth(100);
TableColumn col3 = new TableColumn(table, SWT.LEFT);
col3.setText("涨幅");
col3.setWidth(100);
TableColumn col4 = new TableColumn(table, SWT.LEFT);
col4.setText("换手率");
col4.setWidth(100);
/**
* 添加表格数据
*/
Stock[] sk = StockServer.getStock();
final TableItem[] itemArr = new TableItem[sk.length];
for(int i=0;i<itemArr.length;i++){
itemArr[i] = new TableItem(table, SWT.LEFT);
}
final int time=1000;
Runnable showTime = new Runnable(){
public void run(){
Stock[] sk = StockServer.getStock();
for(int i=0;i<itemArr.length;i++){
itemArr[i].setText(new String[] { String.valueOf(sk[i].getId()), String.valueOf(sk[i].getName()), String.valueOf(sk[i].getPrice())
});
}
display.timerExec(time, this);
}
};
display.timerExec(time,showTime);//你的swt程序的display
// 删除菜单
Menu menu1 = new Menu(shell, SWT.POP_UP);
table.setMenu(menu1);
MenuItem menuitem1 = new MenuItem(menu1, SWT.PUSH);
menuitem1.setText("删除");
menuitem1.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event event) {
MessageBox mbox = new MessageBox(shell, SWT.DIALOG_TRIM|SWT.ICON_INFORMATION);
mbox.setText("删除成功");
mbox.setMessage("删除了" + table.getSelectionCount() + "条记录");
table.remove(table.getSelectionIndices());
mbox.open();
}
});
// 修改table
{}
}
}
//运行结果如下:
不同时段 不同结果
|