`
xinmigo
  • 浏览: 13780 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论
阅读更多

------------------------------------------------------------------------
Class 类型:类
接口
基本数据类型
数组

获得Class对象的方式:
1、Class.forName("类名");
2、类名.class;
3、obj.getClass();


修饰符
类名
父类
接口
属性:修饰符,类型名
方法:修饰符,返回值类型,方法名,参数类型
构造方法:修饰符,参数类型

生成对象:c.newInstance();
cons.newInstance(Object...args);

访问属性:f.get(Object obj);
f.set(Object obj,Object value);

调用方法:m.invoke(Object obj,Object...args);

反射会破坏封装:f.setAccessible(true);
m.setAccessible(true);


异常
当错误发生的时候减少损失,提高容错性

1、异常的分类

Throwable有两个子类:Error和Exception。
一个Error对象表示一个程序错误,指的是底层的、低级的、不可恢复的严重错误。此时程序一定会退出,因为已经失去了运行所必须的物理环境。
对于Error错误我们无法进行处理,因为我们是通过程序来应对错误,可是程序已经退出了。
我们可以处理的Throwable类中只有Exception类的对象(例外/异常)。

Throwable
|
------------------
| |
Error Exception
错误 |
非常严重 |
不能处理 --------------
| |
RuntimeException 非Runtime异常
未检查异常 已检查异常
由于程序员疏忽造成的 不可避免的
可避免的 必须处理
可处理,可不处理


2、异常的产生和传递
throw new一个异常对象; ---表示抛出一个异常
throw new NullPointerException();
相当于return,函数返回上一级

传递:
沿着方法调用链的顺序反向传递! (异常抛出)mc---->mb---->ma----->main----->Java虚拟机(停止运行)
当一个方法中出现异常,而没有作处理,则以异常对象为返回值返回调用处(逐级传递)
异常返回给虚拟机时,虚拟机终止退出,程序结束

3、异常的处理
(1)声明抛出
是方法声明的第五部分 throws+异常名字(多个异常用“,”分隔)
出现异常,不处理,抛给上一级处理
并且子类抛出异常的范围不能比父类抛出异常的范围更宽。
(2)捕获异常
try - catch
try - catch - finally
try - finally //不捕获异常,当异常发生,返回上一级之前,要运行finally中的代码
以上语句可以嵌套

返回类型 方法名(参数){
try{
可能出错语句
正常语句
}catch(异常类 e){ //某种异常的引用
对异常的处理

正常语句


捕获多个异常:
程序任何时刻只发生一个异常
可对产生的每个异常分别捕捉,也可由同一异常进行处理,前提是这个共用的异常应该是所有这些该被捕获的异常的父类,但是,对于非受查异常不成立
当try后面有多个语句块时,注意catch异常的顺序,子类必须放在父类的前面

finally关键字

无论异常是否发生,一定会执行的代码,可放在finally块内。
要点:没有异常产生时:正常执行try{}catch(){} —> 进入finally语句块 —> 方法中剩余代码
有异常产生时(捕找到) —> 进入catch处理 —> 进入finally语句块 —> 方法中剩余代码
有异常产生时(没捕找到)—> 进入finally语句块 —> 离开方法

一般finally写一些释放资源的代码

在try - catch 块中遇到System.exit(0);或断电,则不会执行finally中的代码

Throwable有一个message属性。在使用catch的时候可以调用:
Catch(IOException e){System.out.println(e.getMessage())}; //打印出来的是创建(throw new)异常对象的时候,给定的参数
Catch(IOException e){e.printStackTrace()}; //打印堆栈追踪信息
以上两条语句都是可以打印出错的过程信息。告诉我们出错类型所历经的过程,在调试的中非常有用。

开发中的两个道理:
①如何控制try的范围:根据操作的连动性和相关性,如果前面的程序代码块抛出的错误影响了后面程序 代码的运行,那么这个我们就说这两个程序代码存在关联,应该放在同一个try中。
②对已经查出来的异常,有throw(消极)和try catch(积极)两种处理方法。
对于throws把异常抛到try catch能够很好地处理异常的位置(即放在具备对异常进行处理的能力的位置 )。如果没有处理能力就继续上抛。


4、自定义异常
(1)继承Exception类
(2)构造方法:
不带参数的构造方法
带参数的构造方法:参数指出错误性质,super(message);把参数传递给父类构造异常

当我们自己定义一个异常类的时候必须使其继承excepiton或者RuntimeException。

throw和throws的区别:

throw后跟异常对象 ,写在方法体内,throw是一个语句,用来做抛出异常的功能。后面的代码不会再运行。

throws用在方法的声明中,在参数表之后函数体之前。而throws是表示如果下级方法中如果有异常抛出,那么本方法不做处理,继续向上抛出。
throws后跟的是异常类型。

例:pulbic Animal(String name,int legs) throws Exception{
this.name=name;
if(legs<0||legs%2!=0){
throw new Exception("错误的腿的条数");
}
this.legs=legs;
}


注意:方法的覆盖中,如果子类的方法抛出的异常是父类方法抛出的异常的父类型,那么编译就会出错:子类无法覆盖父类。
结论:子类方法不可比父类方法抛出更多的异常。子类抛出的异常或者与父类抛出的异常一致,或者是父类抛出异常的子类型。或者子类型不抛出异常。
如果父类型无throws时,子类型也不允许出现throws。此时只能使用try catch。

断言:
断言是一种调试工具(assert) 1.4增加的

其后跟的是布尔类型的表达式,如果表达式结果为真不影响程序运行。如果为假系统出现低级错误,在屏幕上出现assert信息。
Assert只是用于调试。在产品编译完成后上线assert代码就被删除了。

到此JAVA第一部分结束了


第二部分API: GUI 图形界面
Thread 多线程
I/O (文件/网络)
net 网络编程

第三部分:JDK5.0的新特性


第六章串讲

1、修饰符
2、接口
接口 抽象类

没有构造方法 有构造方法
没有非抽象方法 可以有非抽象方法
接口中所有的属性都是static final 没有该限制
方法默认访问权限是pulbic的 没有该限制

接口的多态
为什么用接口:1、为了解决JAVA不能多继承的问题 2、可以把标准的制定者与标准的实现者分离

3、内部类

为什么使用内部类:1、缩小命名空间
2、现实中有这样的需求,B类对象的存在以A类对象的存在为前提。(A类是外部类,B类是内部类)
3、B类中访问到A类私有成员

4、反射

5、集合
1、集合框架
会用:1、选择哪种 2、添加、删除、循环遍历,获得

2、 了解每一种集合类型底层数据结构和存储方式
HashSet 添加元素的规则
对我们覆盖hashCode 和 equals 方法有何指导意义

6、包装类 记住金三角

小知识点:
1、equals(),toString(),hashCode()这些方法的覆盖
2、main()方法的参数
3、String 和 StringBuffer
---------------------------------------------------------------------------
java中的图形界面
GUI,图形化的用户接口,为了人机交互使用的。

构造图形界面的步骤
1,选择一个容器
2,设置容器的布局管理器
3,向容器添加组件
4,事件的监听

容器(Container)用于管理其他的组件的对象。组件必须放到容器里。
JFrame,这是一个最顶层的窗体容器,所有其他的组件必须放在顶层容器里。
JFrame frame = new JFrame("Hello Swing"); //创建窗体,字符串为窗体的标题
frame.setSize(500,300); //设置窗口大小,500像素长,300像素高
frame.setVisible(true); //设置可见性
JPanel,他不是顶层容器,必须放在顶层容器中,任何一个容器都有add()方法,Panel面板是透明的(默认)。他也是一个组件。
JDialog 对话框容器,他要依附于其父组件,他不是一个顶层容器。


布局管理:对于任何一个容器类中都有setLayout()方法,用容器对象调用这个方法,来设置容器的布局管理器(LayoutManager这是一个接口,所有布局管理器都实现了这个接口)。

可用的布局管理器:
所有的布局管理器实现了一个接口java.awt.LayoutManager
FlowLayout,流式布局管。尝试在一行中按增加顺序摆放组件,窗体大小改变时,组件位置会相应发生改变
Panel的默认布局管理就是FlowLayout。
FlowLayout flow = new FlowLayout();
frame.setLayout(flow);
BorderLayout,按方位进行布局管理,(North,South,East,West,Middle)不明确指定,就会默认加载在中间(Middle),每个部分只能放一个组件
frame.add(Component comp,String place);这个方法是在指定的位置添加组件。
JFrame的默认布局管理器
GridLayout,网格布局,通过行列,间距,来用网格分割,把组件放入如网格中,先行后列摆放组件。可以保证每个组件的大小都是一样的
frame.setLayout(new GirdLayout(3,2)); //把容器平均的分为3行2列,先左后右,先上到下的顺序排列
CardLayout,卡片布局,组件重叠放置。
GridBagLayout,组件可以跨行跨列的网格布局。

*** 注意:一定要在图形界面都其他功能都设置好之后才能设置可见性。

JButton :按钮
JTextField:单行文本域
JTextArea:多行文本区
JPasswordField:密码输入框
JScrollPane:滚动窗体 使用一个多行文本域作为参数创建滚动窗体
JComboBox:下拉选择框

JRadioButton:单选按钮
JCheckBox:多选按钮
JList:多行列表
JLabel:标签
JEditorPane:显示结构化文档
Border:边框

JMenuBar:菜单条
JMenu:菜单
JMenuItem:菜单项
JPopupMenu:弹出式菜单

JSlider:滑动条
JProgressBar:进度条
JTabbedPane:分层面板
JSplitPane:分隔面板
JToolBar:工具条

JFileChooser:文件选择器
JColorChooser:颜色选择器

显示对话框
JoptionPane 里面有很多静态方法可以弹出对话框

注意:具体的方法可以去参看Java2 SE的API文档。


三、awt事件模型(观察者模式)(重点)

事件模型中,包括事件源对象,事件处理者(事件监听者对象),事件对象。

事件源和事件处理者之间建立了授权注册关系,也就是在事件源类中有一个事件处理者的对象作为属性,也可能是一个事件处理者的集合。

事件对象
事件源————————〉事件处理者

这就是事件模型的机制,也就是由事件源对象发送一个消息(事件对象),然后事件处理者调用相应的方法处理事件。

在事件监听器接口中定义的方法,都要以事件对象为参数。

*** 一个事件源可以注册多个同类型的监听器,也可以注册多种多个事件监听器,
一个事件监听器也可以为多个事件源服务。

事件对象继承自EventObject类,并可以通过getSource()方法获得事件源对象,当然需要在构造事件对象时将事件源对象传入,来区分是哪个事件源发出的事件,所以要用事件对象作为参数。

事件源,事件对象,监听接口,在java.awt包中提供了很多已经定义好的,只需要实现监听接口就好了。

什么是发消息:
A,B,C三个类,分别作为事件源,事件处理者,事件对象。
在A类中有一个B类的属性或者是一个内容为B类对象的集合,也就是事件源和事件处理者之间的建立了授权关系,
在B类需要实现一个自定义的接口,这个自定义的接口继承了EventListener,EventListener接口中没有定义任何方法,这只是一个标记接口。
实现在自定义接口中定义好的用于事件处理的方法,C类要继承EventObject类。
这些方法是以事件对象为参数的b(C c),而后在A类a(C c)方法中使用B类的对象调用B类中的b(C c)方法,
并把事件对象作为参数,并在main方法中用A类的对象调用了a(c)方法,这也就叫做A类对象给B类发送了消息。

也就是说事件源对象间接调用了事件监听器的方法,并以事件对象为实参传到事件监听器的方法中,要就叫事件源给事件监听器的方法发了一个消息(事件对象)。


例子如下:
import java.util.*;
//事件源类
class A{
private String test;
private List li=new ArrayList();
public A(String test){
this.test=test;
}
public String getTest(){return this.test;}
public void addB(B b){
this.li.add(b);
}
public void removeB(B b){
this.li.remove(b);
}
/*
* 所谓的事件源给事件监听器,发送事件对象。
* 其实就是事件源用事件为参数,调用时间监听器的相应方法
*/
public void fire(){
C c=new C(this);
Iterator it=li.iterator();
while(it.hasNext()){
B b=(B)it.next();
b.b(c);
}
}
}
//事件监听器的接口,要继承EventListener标记接口
//监听接口中的每一个方法,都应该以对应的时间对象作为参数
interface Blistener extends EventListener{
void b(C c);
}
//事件监听器,实现接口
class B implements Blistener{
public void b(C c){
A a=(A)c.getSource();
System.out.println(a.getTest()+" "+c.getMessage());
}
}
/*
* 事件对象类
* 事件对象类中要封装事件源对象
*/
class C extends EventObject{
private String message;
public C(Object src){
super(src);
}
public void setMessage(String message){
this.message=message;
}
public String getMessage(){return this.message;}
}
public class Test{
public static void main(String[] args){
A a1=new A("Event");
B b1=new B();
c1.setMessage("Test");
a1.addB(b1);//注册监听器
a1.fire();//发送事件
}
}
以上代码只是事例,在引入包之后可以运行。

在Java的图形编程中,所有动作(事件)都已经提供了相应的事件对象和事件监听接口,例如:实现窗口的关闭按钮,点击关闭按钮会发出相应的事件对象,相应的调用监听器中实现好的方法。
相应的方法清参阅Java2 SE API帮助文档。

缺省适配模式,通过一个抽象类实现接口,抽象类中的接口方法实现,都是一个无意义的空实现,可以继承这个抽象类,只覆盖向覆盖的方法就可以了。

在java.awt.event包中,会有一些适配类,也就是把相应的XXXListener,换成XXXAdapter就是适配类。
在java.awt.event包中的ActionEvent类,在以下操作中会发送这个事件,
1,JButton组件,按钮被点击
2,JTextField组件,在单行文本域中按Enter键。
3,JCheckBox组件,选中了复选框。
4,JRadioButton组件,选中了单选按钮。
5,JMenu组件,选中菜单项
-----------------------------------------------------------------------
事件:上层 ActionEvent
ItemEvent
TextEvent

底层 WindowEvent
MouseEvent
MouseWheelEvent

JCheckBox 复选框
JRadioButton 单选框
JPasswordField 密码输入框
JToggleButton 开关按钮(选中或不选)
JScrollPane 滚动条
JScrollBar 进度条(滚动条的实现)
JSlider 滑块
JComboBox 下拉菜单
JProgressBar 进度条
JButton 按钮

1、菜单
2、文件选择
3、颜色选择器


线程

C++的多进程是OS系统并发的一个任务
Java中没有多进程,一个JVM就是一个进程

线程是在进程中并发的一个顺序的执行流程

多进程:划分时间片,宏观上并行,微观上串行
多线程:cpu在进程内部再划分时间片

一个线程的三部分:CPU ,代码 ,数据

代码是做什么?,数据是对谁做操作?cpu决定何时做?

进程:进程间数据独立
线程:数据空间共享,堆空间的共享(堆空间中存放的是对象),栈空间是独立的
所以线程间切换容易,称为轻量级进程

线程与进程的区别:
1、一个进程有多个线程
2、进程的数据是独立的,线程的数据是共享的,线程中共享的数据是堆空间,栈空间是独占的

一个线程对象代表了一个线程,并非就是一个线程
线程是操作系统中负责维护的资源
java.lang.Thread类的一个对象就代表一个线程
线程是底层OS维护的资源,JVM跑在OS上,在JVM中创建一个Thread对象,调用其start()方法,底层OS会申请一个线程资源,线程对象可到底层管理一个线程
创建好线程之后,把要让线程执行的代码封装到线程对象中(覆盖run()方法)

只有处在运行状态的线程才能执行代码,当一个进程里的所有线程都结束进程才终止


实现线程代码的方式:
1、继承Thread 类,覆盖run()方法
去底层申请线程并运行,对线程对象调start()方法,main方法是一个主线程
宏观并行,微观串行
2、实现Runnable接口
使用多态获得Runnable对象,成为目标对象
再利用目标对象构造线程对象 Thread t = new Thread(MyThread);


四、多线程的状态转换图(7状态图)
见另一文件,名为thread.jpg

static Thread currentThread() 返回对当前正在执行的线程对象的引用。

static void yield() 暂停当前正在执行的线程对象,并执行其他线程。

long getId() 返回该线程的标识符。

synchronized声明一个对象,也可以声明一个方法

用法1:声明一个对象 synchronized(对象){}
只有获得对象的锁标记才能进这个代码块,出代码块要释放对象的锁标记,代码块锁的是对象

2、声明一个方法 在方法修饰符的地方加synchronized,对当前对象this加锁
-------------------------------------------------------------------------
多线程的通信

因为线程的死锁,从而引发要多线程的通信
死锁:每个线程不释放自己拥有的资源,却申请别的线程拥有的资源,会造成死锁问题
没有获得加锁对象的锁标记的线程,不能访问只有获得该对象所标记才能访问的同步方法,但可以访问这个对象的非同步的方法。

例: t1 t2
synchronized(o1){ synchronized(o2){
synchronized(o2){ synchronized(o1){
} }
} }

t1和t2会形成死锁




  ▲ 初始状态 ▲阻塞状态 ▲终止状态
  \ / ┍ 1等待输入 ┓
  \ / \ 2sleep /
  \start / \ 3join /stop
  \ / \ /
  ┙ ┕ \ /
  ▲ 可运行状态 _ _ _ OS选中 _ _ _\ ▲运行状态
  (只缺CPU) \ CPU到期或调用yield
  ┍ / \
  \ / \wait
  \ Synchronized/ \
  \ / \
  \ / \
  \ / \
  \ ┕ ┙
  ▲ 锁池状态 <------ ▲等待队列
notify/notifyall



线程间的通信:等待通知机制

每一个对象都有一个等待队列。

线程t1对O调用wait方法,△必须是在对O加锁的同步代码块中。
调用wait()方法表示让正在执行的线程停止执行进入对象的等待队列去等待,同时释放掉对象的锁

线程间通信使用的空间称之为对象的等待对列(wait pool),该队列也是属于对象的空间的。

进入等待池

使用Object类中wait()的方法,在运行状态中,线程调用wait(),此时表示线程将释放自己所有的锁标记和CPU的占用,同时进入这个对象的等待池。等待池的状态也是阻塞状态,只不过线程释放自己的锁标记。只有在对该对象加锁的同步代码块里,才能掉用该对象的wait(),表示线程将会释放所有锁标记,进入等待队列,线程将进入等待队列状态。

一个线程进入了对一个对象加锁的同步代码块,并对该对象调用了wait()方法,释放自己拥有的所有锁标记,进入该对象等待队列,另一个线程获得了该对象的锁标记,进入代码块对该对象调用了notify()方法(如果对该对象调用了notifyAll()方法,就会使放等待队列里所有的线程),对该对象调用方法的线程也不会释放所拥有的锁标记(对自身没有影响),也就是从等待队列里释放出一线程,释放出的这个线程要继续运行也就还要进入那个同步代码块,因为得不到要访问代码块对象的锁标记,而进入该对象的锁池,等待所标记释放。

注意:用notifyAll()取代notify(),因为在调用notify()方法时,是由系统决定释放出哪个线程。
退出等待池进入锁池

notify():将从对象的等待池中移走一个任意的线程,并放到锁池中,那里的对象一直在等待,直到可以获得对象的锁标记。
notifyAll(): 将从等待池中移走所有等待那个对象的线程并放到锁池中,只有锁池中的线程能获取对象的锁标记,锁标记允许线程从上次因调用wait()而中断的地方开始继续运行

注意:只能对加锁的资源进行wait()和notify()。
1) wait():交出锁和CPU的占用;
2) notify():将从对象的等待池中移走一个任意的线程,并放到锁池中,那里的对象一直在等待,直到可以获得对象的锁标记。
3) notifyAll(): 将从等待池中移走所有等待那个对象的线程并放到锁池中,只有锁池中的线程能获取对象的锁标记,锁标记允许线程从上次因调用wait()而中断的地方开始继续运行



标准I/O流与文件

_______ 输入 __________
| |————>| |
| JVM | | 数据资源 |
|_______| <————|__________|
输出

对文件的操作

File类(java.io.File)可表示文件或者目录(在JAVA中文件和目录都属于这个类中,而且区分不是非常的明显)。

File下的方法是对磁盘上的文件进行磁盘操作,但是无法读取文件的内容。

注意:File类的对象实施表示一个文件并不是真正的文件,只是一个代理而已,通过这个代理来操作文件创建一个文件对象和创建一个文件在JAVA中是两个不同的概念。前者是在虚拟机中创建了一个文件,但却并没有将它真正地创建到OS的文件系统中,随着虚拟机的关闭,这个创建的对象也就消失了。而创建一个文件才是在系统中真正地建立一个文件。
例如:File f=new File(“11.txt”);//创建一个名为11.txt的文件对象,最好用绝对路径
f.createNewFile(); //真正地创建文件
f.delete();
f.mkdir();
System.out.println(f.getName());//相对路径
System.out.println(f.getAbsolutePath());//绝对路径

File[] listFiles(FileFilter filter)
返回表示此抽象路径名所表示目录中的文件和目录的抽象路径名数组,这些路径名满足特定过滤器。
java.io
接口 FileFilter
accept
boolean accept(File pathname)
File pathname是指被遍历目录中所有文件和目录

File类的方法

Boolean createNewFile() //创建文件
Boolean mkdir() //创建目录
Boolean mkdirs() //创建多个目录
Boolean delete() //删除文件,删除的是创建File对象时指定与之关联创建的那个文件。
Boolean deleteOnExit(); //在JVM进程退出的时候删除文件,这样的操作通常用在临时文件的删除。
String[] List()://返回当前File对象下所以显文件和目录名(相对路径)
File[] ListFiles()://返回当前File对象(必须是目录)所有Files对象,可以用getName()来访问到文件名。
isDirectory()和isFile()//来判断究竟是目录还是文件。
String getParent()//得到父类文件名,只有在构造对象时传入了Parent对象才有。
File getParentFile()//父路径名的抽象路径名,如果没有指定Parent对象,则返回 null。
String getPath()//获得相对路径。
exists() 判断文件或文件夹是否存在。
getAbsolutePath() //获得文件的绝对路径

处理跨平台性

对于命令:File f2=new file(“d:\\abc\\789\\1.txt”)
这个命令不具备跨平台性,因为不同的OS的文件系统的分隔符是不相同。
使用file类的separtor属性,返回当前平台文件分隔符。
File newD = new File("aa"+File.separator+"bb"+File.separator+"cc");
File newF = new File(newD,"mudi.txt");
try{
newD.mkdirs();
newF.createNewFile();
}catch(Exception e){}

一个流也是个对象
流的分类:输入流、输出流
字节流、字符流
节点流、过滤流(包装流) (功能,过滤流是给其它增加个功能,本身不传输数据)

字节输入流
java.io
类 InputStream
字节输入流的所有类的超类
如:FileInputStream,ObjectInputStream,PipedInputStrean都是InputStream类的子类。
java.io
类 FileInputStream
public FileInputStream(String name)
throws FileNotFoundException//文件不存在会抛异常
FileInputStream(File file)
FileInputStream(FileDescriptor fdObj)

1) 三个基本的read()方法
a. int read(): 从流里读出的一个字节或者-1; (实际读了多长) 从此输入流中读取一个数据字节。 返回下一个数据字节;如果已到达文件末尾,则返回 -1。
b. int read(byte[]):将数据读入到字节数组中,并返回所读的字节数; (期望读了多长)
从此输入流中将最多 b.length 个字节的数据读入一个字节数组中。
返回:读入缓冲区的字节总数,如果因为已经到达文件末尾而没有更多的数据,则返回 -1。
c. int read(byte[], int off, int len):两个int参数指定了所要填入的数组的子范围。 从此输入流中将最多 len 个字节的数据读入一个字节数组中
2) 其它方法
a. void close(): 关闭流,如使用过滤器流,关闭最外部的流,会关闭其余的流。 关闭此文件输入流并释放与此流有关的所有系统资源
b. int available(): 返回可从流中读取的字节数。
c. skip(long): 丢弃了流中指定数目的字符。
d. boolean markSupported()
e. void mark(int)
f. void rese()

字节输出流:OutputStream

1) 三个基本的write()方法
a. void write():
b. void write(byte[]):
c. void write(byte[], int , int)
2) 其它方法
a. void close(): 关闭流,如使用过滤器流,关闭最外部的流,会关闭其余的流。
b. void flush(): 允许你强制执行写操作。
注意:在流中close()方法由程序员控制。因为输入输出流已经超越了JVM的边界,所以有时可能无法回收资源。
原则:凡是跨出虚拟机边界的资源都要求程序员自己关闭,不要指望垃圾回收。


Reader和Writer (字符流类,所有字符流的父类型)

1) Java技术使用Unicode来表示字符串和字符,而且提供16位版本的流,以便用类似的方法处理字符。
2) InputStreamReader和OutputStreamWriter作为字节流与字符流中的接口。
3) 如果构造了一个连接到流的Reader和Writer,转换规则会在使用缺省平台所定义的字节编码和Unicode之间切换。

RandomAccessFile 随机存取文件的读取和写入

RandomAccessFile用于定位文件位置的方法:

getFilePointer():返回当前读写指针所处的位置。
seek(long pos):设定读写指针的位置,与文件开头相隔pos个字节数。
skipBytes(int n):使读写指针从当前位置开始,跳过n个字节。
length():返回文件包含的字节数

RandomAccessFile的构造方法:

RandomAccessFile(File file,String mode):参数file指定被访问的文件
RandomAccessFile(String name,String mode):参数name指定被访问的文件的路径。
构造方法中的mode参数指定访问模式,可选值包括"r"和"rw"。"r"表示随机读模式,"rw"表示随机读写模式。
如果程序仅仅读文件,那么选择“r”,如果程序需要同时读和写文件,那么选择"rw"。
注意:RandomAccessFile不支持只写文件模式,因此把mode参数设为“w”是非法的
--------------------------------------------------------------------------------
标准I/O流与文件
对文件的操作
1.File类(java.io.File)可表示文件或者目录(在JAVA中文件和目录都属于这个类中,而且区分不是非常的明显)。
File下的方法是对磁盘上的文件进行磁盘操作,但是无法读取文件的内容。
注意:创建一个文件对象和创建一个文件在JAVA中是两个不同的概念。前者是在虚拟机中创建了一个文件,但却并没有将它真正地创建到OS的文件系统中,随着虚拟机的关闭,这个创建的对象也就消失了。而创建一个文件才是在系统中真正地建立一个文件。
例如:File f=new File(“11.txt”);//创建一个名为11.txt的文件对象
f.CreateNewFile(); //真正地创建文件 [/color]2.File的方法
Boolean createNewFile() //创建文件
Boolean mkdir() //创建目录
Boolean mkdirs() //创建多个目录
Boolean delete() //删除文件
Boolean deleteOnExit(); //在进程退出的时候删除文件,这样的操作通常用在临时文件的删除。
String[] List():返回当前File对象下所以显文件和目录名(相对路径)
File[] ListFiles():返回当前File对象所有Files对象,可以用getName()来访问到文件名。
isDirectory()和isFile()来判断究竟是目录还是文件。
String getParent() 得到父类文件名
File getParentFile() 。。。
String getPath() 。。。路径
exists() 判断文件是否存在

2. 处理跨平台性
对于命令:File f2=new file(“d:\\abc\\789\\1.txt”)
这个命令不具备跨平台性,因为不同的OS的文件系统的分隔符是不相同。
使用file类的separtor属性,返回当前平台文件分隔符。
File newD = new File("aa"+File.separator+"bb"+File.separator+"cc");
File newF = new File(newD,"mudi.txt");
try{
newD.mkdirs();
newF.createNewFile();
}catch(Exception e){}
4. 对象的序列化接口
Serializable接口没有方法,是标识接口,
serialVersionUID的静态常量,在接受传输的数据时会自动检查该值,保证版本的相同。

序列化的步骤:
1) 实现Serializable 接口
2) 实例化对象文件输出对象
3) 将对象输出到文件里
4) 有些临时变量生命周期不需要超过虚拟机的生命周期,需要加上:transient 关键字,这个属性不被序列化。

一个序列化对象内部属性的对象也需要序列化接口。
5. I/O流基础
Input/Output:指跨越出了JVM的边界,与外界进行数据交换。
输出

输入
注意:输入/输出是针对JVM而言。

6. 流的分类
1) 从数据类型分:字节流和字符流
字节流类:
抽象父类: InputStream,OutputStream
实现类:
BufferedInputStream 缓冲流-过虑流
BufferedOutputStream
ByteArrayInputStream 字节数组流-节点流
ByteArrayOutputStream
DataInputStream 处理JAVA标准数据流-过虑流
DataOutputStream
FileInputStream 处理文件IO流-节点流
FileOutputStream
FilterInputStream 实现过虑流-字节过虑流父类
FilterOutputStream
PipedInputStream 管道流
PipedOutputStream
PrintStream 包含print() 和 println()
RandomAccessFile 支持随机文件
抽象父类:Reader, Writer
实现类:
BufferedReader
BufferedWriter
PrintWriter //经常使用的字符输出流,比BufferWriter操作更简单,不用使用桥转换
CharArrayReader
CharArrayWriter
FileReader
FileWriter
FilterReader
FilterWriter
InputStreamReader
OutputStreamWriter
PipedReader
PipedWriter
StringReader
StringWriter



2) 从数据方向分:输入流和输出流
InputXXXXX , OutputXXXXX
3) 从流的功能分:节点流和过滤流(使用到油漆工模式)
节点流用来传输数据。
过滤流用来封装节点流或者其他过滤流,从而给节点流或其他的过滤流增加一个功能。
7. I/O输入输出
流的标准写法:
OutputStream os=null;
OutputStream os=null;
try{ //try块里面的代码可能不执行,所有要把局部变量放在外面.
String a="hello";
byte[] b=a.getBytes();
os=new FileOutputStream("D:\\aa.txt");
os.write(b);
}catch(IOException ioe){
ioe.printStackTrace();
}finally{
if(os!=null){ //防止os为空,抛出空指针
try {
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
1. InputStream类
所有字节输入流的父类,如:FileInputStream,ObjectInputStream,PipedInputStrean
1) 三个基本的read()方法
a. int read(): 从流里读出的一个字节或者-1; (实际读了多长)
b. int read(byte[]):将数据读入到字节数组中,并返回所读的字节数; (期望读了多长)
c. int read(byte[], int , int):两个int参数指定了所要填入的数组的子范围。
2) 其它方法
a. void close(): 关闭流,如使用过滤器流,关闭栈顶部的流,会关闭其余的流。
b. int available(): 返回可从流中读取的字节数。
c. skip(long): 丢弃了流中指定数目的字符。
d. boolean markSupported()
e. void mark(int)
f. void rese()

2. OutputStream方法
答:1) 三个基本的read()方法
a. void write():
b. void write(byte[]):
c. void write(byte[], int , int):
写输出流。
2) 其它方法
a. void close(): 关闭流,如使用过滤器流,关闭栈顶部的流,会关闭其余的流。
b. void flush(): 允许你强制执行写操作。
注:在流中close()方法由程序员控制。因为输入输出流已经超越了JVM的边界,所以有时可能无法回收资源。
原则:凡是跨出虚拟机边界的资源都要求程序员自己关闭,不要指望垃圾回收。

3. FileInputStream和FileOutputStream
答:1) 结点流,使用磁盘文件。
2) 要构造一个FileInputStream, 所关联的文件必须存在而且是可读的。
3) 要构造一个FileOutputStream而输出文件已经存在,则它将被覆盖。 FileInputStream infile = new FileInputStream("myfile.dat");
FIleOutputStream outfile = new FileOutputStream("results.dat");
FileOutputStream outfile = new FileOutputStream(“results.dat”,true);
参数为true时输出为添加,为false时为覆盖。
FileOutputStream类代码:(为什么能建文件)
Public FileOutputStream(String name){
This(name!=null?new File(String):null,false);
}

键盘流
PrintWriter : System.in
4. DataInputStream和DataOutputStream
为过滤流。通过流来读写Java基本类,注意DataInputStream和DataOutputStream的方法 是成对的。
过滤流。输出输入各种数据类型。
writeBoolean(boolean b) ------以1bit数据传送
writeByte(int) ------以1 byte数据传送
writeBytes(String s) --------以byte序列数据传送
writeChar(int v) ――――――以 2 byte
writeChars(String s)-------------以 2 byte序列
writeDouble(double d) -------以 8 byte
writeInt(int v)
writeLong(long l)
writeShort(short s)
writeUTF(String)-----------能输出中文!
6.ObjectInputStream和ObjectOutputStream
过滤流。处理对象的持久化
Object o = new Object();
FileOutputStream fos=new FileOutputStream("Object.txt");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(o);
oos.close();
FileInputStream fis =new FileInputStream(“Object.txt”);
ObjectInputStream ois =new ObjectInputStream(fis);
Object o = (Object)Ois.readObject();
ois.close();
7. BufferInputStream和BufferOutputStream
过滤流,可以提高I/O操作的效率
用于给节点流增加一个缓冲的功能。
在VM的内部建立一个缓冲区,数据先写入缓冲区,等到缓冲区的数据满了之后再一次性写出,效率很高。
使用带缓冲区的输入输出流的速度会大幅提高,缓冲区越大,效率越高。(这是典型的牺牲空间换时间)
切记:使用带缓冲区的流,如果数据数据输入完毕,使用flush方法将缓冲区中的内容一次性写入到外部数据源。用close()也可以达到相同的效果,因为每次close都会使用flush。一定要注意关闭外部的过滤流。

8. PipedInputStream和PipedOutputStream
用来在线程间通信.
PipedOutputStream pos=new PipedOutputStream();
PipedInputStream pis=new PipedInputStream();
try
{
pos.connect(pis);
new Producer(pos).start();
new Consumer(pis).start();
}
catch(Exception e)
{
e.printStackTrace();
}
9.RandomAccessFile 随机访问
可以得到文件指针。
long getFilePointer() 得到从文件开始处到文件指针的位置。
seek(long point) 将文件指针移动到此处。
10 Reader和Writer
1) Java技术使用Unicode来表示字符串和字符,而且提供16位版本的流,以便用类似的方法处理字符。
2) InputStreamReader和OutputStreamWriter作为字节流与字符流中的接口。
3) 如果构造了一个连接到流的Reader和Writer,转换规则会在使用缺省平台所定义的字节编码和Unicode之间切换。
4) 字节流与字符流的区别:
编码是把字符转换成数字存储到计算机中。把数字转换成相应的字符的过程称为解码。
编码方式的分类:
ASCII(数字、英文):1个字符占一个字节(所有的编码集都兼容ASCII)
ISO8859-1(欧洲):1个字符占一个字节
GB-2312/GBK:1个字符占两个字节
Unicode: 1个字符占两个字节(网络传输速度慢)
UTF-8:变长字节,对于英文一个字节,对于汉字两个或三个字节。

10
都是过滤流。
BufferedReader的方法:readLine():String
PrintWriter的方法:println(….String,Object等等)和write()
11. 随机存取文件
1) 实现了二个接口:DataInput和DataOutput;
2) 只要文件能打开就能读写;
3) 通过文件指针能读写文件指定位置;
4) 可以访问在DataInputStream和DataOutputStream中所有的read()和write()操作;
5) 在文件中移动方法:
a. long getFilePointer(): 返回文件指针的当前位置。
b. void seek(long pos): 设置文件指针到给定的绝对位置。
c. long length(): 返回文件的长度。

12.编码问题:
编码的方式:
每个字符对应一个整数。
不同的国家有不同的编码,当编码方式和解码方式不统一时,产生乱码。
因为美国最早发展软件,所以每种的编码都向上兼容ASCII 所以英文没有乱码。
终极解决乱码问题(不得已用之):
String s1=”达内软件it软件工程师”;
byte[] bst1=s1.getBytes(“GBK”);
String s2=new String(bs1,”Big5”);
……………..
byte[] bs2=s2.getBytes(“Big5”);
String s3=new String(bs2,”GBK”);
补充:
字节流结束返回-1
字符流结束返回null
对象流结束返回 EOFException
引申---------〉异常经常被用在流程控制, 异常也是方法的一种返回形式
------------------------------------------------------------------------
[color=black]网络编程

网络基础知识

网络编程的目的就是指直接或间接地通过网络协议与其他计算机进行通讯。
计算机网络形式多样,内容繁杂。网络上的计算机要互相通信,必须遵循一定的协议。目前使用最广泛的网络协议是Internet上所使用的TCP/IP协议。
IP地址:计算机在网络中唯一标识,相对于internet,IP为逻辑地址。

IP地址分类:
A类地址
A类地址第1字节为网络地址,其它3个字节为主机地址。另外第1个字节的最高位固定为0。
A类地址范围:1.0.0.1到126.155.255.254。
A类地址中的私有地址和保留地址:
10.0.0.0到10.255.255.255是私有地址(所谓的私有地址就是在互联网上不使用,而被用在局域网络中的地址)。
127.0.0.0到127.255.255.255是保留地址,用做循环测试用的。

B类地址
B类地址第1字节和第2字节为网络地址,其它2个字节为主机地址。另外第1个字节的前两位固定为10。
B类地址范围:128.0.0.1到191.255.255.254。
B类地址的私有地址和保留地址
172.16.0.0到172.31.255.255是私有地址
169.254.0.0到169.254.255.255是保留地址。如果你的IP地址是自动获取IP地址,而你在网络上又没有找到可用的DHCP服务器,这时你将会从169.254.0.0到169.254.255.255中临得获得一个IP地址。

C类地址
C类地址第1字节、第2字节和第3个字节为网络地址,第4个个字节为主机地址。另外第1个字节的前三位固定为110。
C类地址范围:192.0.0.1到223.255.255.254。
C类地址中的私有地址:
192.168.0.0到192.168.255.255是私有地址。

D类地址
D类地址不分网络地址和主机地址,它的第1个字节的前四位固定为1110。
D类地址范围:224.0.0.1到239.255.255.254

Mac地址:每个网卡专用地址,也是唯一的。
端口(port):应用程序(进程)的标识(网络通信程序)OS中可以有65536(2^16)个端口,进程通过端口交换数据。连线的时候需要输入IP也需要输入端口信息。
计算机通信实际上的主机之间的进程通信,进程的通信就需要在端口进行联系。
192.168.0.23:21
协议:为了进行网络中的数据交换(通信)而建立的规则、标准或约定,协议是为了保证通信的安全。
不同层的协议是完全不同的。

OSI网络参考模型(理论性较强的模型)
七层,应用层、表示层、会话层、传输层、网络层、数据链路层、物理层:

网络层:寻址、路由(指如何到达地址的过程)
传输层:端口连接
TCP模型:应用层/传输层/网络层/网络接口
层与层之间是单向依赖关系,上层依赖于下层,下层不依赖于上层,层与层之间的连接是虚连接。对等层之间建立协议。
端口是一种抽象的软件结构,与协议相关:TCP23端口和UDT23端口为两个不同的概念。
端口应该用1024以上的端口,以下的端口都已经设定功能。

TCP/IP模型
Application
(FTP,HTTP,TELNET,POP3,SMPT)
Transport
(TCP,UDP)
Network
(IP,ICMP,ARP,RARP)
Link
(Device driver,….)

注:
IP:寻址和路由
ARP(Address Resolution Protocol)地址解析协议:将IP地址转换成Mac地址
RARP(Reflect Address Resolution Protocol)反相地址解析协议:与上相反
ICMP(Internet Control Message Protocol)检测链路连接状况。利用此协议的工具:ping , traceroute

TCP Socket
TCP是Tranfer Control Protocol的简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须建立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作。
1) 服务器分配一个端口号,服务器使用accept()方法等待客户端的信号,信号一到打开socket连接,从socket中取得OutputStream和InputStream。
2) 客户端提供主机地址和端口号使用socket端口建立连接,得到OutputStream和InputStream。
TCP/IP的传输层协议

[/color]
[color=black]建立TCP服务器端

一般,我们把服务器端写成是分发Socket的,也就是总是在运行,
创建一个TCP服务器端程序的步骤:

1). 创建一个ServerSocket
2). 从ServerSocket接受客户连接请求
3). 创建一个服务线程处理新的连接
4). 在服务线程中,从socket中获得I/O流
5). 对I/O流进行读写操作,完成与客户的交互
6). 关闭I/O流
7). 关闭Socket
ServerSocket server = new ServerSocket(post)
Socket connection = server.accept();
ObjectInputStream put=new ObjectInputStream(connection.getInputStream());
ObjectOutputStreamo put=newObjectOutputStream(connection.getOutputStream());
处理输入和输出流;
关闭流和socket。
典型的服务器端。
public class Server1 {
public static void main(String[] args) throws Exception {
ServerSocket ss=new ServerSocket(9000);
while(true){
Socket s=ss.accept();//获得一个Socket对象。
Thread t=new Thread1(s);//分发Socket。
t.start();
}
}
}
class Thread1 extends Thread{
Socket s;
public Thread1(Socket s){
this.s=s;
}
public void run(){
try {
OutputStream o=s.getOutputStream();
PrintWriter out=new PrintWriter(o);
out.println("Hello Client");
out.flush();
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
建立TCP客户端

创建一个TCP客户端程序的步骤:
1).创建Socket
2). 获得I/O流
3). 对I/O流进行读写操作
4). 关闭I/O流
5). 关闭Socket
Socket connection = new Socket(127.0.0.1, 7777);
ObjectInputStream input=new ObjectInputStream(connection.getInputStream());
ObjectOutputStream utput=new ObjectOutputStream(connection.getOutputStream());
处理输入和输出流;
关闭流和socket。

练习:
实现一个网络应用,客户端会给服务器发送一个字符串,服务器会把这个字符串转换成大写形式发回给客户端
并有客户端显示,同时,服务器会告知客户端,他是第几个客户端

[/color]
[color=black]UDP socket
这种信息传输方式相当于传真,信息打包,在接受端准备纸。
特点:
1) 基于UDP无连接协议
2) 不保证消息的可靠传输
3) 它们由Java技术中的DatagramSocket和DatagramPacket类支持
DatagramSocket(邮递员):对应数据报的Socket概念,不需要创建两个socket,不可使用输入输出流。
DatagramPacket(信件):数据包,是UDP下进行传输数据的单位,数据存放在字节数组中,其中包括了目标地址和端口以及传送的信息(所以不用建立点对点的连接)。
DatagramPacket的分类:
用于接收:DatagramPacket(byte[] buf,int length)
DatagramPacket(byte[] buf,int offset,int length)
用于发送:DatagramPacket(byte[] buf,int length, InetAddress address,int port )
DatagramPacket(byte[] buf,int offset,int length,InetAddress address,int port)
注:InetAddress类网址用于封装IP地址
没有构造方法,通过
InetAddress.getByAddress(byte[] addr):InetAddress
InetAddress.getByName(String host):InetAddress
等。

建立UDP 发送端
创建一个UDP的发送方的程序的步骤:
1). 创建一个DatagramPacket,其中包含发送的数据和接收方的IP地址和端口
号。
2). 创建一个DatagramSocket,其中包含了发送方的IP地址和端口号。
3). 发送数据
4). 关闭DatagramSocket
byte[] buf = new byte[1024];
DatagramSocket datagramSocket = new DatagramSocket(13);// set port
DatagramPackage intputPackage = new DatagramPackage(buf,buf.length);
datagramSocket.receive(inputPackage);
DatagramPackage outputPackage = new DatagramPackage(buf,buf.length,
inetAddress,port);
datagramSocket.send(outputPackage);
没建立流所以不用断开。

建立UDP 接受端
创建一个UDP的接收方的程序的步骤:
1). 创建一个DatagramPacket,用于存储发送方发送的数据及发送方的IP地址和端口号。
2). 创建一个DatagramSocket,其中指定了接收方的IP地址和端口号。
3). 接收数据
4). 关闭DatagramSocket
byte[] buf = new byte[1024];
DatagramSocket datagramSocket = new DatagramSocket();//不用设端口,因为发送的包中端口
DatagramPackage outputPackage=new DatagramPackage(
Buf,buf.length,serverAddress,serverPort);
DatagramPackage inputPackage=new DatagramPackage(buf,buf.length);
datagramSocket.receive(inputPackage);
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics