SortedSet 可自动为元素排序。
SortedSet 的实现类是 TreeSet: 它的作用是字为添加到 TreeSet 中的元素排序。
 
练习:自定义类用 TreeSet 排序。
HashSet 不同, TreeSet 并不需要实现 HashCode() equals()
只要实现 compareable compareTo() 接可以实现过滤功能。
(注: HashSet 不调用 CompareTo() )。
 
如果要查询集合中的数据,使用 Set 必须全部遍历,所以查询的效率低。使用 Map ,可通过查找 key 得到 value ,查询效率高。
集合中常用的是: ArrayList HashSet HashMap 。其中 ArrayList HashMap 使用最为广泛。
 
使用 HashMap put() 表示放置元素, get() 表示取元素。
 
遍历 Map ,使用 keySet() 可以返回 set 值,用 keySet() 得到 key 值,使用迭代器遍历,然后使用 put() 得到 value 值。
上面这个算法的关键语句:
Set s=m.keySet();
Interator it=new interator();
Object key=it.next();
Object value=m.get(key);
 
注意: HashMap HashCode 有关,用 Sort 对象排序。
如果在 HashMap 中有 key 值重复,那么后面一条记录的 value 覆盖前面一条记录。
 
Key 值既然可以作为对象,那么也可以用一个自定义的类。比如:
m.put(new sutdent(“Liucy”,30),”boss”)
如果没有语句来判定 Student 类对象是否相同,则会全部打印出来。
 
当我们用自定义的类对象作为 key 时,我们必须在程序中覆盖 HashCode() equals()
 
注: HashMap 底层也是用数组, HashSet 底层实际上也是 HashMap HashSet 类中有 HashMap 属性(我们如何在 API 中查属性)。 HashSet 实际上为 (key.null) 类型的 HashMap 。有 key 值而没有 value 值。
 
正因为以上的原因, TreeSet TreeMap 的实现也有些类似的关系。
注意: TreeSet TreeMap 非常的消耗时间,因此很少使用。
我们应该熟悉各种实现类的选择——非常体现你的功底。
 
HashSet VS TreeSet HashSet 非常的消耗空间, TreeSet 因为有排序功能,因此资源消耗非常的高,我们应该尽量少使用,而且最好不要重复使用。
基于以上原因,我们尽可能的运用 HashSet 而不用 TreeSet ,除非必须排序。
同理: HashMap VS TreeMap: 一般使用 HashMap ,排序的时候使用 TreeMap
HashMap VS Hashtable (注意在这里 table 的第一个字母小写)之间的区别有些类似于 ArrayList Vector Hashtable 是重量级的组件,在考虑并发的情况,对安全性要求比较高的时候使用。
 
Map 的运用非常的多。
 
使用 HashMap() ,如果使用自定义类,一定要覆盖 HashCode() equals()
 
重点掌握集合的四种操作:增加、删除、遍历、排序。
 
Module8—12 利用两天的时间完成。
Module8 :图形界面
Module9 :事件模型(在本部分最重要)
Module10 AWT
Module11 Swing
Module12 Applet (这个技术基本已经被淘汰)
 
软件应用的三个发展阶段:
单机应用
网络应用( C/S 结构)
BS 结构: B 表示浏览器, S 表示 server 端。即利用浏览器作为客户端,因此对于图形界面的要求已经不高,现在的发展趋势是不使用安装,即不用任何的本地应用,图形很快就会被服务器构件开发所取代。
 
经验之谈: Swing 的开发工作会非常的累,而且这项技术正在走向没落。避免从事有这种特征的工作。
AWT 也即将被取代。
Module8 Module11 所使用的技术都将被 JSF 技术所取代。
JSF 是服务器端的 Swing :目前技术已经成熟,但是开发环境(工具)还不成熟。
Module12 Applet 技术也将被 WebStart 所取代。
Module9 为重点,所谓事件模型是指观察者设计模式的 JAVA 应用。事件模型是重点。
 
Module8 :图形界面( java.awt.*
Awt :抽象窗口工具箱,它由三部分组成:
①组件:界面元素;
②容器:装载组件的容器(例如窗体);
③布局管理器:负责决定容器中组件的摆放位置。
图形界面的应用分四步:
①    选择一个容器:
⑴window:带标题的容器(如Frame);
⑵Panel:面板
通过add()想容器中添加组件。
Java 的图形界面依然是跨平台的。但是在调用了一个窗体之后只生成一个窗体,没有事件的处理,关闭按钮并不工作。此时只能使用CTRL+C终止程序。
②设置一个布局管理器:用setLayout();
③向容器中添加组件;
③    添加组件的事务处理。P198
 
P204 :Panel也是一种容器:但是不可见的。在设置容易的时候不要忘记设置它们的可见性。
Panel pan=new Panel;
Fp.setLayout(null); 表示不要布局管理器。
 
五种布局管理器:
P206 :Flow Layout(流式布局):按照组件添加到容器中的顺序,顺序排放组件位置。默认为水平排列,如果越界那么会向下排列。排列的位置随着容器大小的改变而改变。
Panel 默认的布局管理器为Flow Layout。
 
Border Layout :会将容器非常五个区域:东西南北中。
语句:
Button b1=new Botton(“north”);//botton 上的文字
f.add(b1,”North”);// 表示b1这个botton放在north位置
注:一个区域只能放置一个组件,如果想在一个区域放置多个组件就需要使用Panel来装载。
Frame 和Dialog的默认布局管理器是Border Layout。
 
Grid Layout :将容器生成等长等大的条列格,每个块中放置一个组件。
f.setLayout GridLayout(5,2,10,10)// 表示条列格为5行2类,后面为格间距。
 
CardLayout: 一个容器可以放置多个组件,但每次只有一个组件可见(组件重叠)。
使用first(),last(),next()可以决定哪个组件可见。可以用于将一系列的面板有顺序地呈现给用户。
 
重点:GridBag Layout:在Grid中可指定一个组件占据多行多列,GridBag的设置非常的烦琐。
 
Module9:AWT: 事件模型
事件模型指的是对象之间进行通信的设计模式。
对象1给对象2发送一个信息相当于对象1引用对象2的方法。
模型即是一种设计模式(约定俗成)
对象对为三种:
①事件源:发出事件者;
②事件对象:发出的事件本身;
④    事件监听器:提供处理事件指定的方法。
 
Java AWT 事件模型也称为授权事件模型,指事件可以和监听器之间事先建立一种关系:约定那些事件如何处理,由谁去进行处理。这种约定称为授权。
一个事件源可以授权多个监听者(授权也称为监听者的注册);
多个事件源也可以注册多个事件监听器。
监听者对于事件源的发出的事件作出响应。
 
在java.util中有 EventListener 接口:所有事件监听者都要实现这个接口。
java.util 中有 EventObject 类:所有的事件都为其子类。
 
事件范例在 \CoreJava\Girl.java 文件中。 ( 文件已加注释 )                                          
 
注意:接口因对不同的事件监听器对其处理可能不同,所以只能建立监听的功能,而无法实现处理。
 
下面程序建立监听功能:
// 监听器接口要定义监听器所具备的功能,定义方法
{
  void WhatIdoWhenGirlHappy(EmotionEvent e);
void WhatIdoWhenGirlSad(EmotionEvent e);
}
注意查看参考书:事件的设置模式,如何实现授权模型。
 
事件模式的实现步骤:
开发事件对象(事件发送者)——接口——接口实现类——设置监听对象
一定要理解透彻 Gril.java 程序。
 
重点:学会处理对一个事件源有多个事件的监听器(在发送消息时监听器收到消息的排名不分先后)。
事件监听的响应顺序是不分先后的,不是谁先注册谁就先响应。
事件监听由两个部分组成(接口和接口的实现类)。
事件源      事件对象                          事件监听
 gril       EmotinEvent       EmotionListener( 接口 ) Boy( 接口的实现类 )
鼠标事件: MouseEvent ,接口: MouseListener
P235 ActionEvent
注意在写程序的时候: import java.awt.*; 以及 import java.awt.event.* 注意两者的不同。
 
在生成一个窗体的时候,点击窗体的右上角关闭按钮激发窗体事件的方法:窗体 Frame 为事件源, WindowsListener 接口调用 Windowsclosing()
为了配合后面的实现,我们必须将 WindowsListener 所有的方法都实现,除了 Windowsclosing 方法,其余的方法均为空实现。
(练习:写一个带 button 窗体,点关闭按钮退出。)
上面程序中实现了许多不必要的实现类,虽然是空实现。
为了避免上面那些无用的实现,可以利用 WindowEvent 的一个 WindowEvent 类,还是利用 windowsListener 。还有 WindowAdapter 类,它已经实现了 WindowsListener 。它给出的全部都是空实现,那就可以只写想要实现的类,去覆盖其中的类,就不用写空实现。
注意:监听过多,会抛 tooManyListener 例外。
12.06
Module 10
Canvas 组件:画布,可以实现动画操作。
TextArea :文本域。
在单行文本域中回车会激发 ActionEvent
CheckBoxGroup 实现单选框功能。
Java 中,单选框和复选框都是使用 CheckBox 实现。
菜单: new MenuBar() MenuBar 表示菜单条。
菜单中的每一项为 MenuItem ,一般级联菜单不应该超过三级。
练习:
设计一个计算器:注意设置一个 boolean 值( append )来判断输入数字是位于第一个数的后面还是属于输入的第二个数。
设置一个变量来存放“ + ”,点完运算符后,将 append 设置为 false
String number1
Char operator 存放运算符。
 
Module 11 Swing
AWT Java 最早出现的图形界面,但很快就被 Swing 所取代。
Swing 才是一种真正的图形开发。
AWT 在不同平台所出现的界面可能有所不同:因为每个 OS 都有自己的 UI 组件库, java 调用不同系统的 UI
注意 AWT 为重量级组件,相当消耗资源,且不同系统的组件可能不同。因为这个问题使得 AWT 开发的软件难以作到跨平台。
更为要命的是:不同 OS 的组件库都存在 BUG 。必须多种平台进行测试,并且 AWT 的组件库并不丰富。
为解决以上问题, SUN IBM 以及 NETSCAPE 联合开发出 JAVA 基础类包 Swing :注意 JAVA 的基础类以 Swing 为核心。
注意引用: javax.swing.*;javax 表示 JAVA 的扩展。
 
我们在学习 JDBC 的时候会过度到 J2EE
 
Swing 的组件中,基本上都是在 AWT 组件的名称前面加“ J ”。
一般情况下,除了 Choise 等组件 :
import javax.swing.*; 好要加上: import java.awt.* 以及 import java.awt.event.*
Swing AWT 的最大区别是 Swing JAVA 自身的组件。已经不是对等实体,与底层的 OS 无关。
JBUILDER 就是使用 Swing 写的)
 
Swing AWT 在事件模型处理上是一致的。
Jframe 实际上是一堆窗体的叠加。
Swing AWT 更加复杂且灵活。
JDK1.4 中,给 JFRAME 添加 Button 不可用 jf.add(b) 。而是使用 jf.getContentPane().add(b)
content 是先申请面板。不过在 JDK1.5 中可以使用 add.
Jpanel 支持双缓冲技术。
Jbutton 中可以添加图标。
JscrollPane 可以管理比屏幕还要大的组件。
TextArea 只有装入 JscrollPane 中才能实现滚动条。
JeditorPane 用于显示浏览器。
注意: Tabbed Panel Border 的比较。
进度条: ProgressBar
JcomboBox :下拉菜单:在 AWT 中同类组件是 choice
JlistPanel :选择列表
BorderPanel :设置边框
JsplitPanel :可将容器分为两个部分,其中一个部分有 Jtree
TextBox :也是一种新的容器,可以设置组件的间距。
TextFileChoose :文件选择器。
ColorChoose :颜色选择器
Module 12 Applet
Applet Panel 的子类
Applet java 的自动执行方式(这是它的优势,主要用于 HTML )。
工作四种语法: init() start() stop() destory()
Swing 中有一个 Japplet ,如使用 Swing 组件。
Applet 消亡的原因:
①java为安全起见对Applet有所限制:Applet不允许访问本地文件信息、敏感信息,不能执行本地指令(比如FORMAT),不能访问初原服务器之外的其他服务器。
②    IE 不支持新版本的Applet。
Applet 的优势:
网络传输,自动下载。
Application 的优势:没有执行限制。
WebStart :可在网络传输,并且在本地无限制。因此前景光明。
 
练习:
使用Swing实现一个界面,分为上下两个部分,南边为JtextField组件,可编辑,上面为JtextArea组件,不可编辑,在JtextField组件输入字符,按回车,就可以将内容输入到JtextArea组件。(AREA区域可以滚动)
 
12.07
多线程
进程:任务
任务并发执行是一个宏观概念,微观上是串行的。
进程的调度是有OS负责的(有的系统为独占式,有的系统为共享式,根据重要性,进程有优先级)。
 
由OS将时间分为若干个时间片。
JAVA 在语言级支持多线程。
分配时间的仍然是OS。
参看P377
 
线程由两种实现方式:
第一种方式:
class MyThread extends Thread{
   public void run(){
   需要进行执行的代码,如循环。
}
}
 
public class TestThread{
 main(){
   Thread t1=new Mythread();
   T1.start();
}
}
 
只有等到所有的线程全部结束之后,进程才退出。
 
第二种方式:
Class MyThread implements Runnable{
 Public void run(){
 Runnable target=new MyThread();
 Thread t3=new Thread(target);
 Thread.start();// 启动线程
}
}
P384: 通过接口实现继承
 
练习:写两个线程:
①    输入200个“###”②输入200个“***”
 
下面为线程中的7中非常重要的状态:(有的书上也只有认为前五种状态:而将“锁池”和“等待队列”都看成是“阻塞”状态的特殊情况:这种认识也是正确的,但是将“锁池”和“等待队列”单独分离出来有利于对程序的理解)

阻塞
DEAD
 
 


 

初始
                  ①              ⑴
                 ②                   ⑵
                ③                        ⑶             run()结束
    Start()

运行
可运行
                           OS 分配CPU
 


 

                        CPU 时间片结束
                             yield()                      o.wait()
                                             等待锁标记

锁池
等待队列
 
 


 

                                                 notify()
注意:图中标记依次为
①输入完毕;②wake up③t1退出
⑴如等待输入(输入设备进行处理,而CUP不处理),则放入阻塞,直到输入完毕。
⑵线程休眠sleep()
⑶t1.join()指停止main(),然后在某段时间内将t1加入运行队列,直到t1退出,main()才结束。
特别注意:①②③与⑴⑵⑶是一一对应的。
 
进程的休眠:Thread sleep(1000);//括号中以毫秒为单位
main() 运行完毕,即使在结束时时间片还没有用完, CPU 也放弃此时间片,继续运行其他程序。
Try{Thread.sleep(1000);}
Catch(Exception e){e.printStackTrace(e);}
T1.join() 表示运行线程放弃执行权,进入阻塞状态。
t1 结束时, main() 可以重新进入运行状态。
T1.join 实际上是把并发的线程编程并行运行。
线程的优先级: 1-10 ,越大优先级越高,优先级越高被 OS 选中的可能性就越大。(不建议使用,因为不同操作系统的优先级并不相同,使得程序不具备跨平台性,这种优先级只是粗略地划分)。
注:程序的跨平台性:除了能够运行,还必须保证运行的结果。
 
一个使用 yield() 就马上交出执行权,回到可运行状态,等待 OS 的再次调用。
 
下午:
程序员需要关注的线程同步和互斥的问题。
多线程的并发一般不是程序员决定,而是由容器决定。
多线程出现故障的原因:
两个线程同时访问一个数据资源(临界资源),形成数据发生不一致和不完整。
数据的不一致往往是因为一个线程中的两个关联的操作只完成了一步。
 
避免以上的问题可采用对数据进行加锁的方法
每个对象除了属性和方法,都有一个monitor(互斥锁标记),用来将这个对象交给一个线程,只有拿到monitor的线程才能够访问这个对象。
Synchronized: 这个修饰词可以用来修饰方法和代码块
 
Object obj;
Obj.setValue(123);
Synchronized 用来修饰方法,表示当某个线程调用这个方法之后,其他的事件不能再调用这个方法。只有拿到obj标记的线程才能够执行代码块。
注意:Synchronized一定使用在一个方法中。
锁标记是对象的概念,加锁是对对象加锁,目的是在线程之间进行协调。
 
当用Synchronized修饰某个方法的时候,表示该方法都对当前对象加锁。
给方法加Synchronized和用Synchronized修饰对象的效果是一致的。
 
一个线程可以拿到多个锁标记,一个对象最多只能将monitor给一个线程。
Synchronized 是以牺牲程序运行的效率为代价的,因此应该尽量控制互斥代码块的范围。
 
方法的Synchronized特性本身不会被继承,只能覆盖。
 
线程因为未拿到锁标记而发生的阻塞不同于前面五个基本状态中的阻塞,称为锁池。
每个对象都有自己的一个锁池的空间,用于放置等待运行的线程。
这些线程中哪个线程拿到锁标记由系统决定。
 
锁标记如果过多,就会出现线程等待其他线程释放锁标记,而又都不释放自己的锁标记供其他线程运行的状况。就是死锁。
死锁的问题通过线程间的通信的方式进行解决。
线程间通信机制实际上也就是协调机制。
线程间通信使用的空间称之为对象的等待队列,则个队列也是属于对象的空间的。
Object 类中又一个wait(),在运行状态中,线程调用wait(),此时表示着线程将释放自己所有的锁标记,同时进入这个对象的等待队列。
等待队列的状态也是阻塞状态,只不过线程释放自己的锁标记。
Notify()
如果一个线程调用对象的notify(),就是通知对象等待队列的一个线程出列。进入锁池。如果使用notifyall()则通知等待队列中所有的线程出列。
 
注意:只能对加锁的资源进行wait()和notify()。
 
释放锁标记只有在Synchronized代码结束或者调用wait()。
注意锁标记是自己不会自动释放,必须有通知。
注意在程序中判定一个条件是否成立时要注意使用WHILE要比使用IF要严密。
WHILE 会放置程序饶过判断条件而造成越界。
补充知识:
suspend ()是将一个运行时状态进入阻塞状态(注意不释放锁标记)。恢复状态的时候用resume()。Stop()指释放全部。
这几个方法上都有Deprecated标志,说明这个方法不推荐使用。
 
一般来说,主方法main()结束的时候线程结束,可是也可能出现需要中断线程的情况。对于多线程一般每个线程都是一个循环,如果中断线程我们必须想办法使其退出。

如果主方法main()想结束阻塞中的线程(比如sleep或wait)
那么我们可以从其他进程对线程对象调用interrupt()。用于对阻塞(或锁池)会抛出例外Interrupted Exception。
这个例外会使线程中断并执行catch中代码。
 
多线程中的重点:实现多线程的两种方式,Synchronized,以及生产者和消费者问题(ProducerConsumer.java文件)。
 
练习:
①    存车位的停开车的次序输出问题;
②    写两个线程,一个线程打印1-52,另一个线程答应字母A-Z。打印顺序为12A34B56C……5152Z。通过使用线程之间的通信协调关系。
注:分别给两个对象构造一个对象 o ,数字每打印两个或字母每打印一个就执行 o.wait() 。在 o.wait() 之前不要忘了写 o.notify()
 
补充说明:通过 Synchronized ,可知Vector较ArrayList方法的区别就是Vector所有的方法都有Synchronized。所以Vector更为安全。
同样:Hashtable较HashMap也是如此。
12.08
Module 10 I/O 流( java 如何实现与外界数据的交流)
Input/Output :指跨越出了 JVM 的边界,与外界数据的源头或者目标数据源进行数据交换。
               输出

JMV
数据源
 
 


 

              输入                   
  注意:输入 / 输出是针对 JVM 而言。
File 类( java.io.* )可表示一个文件,也有可能是一个目录(在 JAVA 中文件和目录都属于这个类中,而且区分不是非常的明显)。
Java.io 下的方法是对磁盘上的文件进行磁盘操作,但是无法读取文件的内容。
注意:创建一个文件对象和创建一个文件在 JAVA 中是两个不同的概念。前者是在虚拟机中创建了一个文件,但却并没有将它真正地创建到 OS 的文件系统中,随着虚拟机的关闭,这个创建的对象也就消失了。而创建一个文件才是在系统中真正地建立一个文件。
例如: File f=new File(“11.txt”);// 创建一个名为 11.txt 的文件对象
f.CreateNewFile();     // 真正地创建文件
 
f.CreateMkdir() :创建目录
f.delete() ;删除文件
f.deleteOnExit(); 在进程退出的时候删除文件,这样的操作通常用在临时文件的删除。
 
对于命令: File f2=new file(“d:\\abc\\789\\1.txt”)
这个命令不具备跨平台性,因为不同的 OS 的文件系统很不相同。
如果想要跨平台,在 file 类下有 separtor() ,返回锁出平台的文件分隔符。
File.fdir=new File(File.separator);
String str=”abc”+File.separator+”789”;
使用文件下的方法的时候一定注意是否具备跨平台性。
 
List() :显示文件的名(相对路径)
ListFiles() :返回 Files 类型数组,可以用 getName() 来访问到文件名。
使用 isDirectory()isFile()来判断究竟是文件还是目录。
 
练习:
写一个javaTest程序,列出所有目录下的*.java文件,把子目录下的JAVA文件也打印出来。
 
使用I/O流访问file中的内容。
JVM与外界通过数据通道进行数据交换。
分类:
按流分为输入流和输出流;
按传输单位分为字节流和字符流;
还可以分为节点流和过滤流。
节点流:负责数据源和程序之间建立连接;
过滤流:用于给节点增加功能。
过滤流的构造方式是以其他流位参数构造(这样的设计模式称为装饰模式)。
 
字节输入流:io包中的InputStream为所有字节输入流的父类。
Int read();读入一个字节(每次一个);
可先使用new byte[]=数组,调用read(byte[] b)
read (byte[])返回值可以表示有效数;read (byte[])返回值为-1表示结束。
 
字节输出流:io包中的OutputStream位所有字节输入流的父类。
Write和输入流中的read相对应。
 
在流中close()方法由程序员控制。因为输入输出流已经超越了VM的边界,所以有时可能无法回收资源。
原则:凡是跨出虚拟机边界的资源都要求程序员自己关闭,不要指望垃圾回收。
Stream结尾的类都是字节流。
如果构造FileOutputStream的同时磁盘会建立一个文件。如果创建的文件与磁盘上已有的文件名重名,就会发生覆盖。
FileOutputStream中的boolean,则视,添加情况,将数据覆盖重名文件还是将输入内容放在文件的后面。(编写程序验证)
 
DataOutputStream:输入数据的类型。
因为每中数据类型的不同,所以可能会输出错误。
所有对于:DataOutputStream
          DataInputStream
          两者的输入顺序必须一致。
过滤流:
 bufferedOutputStream
 bufferedInputStream
用于给节点流增加一个缓冲的功能。
VM的内部建立一个缓冲区,数据先写入缓冲区,等到缓冲区的数据满了之后再一次性写出,效率很高。
使用带缓冲区的输入输出流的速度会大幅提高,缓冲区越大,效率越高。(这是典型的牺牲空间换时间)
切记:使用带缓冲区的流,如果数据数据输入完毕,使用flush方法将缓冲区中的内容一次性写入到外部数据源。用close()也可以达到相同的效果,因为每次close都会使用flush。一定要注意关闭外部的过滤流。
 
(非重点)管道流:也是一种节点流,用于给两个线程交换数据。
PipedOutputStream
PipedInputStream
输出流:connect(输入流)
 
RondomAccessFile 类允许随机访问文件
GetFilepoint() 可以知道文件中的指针位置,使用 seek() 定位。
Mode(“r”: 随机读; ”w” :随机写; ”rw” :随机读写 )
练习:写一个类 A JAVA A file1 file2
file1 要求是系统中已经存在的文件。 File2 是还没有存在的文件。
执行完这个命令,那么 file2 就是 file1 中的内容。
 
字符流: reader\write 只能输纯文本文件。
FileReader 类:字符文件的输出
 
字节流与字符流的区别:
字节流的字符编码:
字符编码把字符转换成数字存储到计算机中,按 ASCii 将字母映射为整数。
把数字从计算机转换成相应的字符的过程称为解码。
编码方式的分类:
ASCII (数字、英文) :1 个字符占一个字节(所有的编码集都兼容 ASCII
ISO8859-1 (欧洲): 1 个字符占一个字节
GB-2312/GBK 1 个字符占两个字节
Unicode: 1 个字符占两个字节(网络传输速度慢)
UTF-8 :变长字节,对于英文一个字节,对于汉字两个或三个字节。
 
原则:保证编解码方式的统一,才能不至于出现错误。
Io 包的 InputStreamread 称为从字节流到字符流的桥转换类。这个类可以设定字符转换方式。
OutputStreamred: 字符到字节
Bufferread readline() 使得字符输入更加方便。
I/O 流中,所有输入方法都是阻塞方法。
Bufferwrite 给输出字符加缓冲,因为它的方法很少,所以使用父类 printwrite ,它可以使用字节流对象,而且方法很多。
 
练习:做一个记事本
swing/JfileChoose: getSelect file()
InputStreeamReader :把字节变为字符
JAVA 中对字符串长无限制  bufferedReader ir
 
 
 
 
 
 
 
12.09
class ObjectOutputStream 也是过滤流,使节点流直接获得输出对象。
最有用的方法: WriteObject(Object b)
用流传输对象称为对象的序列化,但并不使所有的对象都可以进行序列化的。只有在实现类时必须实现一个接口: IO 包下的 Serializable( 可序列化的 ) 。此接口没有任何的方法,这样的接口称为标记接口。
Class Student implements Serializable
把对象通过流序列化到某一个持久性介质称为对象的可持久化。
Hibernate 就是研究对象的可持久化。
ObuectInputStream in =new ObjectInputStream;
Object o1=in.readObuect();
Student s1=(Student)o1
注意:因为 o1 是一个对象,因为需要对其进行保存。
 
Transient 用来修饰属性。
 Transient int num;
表示当我们对属性序列化时忽略这个属性(即忽略不使之持久化)。
所有属性必须都是可序列化的,特别是当有些属性本身也是对象的时候,要尤其注意这一点。
判断是否一个属性或对象可序列化: Serialver
Serialver TestObject TestObject 必须为已经编译)
执行结果:如果不可序列化;则出现不可序列化的提示。如果可以序列化,那么就会出现序列化的 ID UID
java.until.*
StringTokenizer (参数 1 ,参数 2 )按某种符号隔开文件
StringTokenizer(s,”:”) 用“:”隔开字符, s 为对象。
 
练习:将一个类序列化到文件,然后读出。下午:
1、  网络基础知识
2、  JAVA 网络编程
 
网络与分布式集群系统的区别:每个节点都是一台计算机,而不是各种计算机内部的功能设备。
Ip: 具有全球唯一性,相对于 internet IP 为逻辑地址。
端口 (port) :一台 PC 中可以有 65536 个端口,进程通过端×××换数据。连线的时候需要输入 IP 也需要输入端口信息。
计算机通信实际上的主机之间的进程通信,进程的通信就需要在端口进行联系。
192.168.0.23:21
协议:为了进行网络中的数据交换(通信)而建立的规则、标准或约定。
不同层的协议是不同的。
 
网络层:寻址、路由(指如何到达地址的过程)
传输层:端口连接
TCP 模型:应用层 / 传输层 / 网络层 / 网络接口
端口是一种抽象的软件结构,与协议相关: TCP23 端口和 UDT23 端口为两个不同的概念。
端口应该用 1024 以上的端口,以下的端口都已经设定功能。
套接字 (socket) 的引入:
Ip+Port=Socket (这是个对象的概念。)
Socket 为传输层概念,而 JSP 是对应用层编程。例:
java.net.*;
(Server 端定义顺序 )
ServerSocket(intport)
Socket.accept() // 阻塞方法,当客户端发出请求是就恢复
如果客户端收到请求:
Socket SI=ss.accept()
注意客户端和服务器的 Socket 为两个不同的 socket
Socket 的两个方法:
getInputStream() :客户端用
 getOutputStream() 服务器端用
使用完毕后切记 Socket.close() ,两个 Socket 都关,而且不用关内部的流。
client 端, Socket s=new Socket(“127.0.0.1”,8000);
127.0.0.1 为一个默认本机的地址。
练习:
1、  客户端向服务器发出一个字符串,服务器转换成大写传回客户端。
大写的函数: String.toUpperCase()
2、  服务器告诉客户端:“自开机以来你是第 n 个用户”。
12.12
UDP 编程:
DatagramSocket (邮递员):对应数据报的 Socket 概念,不需要创建两个 socket ,不可使用输入输出流。
DatagramPacket (信件):数据包,是 UDP 下进行传输数据的单位,数据存放在字节数组中。
UDP 也需要现有 Server 端,然后再有 Client 端。
两端都是 DatagramPacket (相当于电话的概念),需要 NEW 两个 DatagramPacket
InetAddress: 网址
这种信息传输方式相当于传真,信息打包,在接受端准备纸。
模式:
发送端: Server:
DatagramPacket inDataPacket=new DatagramPacket ((msg,msg.length); InetAdress.getByName(ip),port);
接收端:
clientAddress=inDataPack.getAddress();// 取得地址
clientPort=inDataPack.getPort();// 取得端口号
datagramSocket.send; //Server
datagramSocket.accept; //Client
注意比较:
http://Localhost:8080/directory // 查找网络服务器的目录
file://directory                 // 查找本地的文件系统
java 的开发主要以 http 为基础。
反射:主要用于工具和框架的开发。
反射是对于类的再抽象;通过字符串来抽象类。
JAVA 类的运行: classLoader: 加载到虚拟机( vm
Vm 中只能存储对象(动态运行时的概念), .class 文件加载到 VM 上就成为一个对象,同时初始静态成员及静态代码(只执行一次)。
Lang 包下有一个类为 Class :在反射中使用。此类中的每个对象为 VM 中的类对象,每个类都对应类类的一个对象( class.class )。
例:对于一个 Object 类,用 getClass() 得到其类的对象,获得类的对象就相当于获得类的信息,可以调用其下的所有方法,包括类的私有方法。
注意:在反射中没有简单数据类型,所有的编译时类型都是对象。
反射把编译时应该解决的问题留到了运行时。