java2入门经典(读书笔记)

本文摘录了《Java2入门经典》中的关键知识点,包括Java语法特性如常量定义、增强for循环、断言机制、多维数组使用,以及字符串处理技巧等。此外还介绍了集合类如Vector和HashMap的应用细节,数据库操作中的PreparedStatement使用方法和异常处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


序号
内容
1
常量
final int SOCKS = 3;
2
collection-based for
for(type identifier : iterable_expression)
{
}
3
continue break 可以带标号
Loop:
for()
{
    continue Loop;
}
4
断言                                                                                                     P101
(1) 适用情况:一旦执行了某些语句,意味着程序或者环境有十分严重的错误
(2)assert true; 程序继续执行        assert false : 错误信息 ; 程序终止,并输出 java.lang.AssertionError 的错误
(3) 运行时使用 -ea 开启断言,否则断言将被忽略
(4)if (daysInMonth == 31 || daysInMonth == 30 || days InMonth == 29 || daysInMonth == 28)
 {
      // 正常情况
 }
 else
 {
      assert false : 错误:当月天数为 + daysInMonth;
 }
assert false/true;
assert false/true : string;
5
多维数组,不同维度的数组长度可以不同
6
字符串变量值是对字符串本身的引用
7
基本数据类型转换成字符串,是在其包装类中的静态方法 .toString() 完成的
如: 10 + is a number 实际上是通过 Integer.toString(10) + is a number 完成的。
8
等值比较
“==” 可以用于基本数据类型的比较,但用于对象比较时会出现问题,因为对象变量值是对对象本身的引用,即使对象的各种属性值都相同,在内存中是两个地址的话,那么用 == 判断只是比较两个地址的值,是不相等的。典型情况是 String 的等值判断要用 equals()
9
扣留
.intern() String 对象本身的值与其他 String 对象的值进行对比,一样的话则丢弃当前 String 对象,而对象变量是对原来相同字符串的引用,这使得 == 同样起作用,一般来说不要使用 .intern() ,而且使用 equals() 进行相等判断。
10
split
分隔符要写在 [] 中,如 [,.] 表示使用 , . 分隔。重载方法的第二个参数 <0 则返回最后的空标记; =0 则不返回。不带有第二个参数的方法,是表示 =0 的情况。
11
内存中仅有一个实例方法的副本,该类的所有对象均调用这一个方法。
12
所有参数都是指传递
对于基本数据类型会传递实参的副本,对于对象会传递对象变量的副本,但也能通过副本对象应用到对象本身。
13
将参数定义为 final ,可以防止实参的值被修改。
14
静态初始化块
静态变量最好由静态块初始化
static int[] values;
static
{
    values = new int[10];
}
15
垃圾回收
System.gc();
16
在构造函数中调用另外一个构造函数
constructor()
{
    int a = 0;
    this(a);
}
17
根据已有对象建立对象的深拷贝                                                                              P176
Sphere(static Sphere oldSphere)
{
    // 构造函数
    radius = oldSphere.radius;
    xCenter = oldSphere.xCenter;
    yCenter = oldSphere.yCenter;
    zCenter = oldSphere.zCenter;
    ++Count;
}
18
在需要的情况下,实现 toString() 方法
public String toString()
{
   //...
}
19
编译的时候可以使用 “-classpath 包所在路径 ” P186
一般用 javac -classpath .;package path *.java package path 是包所在的上级目录,“ . ”为当前路径
20
CLASSPATH 访问包
可以在 CLASSPATH 环境变量或 java -classpath 中指定 package 所在目录。编译和运行的时候都可能需要制定 classpath
21
JAVA_HOME/jre/lib/ext/ 中存储着扩展包,这里的包会自动访问到,而不用设置 -classpath
22
打包
jar cvf Geometry.jar Geometry/*.class
23
基本数据类型到对应的包装类的转换是由自动装箱 / 拆箱完成的。
24
访问属性
default   包内
public    所有
private   类内
protected 包内、子类
25
对私有成员的访问                                                                                          P194
访问器 accessor 方法,形如 getXXX();
增变 mutator 方法,形如 setXXX();
26
嵌套类 nested class                                                                                      P199
·嵌套类是外部类的成员,并且有自己的访问属性
·嵌套类用于:定义与其外部类的对象有很强关联的对象;在外部类中对有关联的类进行分组
·嵌套类的可见域 P201
      class Outside
      {
          static members
          static class Skinside
          {
              static members
              non-static members
          }
          class Inside
          {
              non-static members
          }
          non-static members
      }
·嵌套类生成的 class 文件名为“外部类名 $ 嵌套类名 .class
·在顶层类之外使用嵌套类       静态嵌套类: new 外部类名 . 嵌套类名 ();
                              非静态嵌套类:外部对象 .new 嵌套类名 ();
·何时使用静态嵌套类?当嵌套类中需要定义静态成员时
·局部嵌套类
  在方法中定义嵌套类,并且只能在该方法中使用局部嵌套类,局部嵌套类可以访问方法中的 final 变量
  适用于方法中的计算要求使用一种特殊类,而这个类在别的地方并不需要,比如事件监听器
27
finalize() 方法                                                                                              P206
在对象销毁前调用,但对象的销毁时机由 JVM 控制,因此对时间敏感的处理不应该放在 finalize() 方法中
可以使用 System.gc() System.runFinalization() 方法调用 JVM 进行垃圾回收
28
本地方法                                                                                                  P207
在类中可以包含一些其他编程语言,在方法声明时使用 native 关键字,适用本地方法将使程序丧失可移植性, applet 处于安全考虑不允许使用本地方法
29
隐藏数据成员                                                                                              P212
当派生类的数据成员的名称与基类的数据成员的名称相同时,基类的成员都会被隐藏起来,但仍可以使用 super. 访问基类成员
30
继承时的构造函数                                                                                          P212
构造函数不能被继承
编译器会在派生类的构造函数的第一条语句前插入 super();
31
覆盖基类方法                                                                                              P215
派生类的方法需要和基类的方法有相同的签名,访问属性一致,或者在派生类中的限制更少
32
通用基类 Object                                                                                           P222
· toString()
  返回“类名 @ 对象的散列码”
· getClass()
  每个类或者接口都只有一个 Class 对象,因此可以使用“对象 .getClass() == .class ”进行精确验证“对象”是否是“类”类型的,并且忽略继承关系
· clone()
  当实现 Cloneable 接口时才可以进行对象的复制
 Object.clone() 将生成一个与当前对象类型相同的新对象来实现复制,并把新的对象中的每个成员域都设置成与当前对象的对应成员域相同的值,因此当原始对象的数据成员引用一个类对象时,类对象在 clone 时不会被复制,而只是复制引用
33
可变实参方法                                                                                             P229
方法定义为“方法名 ( 参数类型 args)
34
instanceof                                                                                               P234
instanceof 比较左侧对象与右侧操作数,类型相同或者是它的子类则返回 true
对象 .getClass() == .class 则进行类型精确比较
当进行类强制转换之前使用 instanceof 进行判断
35
枚举                                                                                                      P235
·枚举也是一种类,自定义枚举继承了 java.lang.Enum
·默认情况下,枚举中的每个常量都分配一个正数值,按照定义顺序 0 开始赋值,可以使用 ordinal() 获取这些值, compareTo() 方法也是使用该值进行比较的
·添加成员
    可以像普通类一样给枚举定义成员变量和成员方法,但构造函数不能定义为 public 类型,因为它只能在枚举类的内部使用,如果需要改变枚举常量的输出显示,覆盖基类的 toString() 方法
    public enum 枚举类名
    {
        枚举常量 1,   // 枚举类的一个实例
        枚举常量 n;   // 逗号分割枚举常量,分号结束
       
         其他成员,如构造函数等
    }
36
类的设计                                                                                                  P238
两种情况:层次结构的类,反映“是 is a ”关系;包含类对象的类,反映“有 has a ”关系。
37
final                                                                                                      P248
final 标记方法时,则这个方法在派生类中不能被覆盖,但抽象方法不能标记为 final ,因为它必须在派生类中实现
final 标记类时,则这个类不能被继承,类似 .net 中的密封类
38
公共常量的访问                                                                                            P249
使用接口(过时):可以使用“接口 . 常量”访问或在实现接口的类中直接访问接口常量
使用类(时髦):使用“类 . 常量”访问或在源文件中使用“ import static 类名 . 常量”引入常量
39
clone() 方法                                                                                               P254
Object.clone() 方法的访问属性是 protected Cloneable.clone() 的访问属性是 public ,因此一个类想要含有克隆方法,必须实现 Cloneable 接口,以获得 clone() 方法的 public 访问属性,在代码中使用下面的方法
public Object clone()
{
    return super.clone();    // 这里实际上调用了 Object clone() 方法
}
不甚了了
40
接口                                                                                                      P248
·接口是一组相关常量抽象方法
·接口中的方法默是 public abstract 类型,常量总是 public static final 类型,不应该去改变它们
·实现接口中定义的全部方法的类可以实例化,实现接口中定义的部分方法的类是抽象类
·接口可以进行扩展,使用 extends 关键字继承超接口即可,接口可以多重继承(同时继承多个接口)而类不可以
·接口的重要意义,为实现相同接口的类产生多态,而不局限于类于子类之间。虽然不能生成一个接口对象,但是可以定义一个接口类型的变量,使用它来存储实现接口的任何类型的对象的引用,也就意味着可以使用这个变量来多态调用在接口中声明的方法,也可以把方法的形参定义为接口类型
·在接口中可以定义嵌套类,并且是 public static 类型的
41
匿名类                                                                                                    P262
当需要一个作为方法实参的对象,并且这个对象实现某个接口或者继承某个类时,可以使用匿名类,匿名类适用于定义简短的情况,比如
pickButton.addActionListener(new ActionListener()
                               {
                                   // 实现 ActionListener 接口方法的代码
                               }
                          );
不甚了了
 
 
 
7 异常
1
使用异常的思想                                                                                            P265
并非所有的错误都需要由异常来指出,异常指出的是可能出现的灾难情况,异常处理涉及到很大处理负担
Java 中异常是党程序出现不正常情况时生成的一个对象,这个异常对象具有存储问题信息的成员域
4 种可能抛出异常的情况:代码或者数据错误、标准方法异常、自定义异常、 Java 语言错误
2
异常类型                                                                                                   P265
Throwable 类是 Java 语言中所有错误或异常的超类。只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型,她包含两个直接子类 Error Exception
3
Error                                                                                                    P265
用于指示合理的应用程序不应该试图捕获的严重问题,又包含 ThreadDeath LinkageError VirtualMachineError 三个直接子类,对于 ThreadDeath 可以捕获它,进行清理工作,但必须要再次抛出这个异常,以销毁相关线程。而 LinkageError VirtualMachineError 一般不需要捕获
4
RuntimeException                                                                                         P266
一般来说,当程序中有可能会抛出异常时,必须对代码段做 try-catch 处理,或注明方法将抛出异常,但有一个例外—— RuntimeException RuntimeException 允许编译器忽略它们,因为他们通常由代码中的严重错误产生。这将包含 ArithmeticException IndexOutOfBoundsException NegativeArraySizeException NullPointerException ArrayStoreException ClassCastException IllegalArgumentException SecurityException IllegalMonitorStateException IllegalStateException UnsupportedOperationException
5
多次 catch                                                                                                 P272
当需要多次 catch 时,把派生次数最多的类写在前面,而基础的在后面
6
finally 的新用法                                                                                            P273
允许存在 try-finall 形式的异常处理, try 块中的代码可以不抛出任何异常。因为异常处理支持上面两点特性,因此可以用于处理下面的情况:当 try 块中有多个可能的退出点时(如多个 break return ),希望在 try 代码块后总是执行一些语句,就可以将这些语句放到 finally 块中,但 finally 块中的返回值会覆盖掉原来 try 块中的返回值
7
执行域( execution stack                                                                                   P280
执行域跟踪在任何特定实例中运行的所有方法,为方法提供返回调用点的途径,生成产生异常时的行号,方法的调用记录
8
Throwable                                                                                              P280
· getMessage() 显示异常信息
· printStackTrace() 将栈的跟踪记录输出到标准错误输出流
· printStackTrace(PrintStream s) 输出到指定的流, printStackTrace() 等价于 printStackTrace(System.err)
· fillInStackTrace() 记录异常点,常用于
 catch(Exception e)
 {
      e.fillInStackTrace();
      throw e;
 }
 
 
 
8
1
缓冲流                                                                                                    P290
为了提高流传输数据的效率,为流配备一个大小合理的缓冲区,可以使传输过程更加有效,这样的流成为缓冲流
2
字符数据到流的转换                                                                                        P290
向字节流写入字符或者从字节流读取字符,不会发生任何转换过程;但是在写字符流时,字符从 Unicode 字符码转换为字符的本地机器表示,读取时发生逆向转换
3
BufferedInputStream                                                                                       P293
派生自 InputStream 的派生类 FilterInputStream
BufferedInputStream bis = new BufferedInputStream(InputStream, bufferSize);
默认情况下 bufferSize = 8kb BufferedOutputStream 的作用与用法类似
4
InputStream OutputStream                                                                             P295
字节流由 InputStream 类和 OutputStream 类的子类来表示,它们都是抽象基类,使用时应根据具体情况使用它们的派生类,字符流操作由 Reader 类和 Writer 类的子类提供
5
PrintWriter 的特点                                                                                          P297
PrintWriter 对象的方法不会抛出异常,因此为了确定是否发生错误,必须调用 checkError 方法
6
标准流                                                                                                    P298
标准输入流—— System.in InputStream 类型,默认键盘
标准输出流—— System.out PrintStream 类型,默认命令行
标准错误输出流—— System.err PrintStream 类型,默认命令行
7
切分流 StreamTokenizer                                                                                    P298
针对 Ascii 编码的单字节字符流进行切分,可以解析出数、单词、字符串、注释、空白,并且可以自行制定分割器,在定制之前,通常先调用 resetSyntax() 方法
8
Printf 方法                                                                                                 P304
同样作用的还有 String.format() 方法和 Formatter
StringBuilder sb = new StringBuilder();
Formatter f = new Formatter(sb);
f.format("Today is %s", new Date());
System.out.print(sb);
9
Locale                                                                                                 P308
定义语言环境,影响各种类型数据(如日期和货币)的表示方式,可以调用构造函数得到对象或调用 Locale 类的静态变量,而后一种方法更为常用
 
 
 
9
1
File
1 File 对象                                                                                              P310
    File 对象并不代表一个文件,它只是封装了路径名和引用,该引用指向的文件或目录可能不存在
2 File 对象的目的                                                                                        P310
    检查 File 对象引用的文件或者目录是否存在;创建文件流对象
3 File 的构造函数                                                                                        P310
    new File(" 路径 ");                         // 路径并不一定有效
    new File(" 目录名 ", " 文件名 ");
    new File( 目录 File 对象 , " 文件名 ");
    new File(URI 对象 );
4 File 对象的不变性                                                                                       P311
    一旦创建了 File 对象,就不能改变它所封装的路径,当使用 renameTo() 方法改变 File 对象所应用的文件或目录名称后, File 对象指向的路径将不再有效
5 File 对象的方法                                                                                       P315
getParent()
如果仅使用文件名创建 File 对象用来表示当前目录下的文件,就没有指定的父目录
eqauls()
两个 File 对象拥有相同的路径,则认为相等
toString()
等同于 getPath() 方法,返回路径(包括目录名和文件名)
getAbsolutePath()
如果定义 File 对象的时候包括了绝对路径,那么返回 getPath()
否则将试图使用当前用户目录( user.dir )解析,来获得绝对路径
getAbsoluteFile()
对于 getParent() 方法可能出现的问题,可以使用下面的方法解决
File f = new File("abc.java");
f = f.getAbsoluteFile();
listRoots()
返回文件系统的根目录列表
list listFiles()
File 对象是目录时,列出其下的子目录和文件,他们可以接受实现 FilenameFilter FileFilter 接口的对象作为实参,从而实现列表的过滤,也就是说想要实现目录或文件的过滤,不光要给出过滤规则,还要实现规则
mkdir()
使用 File 对象所表示的路径创建一个目录
mkdirs()
使用 File 对象所表示的路径创建需要的任何父目录及其自身
createNewFile()
创建 File 对象引用的文件名,不会自动创建所需要的路径
createTempFile()
参数分别是:前缀、后缀(扩展名)和目录
在指定目录中创建临时文件,文件名将使用前缀 +5 个或更多的随机字符 + 后缀组成。其中的前缀至少要三个字符,创建的临时文件不会被自动删除
delete()
不能删除非空目录
deleteOnExit()
JVM 正常结束 时,删除 File 对象引用的文件或目录
2
路径常量                                                                                                  P312
File 静态对象
作用
String
Char
separator
separatorChar
路径各级间的分割符
pathSeparator
pathSeparatorChar
两个路径间的分割符
路径可以分为三种形式:
    绝对路径:包含前缀的路径,前缀在 windows 中如 "c:/" ,在 unix 中是 "/"
    相对路径:相对于当前目录,如 new File("dir//Output.txt"); 指当前路径下的 dir 文件夹下的 Output.txt 文件
    UNC Universal Naming Convention ,通用命名标准)路径: windows 环境中如“ // 机器名 / 共享目录名 / 文件名”;非 windows 环境中如“ // 机器名 / 共享目录名 / 文件名”,即 File.separator + File.separator + 机器名 + File.separator + 共享目录名 + File.separator + 文件名
3
系统属性                                                                                                  P319
System.getProperties() 方法可以返回 java.util.Properties 类型的系统属性,其中
"user.dir" 定义了默认相对路径
"user.home" 定义了用户的主目录(如“ c:/Document and Settings/ 登录用户名”)
4
FileDescriptor (文件描述符)对象                                                                             P328
InputStream OutputStream 对象通过 getFD() 方法返回 FileDescriptor 对象。它用作与基础机器有关的某种结构的不透明句柄,该结构表示开放文件、开放套接字或者字节的另一个源或接收者。文件描述符的主要实际用途是创建一个包含该结构的 FileInputStream FileOutputStream 。这样就可以对一个文件同时获得多个输入、输出流,但不能同时获得输入和输出流
 
 
 
10 写文件
1
对文件的访问方式                                                                                          P330
·顺序存取
·随机存取
2
JDK1.4 引入的文件 I/O 功能                                                                                 P331
主要涉及到三个对象:
·文件流对象,包括 java.io.InputStream java.io.OutputStream
·缓冲区对象,包括 java.nio.ByteBuffer
·通道对象: java.nio.channels.* ,使用一个或多个缓冲区对文件进行读写
    读文件和写文件的过程基本相同,写文件时,先将数据载入一个或多个缓冲区,然后调用通道对象的方法将数据写入到文件中。读文件时,先调用通道对象的方法,将数据从文件读入到一个或多个缓冲区中,然后从缓冲区中获取数据
3
通道                                                                                                      P332
1 JDK1.4 引入通道,它提供比流类的方法更快的输入、输出性能,输入、输出的对象包括文件、网络套接字和程序之间的管道 I/O 操作,通道机制可以充分利用缓冲区以及操作系统提供的其他功能
2 )通道的接口层次
    Closeable :可以关闭数据源或数据目的地
    Channel :与驱动器(如文件或套接字)的连接,继承 Closeable
    InterruptibleChannel :可异步中断的通道,继承 Channel
    WritableByteChannel :将数据从一个缓冲区写入驱动器的通道,继承 Channel
    GatheringByteChannel :将数据从多个缓冲区写入驱动器的通道,继承 WritableByteChannel
    ReadableByteChannel :将数据从驱动器读取到一个缓冲区的通道,继承 Channel
    ScatteringByteChannel :将数据从驱动器读取到多个缓冲区的通道,继承 ReadableByteChannel
    ByteChannel :将数据从单个缓冲写入到驱动器或从驱动器读取到单个缓冲区的通道,继承 WritableByteChannel ReadableByteChannel
4
缓冲区
1 )视图缓冲区                                                                                           P334
java.nio.Buffer 为基类,其派生类有 ByteBuffer CharBuffer ShortBuffer IntBuffer LongBuffer FloatBuffer DoubleBuffer ,只有 ByteBuffer 才能在文件 I/O 操作中使用,其他 6 种缓冲称为视图缓冲。
2 )缓冲区的属性
·容量                                                                                                    P335
  指缓冲区能包含值的最大数量,而非字节数,一旦被初始化,就不能再改变
·位置                                                                                                    P336
  指下一个将要访问(读取或写入)的元素的索引,类似文件指针,当顺序访问文件的时候,每次读取或写入元素,位置将自动增加
·边界                                                                                                    P336
  缓冲区第一个不能读取或写入的值的索引,缓冲区允许 0 <= 位置 <= 边界 <= 容量,而默认值是 0 = 位置 <= 边界 = 容量
3 )方法
· hasRemaining()                                                                                          P338
  将确定缓冲区位置和边界之间是否含有元素
· remainging()                                                                                             P338
  将返回缓冲区从当前位置开始,还可以容纳多少个元素
· allocate()                                                                                                P338
  静态方法,参数为缓冲区的容量,创建间接缓冲区,间接黄冲区独立于系统缓冲区,它使用系统缓冲,其间涉及到数据的复制,因此适合小容量的缓冲
· allocateDirect()
  创建直接缓冲区,它将直接分配系统缓冲区,它的分配和回收需要消多资源,因此适合大容量的缓冲
· isDirect()
  判断是否封装了直接缓冲区
· asXXXBuffer()
  ByteBuffer 对象的当前位置开始,到边界结束之间的元素,尽可能大的创建指定类型的视图缓冲区,新创建的视图缓冲区元素将和 ByteBuffer 对象中元素共享同一个内存空间,这也就是它被称之为“视图”的原因,新创建的视图缓冲区有独立的位置、边界,并且位置默认为 0 ,边界默认为容量。一个 ByteBuffer 对象可以创建多个视图缓冲区,他们可以互相重叠。
· duplicate()                                                                                               P340
  复制缓冲区,复制后的缓冲区中元素将和原缓冲区中元素共享同一个内存空间,复制后的缓冲区有独立的位置和边界,但复制后的缓冲区位置和边界初始值与原缓冲区的相同
· slice()                                                                                                   P341
  划分缓冲区,其结果是将原缓冲区中当前位置到边界之间的元素引用到新的缓冲区,新缓冲区有独立的位置和边界,位置初始值为 0 ,边界为新缓冲的容量
· wrap()                                                                                                   P341
  静态方法,从数组对象创建缓冲区对象,创建后的缓冲区元素将和数组元素共享同一个内存空间
  创建 CharBuffer ,有 4 种变量可以作为 wrap 的参数: String 对象,创建的 CharBuffer 对象是只读的; char[] 数组对象; StringBuilder 对象; StringBuffer 对象
· hasArray()                                                                                               P342
  判断缓冲区是否从数据对象创建
· array()                                                                                                  P342
  如果缓冲区是从数组创建的,那么返回该数组的引用,否则抛出 UnsportedOperationException 异常
· mark()                                                                                                  P343
  将缓冲区的当前位置进行标记,视图缓冲区与创建它的缓冲区的标记是独立的
· reset()                                                                                                  P343
  将缓冲区的当前位置重置到标记处
· put() putXXX()                                                                                           P344
  将数据传入缓冲区 , 在自定义的位置传入数据 , 缓冲区的位置不会自动变化 , 需要根据传入的数据类型手工设置
  由于视图缓冲区的位置与基础缓冲区的位置是相互独立的,因此在使用视图缓冲区访问元素后,必须手工设置基础缓冲区的位置
 ByteBuffer byteBuffer = ByteBuffer.allocate(1024);    // 缓冲区大小是否可以预先确定?
 CharBuffer charBuffer = byteBuffer.asCharBuffer();
 charBuffer.put("Hello");
  /* 或者使用:
 charBuffer.put(0, 'H');    charBuffer.position(charBuffer.position() + 1);
 charBuffer.put(1, 'e');    charBuffer.position(charBuffer.position() + 1);
 charBuffer.put(2, 'l');    charBuffer.position(charBuffer.position() + 1);
 charBuffer.put(3, 'l');    charBuffer.position(charBuffer.position() + 1);
 charBuffer.put(4, 'o');    charBuffer.position(charBuffer.position() + 1);
 */
 byteBuffer.position(byteBuffer.position + Character.SIZE / 8 * charBuffer.position()); // 每个 char 占用 2 个字节
 byteBuffer.putDouble(1.23);
· flip()                                                                                                    P346
  通常在将缓冲区中数据写入到文件之前使用,它将缓冲区的边界设置为当前位置,当前位置设置为 0
· clear()                                                                                                  P347
  将缓冲区的当前位置设置为 0 ,边界设置为容量值
· rewind()                                                                                                P347
  将缓冲区的当前位置设置为 0
· compact()                                                                                              P347
  将缓冲区中当前位置和边界之间的元素复制到缓冲区开头,并把当前位置设置到最后一个元素后面,边界设置成容量
5
写入文件
1 )写入源和目的
从缓冲区当前位置开始,到边界为止,将其中的元素写入到文件中,并且从文件的当前位置开始写入
2 )通道对象的方法
· write()
  写入缓冲区中可访问的元素,文件位置自动增长。而另一种在文件制定的位置写入缓冲区中可访问元素的重载方法,文件当前位置不变
· force()
  在调用 write() 方法后,数据可能还未被写入到基础设备中,调用 force() 方法将保证数据写入到本地存储设备中,但不能保证数据写入到网络存储设备中
· position()
   获取、指定文件当前位置
· close()
  关闭通道
· size()
  获取文件中的字节数
· trnsferTo()
  写入到另一个通道
· transferFrom()
  从另一个通道读取
· read(ByteBuffer buf, long position)
· write(ByteBuffer buf, long position)
  用于随机读写文件,完成后通道位置(也就是文件指针)不变
3 )写入代码
String phrase = "Hello";
File aField = new File(dirname, filename);
FileOutputStream file = new FileOutputStream(aFile, true);
FileChannel outChannel = file.getChannel();
byte[] bytes = phrase.getBytes();
buf.put(bytes);
buf.flip();
outChannel.write(buf);
file.close();   // 同样会关闭 outChannel
4 )集中写操作
将多个缓冲区中数据依次写入文件,调用 write(ByteBuffer[] buffers) 方法
 
 
 
11 读文件
1
FileInputStream
1 )构造函数
构造函数会验证文件是否存在,不存在则抛出异常
三种形参:文件路径名、 File 对象、 FileDescriptor 对象
2 read() 方法
使用 read() 方法将数据从文件读入缓冲区,文件位置将自动递增。从文件读入缓冲区的数据量取决于缓冲区的位置和边界
2
对一个文件同时进行读写
对同一个文件穿件 FileInputStream FileOutputStream ,然后分别创建通道进行读写
使用 RandomAccessFile.getFilePointer() 获取文件指针与 FileChannel.getPosition() 获取通道位置是相同的
3
从标准输入流获取读取器
BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in))
 
 
 
12 对象的序列化
1
序列化定义 P405
在外部文件中存储和获取对象的过程称之为序列化( serialization )。将对象写入文件称为对象序列化( serializing an object ),而从文件读取对象称为将对象逆序列化( deserializing )。序列化包括将对象以及它们所包含的成员域写入流,但不涉及类的 static 成员。
2
将对象写入文件 P408
File f = new File("MyFile");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(myObject);
oos.close();
fos.close();
为了提高效率使用
ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
3
将对象序列化的条件 P408
对象所属类必须为 public 类型,必须实现 Serializable 接口。如果这个类的超类不可序列化,那么当这些超类有 public 类型的默认构造函数,且本类负责将不可序列化的超类的成员域序列化及逆序列化,那么本类也是可以序列化的。
4
将基本数据类型写入对象流 P409
ObjectOutputStream 除了定义了将对象写入流的 writeObject() 方法外,还定义了将基本类型数据写入流的方法,如 writeInt() writeChar() 等,此外还有与之相对应的读取方法,如 readInt() readChar()
5
transient 型数据成员 P413
对于不可序列化或者不希望序列化的成员域,可以将其定义为 transient 型,当对象逆序列化时,这样的成员域会被正确创建,其值为 null
6
从文件读取对象 P413
File f = new File("MyFile");
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
myObject = ois.readObject();
ois.close();
fis.close();
7
自定义序列化 P420
将类声明为 public 类型,并实现 Serializable 接口,重写
private void readObject(ObjectInputStream in) throws IOException
private void writeObject(ObjectOutputStream out) throws IOException, ClassNotFoundException 方法。一般来说先使用 in.defaultReadObject() out.defaultWriteObject() 方法进行默认序列化操作,然后再自行处理需要的序列化、反序列化操作。
此外,可以通过在类中实现 Externalizable 接口来完全控制序列化过程。
8
将对象的变体写入对象流 P423
试图将同一个对象的多个变体(通过修改对象的成员域来形成多个变体)写入对象流,将会重复写入对象的第一个变体,如
String str;
str = "Str1"; out.writeObject(str);
str = "Str2"; out.writeObject(str);
str = "Str3"; out.writeObject(str);
这样实际上会重复写入对象 "Str1" 。采用 reset() 方法可以避免这个问题,如
String str;
str = "Str1"; out.reset(); out.writeObject(str);
str = "Str2"; out.reset(); out.writeObject(str);
str = "Str3"; out.reset(); out.writeObject(str);
 
 
13 泛型类
1
泛型定义 P425
泛型,又称参数化类型,是含有单个或多个类型参数的类或接口的定义。 <> 中的参数称为类型参数,泛型的类型实参只能是类或接口,而不能是基本数据类型,如果需要的话,使用他们的包装类
2
最左限制 P431
当提供类型实参后,泛型类将重新生成。编译器将使用 Object 类型替换类型变量的类型,因为 Object 是所有类的最终超类,所以 Object 类型是任何类的默认最左限制,最左限制取决于类型参数限制
3
相同的运行时类型 P434
同一个泛型的多个泛型类(给泛型提供不同类型的类型参数),它们的实例有相同的运行时类型,即范型本身
4
泛型类型参数的作用域 P435
泛型类型参数的作用域是除静态成员、静态方法、初始化器以外泛型类的全部定义。注意与泛化方法是不同的,这里讨论的是泛型类
5
泛型中的静态成员域 P435
尽管由泛型生成的新类型共享相同的运行时类型,但它们仍然拥有独立的静态成员域
6
类型参数限制 P436
可以对类型实参进行一些约束,约束包括继承类、实现接口
public class MyType(T extends MyClass & Serializable & MyInterface>
{
}
如果不进行约束限制,则默认为 <T extends Object> ,这也就是 Object 作为默认最左限制的原因
7
泛型接口
·泛型可以实现一个或多个接口(包括泛型接口)。要求类型参数本身实现制定的接口,而不是继承它超类对该接口的实现,这就是内建限制
·典型任务:使泛型容器类使用 collection-based for 循环
  条件:实现接口 Iterable<> (实现该接口中的方法 iterator() ),然而方法 iterator() 的返回值类型 Iterator<T> 也是泛型接口,因此这个返回值类型要实现 Iterator<T> 接口中定义的所有方法,如:
import java.util.Iterator;
public class LinkedList<T> implements Iterable<t>
{
    public Iterator<T> iterator()
    {
        return new ListIterator();
    }
 
    private class ListIterator implements Iterator<T>
    {
        public ListIterator() {...}
        public boolean hasNext() {...}
        public T next() {...}
        public void remove() {...}
    }
}
8
原生类型 P452
将泛型类的泛型参数“去掉”后的类型称为原生类型。“去掉”是指将类型变量使用相应类型参数的最左限制替换,这个过程称为类型擦除,可以修改类型参数限制来控制最左限制
9
通配符 P452
·实现描述 ? 为通配符,它表示任何类或接口。如果方法代码不依赖于类型实参,可以使用通配符描述类型参数
·约束
  通配符可以有两种限定约束
  上界: <? extends T> ,表示 T 以及 T 的之类可作为类型参数
  下界: <? super T> ,表示 T 以及 T 的超类可作为类型参数
10
Class P457
Class 类不是普通的类,他被定义为泛型。对于一般的类而言,类型本身就是泛型 Class<> 的类型实参,如 Class<String>
11
数组和泛型 P 458
数组元素不予许是由泛型生成的具体类型,只能使用无界限的通配符创建泛型数组,且泛型数组允许数组元素是相同泛型的多个泛型类实例,如 Vector<?>[] list = { new Vector<String>(), new Vector<Integer>()};
12
参数化方法 P460
含有一个或多个独立的类型参数的方法,称为参数化方法或泛化方法。类型参数可以增加约束,并且构造函数也可以作为泛化方法。如 public static <T> T createInstance(Class<T> cls) ,是方法的独立类型参数。
13
参数化类型和继承 P466
可以将类定义为泛型类型实例的之类,方法和成员域可以从基类继承,但要注意,当派生类中的方法需要覆盖超类中方法时,采用一般的方法将没有效果,因为编译器用不同的记号将方法进行编译处理,所以基类中的方法不会被覆盖,为了达到覆盖的目的,编译器将采用桥接方法,将对继承的方法的任何调用转换为对派生类中定义的方法的调用,这个过程时隐式进行的。
 
 
 
14 集合框架
1
集合类型 P469
·集:集中的对象没有排序方式,只是简单的把对象添加到集中,集中的对象不能有重复
·序列:线型方式存储,有开头和结尾。 java 序列划分为列表和队列两种,列表包括向量、链表、栈
·映射:存储 < , > 对,键用来标识对象,通过散列法确定值的存储位置
Java 对象集合指对象引用的集合,即集合只存储引用,而对象本身存储在集合之外
2
迭代器 P471
·枚举器 java.util.Enumeration<>
  比标准迭代器少声明了一个方法 remove()
·迭代器 java.util.Iterator<>
  声明方法 T next();    boolean hasNext();    void remove();
  每次遍历集合后都需要重新获取迭代器,因为迭代器是单向、一次性的
·列表迭代器 java.util.ListIterator<>
  比标准迭代器多声明了向前或向后遍历对象集合的方法
3
集合类 P475
AbstractCollection<T>
AbstractMap<T>
AbstractSet<T>
  EnumSet<T>
  TreeSet<T>
  HashSet<T>
    LinkedHashSet<T>
AbstractList<T>
  Vector<T>
  │└ Stack<T>
  AbstractSequentialList<T>
  │└ LinkedList<T>
  ArrayList<T>
AbstractQueue<T>
  PriorityQueue<T>
EnumMap<T>
IdentityHashMap<T>
HashMap<T>
│└ LinkedHashMap<T>
WeakHashMap<T>
TreeMap<T>
    
4
集合接口 P476
Iterable<T> 用于集、列表和队列
Map<K, V> 用于映射
Collection<T>
  Set<T>
  │└ SortedSet<T>
  List<T>
  Queue<T> 
SortedMap<K, V>
5
向量 Vector
1 )构造函数 P478
    向量的工作方是和数组类似 ,但它能自动增大容量。默认的初始容量是 10 个对象,当容量不足时,容量将扩充一倍。这个默认设置有时并不适用,因此构造函数的重载方法中允许定义初始容量和增量值。需要注意的时,向量中存储的元素实际是对象的引用,也就是 int 型变量,而不是对象本身,其它的容器类也是一样的存储方式。向量中元素是连续存储的,在内存中是一整块,当容量改变时,需要将向量中的内容复制到新的内存空间,这个过程会消耗一定时间
2 )方法
    ensureCapacity() 确保容量
    setSize() trimToSize() 改变容量
    set() 改变元素
    listIterator() 使用 ListIterator 迭代器遍历
    toArray() 以数组形式返回向量中元素
3 )应用
    集合中元素的排序。 java.util.Collections 定义有方法 sort() 实现 List<> 接口集合类中元素的排序,前提是集合中的元素实现了 Comparable<> 接口,即实现了 int compareTo() 方法
6
Stack
派生自 Vector
int search(Object obj) 返回值是基于 1 的索引。
java.util.Collection.shuffle(java.util.List<>) List<> 接口的集合中的内容搅乱顺序。
7
HashMap 映射
1 )机制 P496
映射 map 是一种数据存储方式,以这种方式存储可以最小化获取对象时所需的搜索代价。在 java 的集合框架中,由 HashMap<> 类实现的映射设置了一个用于成对存储键和对象的数组,用于存储键 / 值对的项称为桶。这个数组的索引是由键对象生成,方法是用该键对象的散列码计算存放键 / 对象对的数组偏移量,在默认情况下,这个操作由作为对象的 hashCode() 方法完成。虽然每个键各不相同,但并非每个键生成的散列码是唯一的,当两个或多个不同的键生成相同的散列码时,这种情况被称为冲突, HashMap<> 对象的冲突处理方式是将所有散列码相同的键 / 对象存入同一个链表中,如果冲突频繁发生,会降低数据的存取速度。 Object 类定义的 hashCode() 方法利用对象的存储地址产生散列码,所以不同的对象总是有不同的散列码。从某种意义上这么做很好,因为可能每个键生成的散列码越不同,三列映射的操作就越有效。缺点上含有相同数据的不同对象将得到不同的散列码,这样就无法比较他们了。
2 )用自己创建的类的对象做键
两种方式:
覆盖 Object 类的 equals() 方法,比较两个不同的对象,但他们含有相同的数据,应该返回 true
覆盖 Object 类的 hashCode() 方法,应该使得方法产生的散列码在取值范围内均匀分布,且键值唯一。可以使用每个数据成员对应的整数值乘以不同的素数,然后求和作为散列码。
3 HashMap 的构造函数
可以指定初始容量和填充因子,填充因子值当散列表的长度达到填充因子和容量乘积的时候,容量将自动扩充为原来的两倍加一,容量默认为 16 ,填充因子默认为 0.75
4 .get(K key)
如果实参键值不存在或者存储的对象为空,都返回 null
5 )处理映射中的所有元素, 3 种方法
· .keySet() 返回所有键的 Set<K> 对象
 Set<K> keys = map.keySet();
 for(K key : keys) {...}
· .values() 返回所有对象的 Collection<V> 对象
 Collection<V> values = map.values();
 for(V value : values) {...}
· .entrySet() 返回所有键 / 对象对的 Set<Map.Entry<K, V>> 对象,每一对都是 Map.Entry<K, V> 类型的对象
 
 
 
15 实用类的集合
1
数组工具方法 java.util.Arrays
1 )填充数组 P511
void Arrays.fill(type[] array, type value)
除了可以填充基本数据类型数组,还可以填充对象数组,但在填充时,填充的是对象的引用,也就是说所有数组元素都引用同一个对象。
2 )比较数组 P512
boolean equals(type[] array1, type[] array2)
包含数据组元素数目相同且所有对应元素的值相等,返回 true 。元素的比较通过调用类的 equals() 方法判断的。
3 )对数组排序 P513
void sort(type[] array)
将数组元素进行升序排序
<T> void sort(T[] array, Comparator<? super T> comparator)
实用 comparator 比较器对数组元素进行排序,实现比较器接口 Comparator<> 的类可以是:
public class CompareElement<Element> implements Comparator<Element>
{
       public int compare(Element e1, Element e2)
    {
        if (e1 > e2)
            return 1;
        else if (e1 < e2)
            return -1;
        else
            return 0;
    }
       
    public boolean equals(Object comparator)
    {
            /*
             * 实参comparator与当前比较器排序方式相同返回true
             * 例如:
             */
            if ( this == comparator)
                return true ;
            if (comparator == null )
                return false ;
            return getClass() == comparator.getClass();
    }
}
4 )搜索数组 P516
int binraySearch(type[] array, type value)
实用二分法在已经升序排序的数组中查找指定元素,找到返回索引值,否则返回一个负数
<T> int binraySearch(T[] array, type value, Comparator<? super T> comarator)
与上一个方法不同之处在于,该方法正确工作的前提是数组使用比较器 comparator 经过了排序
2
Observable Observer 对象 P519
1 )当文档对象发生改变的时候,它的所有视图都需要被告知一种更改已经发生,因为他们需要更新显示的内容。文档是可观察的 Observable ,而视图是观察者 Observer ,这样就使得视图可以响应文档发生的变化。文档 - 视图结构描绘的是一个多对多关系,一个文档可能会有多个视图,一个视图可以观察多份文档。
2 Observable 是类,而 Observer 是接口,需要实现他的 update() 方法
    /*
     * 文档(可观察)
     */
    public class Document extends Observable
    {
        private Object data ;
       
        public void setData(Object data)
        {
            this . data = data;
            // 设置当前对象已经发生变化
            this .setChanged();
            // 如果当前对象设置为已改变,则通知所有观察者,调用观察者的update()方法
            this .notifyObservers();
        }
       
        public Object getData()
        {
            return data ;
        }
    }
   
    /**
      * 视图(观察者)
      * @author lnj
      *
      */
    public class View implements Observer
    {
        /**
          * 必须实现必须实现update方法
          * observable - 发生改变的Observable对象
          * arg - 附加信息
          */
        public void update(Observable observable, Object arg)
        {
            if (observable instanceof Document)
                System. out .println( this .toString() + " 发现变化:" + ((Document)observable).getData());
        }
    }
   
    public void reg()
    {
        Document doc = new Document();
        View view1 = new View();
        View view2 = new View();
       
        // 将观察者进行注册
        doc.addObserver(view1);
        doc.addObserver(view2);
       
        doc.setData( " 下雨啦" );
    }
3
产生随机数 P523
1 )构造函数
    Random r1 = new Random(); 使用当前时钟作为随机数的种子。
    Random r2 = new Random(); 使用长整型数值作为种子值。
    使用相同的种子创建的 Random 对象总会产生相同的序列。
2 )方法
方法
随机数区间
nextInt()
[Integer.MIN_VALUE, Integer.MAX_VALUE]
nextInt(int limit)
[0, limit)
nextFloat()
[0.0, 1.0)
setSeed(long seed)
使用新种子来产生序列
4
时期和时间 P525
1 Date
    日期时间对象,精确到毫秒
·解释 Date 对象
    java.text.DateFormat 中定义了 4 种日期、时间格式: SHORT MEDIUM LONG FULL
    java.util.Locale 中定义了国家、地区、语言信息
    DateFormat 中定义了静态方法获取 DateFormat 对象:
        getTimeInstance() 获取时间格式
        getDateInstance() 获取日期格式
        getDateTimeInstance() 获取日期时间格式
·解析日期时间字符串
    parse()
2 GregorianCalendar 公历 P530
    GregorianCalendar calendar = new GregorianCalendar();
    .set() 设置日期和时间
    .clear() 所有字段清零
    .get() 获取字段值
    .add() .roll() 增加或减小字段值
5
正则表达式 P535
1 )正则表达式功能通过 java.util.regex 包中的两个类实现, Pattern 类,封装了正则表达式对象, Matcher 封装了状态机的对象
2 )创建模式 Pattern
Pattern pattern = Pattern.compile(" 正则表达式字符串 ");
Pattern pattern = Pattern.compile(" 正则表达式字符串 ", 标志位 );  标志位来自 Pattern 中的常量字段
3 )创建 Matcher 对象
Matcher matcher = pattern.matcher(" 待搜索字符串 ");
matcher.reset(" 改变待搜索的字符串 ");
matcher.reset(); 重置搜索结果索引
matcher.find() 搜索模式下一次的出现位置,通过 matcher.start() matcher.end() 可以获取模式出现位置的索引值,也可以使用 matcher.group() 获取匹配的字符串
matcher.matches() 整个字符串与模式匹配时返回 true
4 )字符集
简单类
正则表达式
说明
[aeiou]
a e i o u 五个字符中的任意一个
[^aeiou]
a e i o u 五个字符以外的任何其他字符
[a-e]
a e 之间的任意字符
[a-cs-zA-E]
a c s z A E 之间的任意字符
逻辑操作符
[a-z&&[^aeiou]]
辅音字母中的任意一个字符
hid|had|hod
hid had hod 字符串
[h|H][aeiou]d
h H 开头,元音字母作中间字符, d 结尾的字符串
预定义字符集
.
除行结束符以外的任何其他字符
/d
数字,等效 [0-9]
/D
非数字,等效 [^0-9]
/s
空白字符
/S
非空白字符,等效 [^/s]
/w
成词字符,等效 [a-zA-Z_0-9]
/W
非成词字符,等效 [^/w]
边界
^Java
在每行起始查找 Java
Java$
在每行结束查找 Java
/b
指定边界。 /bh.d/b 查找以 h 起始, d 结尾中间任意字符的字符串
/B
非边界
/A
指定被搜索字符串的起始。 /AThe/b 查找以 The 开头的字符串
/z
指定被搜索字符串的末尾。 /bworld/z 查找以 world 结尾的字符串
/Z
除了最后终止符以外的换行符
量词
+
一个或多个
?
零个或一个
*
零个或多个
5 )查找和替换
        String str = "<td>A</td><td>B</td>" ;
        String regEx = "<td>" ;
       
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
       
        // 存放替换后的新字符串
        StringBuffer sb = new StringBuffer();
        while (m.find())
        {
            // 将找到的模式之前的字符串追加到sb中
            m.appendReplacement(sb, "<td nowrap>" );
        }
        // 将剩余的字符追加到sb中
        m.appendTail(sb);
        // 此时sb为<td nowrap>A</td><td nowrap>B</td>
6 )捕获组
Matcher 对象的 group() 方法获得与正则表达式所定义的整个模式相匹配的子列,整个模式表示的内容被称为捕获组( capturing group )。除了整个表达式所定义的组之外,正则表达式中的每对括号都定义了一个独立的捕获组。整个正则表达式的捕获组编号为 0 ,其他组编号按从正则表达式的左边开始计算开放圆括号的个数来进行。如:
正则表达式 [+|-]?(/d+(/./d*)?)|(/./d+)
字符串 0.1234
组0 [+|-]?(/d+(/./d*)?)|(/./d+)
0.1234
组1 (/d+(/./d*)?)
0.1234
组2 (/./d*)
.1234
组3 (/./d+)
null
7 )重排捕获组顺序
matcher.appendReplacement(" 新字符串 ", " 替换成字符串 "); 其中的 " 替换成字符串 " 可以引用捕获组文本,方法是使用“ $ 捕获组编号”,如 matcher.appendReplacement(newCode, "$1//($8, $2//)");
7
扫描器Scanner P552
java.util.Scanner 类定义了一个对象,该对象使用正则表达式扫描来自各种输入源的字符输入,并把输入表示为由各种基本类型组成的标记序列或者字符串。默认情况下,Scanner对象使用空白进行分割,空白字符是使Character类的isWhitespace()方法返回true的任意字符。使用scanner对象的userDelimiter()方法可以设置分隔符。
        String str = "windowsXP windows2000 windows2003 windowsVista" ;
        Scanner scanner = null ;
       
        // 使用默认的空白分隔符进行分割
        scanner = new Scanner(str);
        while (scanner.hasNext())
            System. out .println(scanner.next());
       
        // 使用默认的空白分隔符,查找有名字的windows(非数字)
        scanner = new Scanner(str);
        Pattern pattern = Pattern.compile( "//w*[^0-9]" );
        while (scanner.hasNext())
        {
            if (scanner.hasNext(pattern))
                System. out .println( " 找到" + scanner.next(pattern));
            else
                System. out .println( " 跳过" + scanner.next());
        }
       
        // 使用新的分隔符(windows或者空格)
        scanner = new Scanner(str);
        scanner.useDelimiter( "windows| " );
        while (scanner.hasNext())
            System. out .println(scanner.next());
 
 
 
第16章
1
创建线程 P562
(1)将线程定义为Thread类的子类,并提供run()方法来取代继承的run()方法。
public class MyThread extends Thread
{
    public void run()
    {
        try
        {
            while ( true )
            {
                System. out .println( "I am running" );
                sleep(1000);
            }
        }
        catch (InterruptedException e)
        {
            System. err .println( "InterruptedException" );
        }
    }
   
    public static void main(String[] args)
    {
        Thread t = new MyThread();
        t.start();
    }
}
(2)使线程类实现Runnable接口,实现void run()方法。
public class MyThread1 implements Runnable
{
    public void run()
    {
        try
        {
            while ( true )
            {
                System. out .println( "I am running" );
                Thread.sleep(1000);
            }
        }
        catch (InterruptedException e)
        {
            System. err .println( "InterruptedException" );
        }
    }
   
    public static void main(String[] args)
    {
        Thread t = new Thread( new MyThread1());
        t.start();
    }
}
2
线程方法 P564
(1)守护线程
守护线程是一个后台线程,它从属于创建它的线程,当创建守护线程的线程结束时,守护线程也随之结束。守护线程使用Thread对象的setDaemon(true)进行设置。非守护线程称为用户线程,它将拥有自己的生命周期,不依赖于创建它的线程,创建它的线程结束后,它仍然继续运行,用户线程使用Thread对象的setDaemon(false)设置。
(2)停止线程
Thread 对象的interpt()方法将向线程发送一个停止的信号,这样在线程执行sleep()方法时将引发InterruptedException异常,程序捕获这个异常即可中止线程。isInterrupted()检测线程是否已经发送停止信号。
(3)连接线程
thread1.join() 表示在当前线程中等待thread1线程结束,等待过程中可能发生InterruptedException。
(4)线程调度
当调用线程的sleep()方法时,即使没有其他线程在等待,该线程也至少会停止实参指定的一段时间,而调用yield()方法时,如果没有其他线程在等待,当前线程马上重新开始执行。
3
线程同步 P570
(1)同步方法
public synchronized void syncMethod()
{
}
确保在一个对象的所有同步方法中,一次只能有一个可以执行,不能保证一个类的多个对象同步方法互斥执行。
(2)静态同步方法
public static synchronized void syncMethod()
{
}
确保一个类的所有静态同步方法中,一次只能有一个可以执行,是类范围的同步。
(3)同步代码块
synchronized (theObject)
{
    // 语句块
}
theObject 对象的同步语句块执行时,同一theObject对象的其他同步代码块或同步方法就不能执行。
(4)wait()、notify()、notifyAll()
只有在同步方法或者同步代码块中才能调用这3个方法。
wait() 挂起当前线程,直到调用了wait()方法所属于的那个对象的notify()或notifyAll()方法,调用wait()方法后,会释放当前对象的同步锁,这样该对象的其他同步方法或同步代码块才得以执行,该对象的notify()或notifyAll()方法才可能被调用。
notify() 重新启动一个线程,该线程调用了notify()方法所属的那个对象的wait()方法。
notifyAll() 使调用了wait()方法的所有线程都需重新启动,而wait()方法和notifyAll()方法属于同一个对象。
自悟:wait()、notify()、notifyAll()都是针对同一个对象不同线程而言的,而这个对象是一个“互斥资源”
public class Counter
{
    private int m_CurrentNum ;
    private int m_MaxNum ;
   
    public Counter()
    {
        m_CurrentNum = 0;
        m_MaxNum = 0;
    }
   
    synchronized public void increase()
    {
        while ( m_CurrentNum >= m_MaxNum )
        {
            try
            {
                Log.info( " 数量饱和,请等待" );
                wait();
            }
            catch (InterruptedException e)
            {
                Log.info( " 等待过程中发生异常,该异常将被忽略" );
                Log.info(e.toString());
            }
        }
       
        m_CurrentNum ++;
        notifyAll();
        Log.info( " 数量增加,当前数量为" + m_CurrentNum );
    }
   
    synchronized public void decrease()
    {
        m_CurrentNum --;
        notifyAll();
        Log.info( " 数量减少,当前数量为" + m_CurrentNum );
    }
   
    /**
      * 获取当前计数
      * @return
      */
    synchronized public int getCurrentNum()
    {
        return m_CurrentNum ;
    }
   
    /**
      * 获取最大计数
      * @return
      */
    synchronized public int getMaxNum()
    {
        return m_MaxNum ;
    }
   
    /**
      * 设置当前计数
      * @param num
      */
    synchronized public void setCurrentNum( int num)
    {
        m_CurrentNum = num;
    }
   
    /**
      * 设置最大计数
      * @param num
      */
    synchronized public void setMaxNum( int num)
    {
        m_MaxNum = num;
    }
}
4
包装非同步集合类 P591
java.util.Collections 类提供了从非同步的对象创建同步集、列表和映射的方法。
 
 
 
第22章 Java与XML
1
XML
Extensible Markup Language
2
XML 文档结构 P873
序言Prolog
    XML 声明 XML declaration
    文档类型声明 Document type declaration
文档体 Document body
XML 声明: <? xml version = "1.0" encoding = "UTF-8" standalone = "yes" ?>
文档类型声明: <! DOCTYPE rootElem SYSTEM "proverb.dtd" >
3
预定义实体 P875
&
&amp;
'
&apos;
"
&quot;
&lt;
&gt;
4
元素命名 P877
以字母或下划线开始,名字中可以使用数字.-。XML是区分大小写的,但忽略空白字符。
5
通用实体general entity P877
<!ENTITY copyright "(c) 2006 devtemptation">
  定义copyright实体,它代表字符串“(c) 2006 devtemptation”。
<!ENTITY doc SYSTEM "http://www.devtemptation.org/doc.txt">
  定义doc实体,他代表http://www.devtemptation.org/doc.txt中的内容。
&copyright;
  引用实体
6
CDATA 段 P878
CDATA 段用来嵌入不希望XML处理器解析的数据,可以是二进制数据,CDATA段格式为 <![CDATA[ 内容 ]]>
7
元素常规和属性常规(element-normal & attribute-normal)P879
元素常规:所有数据都是元素
属性常规:所有数据都被定义为属性值
8
文档类型定义
文档类型定义(Document Type Definition DTD)定义了如何为特定类型的文档构造有效的元素
(1)声明DTD P881
XML 1.0 版本的文档只能有一个DOCTYPE声明。在声明中显示地包含文档中使用元素的标记声明称为内部子集(internal subset),而通过指定标识文档DTD的URI称为外部子集(external subset)。
<! DOCTYPE 文档根元素名 SYSTEM "URI" >
    外部子集,"URI"被称为系统标识符System ID。
<! DOCTYPE 文档根元素名 PUBLIC "URI" >
    外部子集,"URI"被称为公有标识符Public ID。
<! DOCTYPE 文档根元素名 [<!ELEMENT 文档根元素(#PCDATA) >] >
    内部子集
(2)定义元素 P883
<!ELEMENT address (buildingnumber, street, city, state, zip)>
    元素address可以按序出现元素buildingnumber、street、city、state、zip。
<!ELEMENT buildingnumber (#PCDATA)>
    元素buildingnumber只能含有可解析字符数据
<!ELEMENT buildingnumber (#PCDATA|suite)*>
    元素buildingnumber可以含有可解析字符数据或suite子元素,并且他们可以出现0次或多次,但不能限制他们的出现顺序。
<!ELEMENT address (buildingnumber?, street, city, state, zip?)>
    元素address含有的子元素中,buildingnumber和zip可选。
<!ELEMENT address ((buildingnumber|buildingname))>
    元素address必须且只含有子元素buildingnumber或buildername之一。
<!ELEMENT address ((buildingnumber|buildingname)+)>
    元素address必须至少含有一个子元素buildingnumber或buildername。
<!ELEMENT address ((buildingnumber|buildingname)?)>
    元素address含有一个子元素buildingnumber或一个子元素buildername或不含子元素。
<!ELEMENT address ((buildingnumber|buildingname)*)>
    元素address可以含有子元素buildingnumber或子元素buildername或两种子元素或不含子元素。
<!ELEMENT zip EMPTY>
    元素zip不能含有任何子元素和可解析字符数据。
至少出现一次;* 出现零次或多次;? 出现零次或一次;| 有左操作数或右操作数,但不能同时出现。
(3)定义元素属性 P885
<!ATTLIST 属性名 值类型 属性是否强制出现或默认值 >
<!ATTLIST address
    name CDATA #REQUIRED
    country CDATA #IMPLIED
    level CDATA "unknown"
    area ( small|medium|large) #REQUIRED
    iscapital CDATA #FIXED "no"
元素address必须具有属性name和area,属性country可选,level属性默认为unknown,area属性取值为small、medium、large三者之一,iscapital属性默认且只能为no。
(4)定义参数实体parameter entity P887
参数实体通过名字来表示一块解析文本,可以将这块文本插入DTD中不同的位置。参数实体只能用于DTD中,而通用实体用于文档中。
定义参数实体
<!ENTITY % coordinates "X CDATA #REQUIRED
                        Y CDATA #REQUIRED" >
引用参数实体
<!ATTLIST address
    name CDATA #REQUIRED
    country CDATA #IMPLIED
    level CDATA "unknown"
    area ( small|medium|large) #REQUIRED
    iscapital CDATA #FIXED "no"
    %coordinates;
(5)更多属性值类型 P887
ENTITY
实体
ENTITIES
空格分隔的实体列表
ID
元素标识
IDREF
通过ID对元素的引用
IDREFS
空格分隔的ID引用列表
NMTOKEN 、NMTOKENS、NOTATION
 
9
构造良好文档的规则P891
如果在序言中出现XML声明,那么它必须包含XML的版本信息。XML文档的其他规范必须按照规定的顺序出现,字符编码后是standalone规范。
如果在序言中出现文档定义类型,那么DOCTYPE的名字必须与根元素的名字相一致,而且DTD中的标记声明必须符合书写标记声明的规则。
文档必须至少包含一个元素,即根元素,它包含其他所有元素,而且根元素的实例不能出现在另一个元素的文档中。所有元素必须嵌套正确。
文档体中的元素必须和DOCTYPE声明中标记的标记声明相一致。
10
XM 名字空间
(1)解决多份XML文档组合成一个XML文档时发生的元素名冲突的问题。XML名字空间对标记中使用的名字进行限定,将同样的名字放在不同的名字空间中,就可以在不同标记中重复使用它们。从概念上讲,每个名字都是由包含它的名字空间的唯一URI进行限定,在实际使用中,通过名字空间前缀(namespace prefix)进行名字限定,名字空间的作用域是在其中声明名字空间的元素内容,和该元素的所有子元素。
(2)
<? xml version = "1.0" encoding = "UTF-8" standalone = "no" ?>
< sketcher:sketch xmlns:sketcher = "http://www.devtemptation.org/dtds/sketches" >
    < sketcher:circle radius = "15" angle = "0" >
        < sketcher:color R = "150" G = "250" B = "100" />
        < sketcher:position x = "30" y = "40" />
    </ sketcher:circle >
</ sketcher:sketch >
    在元素sketch上定义名字空间,前缀为sketcher,URI为http://www.devtemptation.org/dtds/sketches。并对元素名sketch、circle、color、position进行限定。
<? xml version = "1.0" encoding = "UTF-8" standalone = "no" ?>
< sketch xmlns = "http://www.devtemptation.org/dtds/sketches" >
    < circle radius = "15" angle = "0" >
        < color R = "150" G = "250" B = "100" />
        < position x = "30" y = "40" />
    </ circle >
</ sketch >
    使用默认名字空间,可以不加限定名而使用这个名字空间的元素名和属性名,他们都隐式的存在于这个名字空间中。
<? xml version = "1.0" encoding = "UTF-8" standalone = "no" ?>
< sketch xmlns = "http://www.devtemptation.org/dtds/sketches"
        xmlns:print = "http://www.devtemptation.org/dtds/printed" >
    < circle radius = "15" angle = "0" >
        < color R = "150" G = "250" B = "100" />
        < position x = "30" y = "40" />
    </ circle >
    < print:circle print:lineweight = "3" print:linestyle = "dashed" />
</ sketch >
    可以在单个元素中声明若干个名字空间,如使用一个默认名字空间和另一个名字空间
(3)DTD并没有为名字空间提供支持,因此要保持文档有效,必须在DTD中考虑名字空间前缀和声明名字空间元素的xmlns属性。
11
XML 模式
(1)定义 P893
为描述XML文档的结构,W3C开发了XML模式,它和DTD起着同样的作用,但它比DTD提供了更多的功能,如数据类型和格式,因此使用XML模式更好,XML模式语言也被称为XSD(XML Schema Definition)。XSD本身也是XML文档,它是用来描述XML文档结构的XML文档。在XML模式中,声明(declaration)指定作为文档文本的元素;定义(definition)定义元素类型。
(2)定义模式 P894
<? xml version = "1.0" encoding = "UTF-8" ?>
< schema xmlns = "http://www.w3.org/2001/XMLSchema" >
    < element name = "address" type = "AddressType" />
    < complexType name = "AddressType" >
        < sequence >
            < element name = "buildingnumber" type = "positiveInteger" />
            < element name = "street" type = "string" />
            < element name = "city" type = "string" />
            < element name = "state" type = "string" />
            < element name = "zip" type = "decimal" />
        </ sequence >
    </ complexType >
</ schema >
模式必须有唯一的根元素schema,并且可以使用名字空间。模式文档拥有元素element、complexType、schmea等元素,element元素可以有属性name和type。它定义了实例文档根元素为address,它有子元素buildingnumber、street、city、state、zip且子元素必须按顺序出现。
(3)定义元素P895
复杂元素:包括子元素或属性,使用complexType定义,简单元素:不含子元素或属性,只含数据(标准类型数据或自定义类型数据),使用simpleType定义。
< element
    name = "city"    元素名称
    type = "string"  元素数据类型
    minOccurs = "1"  元素最少出现次数,默认为1
    maxOccurs = "1"  元素最多出现次数,默认为1
    default = " 北京"  默认值
    fixed = " 北京" /> 固定元素值
(4)定义复杂元素属性P896
<? xml version = "1.0" encoding = "UTF-8" ?>
< xsd:schema xmlns:xsd = "http://www.w3.org/2001/XMLSchema" >
    < xsd:element name = "circle" type = "circleType" ></ xsd:element >
    < xsd:complexType name = "circleType" > 圆的元素类型
        < xsd:attribute name = "x" type = "xsd:double" use = "required" /> 属性x、y必须,且为double类型
        < xsd:attribute name = "y" type = "xsd:double" use = "required" />
        < xsd:attribute name = "radius" use = "required" > 属性radius必须
            < xsd:simpleType >
                < xsd:restriction base = "xsd:double" > 为double类型,比0大
                    < xsd:minExclusive value = "0" />
                </ xsd:restriction >
            </ xsd:simpleType >
        </ xsd:attribute >
        < xsd:attribute name = "color" use = "required" > 属性color必须
            < xsd:simpleType >
                < xsd:restriction base = "xsd:string" > 为string类型且来自枚举值red、blue
                    < xsd:enumeration value = "red" />
                    < xsd:enumeration value = "blue" />
                </ xsd:restriction >
            </ xsd:simpleType >
        </ xsd:attribute >
    </ xsd:complexType >
</ xsd:schema >
(5)属性组 P897
若干不同元素具有相同的属性组,为避免重复定义,可以使用属性组。
定义属性组coords,它由两个元素组成。
    < attributeGroup name = "coords" >
        < attribute name = "x" type = "double" use = "required" />
        < attribute name = "y" type = "double" use = "required" />
    </ attributeGroup >
使用属性组定义点的元素类型
    < complexType name = "PointType" >
        < attributeGroup ref = "coords" />
    </ complexType >
(6)定义备选元素
    < complexType name = "sketchType" >
        < choice minOccurs = "0" maxOccurs = "unbounded" >
            < element name = "line" type = "LineType" / >
            < element name = "rectangle" type = "RectangleType" / >
            < element name = "circle" type = "CircleType" / >
        </ choice >
    </ complexType >
定义SketchType类型元素,包含0个或更多个子元素,且每个子元素都是LineType、RectangleType、CircleType类型其中之一。
(7)使用XML模式 P903
<? xml version = "1.0" encoding = "UTF-8" ?>
< circle xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation = "root.xsd" >
</ circle >
表示该实例文档名字空间为http://www.w3.org/2001/XMLSchema-instance,且前缀为xsi,名字空间xsi中的属性noNamespaceSchemaLocation是文档的模式所在的路径。
12
使用XML文档编程P904
SAX :用于XML解析的简单API(Simple API for XML)
使用基于事件的处理来阅读XML文档,它由回调机制实现,SAX是快速、储存效率高的、有选择处理XML文档内容的方法。
javax.xml.parsers.SAXParserFactory SAX 工厂
javax.xml.parsers.SAXParser          SAX 解析器
DOM :XML的文档对象模型(Document Object Model)
解析XML文档时,整个文档都在内存中形成,作为封装好的Document类型对象返回给应用程序,缺点是占用内存较大。
javax.xml.parsers.DocumentBuilderFactory DOM 工厂
javax.xml.parsers.DocumentBuilder          Dom 解析器
这4个类都是抽象类,JAXP被设计为允许插入不同解析器及它们的工厂类,DOM和SAX解析器都是独立于JDK开发的,他们可以随着发展集成新的解析器。随J2SE5发布的是Apache的Xerces解析器,J2SE5支持DOM3rd、SAX2.0.2和XLST1.0。
13
使用SAX P906
(1)
// 创建SAX解析器工厂
SAXParserFactory spf = SAXParserFactory.newInstance();
System. out .println( "SAXParserFactory:/t" + spf.toString());
 
// 将解析器设置为可识别名字空间,这样解析器将能获取每个元素和属性的uri和localName,否则只能将元素名和属性名作为单独的名字报告。
spf.setNamespaceAware( true );
 
// 验证DTD、XSD及文档体内容与DTD、XSD中的定义是否一致
spf.setValidating( true );
 
// 创建解析器
SAXParser parser = spf.newSAXParser();
System. out .println( "SAXParser:/t" + parser.toString());
 
File f = new File(filename);
 
// 声明自定义的XML解析器实践处理器
DefaultHandler dh = new MySAXHandler();
parser.parse(f, dh);
 
public class MySAXHandler extends DefaultHandler
{
    // 通过继承DefaultHandler类,覆盖掉其中的无为方法,从而实现SAX解析事件的处理。覆盖startDocument()、endDocument()、startElement()、endElement()等方法解析xml文档;覆盖warning()、error()、fatalError()方法捕获解析XML过程中出现的警告、错误、致命错误。
}
如果XML文档没有DTD定义,那么解析器将无法区分可忽略空白字符,从而将它们当作字符数据处理。
可以处理带有名字空间的文档,并且可以使用限定名,但若要处理名字空间前缀,需要打开“报告名字空间前缀”特征。
(2)使用不同的解析器P909
可以使用不同的SAX解析器,只需将该解析器的jar文件加入到-classpath中。
(3)解析器的特征和特性P909
特定的解析器有自己的特征和特性,从而来控制和报告XML文档的处理。
使用SAXParserFactory对象的getFeature()、setFeature()访问特性;SAXParser对象的getProperty()、setProperty()访问特性;XMLReader对象的getFeature()、setFeature()、getProperty()、setProperty()访问特征和特性。
(4)使用模式 P921
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants. W3C_XML_SCHEMA_NS_URI );
Schema schema = sf.newSchema( new File( "root.xsd" ));
spf.setSchema(schema);
SchemaFactory.newInstance() 的实参指明了模式定义语言,常量javax.xml.XMLConstants. W3C_XML_SCHEMA_NS_URI 为http://www.w3.org/2001/XMLSchema;SchemaFactory.newSchema()的实参指明了xsd文件对象。
 
 
 
第23章 创建和修改XML文档
1
设置DOM解析器
javax.xml.parsers.*
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
builderFactory 对象常用方法:
   
setNamespaceAware()
设置识别名字空间
setValidating()
设置验证XML文档
setIgnoringElementContentWhitespace()
设置忽略元素内容中的空白字符
setIgnoringComments()
设置忽略注释
setExpendEntityReferences()
设置扩展实体引用
setSecureProcessing()
设置“安全处理”,实际上是设置处理行为的一些极限值
setErrorHandler()
设置解析错误处理,当调用setValidating(true)后,必须设置解析错误处理类
setSchema
设置XML模式
DocumentBuilder builder = builderFactory.newDocument();
builder 对象常用方法:
parse()
解析XML文档,返回org.w3c.dom.Document对象
2
常用接口 P929
(1)org.w3c.dom.Node
它封装文档树中节点的对象类型,是XML文档组件对象的基础,它也是其他接口的超接口,它们是:Element元素、Attr元素属性、Text元素文本、CDATASection不解析字符数据、Comment注释、DocumentType文档类型、Document文档、DocumentFragment轻量级文档,封装文档的子树、Entiry实体、EntityReference实体引用、Notation记号、ProcessingInstruction预处理指令。
getChildNodes()
获取子节点的NodeList引用
getNodeType()
获取节点类型,如文档、元素、属性
hasAttributes()
节点是否有属性
getAttributes()
获取属性的NamedNodeMap引用
(2)Document
由DocumentBuilder的parse()方法返回,是文档的最顶层节点。
getDocumentElement()
返回根元素
getDoctype()
获取DTD文档类型节点对象
(3)NodeList
由Node对象的getChildNodes()方法返回。
getLength()
返回数量
item(int index)
获取index位置的Node对象
(4)NamedNodeMap
由Node对象的getAttributes()方法返回。
getLength()
获取长度
getNamedItem(String name)
返回节点为name的Node引用
getNamedItemNS(String uri, String localname)
返回指定名字空间uri,本地名字为localname的Node引用
(5)Attr
由Node对象getAttributes()方法得到的NamedNodeMap对象的item(int index)方法强制转换而来。
getName()
获得属性名
getValue()
获取属性值
3
处理可忽略空白字符和元素内容P935
某些元素含有多个#text元素,他们可能是元素内容或标记中可忽略的空白符。使用builderFactory对象的setIgnoringElementContentWhitespace(true)可避免将可忽略字符报告为一个节点。对于元素内容中产生的#text元素,可使用((Text)node).getWholeText()获取其内容。
4
创建XML文档P939
可以使用Document doc = builder.newDocument();创建Document对象的引用,但这种方法有局限性,因为没有办法修改DocumentType节点来反映合适的DOCTYPE声明。使用下面的方法可以解决这个问题:
DOMImplementation domImpl = builder.getDOMImplementation();
DocumentType docType = domImpl.createDocumentType(" 根元素限定名", "publicID", "systemID");
Document doc = domImpl.createDocument(" 名字空间", "根元素名", docType);
填充文档。org.w3c.Document接口声明了向Document对象中添加节点的方法,可以创建节点来封装元素、属性、文字、实体引用、注释、CDATA段和预处理指令,调用Document对象的createXXX()方法。
 
 
 
24
1
JDBC                                                                                                   P967
建立在其他标准程序 —— 数据库接口的基础上,这就是 X/Open SQL CLI(Call Level Interface 调用级接口 ) 的技术规范。
这个库是在 java.sql 程序包中实现的,这是一个为访问多种数据库而提供统一 API 的类和接口的集合。
2
数据库编目( Catalog                                                                                     P969
指数据库的系统表,系统标用于存储关于数据库、表以及标的组成的信息。
3
元数据( metadata                                                                                       P969
描述数据库内容的数据成为元数据,或者数据字典( data dictionary
4
带空格的列别名                                                                                           P976
使用双引号引起来
5
JDBC                                                                                                 P978
JDBC 库被设计为执行 SQL 语句的接口,而不是进行数据库访问的高级抽象层。
JDBC 是通过实现针对每个特定数据库的 JDBC 接口,即驱动程序来实现对不同数据库的操作。
6
数据库驱动程                                                                                             P980
(1)JDBC 驱动程序是由实现 Driver 接口的类定义的
(2) 系统属性 jdbc.drivers 定义了 JDBC 驱动程序, DriverManager 类在装入系统的时候将尝试装入这个驱动程序
     System.setProperty(jdbc.drivers, sun.jdbc.odbc.jdbcOdbcDriver;com.microsoft.sqlserver.jdbc);
     因为安全策略的限制,在使用 setProperty() 时会抛出 SecurityException 异常
(3) 使用 Class.forName() 注册
     调用 forName() 使得 java 解释器的类装入实参指出的驱动程序。当装入了这个驱动程序类之后,这个类装入器将判断这个驱动程序是否有 static 初始化代码,如果有,那么将在装入该类之后立即执行 static 初始化代码。这就是驱动程序类可以实例化自身,并且注册 DriverManager 对象创建实例的原因。此外,它还可以执行其他可能需要的初始化代码,例如该驱动程序使用本机的方法则要装入一个动态链接库,并且由于这些都是在这个类装入时发生的,因此可以保证这些处理都发生在调用其他驱动程序方法之前。
7
使用 java.util.Properties 作为 DriverManager.getConnection(String url, Properties info) 的实参                      P983
Properties prop = new Properties();
prop.setProperty(user, sa);
prop.setProperty(password, );
Connection conn = DriverManager.getConnection(sourceURL, prop);
8
JDBC 驱动程序操作的日志记录                                                                             P983
DriverManager 的静态方法 public static void setLogWriter(PrintWriter out) public static PrintWriter getLogWriter()
使用 DriverManager.setLogWriter(null); 取消日志记录
9
登录超时设置 P983
DriverManager.setLoginTimeout(int secs) DriverManager.getLoginTimeout()
10
JDBC 驱动的 4 种实现形式
(1)JDBC-ODBC 桥驱动程序
    JDBC 方法翻译成 ODBC 函数调用实现,适用于没有 JDBC 驱动的情况下
(2) 本机 API/ 部分 Java 驱动程序
    通过本机方法访问数据库,需要调用厂商库
(3) 网络协议全部为 Java 客户
    通过中间件通讯(通常是 TCP/IP )把 JDBC 请求翻译成数据库访问的调用
(4) 本机协议全部为 Java (如果可能的话,尽量使用该方式)
    直接使用该服务器的本机协议于数据库服务器通信,没有把 Java 初始化请求转换成其他形式的翻译过程
11
JDBC 驱动官方网址
http://servlet.java.sun.com/products/jdbc/drivers
12
DriverManager.getConnection() 的工作原理
当调用该方法时,会在 DriverManager 注册的驱动程序中迭代处理,并且依次询问每个驱动程序是否能够处理 URL ,第一个处理的驱动程序将创建一个 Connection 对象,然后将其返回给应用程序。
13
获取 Driver 对象
使用 DriverManager.getDriver(String url)
14
批处理执行 SQL 语句
需要批处理执行的 SQL 语句依次使用 addBatch() 方法, executeBatch() 用于执行, clearBatch() 方法清除用过的批处理语句
15
ResultSet 的一些特殊 get 方法
getDate() 返回 java.sql.Date
getTime() 返回 java.sql.Time
getTimestamp() 返回 java.sql.Timestamp
getAsciiStream() 返回 java.io.InputStream ,用于 SQL LONGVARCHAR 类型
大多数基本数据访问方法都能很灵活的从 sql 数据类型转换成 java 数据类型,比如任何 sql 数据都可以用 getString() 来读取
16
ResultSetMetaData
使用 rs.getMetaData() 来获取,而不需要 rs.next() 方法。
 
 
 
 
 
 
 
 
 
25
1
SQL-92 标准定义了一个数据类型集,但这个集与 java 中的数据类型并非一一对应
SQL 数据类型
Java 数据类型
Java 数据类型
SQL 数据类型
CHAR
String
String
VARCHAR
LONGVARCHAR
VARCHAR
String
java.math.BigDecimal
NUMERIC
LONGVARCHAR
String
boolean
BIT
NUMERIC
java.math.BigDecimal
byte
TINYINT
DECIMAL
java.math.BigDecimal
short
SMALLINT
BIT
boolean
int
INTEGER
TINYINT
byte
long
BIGINT
SMALLINT
short
float
REAL
INTEGER
int
double
DOUBLE
BIGINT
long
byte[]
VARBINARY
LONGVARBINARY
REAL
float
java.sql.Date
DATE
FLOAT
double
java.sql.Time
TIME
DOUBLE
double
java.sql.Timestamp
TIMESTAMP
BINARY
byte[]
VARBINARY
byte[]
LONGVARBINARY
byte[]
 
 
DATE
java.sql.Date
 
 
TIME
java.sql.Time
 
 
TIMESTAMP
java.sql.Timestamp
 
 
2
约束结果集
statement.getMaxRows();statement.setMaxRows(); 设置结果集最大行数, 0 表示没有限制。
statement.getMaxFieldSize();statement.setMaxFieldSize(); 结果集任意字段的最大字节数, 0 表示没有限制。
statement.getQueryTimeout();statement.setQueryTimeout(); 查询超时时间, 0 表示没有限制。
3
LONGVARCHAR LONGVARBINARY 类型数据的处理
设置: setAsciiStream() setUnicodeStream() setBinaryStream()
4
检测空值
ResultSet 中获取数据后调用 wasNull() 方法
5
特殊数据类型
 java.sql.Date ,定义了 ResultSet.getDate() 返回值类型,继承 java.util.Date
 java.sql.Time ,定义了 ResultSet.getTime() 返回值类型,继承 java.util.Date
 java.sql.Timestamp ,定义了 ResultSet.getTimestamp() 返回值类型,继承 java.util.Date
 java.math.BigDecimal ,定义了任意精度的十进制数, java.math.BigInteger java.math.BigDecimal 运算速度慢
6
流的处理 P1028
LONGVARCHAR    getAsciiStream()
LONGVARCHAR    getCharacterStream()
LONGVARBINARY getBinaryStream()
7
调用存储过程 P1030
  通过 java.sql.CallabelStatement 接口提供功能
  调用字符串 {? = call procedureName(?, ?)}
  使用 setXXX() 方法提供输入参数值
  使用 registerOutParameter(index, type) 注册输出参数
  使用 getXXX() 方法获取输出参数值
  返回值也是一种输出参数
8
SQL Exception
(1) 三种基本信息
   异常消息 getMessage()
   SQL 状态  getSQLState()
   厂商错误编码 getErrorCode()
(2) 异常链
   ·抛出的异常可能会形成一个链,特定的 SQL Exception 是链上的一个结点
   ·显示链上全部异常
       catch(SQLException e)
       {
           do
           {
               // 输出异常信息
           }while((e = e.getNextException()) != null);
       }
   ·把自定义的异常加入到链上的第一个结点前
       catch(SQLException e)
       {
           // 自定义异常
           SQLException e1 = new SQLException(message, sqlState, errorCode);
           e1.setNextException(e);
           throw e1;
       }
   ·把自定义的异常加入到链上的最后一个结点之后
       catch(SQLException e)
       {
           // 找到链上的最后一个结点
           SQLException lastE = e;
           while(lastE.getNextException() != null)
               lastE = lastE.getNextException();
           // 将异常加入到链上的最后一个结点之后
           SQLException e1 = new SQLException(message, sqlState, errorCode);
           lastE.setNextException(e1);
           throw e;
       }
   ·我认为应该把自定义的异常加入到链上的第一个结点前,这样就能形成一个异常链,这个链越在后的结点,对应的异常就越底层
9
SQLWarning
  派生自 SQLException ,同样有三种“基本信息”和“链”
  必须显示请求 getWarning() 方法获得警告信息
 Connection Statement ResultSet 接口都定义了 getWarning() 方法

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值