Introduction to Java Programming

中文是《java语言程序设计基础篇》和《java语言程序设计进阶篇》,适合java初学者。

rel="File-List" href="file:///C:%5CDOCUME%7E1%5C%E4%B8%B0%E5%9B%BD%E6%A0%8B%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml"> rel="Edit-Time-Data" href="file:///C:%5CDOCUME%7E1%5C%E4%B8%B0%E5%9B%BD%E6%A0%8B%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_editdata.mso">

Introduction to Java Programming

1

Java程序编译后,产生字节码(bytecode),字节码可以在任何装有java虚拟机(Java Virtual MachineJVM)的计算机上运行。Java虚拟机是解释Java字节码的程序。

2

数值类型转换:当两个类型不同的运算对象进行二元运算时,

运算对象之一是double,结果转换为double

否则,之一为float,结果为float

否则,之一为long,结果为long

否则,转换为int

所以下列一段代码有错误

short i=1

 i=i+1;//错误原因:int无法转换为short

可以改成i=(short)(i+1);或者i+=1;

3

Java运算符优先级

除了赋值运算符,所有双目运算符都是左结合的。

a-       b+c-d等于((a-b)+c)-da=b+=c=5等于a=(b+=(c=5))

 

&&&|||的不同在于:&为无条件或,&&为条件或,即a&&b,如果afalse则不计算b&不管a是否为false,都要计算b

4

If语句中,最好最后一个语句采用else而不是else if,不然解释器可能认为还没有结束。

public static int sign(int n)

    {

       if(n < 0) return 1;

       else if(n == 0) return 0;

       else if(n < 0) return -1;

    }

errorThis method must return a result of type int    

5

每当调用一个方法时,系统将参数、局部变量和系统寄存器存储在内存区域堆栈中(stack),后进先出的方式存储数据。当一个方法调用另一个方法时,调用者的空间不变,新开辟的空间保存新方法的调用。一个方法结束返回到调用者时,其相应的空间也被释放。

6

方法的参数传递过程中,无论形参如何改变,实参不受影响。形参是方法中具有自己存储空间的局部变量,局部变量再调用方法时分配的,当方法返回时就消失了。

7

Java中可以使用赋值语句复制基本类型的变量,但是不能复制数组。将一个数组变量赋值给另一个数组变量,实际上是将一个数组的引用复制给另一个变量,使两个变量指向相同的内存地址。

如下例输出10 10 10 10

public static void main(String[] args) {

       // TODO Auto-generated method stub

       int[] arrayA = new int[4];

       int[] arrayB = arrayA;

       change(arrayB);

      

       for(int value:arrayA)

       {

           System.out.println(value);

       }

    }

    public static void change(int[] array)

    {

       for(int i = 0; i < array.length; i++)

       {

           array[i] = 10;

       }

    }

8

数组复制的3种方法:

用循环语句复制数组的每一个元素

     
     
     
     用System类的静态方法arraycopy,
      
      
public static void arraycopy(Object src,
      
      

                             int srcPos,

                             Object dest,

                             int destPos,

                             int length)

arraycopy没有给目标数组分配内存空间,复制前必须创建目标数组并给其分配内存空间。

clone方法复制数组

9

给方法传递参数:

对于基本数据类型的参数,传递的是实参的值

对于数组类型的参数,参数值是数组的引用,给方法传递的是这个引用

对于对象,结构等的参数,传递的也是引用

数组存储在堆(heap)的内存空间,堆用于动态内存分配,在堆中内存块可以按任意的顺序分配和释放。

10

对于排序,java.util.Array类提供了排序的方法,可以用于intdoublecharshortlongfloat型数组。对于已经排序好的数组,java.util.Array提供了binarySearch方法。

11

永久类:

类的所有数据是私有的并且没有修改器

并且不含有返回引用非永久对象数据域的修改器和访问器。

12

如果让类的所有实例共享数据,采用静态变量(static variabl),静态变量存储在类的公用内存中。静态方法:不创建实例就可以调用静态方法。

13

类(inner class)特征:

内部类可以引用包含在他的外部类中的数据和方法,所以不必把外部类的引用传递给内部类的构造方法

内部类只是用来支持其外部类的工作,编译后,名称如“外部类名称$内部类名称.class

内部类可以声明为publicprotectedprivate,意义与用在类的其他成员相同

内部类可以声明为静态(static)类,可以使用外部类的类名来访问静态的内部类,静态内部类不能访问外部类的非静态成员。

可以在外部类中创建内部类的对象实例,也可以在另外的类中创建内部类的对象实例。如果内部类是非静态的,必须先创建外部类的实例,再使用下列语句来创建内部类的实例:

外部类.内部类 内部类对象名 = 外部类对象.new 内部类();

如果内部类是静态的,采用下列语法创建它的对象:

外部类.内部类 内部类对象名 = new 外部类.内部类();

 

下面例子有错:

public class MyInnerClass {

    private int data;

    public void m(){

       InnerClass instance = new InnerClass();

    }

    //inner class

    static class InnerClass{//error,因为定义为静态内部类,不能访问外部类的

//非静态成员

       public void mi(){

           data++;

           m();

       }

    }

}

14

Static inner class inner class的区别:

static inner class 不能访问外部类的非静态成员

static inner class可以用外部类名来创建,不必须外部类的对象。可以用外部类的类名来访问静态内部类。

15

String对象是永久的,内容不能改变。

String s = “Java”;

S = “HTML”;

首先创建了内容为“Java”String对象,并将其引用赋值给s。第二条是创建了一个内容为”HTML”的新的String对象,并将其引用赋给s”Java”这个String对象还是存在的,只是不能再访问他。

如果两个String对象是通过快捷初始化用相同的字符串直接构建,JVM将他们存储在同一个对象中,如:

String s = "Java";

       String s1 = new String("Java");

       String s2 = s1.intern();

       String s3 = "Java";

       System.out.println("s1 == s is "+(s1 == s));

       System.out.println("s2 == s is "+(s2 == s));

       System.out.println("s3 == s is "+(s3 == s));

输出为:

s1 == s is false

s2 == s is true

s3 == s is true

16

String s = new String("xyz");创建了几个String Object

2个,"xyz "作为一个常量字符串首先被创建,它被保存在“串池”中。所谓串池,简单讲就是从程序运行开始,你创建的所有常量字符串被统一保存的地方。在串池中已经存在 "xyz "这个串的情况下,如果你需要一个内容相同的串,你不需要再次创建一个,而是直接用这个就可以,这样当然是为了节省空间。注意,一个字符串是无法被修改的,所以在程序的不同地方用不同变量引用同一个常量串没有任何危险,因为你只能读取它而不能修改它。

17

使用多个单个字符为定界符扫描一个字符串时,使用StringTokenizer类,如果用一个单词作为定界符,使用Scanner类。

18

http://java.ccidnet.com/art/297/20060325/489133_1.html

http://java.ccidnet.com/art/297/20060325/489133_2.html

前言:
本来是想总结一下inner class 的用法,但是却发现这几位颇为亲近。索性一起拉出来溜溜。
写作目的:
static , final, inner class 搞好关系,以便将来遇见了,就像用if ,else一样,一清二楚。
文中的术语定义以java language spec为准。

先想想,要关注的是那些地方?
1
。语法。 code, 我们吃饭的家伙)
2
。语义。 (其实写代码也就是为了这个)
3
。怎么用简单,可人的结构来表达语义。(这也是每个程序员追求的)
语义无限的,语法是Limited, 我们要理解不同的语法所表现的语义,这是本文的重点。

1
final
final
做为一个独立的存在,也表现的与众不同。一般情况都可以理解为 can't be changed.
1)final data:
实现constant语义。说明这个值:在编译时不会变;在运行时也不能被改变。
java中,提供了blank final:允许大家将初始化的动作延迟到constructor中。这是极限,有编译器保证。
2)final parameter:
同上语义。
3)final method:
a)
防止子类overriden.(注:这个角度,private 隐含了final语义) b)efficiency: 允许编译器转换调用为inline call.
4)final class:
拒绝inherited.

2
static
1
。定义:static is modifier.本想找一个权威的定义给大家,才发现此物没有特定范围。也就意味着可能明天还有新的用法,也说明了语言的无限扩展性。不得以,我们只好在此注明:以下用法为java 1.5 之前的说明:

言碎语:这 static 可不得了,跟谁沾上整个就变质了。如果你想标榜独立个性,请用。static 一上,就表明我是人民的公仆,你只要找得着我,就可以让我为您服务。它属于定义层次,在jvm层次独一无二。从另一个角度上,它只能用于成员定义。我们不能定义一 top-level class static.
public static class Outest { // compile error
...;
}

装载:
static成员(include field, method, nested class)是在存储在类定义层次的,只要任何与其类相关的操作,均会产生它的初始化动作。(也就意味着,它已经准备就绪,你只要想用就用。 classname.staticMember

所有的static object/primitive and static block,按照先来后到的顺序执行初始化操作。
与其他一样。

可以用在:
1
static import (static import ...)
single-static-import declaration: import static TypeName.Identifier
使得访问标识得以简化。(简单,无二义)
2) static initializer: (static {}):
完成一段初始化操作.常见用法:
3) static field: (static type field)
static field :
别名:class variable ;
non-static fileds:
别名:instance variable.
4) static method: (static type method())
同上。
5
static member type.( member class & member interface:
此处放在 nested class 部分讲解)

jvm
是实现这些java程序语义的根源:类变量是作为类型信息的一部分存储在方法区(jvm放置类定义的内存结构)。jvm在使用类之前,必须在方法区中为这些类变量分配空间。所以类变量是所有类实例共享的,即使没有任何类实例,它也可以被访问。这些变量只与类有关。

下面是重头戏:nested class.
3
nested class
说到类定义,我们先看看有那些值得关注的:
java中,类声明的表现形式可以分为两种:
1
top level class:
2
nested class
define: nestd class is any class whose declaration occurs within the body of another class or interface.
top level class is a class that is not a nested class.

而在nested class 我们需要特殊关注的是inner class, local class, anonymous class的用法。
在讨论下面两种特殊定义时,我们先看看一个重要概念:inner class.
1
An inner class is a nested class that is not explicitly or implicitly declared
static. Inner classes may not declare static initializers or member interfaces.
Inner classes may not declare static members, unless they are compile-time
constant fields
。(对内部类的限制:不能声明static 初始化操作)

在这里我要澄清一点:Nested class != inner class inner class 是一种特殊的 Nested class.Bruce 大叔在thinking java 3rd中混肴了这两个概念。(汗,直到写此文时我才究正过来,还好我写得时候把 java language spec jvm spec 拿来参考)
看看inner class 的表现形式吧。
/*
普通的情况 */
class HasStatic{
static int j = 100;
|
class Outer{
class Inner extends HasStatic {
static final int x = 3; // ok - compile-time constant
static int y = 4; // compile-time error, an inner class
}
static class NestedButNotInner {
static int z = 5; // ok, not an inner class
}
interface NeverInner{} // interfaces are never inner
}


2
local class: is a nested class that is not a member of any class and that has a name. all local classes are inner classes. local class 不能用public, protected, private, or static声明(编译错误).
从定义中我们可以看出,它的生命期是 block scope.比较local variable的形式,就不难理解其语义。同样你也不能用modifier(public/static etc.)去定义一个局部变量。
e.p
class Test {
public static void main (String[] args) {
int i ;
// public class Local{} : compile error: illegal start of expression
class Local {
{
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}

public void p() {
System.out.println("call local class p():");
}
}
Local l = new Local();
l.p();
}
}
3
anonymous classis automatically derived from a class instance creation expression by the compiler.
1.never abstract; 2.inner class; 3.never static; 4.impicitly final.
interface Contents{};
public class Parcel6 {
public Contents cont() {
return new Contents() {
private int i = 11;
public int value() { return i; }
};
}
public static void main(String[] args) {
Parcel6 p = new Parcel6();
Contents c = p.cont();
}
} ///:~

这个看似神秘的结构,让你将类的定义和构建过程融为一体。实际上它实现的语义是:
class MyContents implements Contents {
private int i = 11;
public int value() { return i; }
}
return new MyContents();
impicitly final)这样大家就一目了然了吧。

了以上或简单,或复杂的类定义。也许大家都有些头痛。为什么java提供如此丰富的类定义方式呢?不如让我们问问自己,我们定义类的目的是什么?是为了让 我们的程序拥有更好的逻辑结构。类定义是信息组织的形式。java语言给我们提供了在各个的实现阶段允许我们去做信息的封装,真正是everything is object.这些是我们应该高兴的事才对。它绝不是负担,只是给我们更多的选择空间。

语义特点:(以下inner class is thinkingInjava3th 中的定义,可以看作本文所定义的nested class
Each inner class can independently inherit from an implementation. Thus, the inner class is not limited by whether the outer class is already inheriting from an implementation.
(是不是看到了点什么,多继承!!visitor pattern!!)
1
The inner class can have multiple instances, each with its own state information that is independent of the information in the outer class object. 一个独立的实体,诞生于某个更大的实体中(外部实体),却可以用外部实体的资源(请联想寄生虫:<
2
In a single outer class you can have several inner classes, each of which implement the same interface or inherit from the same class in a different way. (可以有不同种类的寄生虫)
3
The point of creation of the inner class object is not tied to the creation of the outer class object.
(它的创建过程并不系于外部对象的创建)
4
There is no potentially confusing “is-a” relationship with the inner class; it’s a separate entity.
(于外部类无inherit关系)


经过以上的说明,你是否头脑中更清晰了些:
Inner class
常见用法:
Closures & Callbacks
1.
java中可以利用Inner class 实现Closure(闭包) Callback(回调) 语义:
Closure
的定义:(我试图从不同侧面来阐述这个概念)
Martin Fowler :Essentially a closure is a block of code that can be passed as an argument to a function call.
Bruce
A closure is a callable object that retains information from the scope in which it was created.
那什么时候使用它呢?它有什么优点呢?
打个比方:让你去照看小孩:你是想要婴儿还是小学生呢?我想大多数人会选择小学生。为什么?因为小学生可以自己吃饭,自己上厕所,自己洗澡。这两个对象的实现,你更偏向哪一个呢?

call back:With a callback, some other object is given a piece of information that allows it to call back into the originating object at some later point. (
顺藤摸瓜,制造一个可控的接口)

19

父类和子类的构造关系:

子类构造时,默认的会调用父类的默认无参构造方法,即相当于子类构造的第一句调用super(),这里的效果和显式调用是一样的。也可以在子类构造的第一句显式调用父类覆盖的构造方法。在任何情况下,构造一个类的实例时,会沿着继承链调用所有父类的构造方法(构造链)。

public class FacultyTest extends Employee{

 

    /**

     * @param args

     */

    public static void main(String[] args) {

       // TODO Auto-generated method stub

       new FacultyTest();

    }

    public FacultyTest(){

       super();//这里屏蔽super的效果是一样的

       System.out.println("Faculty's no arg constructor is invoked");

    }

}

class Employee {

    public Employee(){

       System.out.println("Employee's no arg constructor is invoked");

    }

    public Employee(String s){

       System.out.println(s);

    }

}

下面的例子是有错误的,因为类显式定义了构造方法,没有无参数构造方法,在子类构造中又没有显式的调用super(参数):

public class FacultyTest extends Employee{

 

       /**

        * @param args

        */

       public static void main(String[] args) {

              // TODO Auto-generated method stub

              new FacultyTest();

       }

       public FacultyTest(){

              System.out.println("Faculty's no arg constructor is invoked");

       }

}

class Employee {

       public Employee(String s){

              System.out.println(s);

       }

}

错误信息:

Implicit super constructor Employee() is undefined. Must explicitly invoke another constructor

20

调用父类的方法和方法覆盖:

public class ReflectTest {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

       // TODO Auto-generated method stub

       MyCylinder test = new MyCylinder(2.0,3.0);

       System.out.println(test.findArea());

       MyCircle test1 = new MyCylinder(2.0,3.0);

       System.out.println(test1.findArea());

       MyCircle test2 = new MyCircle(2.0);

       System.out.println(test2.findArea());

    }

 

}

 

class MyCircle{

    private double radius = 1.0;

    public MyCircle() {

       // TODO Auto-generated constructor stub

       System.out.println(" Invoke Circle without arg");

    }

    public MyCircle(double radius){

       this.radius = radius;

       System.out.println(" Invoke Circle with arg");

    }

    public void setRadius(double radius){

       this.radius = radius;

    }

    public double getRadius(){

       return this.radius;

    }

    public double findArea(){

       return Math.PI * radius * radius;

    }  

}

 

class MyCylinder extends MyCircle {

    private double length = 1.0;

    public MyCylinder() {

        // TODO Auto-generated constructor stub

       System.out.println("Invoke Cylinder without arg");

    }

    public MyCylinder(double radius, double length){

       super(radius);

       this.length = length;

       System.out.println("Invoke Cylinder with arg");

    }

    public double getLength(){

       return this.length;

    }

    public void setLength(double length){

       this.length = length;

    }

    public double findArea(String s){

       return (2 * super.findArea() + 2 * getRadius() * Math.PI * length);

    }

}

输出为:

Invoke Circle with arg

Invoke Cylinder with arg

12.566370614359172

Invoke Circle with arg

Invoke Cylinder with arg

12.566370614359172

Invoke Circle with arg

12.566370614359172

 

在子类(extended class)中重写父类的方法,必须要有相同的修饰符和方法名,形式参数名,方法重载需要有不同的形式参数,如果仅仅是返回值类型不同,不能作为方法重载。

注意:不能使用super.super.方法()来访问祖父类的方法,有语法错误。

class A{

method1(){}

}

class B extends A{

method1(){}

}

B的实例不能够访问Amethod1方法,因为在Bmethod1方法被覆盖了。

注意:实例方法仅当可以被访问时才会被覆盖。私有方法不能在定义它的类外访问,所以不能被覆盖。如果子类的方法在父类中是私有的,则这两个方法完全没有关系。

注意:每个子类的实例都是父类的实例,反之不行。

21

多态的一个例子:

public class PolyTest {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

       // TODO Auto-generated method stub

       m(new GraduateStudent());

       m(new Student());

       m(new Person());

       m(new Object());

       Person test = new GraduateStudent();

       Student test2 = (Student)test;

       m(test2);

        //test.finde(); error!

        if(test instanceof Student){

           Student test3 = (Student)test;

           test3.finde();

       }

    }

    static public void m(Object x){

       System.out.println(x.toString());

    }

}

class GraduateStudent extends Student {  

    public String toString(){

       return "GraduateStudent";

    }

    public void finde(){

       System.out.println("hoho");

    }

}

class Student extends Person{  

    public String toString(){

       return "Student";

    }

}

class Person{

    public String toString(){

       return "Person";

    }

}

输出:

GraduateStudent

Student

Person

java.lang.Object@61de33

GraduateStudent

Hoho

 

为父类对象设计的代码都可以引用于子类,这个特征成为多态(polymorphism)

动态绑定机制:类c1->c2->…->cn,c1为父类,c2为子类,ocn的实例,则o调用一个方法p,依次在cncn-1c1中查找p的实现,直到找到为止。一旦找到一个实现,停止查找并调用这个第一次找到的实现。

向上转换:将一个子类的实例转换为一个父类的实例总是可行的

向下转换:必须使用显式转换,为是转换成功,转换的对象必须是子类的一个实例。在转换时确保该对象是另一个对象的实例,用instanceof来判断。

22

隐藏数据域和静态方法(static):

可以覆盖一个实例方法,但是不能覆盖一个数据域(不管是实例或者静态的)和静态的方法。子类声明的数据域或者静态方法和父类中的相同,父类的将被隐藏,但是没有被覆盖。在子类中还可以使用super来调用父类的隐藏的数据或者静态方法。

23

finalize方法:

由于java中没有显式的释放资源和内存的函数,存在gabbage collection的机制,当资源变成垃圾时,finalize会被该对象的垃圾回收gc调用。子类可以覆盖finalize方法,释放系统资源或者进行其他清洁工作。

Protected void finalize() throws Throwable

24

Clone方法,创建一个新的对象,并使得其和就对象内容方法相同

newObject = oldObject.clone();

不是所有的对象都可以被克隆,要成为一个可被克隆的对象,它的类必须实现java.lang.Cloneable接口。

数组的cloneint [] B = (int[])A.clone();

25

Collection Collections的区别

Collection是个java.util下的接口,它是处理对象集合的根接口。

Collections是个java.util下的类,它包含管理集合与图、创建同步集合类、创建只读集合类等静态方法。

26

http://dev.youkuaiyun.com/article/85006.shtm

正则表达式:

正则表达式用来指定字符串模式。当你需要定位匹配某种模式的字符串时就可以使用正则表达式。例如,我们下面的一个例程就是在一个HTML文件中通过查找字符串模式<a href="...">来定位所有的超链接。

    当然,为了指定一种模式,使用...这种记号是不够精确的。你需要精确地指定什么样的字符排列是一个合法的匹配。当描述某种模式时,你需要使用一种特殊的语法。

    这里有一个简单例子。正则表达式
[Jj]ava.+
匹配下列形式的任何字符串:

  • 首字母是J或j
  • 后续的三个字母是ava
  • 字符串的剩余部分由一个或多个任意字符组成


    例如,字符串“javaness”匹配这个特殊的正则表达式,但是字符串“Core Java”却不匹配。

    如你所见,你需要了解一点语法来理解正则表达式的含意。幸运的是对于大多数的用途,使用少量的简单构造(straightforward constructs)就已足够。

  • 字符类是可选自符的集合,用‘[’封装,比如[Jj],[0-9],[A-Za-z]或[^0-9]。这里的-表示范围(Unicode落在两个边界之间的所有字符),^表示求补(指定字符外的所有字符)。
  • 有许多预定以的字符类,像/d(数字)或/p{Sc}(Unicode货币符号),见表12-8和12-9。
  • 大多数字符与它们自身匹配,像上例中的ava字符。
  • 符号.匹配任何字符(可能行终止符(line terminators)除外,这依赖于标识设置(flag settings))
  • /用作转义符,比如/.匹配一个句点,//匹配一个反斜杠。
  •  ^和$分别匹配行头和行尾
  • 如果X和Y都是正则表达式,则XY表示“X的匹配后面跟着Y的匹配”。X|Y表示“任何X或Y的匹配”
  • 可以将量词(quantifier)用到表达式中,X+ 表示X重复1次或多次,X* 表示X重复0次或多次,X? 表示X重复0次或1次
  •  默认地,一个量词总是与使总体成功匹配的最长的可能重复匹配。可以加上后缀?(称为reluctant或stingy 匹配,用以匹配最小的重复数),和+(称为possessive或贪婪匹配,用以即使在总体匹配失败的情况下也匹配最大的重复数)来更改这种属性。

 

例如,字符串cab匹配[a-z]*ab,但不匹配[a-z]*+ab。第一种情况下,[a-z]*只匹配字符c,因此字符ab正好与模式的剩余部分匹配。但是贪婪版本[a-z]*+就与字符cab匹配,模式的剩余部分ab就匹配失败(,这样总体也就匹配失败)。

  • 可以使用分组来定义子表达式。将分组封装在()中,如([+-]?)([0-9]+)。然后你可以让模式匹配符(the pattern matcher)返回每个分组的匹配,或者使用/n来回引分组(refer back to a group with /n),其中n是组号(以/1起始)


    这里有一个稍微有点复杂却又很有用的正则表达式--它用来描述十进制和十六进制的整数。
[+-]?[0-9]+|0[Xx][0-9A-Fa-f]+

    不幸的是,在使用正则表达式的各种程序和库之间,它的语法还没有完全标准化。对基本的构造上已达成了共识,但在细节方面有许多令人“抓狂”的区别 (many maddening differences)。Java的正则表达式类使用了与Perl语言类似的语法,但也不尽相同。表12-8显示了Java语法的所有正则表达式构造。 要了解更多关于正则表达式的信息,请参考Pattern类的API文档,或者Jeffrey E. F. Friedl的著作《Mastering Regular Expressions》(O'Reilly and Associates, 1997)(刚去第二书店查了一下,东南大学出版社已经引入了其第二版,影印)

表12-8 正则表达式语法


语法                                                          解释


字符
c                                                            字符c
/unnnn, /xnn, /0n, /0nn, /0nnn          带有十六或八进制值的代码单元

/0n                                           八进制0n代表的字符(0<=n<=7)

/0nn                                         八进制0nn代表的字符(0<=n<=7)

/0mnn                                     八进制0mnn代表的字符(0<=m<=3,0<=n<=7)

/xnn                                         十六进制 0xnn所代表的字符

/uhhhh                                    十六进制 0xhhhh所代表的字符

/t, /n, /r, /f, /a, /e                                    控制字符,依次是制表符,换行符,回车符,换页符,报警符和转义符
/cc                                                         控制字符中出现的相应字符c


字符类
[C1C2. . .]                       C1、C2……中的任何字符。Ci可以是字符,字符范围(C1-C2)或者字符类。
[^. . .]                                字符类的补集
[ . . . && . . .]                    两个字符类的交集


预定义字符类
.                                        除行终止符外的任何字符(如果DOTALL标志置位,则表示任何字符)
/d                                      数字[0-9]
/D                                    非数字[^0-9]
/s                                     空白字符[/t/n/r/f/x0B]
/S                                     非空白字符
/w                                    单词字符[a-zA-Z0-9_]
/W                                   非单词字符
/p{name}                        一个指定的字符类,见表12-9
/P{name}                       指定字符类的补集


边界匹配符
^ $                                   输入的开头和结尾(在多行模式(multiline mode)下是行的开头和结尾)
/b                                    单词边界
/B                                    非单词边界
/A                                     输入的开头
/z                                     输入的结尾
/Z                                    除最后行终止符之外的输入结尾
/G                                   上个匹配的结尾


量词
X?                                    可选的X(即X可能出现,也可能不出现)
X*                                    X,可以重复0次或多次
X+                                    X,可以重复1次或多次
X{n} X{n,} X{n,m}          X重复n次,至少重复n次,重复n到m次


量词后缀
?                                   设默认(贪婪)匹配为reluctant匹配
+                                   设默认(贪婪)匹配为possessive匹配


集合操作
XY                                  X的匹配后面跟着Y的匹配
X|Y                                 X或Y的匹配


分组
(X)                                匹配X并且在一个自动计数的分组中捕获它
/n                                  与第n个分组的匹配


转义
/c                                   字符c(必须不是字母)
/Q.../E                            逐字地引用...
(?...)                       特殊构造,看Pattern类的API



    正则表达式的最简单使用是测试一个特殊的字符串是否与之匹配。这里有一个Java写的测试程序。首先从表示正则表达式的字符串构造一个Pattern对象。然后从该模式获得一个Matcher对象,并且调用它的matches()方法:

Pattern pattern = Pattern.compile(patternString);

Matcher matcher = pattern.matcher(input);

if (matcher.matches()) . . .


    表12.9 预定义的字符类名(Predefined Character Class Names)


Lower                         小写的ASII字符[a-z]
Upper                         大写的ASCII字符[A-Z]
Alpha                          ASCII字母[A-Za-z]
Digit                            ASCII 数字 [0-9]
Alnum                         ASCII 字母或数字[A-Za-z0-9]
Xdigit                         十六进制数字[0-9A-Fa-f]
Print or Graph          可打印的ASCII字符[/x21-/x7E]
Punct                         非字母或数字ASCII [/p{Print}&&/P{Alnum}]
ASCII                         所有ASCII字符 [/x00-/x7F]
Cntrl                          ASCII控制字符[/x00-/x1F]
Blank                         空格符或制表符[ /t]
Space                        空白符 [ /t/n/r/f/0x0B]
javaLowerCase       取决于Character.isLowerCase()的小写字符
javaUpperCase      取决于Character.isUpperCase()的大写字符
javaWhitespace     取决于Character.isWhitespace()的空白符
javaMirrored            取决于Character.isMirrored()的Mirrored(?)
InBlock                      这里的Block是unicode字符的块名,用空格隔开,比如BasicLatin 或 Mongolian。块名列表                                  参考http://www.unicode.org
Category 或InCategory     这里的Category是Unicode字符的种类名,比如L(字母)或者Sc(货币符号)。种 类                                        名列表参考http://www.unicode.org 



    matcher的输入可以是实现CharSequence接口的任何类对象,像String,StringBuilder或CharBuffer。

    当编译模式时,可以设置一个或多个标志,例如

Pattern pattern = Pattern.compile(patternString,

Pattern.CASE_INSENSITIVE + Pattern.UNICODE_CASE);


下面六个标志都是支持的:

CASE_INSENSITIVE:匹配字符时与大小写无关,该标志默认只考虑US ASCII字符。

UNICODE_CASE:当与CASE_INSENSITIVE结合时,使用Unicode字母匹配

MULTILINE:^和$匹配一行的开始和结尾,而不是整个输入

UNIX_LINES: 当在多行模式下匹配^和$时,只将'/n'看作行终止符

DOTALL: 当使用此标志时,.符号匹配包括行终止符在内的所有字符

CANON_EQ: 考虑Unicode字符的规范等价

     如果正则表达式包含分组,Matcher对象能够揭示分组边界。方法

int start(int groupIndex)

int end(int groupIndex)

返回某个特殊分组的起始索引和结尾后索引(past-the-end index )。
通过调用String group(int groupIndex),你可以简单地得到匹配的字符串。
第0个分组代表所有的分组,第一个实际分组的索引是1。调用groupCount来获得总的分组数。

     使用开放圆括号来安排嵌套分组。例如,给定模式((1?[0-9]):([0-5][0-9]))[ap]m,并且输入11:59am,Matcher对象报告下列分组
((1?[0-9]):([0-5][0-9]))[ap]m
并输入
11:59am
matcher报告下列分组


分组索引  起始  结束  字符串


0              0          7      11;59am
1              0          5     
11:59
2              0          2      11
3              3          5      59


 
例12-9提示输入一个模式和一个欲匹配的字符串。它将输出输入的字符串是否匹配模式。如果输入匹配包含分组的模式,程序将会使用圆括号来打印分组边界,如((11):(59))am

Example 12-9. RegexTest.java
 1. import java.util.*;
 2. import java.util.regex.*;
 3.
 4. /**
 5.    This program tests regular expression matching.
 6.    Enter a pattern and strings to match, or hit Cancel
 7.    to exit. If the pattern contains groups, the group
 8.    boundaries are displayed in the match.
 9. */
10. public class RegExTest
11. {
12.   public static void main(String[] args)
13.   {
14.      Scanner in = new Scanner(System.in);
15.      System.out.println("Enter pattern: ");
16.      String patternString = in.nextLine();
17.
18.      Pattern pattern = null;
19.      try
20.      {
21.         pattern = Pattern.compile(patternString);
22.      }
23.      catch (PatternSyntaxException e)
24.      {
25.         System.out.println("Pattern syntax error");
26.         System.exit(1);
27.      }
28.
29.      while (true)
30.      {
31.         System.out.println("Enter string to match: ");
32.         String input = in.nextLine();
33.         if (input == null || input.equals("")) return;
34.         Matcher matcher = pattern.matcher(input);
35.         if (matcher.matches())
36.         {
37.            System.out.println("Match");
38.            int g = matcher.groupCount();
39.            if (g > 0)
40.            {
41.               for (int i = 0; i < input.length(); i++)
42.               {
43.                  for (int j = 1; j <= g; j++)
44.                     if (i == matcher.start(j))
45.                        System.out.print('(');
46.                  System.out.print(input.charAt(i));
47.                  for (int j = 1; j <= g; j++)
48.                     if (i + 1 == matcher.end(j))
49.                        System.out.print(')');
50.               }
51.               System.out.println();
52.            }
53.         }
54.         else
55.            System.out.println("No match");
56.      }
57.   }
58. }

     通常地,你不希望匹配整个输入到某个正则表达式,而是希望在输入中找出一个或多个匹配的子字符串。使用Matcher类的find方法来寻找下一个匹配。如果它返回True,再使用start和end方法找出匹配的范围。

while (matcher.find())

{

   int start = matcher.start();

   int end = matcher.end();

   String match = input.substring(start, end);

   . . .

}


例12-10用到了这种机制。它在一个网页中定位所有的超文本引用并打印它们。为运行程序,在命令行提供一个URL,比如
package edu.ustc.ielab.regmatch.page;

 

import java.io.*;

import java.net.*;

import java.util.regex.*;

 

public class RefMatch

{

    public static void main(String[] args)

    {

        try

        {

            // get URL string from command line or use default

            String urlString;

            if (args.length > 0) urlString = args[0];

            else urlString = "http://bbs.ustc.edu.cn/cgi/bbsall";

 

            // open reader for URL

            InputStreamReader in = new InputStreamReader(new URL(urlString).openStream());

 

            // read contents into string buffer

            StringBuilder input = new StringBuilder();

            int ch;

            while ((ch = in.read()) != -1) input.append((char) ch);

 

            // search for all occurrences of pattern

            //String patternString = //"<a//s+href//s*=//s*(/"[^/"]*/"|[^//s>])//s*>";

            String patternString = "<a//s+href//s*=//s*/"[^/"]*/"[^>]*>";

            Pattern pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);

            Matcher matcher = pattern.matcher(input);

 

            while (matcher.find())

            {

                int start = matcher.start();

                int end = matcher.end();

                String match = input.substring(start, end);

                System.out.println(match);

            }

        }

        catch (IOException e)

        {

            e.printStackTrace();

        }

        catch (PatternSyntaxException e)

        {

            e.printStackTrace();

        }

    }

}

    Matcher类的replaceAll方法用一个替换字符串代替出现的所有正则表达式的匹配。比如,下列指令用#替换所有数字序列

Pattern pattern = Pattern.compile("[0-9]+");

Matcher matcher = pattern.matcher(input);

String output = matcher.replaceAll("#");

    替换字符串可以包含模式中的分组引用:$n被第n个分组替换。替换文本中出现$时,使用/$来包含它。
replaceFirst方法只替换模式的第一次出现。

    最后讲一点,Pattern类有一个split方法,它类似于字符串tokenizer。它使用正则表达式匹配作边界,将输入分离成字符串数组。比如,下面的指令将输入分离成记号(token),

Pattern pattern = Pattern.compile("//s*//p{Punct}//s*");

String[] tokens = pattern.split(input);



java.util.regex.Pattern 1.4


方法
static Pattern compile(String expression)
static Pattern compile(String expression, int flags)
编译正则表达式字符串到pattern对象用以匹配的快速处理
参数:
 expression 正则表达式
 flags            下列标志中的一个或多个 CASE_INSENSITIVE, UNICODE_CASE, MULTILINE, UNIX_LINES, DOTALL, and CANON_EQ
 
Matcher matcher(CharSequence input)
返回一个matcher对象,它可以用来在一个输入中定位模式匹配

String[] split(CharSequence input)
String[] split(CharSequence input, int limit)
将输入字符串分离成记号,并由pattern来指定分隔符的形式。返回记号数组。分隔符并不是记号的一部分。
参数:
input 分离成记号的字符串
limit 生成的最大字符串数。


 类


java.util.regex.Matcher 1.4


方法


boolean matches()
返回输入是否与模式匹配

boolean lookingAt()
如果输入的起始匹配模式则返回True

boolean find()
boolean find(int start)
尝试查找下一个匹配,并在找到匹配时返回True
参数:
 start  开始搜索的索引
 
int start()
int end()
返回当前匹配的起始位置和结尾后位置

String group()
返回当前匹配

int groupCount()
返回输入模式中的分组数

int start(int groupIndex)
int end(int groupIndex)
返回一个给定分组当前匹配中的起始位置和结尾后位置
参数:
 groupIndex分组索引(从1开始),0表示整个匹配

String group(int groupIndex)
返回匹配一个给定分组的字符串
参数:
 groupIndex
 分组索引(从1开始),0表示整个匹配

String replaceAll(String replacement)
String replaceFirst(String replacement)
返回从matcher输入得到的字符串,但已经用替换表达式替换所有或第一个匹配
参数:
 replacement 替换字符串

Matcher reset()
Matcher reset(CharSequence input)
复位mather状态。

27

Java的中文帮助文档:

http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/overview-summary.html

28

Hashtable,Hashmap

 


本书是Java语言的经典教材,中文版分为基础篇和进阶篇,主要介绍程序设计基础、面向对象编程、GUI程序设计、数据结构和算法、高级Java程序设计等内容。本书以示例讲解解决问题的技巧,提供大量的程序清单,每章配有大量复习题和编程练习题,帮助读者掌握编程技术,并应用所学技术解决实际应用开发中遇到的问题。您手中的这本是其中的基础篇,主要介绍了基本程序设计、语法结构、面向对象程序设计、继承和多态、异常处理和文本I/O、抽象类和接口等内容。本书可作为高等院校程序设计相关专业的基础教材,也可作为Java语言及编程开发爱好者的参考资料。 作者:(美国)粱勇(Y.Daniel Liang) 译者:戴开宇 梁勇(Y.Daniel Liang),现为阿姆斯特朗亚特兰大州立大学计算机科学系教授。之前曾是普度大学计算机科学系副教授。并两次获得普度大学杰出研究奖。他所编写的Java教程在美国大学Java课程中采用率极高。同时他还兼任Prentice Hall Java系列丛书的编辑。他是“Java Champion”荣誉得主,并在世界各地为在校学生和程序员做JAVA程序设计方法及技术方面的讲座。 戴开宇,复旦大学软件学院教师,工程硕士导师。中国计算机学会会员。博士毕业于上海交通大学计算机应用专业,2011~2012年在美国佛罗里达大学作访问学者。承担多门本科专业课程、通识教育课程以及工程硕士课程,这些课程被评为校精品课程,上海市重点建设课程,IBM—教育部精品课程等。
This book is a brief version of Introduction to Java Programming, Comprehensive Version, 8E. This version is designed for an introductory programming course, commonly known as CS1. This version contains the first twenty chapters in the comprehensive version. This book uses the fundamentals-first approach and teaches programming concepts and techniques in a problem-driven way. The fundamentals-first approach introduces basic programming concepts and techniques before objects and classes. My own experience, confirmed by the experiences of many colleagues, demonstrates that new programmers in order to succeed must learn basic logic and fundamental programming techniques such as loops and stepwise refinement. The fundamental concepts and techniques of loops, methods, and arrays are the foundation for programming. Building the foundation prepares students to learn object-oriented programming, GUI, database, and Web programming. Problem-driven means focused on problem-solving rather than syntax. We make introductory programming interesting by using interesting problems. The central thread of this book is on solving problems. Appropriate syntax and library are introduced to support the writing of a program for solving the problems. To support teaching programming in a problemdriven way, the book provides a wide variety of problems at various levels of difficulty to motivate students. In order to appeal to students in all majors, the problems cover many application areas in math, science, business, financials, gaming, animation, and multimedia. 精美文字版pdf电子书。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值