一关键字
Java
标识符的命名规则:
a)
应以字母、下划线、美元符开头
b)
后跟字母、下划线、美元符或数字
所有
Java
关键字都是小写的,
TURE
、
FALSE
、
NULL
等都不是
Java
关键字
goto
和
const
虽然从未使用,但也作被为
Java
关键字保留;
关键字
final
:
在
Java
中声明类、属性和方法时,可使用关键字
final
来修饰。
final
标记的类不能被继承。
final
标记的方法不能被子类重写。
final
标记的变量
(
成员变量或局部变量
)
即成为常量,只能赋值一次。
final
标记的成员变量必须在声明的同时或在每个构造方法中显式赋值,然后才能使用。
二 文件的命名规则,当类声明为public时,文件名必须与类名相同。
三 运算符,结合律,按位运算符^ | & ~ << >> ++运算符
短路逻辑运算符应用
&& --
第一个操作数为假则不判断第二个操作数
|| --
第一个操作数为真则不判断第二个操作数
~6 = -7
6->00000110->11111001(
补码
)->10000111(
原码
)->-7
补码变原码:从低位第一个
1
开始,第一个
1
不变,依次将高位取反(符号位不变)。
–
适用数据类型
:byte
、
short
、
char
、
int
、
long
,对低于
int
型的操作数将先自动转换为
int
型再移位
–
对于
int
型整数移位
a>>b
,系统先将
b
对
32
取模,得到的结果才是真正移位的位数
8>>65 = 4
–
对于
long
型整数移位时
a>>b
,则是先将移位位数
b
对
64
取模
四 数据类型转换
1 数据类型转换的种类
java数据类型的转换一般分三种,分别是:
(1). 简单数据类型之间的转换
(2). 字符串与其它数据类型的转换
(3). 其它实用数据类型转换
2 简单数据类型之间的转换
在Java中整型、实型、字符型被视为简单数据类型,这些类型由低级到高级分别为
(byte,short,char)--int--long--float--double
简单数据类型之间的转换又可以分为:
●低级到高级的自动类型转换
●高级到低级的强制类型转换
●包装类过渡类型能够转换
2.1自动类型转换
低级变量可以直接转换为高级变量,笔者称之为自动类型转换,例如,下面的语句可以在Java中直接通过:
byte b;int i=b;long l=b;float f=b;double d=b;
如果低级类型为char型,向高级类型(整型)转换时,会转换为对应ASCII码值,例如 char c='c'; int i=c; System.out.println("output:"+i);
输出:output:99;
对于byte,short,char三种类型而言,他们是平级的,因此不能相互自动转换,可以使用下述的强制类型转换。
short i=99;char c=(char)i;System.out.println("output:"+c);
输出:output:c;
2.2强制类型转换
将高级变量转换为低级变量时,情况会复杂一些,你可以使用强制类型转换。即你必须采用下面这种语句格式:
int i=99;byte b=(byte)i;char c=(char)i;float f=(float)i;
可以想象,这种转换肯定可能会导致溢出或精度的下降,不推荐使用这种转换。
2.3包装类过渡类型转换
在我们讨论其它变量类型之间的相互转换时,我们需要了解一下Java的包装类,所谓包装类,就是可以直接将简单类型的变量表示为一个类,在执行变量类型的相互转换时,我们会大量使用这些包装类。Java共有六个包装类,分别是Boolean、Character、Integer、Long、Float和Double,从字面上我们就可以看出它们分别对应于 boolean、char、int、long、float和double。而String和Date本身就是类。所以也就不存在什么包装类的概念了。
在进行简单数据类型之间的转换(自动转换或强制转换)时,我们总是可以利用包装类进行中间过渡。
一般情况下,我们首先声明一个变量,然后生成一个对应的包装类,就可以利用包装类的各种方法进行类型转换了。例如:
例1,当希望把float型转换为double型时:
float f1=100.00f; Float F1=new float(f1); Double d1=F1.doubleValue();//F1.doubleValue()为Float类的返回double值型的方法
当希望把double型转换为int型时:
double d1=100.00; Double D1=new Double(d1); int i1=D1.intValue();
当希望把int型转换为double型时,自动转换:
int i1=200; double d1=i1;
简单类型的变量转换为相应的包装类,可以利用包装类的构造函数。即:
Boolean(boolean value)、Character(char value)、Integer(int value)、Long(long value)、Float(float value)、Double(double value)
而在各个包装类中,总有形为××Value()的方法,来得到其对应的简单类型数据。利用这种方法,也可以实现不同数值型变量间的转换,例如,对于一个双精度实型类,intValue()可以得到其对应的整型变量,而doubleValue()可以得到其对应的双精度实型变量。
3 字符串型与其它数据类型的转换
通过查阅类库中各个类提供的成员方法可以看到,几乎从java.lang.Object类派生的所有类提供了toString()方法,即将该类转换为字符串。例如:Characrer,Integer,Float,Double,Boolean,Short等类的toString()方法toString()方法用于将字符、整数、浮点数、双精度数、逻辑数、短整型等类转换为字符串。如下所示:
int i1=10;float f1=3.14f;double d1=3.1415926;Integer I1=new Integer(i1);//生成Integer类\rFloat F1=new Float(f1); //生成Float类\rDouble D1=new Double(d1); //生成Double类\r//分别调用包装类的toString()方法转换为字符串String si1=I1.toString();String sf1=F1.toString();String sd1=D1.toString();Sysytem.out.println("si1"+si1);Sysytem.out.println("sf1"+sf1);Sysytem.out.println("sd1"+sd1);
4 将字符型直接做为数值转换为其它数据类型
将字符型变量转换为数值型变量实际上有两种对应关系,在我们在第一部分所说的那种转换中,实际上是将其转换成对应的ASCII码,但是我们有时还需要另一种转换关系,例如,'1'就是指的数值1,而不是其ASCII码,对于这种转换,我们可以使用Character的getNumericValue(char ch)方法。
五 数组的操作
数组声明:
int a[]; int[] a1;
数组操作:
System.arraycopy(source, 0, dest, 0, source.length);
System.arraycopy()
方法只复制元素。如果数组元素是引用型变量,则只复制引用,不复制对象实体。
六 包机制,具有包声明的类的编译、运行
在使用包的过程中有很多需要注意的小细节,这里把常见的问题都列举如下:
1
、对类路径的设置通常有两种方法:
i)
在系统的环境变量中设置,设置方法依据平台而变;
ii)
以命令参数的形式来设置。
如:
java
c -classpath d:\jdk1.4.2\lib
d:\cjm\edu\test\TestFile.java
java -classpath .;d:\jdk1.4.2\lib; d:\cjm edu.test.TestFile
注意:
i)javac
和
java
命令有很大区别,可以这样区分,
java
c
是一个平台命令,它对具体的平台文件进行操作,要指明被编译的文件路径。而
java
是一个虚拟机命令,它对类操作,即对类的描述要用点分的描述形式,并且不能加扩展名,还要注意类名的大小写。
ii)
有一个很奇怪的问题,即
java
c
命令后面的
classpath
默认包含当前目录(符合
windows
的习惯),可是在
java
命令后面的
classpath
却不包含当前目录,所以在它的
classpath
中一定不能忘了加上当前目录的描述,即加上
"."
。
2
、类的目录结构一定要和类中第一句
"
包声明
"
一致。如类
TestFile.class
对应的
.java
文件的第一句必须包含:
package edu.test;
确保类的存放路径和类中指明的
"
包路径
"
一致的方法一般有两种:
i)
编写
.java
文件时存放的目录事先确定好,如
TestFile.java
就直接放在
edu\test
目录下,然后用下面的语句编译:
java
c -classpath d:\jdk1.4.2\lib
d:\cjm\edu\test\TestFile.java
当编译完成后,产生的
TestFile.class
文件会出现在编译命令中
java
文件的描述路径中。即出现在
d:\test\edu\test
中
ii)
通过
-d
参数的使用来编译程序。如使用下面的语句来编译:
java
c -d d:\cjm d:\temp\TestFile.java
将在
-d
后指定的目录
d:\cjm
下面自动按照
packagek
中指定的目录结构来创建目录,并且将产生的
.class
文件放在这个新建的目录下,即在
d:\cjm
下面建立
\edu\test
目录,然后产生的
TestFile.class
放在
d:\cjm\edu\test
目录下。
3
、为了便于工程发布,可以将自己的类树打成
.jar
文件。如将图
1
中的
edu
下面的所有类文件打成一个
.jar
文件,可以先转到
d:\cjm
目录,再用下面的命令:
jar -cvf test.jar edu\
这时会在
d:\test
下产生一个
test.jar
文件,此
.jar
文件中包含
edu\
下的完整目录结构和文件。使用这个
.jar
文件时,只需在
classpath
中指明
.jar
文件的存放路径即可。
4
、对其它资源的使用,如图标文件,文本等资源文件的使用必须要注意,查找资源文件不应从类文件所在的目录开始,而是应该从
package
指定的类路径的起点开始。
七 类继承概念,创建子类对象时,构造方法的调用过程&& super、this关键字
八 方法重载注意的问题(略)
九 方法重写注意的问题(访问权限、异常抛出)
-
在子类中可以根据需要对从父类中继承来的方法进行改造
----
方法的重写
-
重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值类型
-
在子类中创建的静态方法并不会覆盖父类中相同名字的静态方法。
-
重写方法不能使用比被重写方法更严格的访问权限
,
抛出的异常不能广于父类方法抛出的异常范围。如,
class A{
protected void test() throws IOException
{
…….
}
}
class B extends A
{
public
void test() throws Exception // Error! Public >protected, Exception>IOException
{
……
}
}
十
静态方法、抽象方法
静态方法
:又称类方法,即不需要通过类的实例就可以引用的方法,调用一个静态方法就是
“
类名
.
方法名
”,
静态方法的使用很简单如上所示。一般来说,静态方法常常为应用程序中的其它类提供一些实用工具所用,在
Java
的类库中大量的静态方法正是出于此目的而定义的。静态方法不能调用实例方法。
静态变量
:静态变量与静态方法类似。所有此类实例共享此静态变量,也就是说在类装载时,只分配一块存储空间,所有此类的对象都可以操控此块存储空间。值得注意的是静态变量的初始化问题,
static
定义的变量会优先于任何其它非
static
变量,不论其出现的顺序如何。在
static{
后面跟着一段代码,这是用来进行显式的静态变量初始化,这段代码只会初始化一次,且在类被第一次装载时。如果你能读懂并理解这段代码,会帮助你对
static
关键字的认识。在涉及到继承的时候,会先初始化父类的
static
变量,然后是子类的,依次类推。
抽象方法
:实际上是没有实现体的虚方法。
抽象类:包含抽象方法的类。如果你覆写所有的抽象方法
,
子类就变成一个普通的类
.
如果没有覆写所有方法
,
子类仍是抽象的
.
如果一个类中中包含有抽象方法
(
哪怕只有一个
),
你必须声明这个类是抽象的
,
在
class
关键字前加上
abstract.
十一
Object
类中与线程操作相关的方法及多线程
wait
与
notify
首先要强调,线程
sleep( )
的时候并不释放对象的锁,但是
wait( )
的时候却会释放对象的锁。也就是说在线程
wait( )
期间,别的线程可以调用它的
synchronized
方法。当线程调用了某个对象
wait( )
方法之后,它就中止运行并释放那个对象锁了。
Java
有两种
wait( )
。第一种需要一个以毫秒记的时间作参数,它的意思和
sleep( )
一样,都是
:"
暂停一段时间。
"
区别在于
:
-
wait( )
会释放对象的锁。
-
除了时间到了,
wait( )
还可以用
notify( )
或
notifyAll( )
来中止
第二种
wait( )
不需要任何参数;它的用途更广。线程调用了这种
wait( )
之后,会一直等下去,直到
(
有别的线程调用了这个对象的
)notify( )
或
notifyAll( )
。
和
sleep( )
属于
Thread
不同,
wait( )
,
notify( )
,
和
notifyAll( )
是根
Object
的方法。虽然这样做法
(
把专为多线程服务的方法放到通用的根类里面
)
看上去有些奇怪,但却是必要的。因为它们所操控的是每个对象都会有的锁。所以结论就是,你可以在类的
synchronized
方法里调用
wait( )
,至于它继不继承
Thread
,实没实现
Runnable
已经无所谓了。实际上你也只能在
synchronized
方法里或
synchronized
段里调用
wait( )
,
notify( )
或
notifyAll( )(sleep( )
则没有这个限制,因为它不对锁进行操作
)
。如果你在非
synchronized
方法里调用了这些方法,程序还是可以编译的,但是一运行就会出一个
IllegalMonitorStateException
。这个异常带着一个挺让人费解的
"current thread not owner"
消息。这个消息的意思是,如果线程想调用对象的
wait( )
,
notify( )
,或
notifyAll( )
方法,必须先
"
拥有
"(
得到
)
这个对象的锁。
你可以让另一个对象来操控这个对象的锁。要想这么做,第一步是先获取对象的锁。比方说要想调用对象
x
的
notify( )
,可以在
x
的
synchronized
段里:
synchronized(x) {
x.notify();
}
通常情况下,如果条件是由方法之外的其他力量所控制的
(
最常见的就是要由其他线程修改
)
,那么你就应该用
wait( )
。你总不希望闲着的时候还让线程不停地作测试吧;这种
"
瞎忙活
"
是对
CPU
资源的巨大浪费。所以
wait( )
能让你在等待世道改变的同时让线程休眠,当
(
其他线程调用了对象的
)notify( )
或
notifyAll( )
的时候,线程自会醒来,然后检查条件是不是改变了。所以说
wait( )
提供了一种同步线程间的活动的方法。
举个例子,假设有这么一间饭店,它有一个厨师和一个服务员。服务员必须等厨师烧菜。厨师做完一道菜就通知服务员,服务员上完菜接着等。这是一个很精彩的线程合作的例子:厨师就是
producer
,而服务员就是
consumer
。下面我们用代码来为这个故事建模:
//: c13:Restaurant.java
// The producer-consumer approach to thread cooperation.
import com.bruceeckel.simpletest.*;
class Order {
private static int i = 0;
private int count = i++;
public Order() {
if(count == 10) {
System.out.println("Out of food, closing");
System.exit(0);
}
}
public String toString() { return "Order " + count; }
}
class WaitPerson extends Thread {
private Restaurant restaurant;
public WaitPerson(Restaurant r) {
restaurant = r;
start();
}
public void run() {
while(true) {
while(restaurant.order == null)
synchronized(this) {
try {
wait();
} catch(InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(
"Waitperson got " + restaurant.order);
restaurant.order = null;
}
}
}
class Chef extends Thread {
private Restaurant restaurant;
private WaitPerson waitPerson;
public Chef(Restaurant r, WaitPerson w) {
restaurant = r;
waitPerson = w;
start();
}
public void run() {
while(true) {
if(restaurant.order == null) {
restaurant.order = new Order();
System.out.print("Order up! ");
synchronized(waitPerson) {
waitPerson.notify();
}
}
try {
sleep(100);
} catch(InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Restaurant {
private static Test monitor = new Test();
Order order; // Package access
public static void main(String[] args) {
Restaurant restaurant = new Restaurant();
WaitPerson waitPerson = new WaitPerson(restaurant);
Chef chef = new Chef(restaurant, waitPerson);
monitor.expect(new String[] {
"Order up! Waitperson got Order 0",
"Order up! Waitperson got Order 1",
"Order up! Waitperson got Order 2",
"Order up! Waitperson got Order 3",
"Order up! Waitperson got Order 4",
"Order up! Waitperson got Order 5",
"Order up! Waitperson got Order 6",
"Order up! Waitperson got Order 7",
"Order up! Waitperson got Order 8",
"Order up! Waitperson got Order 9",
"Out of food, closing"
}, Test.WAIT);
}
} ///:~
Order
是一个会自己计数的类,同时它还负责中止程序;数到
10
的时候,它会调用
System.exit( )
。
WaitPerson
必须知道它是为哪家
Restaurant
服务的,所以他得从那家饭店的
"
帐台
"
,也就是
restaurant.order
,拿单子。
WaitPerson
的
run( )
调用了
wait( )
方法,所以除非
Chef
用
notify( )
叫醒他,否则他会一直等下去。这是个非常简单的程序,所以我们知道只会有一个线程在等
WaitPerson
的锁
:
就是
WaitPerson
线程自己,所以
notify( )
是安全的。如果情况比较复杂,有很多线程在等一个对象的锁,那么你可能就不知道该叫醒哪个线程了。遇到这种情况,可以用
notifyAll( )
,这个方法会叫醒所有在等这个对象的锁的线程。这样线程就能自行判断本次唤醒是否与自己有关。
请注意,
wait( )
所在的
while
循环,它的测试条件正是
wait
要等的东西。乍看上去真有点奇怪
——
如果你等的是订单,那么醒过来之后肯定会有订单,难道不是吗?问题在于在多线程环境下,还没等
WaitPerson
醒过来,订单就可能被其他线程给抢走了。所以唯一安全的做法就是套用下面这个
wait( )
定式
:
while(conditionIsNotMet)
wait( );
十二
equals
方法的使用
eqauls
与
= =
之异同
1
)比较方式角度:
= =
是面向过程的操作符;
equals
是面向对象的操作符
= =
不属于任何类,
equals
则是任何类(在
Java
中)的一个方法;
我们可以用这三种比较
1
)
Primitive1 (
基本类型
)= = Primitive2(
基本类型
)
;
2
)
Object Reference1(
对象引用
)= = Object Reference2(
对象引用
)
3
)
Object Reference1 (
对象引用
) .equals(Object Reference2 (
对象引用
))
但却不能
Primitive1 (
基本类型
).equals( Primitive2(
基本类型
))
;
2)
比较目的角度
:
1
)如果要比较两个基本类型是否相等,请用
= =
;
2
)如果要比较两个对象引用是否相等,请用
= =
;
3
)如果要比较两个对象(逻辑上)是否一致,请用
equals
;
例子:
s1 = new String("null");
s2 = new String("null");
System.out.println(s1==s2);//false
System.out.println(s1.equals(s2));//true
s1 = "null";
s2 = "null";
System.out.println(s1==s2);//true
System.out.println(s1.equals(s2));//true
十三
基本类型包装类的特点
P152
,
byteValue intValue
方法(见
四数据类型转换)
十四
集合类所在的工具包,
List
接口(
Vector
,
ArrayList
)
Set
接口(
HashSet, TreeSet
)
遍历问题
集合类型主要有
3
种:
set(
集)、
list(
列表)和
map(
映射
)
。
集:
HashSet
:
使用
HashMap
的一个集的实现。虽然集定义成无序,但必须存在某种方法能相当高效地找到一个对象。使用一个
HashMap
对象实现集的存储和检索操作是在固定时间内实现的
.
TreeSet
:
在集中以升序对对象排序的集的实现。这意味着从一个
TreeSet
对象获得第一个迭代器将按升序提供对象。
TreeSet
类使用了一个
TreeMap.
列表:
Vector
:
实现一个类似数组一样的表,自动增加容量来容纳你所需的元素。使用下标存储和检索对象就象在一个标准的数组中一样。你也可以用一个迭代器从一个
Vector
中检索对象。
Vector
是唯一的同步容器类
??
当两个或多个线程同时访问时也是性能良好的。
Vector
类关键方法
:
void addElement(Object obj)
void add(int index, Object element)
Object elementAt(int index)
void insertElementAt(Object obj, int index)
Stack:
这个类从
Vector
派生而来,并且增加了方法实现栈的一种后进先出的存储结构。
LinkedList:
实现一个链表。由这个类定义的链表也可以像栈或队列一样被使用。
ArrayList:
实现一个数组,它的规模可变并且能像链表一样被访问。它提供的功能类似
Vector
类但不同步。
映射:
HashTable
:
实现一个映象,所有的键必须非空。为了能高效的工作,定义键的类必须实现
hashcode()
方法和
equal()
方法。这个类是前面
java
实现的一个继承,并且通常能在实现映象的其他类中更好的使用。
put
(Object key, Object value)
get
(Object key)
keys
()
Returns an enumeration of the keys in this hashtable.
elements
() Returns an enumeration of the values in this hashtable.
HashMap
:
实现一个映象,允许存储空对象,而且允许键是空(由于键必须是唯一的,当然只能有一个)。
TreeMap
:
实现这样一个映象,对象是按键升序排列的。
List list = new LinkedList();
list.add(new Integer(5));
list.add(new Double(3.14));
list.add("123");
Iterator iter = list.iterator();
while(iter.hasNext()) {
System.out.println(iter.next());
}
Set set = new TreeSet();
set.add("nihao");
set.add(new String("abcd"));
set.add("xyz");
set.add("1234");
Iterator iter2 = set.iterator();
while (iter2.hasNext()) {
System.out.println(iter2.next());
}
Map map = new HashMap();
map.put("1", new Integer(1));
map.put("5", new Double(32.1));
map.put("2", new String("abc"));
Iterator iter3 = map.keySet().iterator();
while(iter3.hasNext()) {
Object key = iter3.next();
System.out.println("key: " + key + "\tvalue: " + map.get(key));
}
//property and enumeration
import java.util.Properties;
import java.util.Enumeration;
public class Test9_4 {
public static void main(String[] args) {
Properties ps = System.getProperties();
Enumeration pn = ps.propertyNames();
while ( pn.hasMoreElements() ) {
String pName = (String) pn.nextElement();
String pValue = ps.getProperty(pName);
System.out.println(pName + "----" + pValue);
}
}
}
//
实现
Comparable
接口
,
使该类的对象可排序
import java.util.Arrays;
public class TestComparable implements Comparable {
//
该类的属性
i
private double i = Math.random();
//
实现
Comparable
接口的抽象方法
,
定义排序规则
public int compareTo(Object o) {
//
定义排序规则
: TestComparable
对象里的属性
i
大的则排序时比较
"
大
"(
排序靠后
)
if (o instanceof TestComparable) {
if (i > ((TestComparable) o).i) {
return 1;
} else {
return -1;
}
return 0;
} else {
//
非
TestComparable
对象与之比较
,
则抛出异常
throw new ClassCastException("Can't compare");
}
}
十五
String
类的常用操作(
toCharArray, substring,trim
),
StringBuffer(append,toString)
,
StringTokenizer
类的应用
(p155-p161
略
)
StringTokenizer st = new StringTokenizer("this is a test");
while (st.hasMoreTokens()) {
println(st.nextToken());
}
十六
内部类的使用,内部类对象的创建
内部类的定义和使用:
内部类是在一个类的内部嵌套定义的类,它可以是其它类的成员,也可以在一个语句块的内部定义,还可以在表达式内部匿名定义。
内部类有如下特性:
◇
一般用在定义它的类或语句块之内
,
在外部引用它时必须给出完整的名称
.
名字不能与包含它的类名相同。
◇
可以使用包含它的类的静态和实例成员变量
,
也可以使用它所在方法的局部变量。
◇
可以定义为
abstract
。
◇
可以声明为
private
或
protected
。
◇
若被声明为
static,
就变成了顶层类
,
不能再使用局部变量。
◇
若想在
Inner Class
中声明任何
static
成员
,
则该
Inner Class
必须声明为
static
。
十七
流操作,文件读写操作,随机文件读写对象的创建,工具包
//
对象序列化
import java.io.*;
import java.util.*;
public class ObjectPersistence {
public static void main(String[] args) throws IOException,ClassNotFoundException{
MyData md = new MyData();
md.v = new Vector();
md.v.add(new String("hi, my students,"));
md.v.add(new Integer(5));
FileOutputStream fos = new FileOutputStream("mydata.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(md);
oos.close(); fos.close();
//after 1 day,
FileInputStream fis = new FileInputStream("mydata.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
md = (MyData) ois.readObject();
System.out.println(md.s);
System.out.println(md.f);
System.out.println(md.i);
System.out.println(md.v.get(0));
ois.close(); fis.close();
}
}
class MyData implements Serializable {
String s = "abc";
float f = 3.14f;
transient int i = 5; //transient variable can't be serialized.
Vector v = null;
}//end
//
从键盘逐行读入数据输出到文件
import java.io.*;
public class Test9_2 {
public static void main (String[] args) {
File file = new File("tt.txt");
try {
InputStreamReader is = new InputStreamReader(System.in);
BufferedReader in=new BufferedReader(is);
PrintWriter out = new PrintWriter(new FileWriter(file));
String s = in.readLine();
while (!s.equals("")) {//
从键盘逐行读入数据输出到文件
out.println(s);
s = in.readLine();
}
in.close(); //
关闭
BufferedReader
输入流
.
out.close(); //
关闭连接文件的
PrintWriter
输出流
.
}catch (IOException e) {System.out.println(e); }
}
}//end
// ReadData
import java.io.*;
public class ReadData {
public static void main(String[] args) {
try{
//stream chaining.
File f = new File("p1.txt"); //use a File object instead String.
FileInputStream fis = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
//int r = dis.readInt();
int r1 = dis.readInt();
String r = dis.readUTF();
//String r1 = dis.readUTF();
System.out.println(r1 + r );
dis.close(); bis.close(); fis.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}//end
RandomAccessFile
类用于文件的输入输出,处理方式是利用文件指针进行随机定位读写。
构造函数为:
RandomAccessFile(File file, String mode);
RandomAccessFile(String name, String mode);
其中
mode
为操作状态,有两种状态:
r,
用于读;
rw
,用于读写
主要成员方法:
void close();//
long getFilePointer();//
获取文件指针位置
long length();//
获取文件长度,单位为字节
int read();//
从文件输入流中读取一个字节的数据,遇文件结束返回
-1
int read(byte[] b);
byte readByte()
void seek(long pos);//
指针定位于
pos
处
void writeBytes(String s)
...
String readLine()
//example of RandomAccessFile
public void setFile(String dir,String filename){
if((filename == null)||(filename.length() == 0)) return;
RandomAccessFile file = new RandomAccessFile(dir+filename,"r");
byte[] buffer=new byte[4096];
int len;
textArea.setText("");
while((len=file.read(buffer))!=-1){
String s=new String(buffer,0,len);
textArea.append(s);
}
file.close();
} catch(IOException e){
textArea.setText(e.getMessage());
}
}
十八
异常处理机制
(
略
)
十九
socket
编程
//TestServer.java
import java.net.*;
import java.io.*;
public class TestServer {
public static void main(String args[]) {
ServerSocket s = null;
try {
s = new ServerSocket(8888);
} catch (IOException e) {}
while (true) {
try {
Socket s1 = s.accept();
new MyThread(s1).start();
} catch (IOException e) {}
}
}
}
class MyThread extends Thread
{
Socket s;
MyThread(Socket s)
{this.s = s;}
public void run()
{
try{
DataInputStream dis = new DataInputStream(s.getInputStream());
DataOutputStream dos = new DataOutputStream(System.out);
String str = dis.readUTF();
dos.writeUTF("echo "+str);
dos.flush();
dis.close();
dos.close();
s.close();
}catch(Exception e)
{
}
}
}
//TestClient.java
import java.net.*;
import java.io.*;
public class TestClient {
public static void main(String args[]) {
try {
Socket s1 = new Socket("127.0.0.1", 8888);
OutputStream os = s1.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
dos.writeUTF(str);
dos.flush();
s1.close();
dos.close();
} catch (ConnectException connExc) {
System.err.println("
服务器连接失败!
");
} catch (IOException e) {
}
}
}
二十
JDBC
import java.sql.*;
public class JDBCDemo
{
public static void main(String[] args)
{
try
{
Statement stmt;
PreparedStatement pstmt;
ResultSet rs;
//load the jdbc-odbc driver
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
//define the JDBC url
String url = "jdbc:odbc:JDBCDemo";
//get the connection of database
Connection con = DriverManager.getConnection(url);
System.out.println("URL " + url);
System.out.println("Connection: " + con);
//get the statement object
stmt = con.createStatement();
//if exit the DemoTable, delete it, or throw exception
System.out.println("DROP TABLE DemoTable, if it exits");
try
{
stmt.executeUpdate("DROP TABLE DemoTable");
}
catch (Exception e)
{
System.out.print(e);
System.out.println("No existing table to delete");
}
//Create a Demotable
stmt.executeUpdate("CREATE TABLE DemoTable(test_id int, test_val char(15) not null");
//insert the entries in the table
stmt.executeUpdate("INSERT INTO DemoTable(test_id, test_val) VALUES(1,'one')");
stmt.executeUpdate("INSERT INTO DemoTable(test_id, test_val) VALUES(2,'two')");
stmt.executeUpdate("INSERT INTO DemoTable(test_id, test_val) VALUES(3,'three')");
stmt = con.createStatement();
//get the records of DemoTable
rs = stmt.executeQuery("SELECT * FROM DemoTable ORDER BY test_id");
//show them
while(rs.next())
{
int theInt = rs.getInt("test_id");
String theString = rs.getString("test_val");
System.out.println("\t test_id = "+theInt+"\t test_val = "+theString);
}
//use of preparedStatement
pstmt = con.prepareStatement("update DemoTable set test_val = ? where test_id = ?");
pstmt.setString(1,"hello");
pstmt.setInt(2,2);
pstmt.executeUpdate();
System.out.println("Update row number 2: OK");
con.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}