java要点
Java要点总结
http://tech.163.com/special/00091T71/javashipin.html (Java学习网站)
一、Java基础:
1、计算机平台:⑴硬件:主要是cpu(指令集)的不一样;⑵软件:操作系统。
1)Java实现跨平台的方法:主要是给不同的平台一个虚拟机(JVM=Java Virtual Machine软件)。
JIT(Just In Time即时)—HotSport的字节码编译器,是Java虚拟机的一部分,它根据需要一部分一部分地将所选的字节码实时编译为可执行代码。因Java在运行时才执行检查,JIT不能将整个Java程序一次性全部编译为执行的代码,剩余代码仍只是进行解释。Java程序进行JIT后可移植性和安全性仍能得到保证。
Java是一种严格的类型语言,它不但在编译时检查代码,而且在运行时也检查代码。
Java特性:安全Secure、可移植Portable、面向对象Object-oriented、健壮Robust、多线程Mutithreaded、体系结构中立Architecture-neutral、解释执行Interpreted、分布式Distributed、动态Dynamic。
2)Java语言执行的过程:.java(源文件)à.class(编译后,二进制的字节码文件)àjava [option] classname把class文件装入虚拟机解释执行(执行时classname后不要加后缀.class,但对Java原文件进行编译或形成API文档时须加后缀名.java)。
2、java程序的类型:⑴applet java小应用程序,嵌入到网页中,目前几乎没有人使用;⑵GUI图形用户界面;⑶网络应用程序,比如网站的bbs,网上银行(java EE)。
3、java的版本(官方):⑴j2SE (java 2 Standard Edition) java标准版本,用于桌面开发,低端商务(J2SE程序的分类:㈠Applet:浏览器端小程序;㈡Application:独立应用程序;㈢Servlet:服务器端小程序;㈣JavaBean:组件);⑵j2ME (java 2 Micro Edition) java微型版本(适用于小型设备和智能卡的版本,致力于消费产品和嵌入式设备,如移动电话);⑶j2EE (java 2 Enterprise Edition) java企业版本。
4、java开发环境JDK(Java Development ToolKit—Java开发工具包):⑴将java安装后形成的目录文件硬拷贝到磁盘下(比如:jdk
5、JBuilder的使用(Java的开发工具之一):⑴启动JBuilder:在“安装目录/bin/JBuilderw.exe”中运行JBuilderw.exe(JBuilder无需安装,直接运行);⑵建立工程(管理项目中的源代码、图片等资源文件,其扩展名为.jpx):file→new project→录入工程名后选择directory→finish;⑶建立类文件:file→new class→输入类名,保留public选项→ok。⑷编译和运行:鼠标右击类文件夹,选make或rebuild “classname”编译生成.class文件,选run using defaults运行。或编译运行工程:project→make project“projectName.jpx”生成.class文件,然后run project。⑸开发环境重要键值对的参考,在JBuilder的help菜单下About JBuilder目录树的System Properties和Environment Variables。
工程目录结构:src 中存放源代码文件,classes目录中存放编译后的.class文件
快捷键:写一个main然后ctrl+j就生成main()函数;写一个 out 然后ctrl+j生成系统输出代码;写一个err然后ctrl+j输出System.err.println(“”);写一个for然后ctrl+j生成for循环;选定行然后ctrl+/则开关注释行;ctrl+h显示定义或内置变量、方法、类名;选中异常处理代码块后按ctrl+shift+c将自动增加try/catch块;鼠标点中类名或方法名后按ctrl+回车键,则显示源代码;找不到的标识符可用alt+回车键,则显示支持类引用、创建类、创建接口、包引入等,选suggest class reference...项,找匹配的标识符。
设置断点,用debug using defaults命令运行主文件(含main()方法),然后按F8(Step Over)
6、Java命令:⑴javac [-options] sourcename.java编译源文件;⑵java [-options] classname [arguments]或java [-options] –jar jarfile [arguments]运行.class文件或运行.jar文件;⑶appletviewer [-options] url 查看applet的html文件;⑷jar:解压jar文件;⑸javadoc [-options] sourcename.java提取注释形成程序帮助文件;⑹jdb:Java 调试器,可以逐行执行程序,设置断点和检查变量;⑺Javah [-options] <类>产生可以调用Java 过程的C过程,或建立能被Java程序调用的C过程的头文件;⑻Javap:Java反汇编器,显示编译类文件中的可访问功能和数据,同时显示字节代码含义。
7、java行业中的命名规范:⑴类名首字母大写,如果由多个单词组成,则每个单词的首字母大写。应该避免使用下划线。⑵变量,属性,方法名首字母一律小写,如果由多个单词组成则每个单词的首字母大写。第一个单词除外。应该避免使用下划线。
8、字符转义序列:
转码 |
说 明 |
转码 |
说 明 |
\ddd |
八进制字符(字符用三位八进制数表示) |
\uxxxx |
十六进制Unicode码字符(xxxx) |
\n |
将光标移到下一行(称为换行符) |
\r |
将光标移到当前行的开头(称为回车符) |
\f |
换页 |
\b |
退格 |
\t |
将光标移到下一制表位,一个制表位8个空格 |
\\ |
输出反斜线 |
\’ |
输出单引号 |
\” |
输出双引号 |
不同操作系统的转义字符表示方式不同。如linux操作系统的换行符是ASCII码的10("\n"),而windows操作系统的换行符是ASCII码的1310("\r\n")。
分隔符:
符号 |
名称 |
用途 |
( ) |
圆括号 |
在定义和调用方法时容纳参数表。在控制语句的优先权或强制类型转换的数据类型。 |
{ } |
花括号 |
用来初始化的数组赋值,也用来定义程序块、类、方法以及局部范围。 |
[ ] |
方括号 |
用来声明数组的类型,也用来表示撤消对数组值的引用。 |
; |
分号 |
用来终止程序语句。在for语句中,用来分隔三个部分。 |
, |
逗号 |
在变量声明中,用于分隔变量表中的各个变量。 |
. |
句号(点) |
用来将软件包的名字与它的子包或类分隔,将引用变量与变量或方法分隔。 |
9、Java的内存分配:栈内存和堆内存。⑴栈内存:当在一段代码块(也就是一对{ }之间)定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉该内存空间。所有的基本数据类型都在栈中分配内存。⑵堆内存:存放由new创建的对象和数组,当数组或者对象没有任何一个引用的时候,就变成了垃圾,由java虚拟机的垃圾回收器来释放。所有的引用数据类型(数组、类、接口)都在堆中分配。栈内存中数组变量名存储的是堆内存数组值的首地址,在java中叫做引用。
10、⑴标识符:标识符必须以字母或下划线或$符号开始。其余字符可以是字母、数字、$ 符号和下划线。常量(字面量literal,java中常数用字面量表示):Java小数默认为double型,所以float常量类型后面一定要加f;长整型常量后要加l。⑵数据类型:Java的数据类型分为8种基本(primitive)数据类型(不属于对象):byte、short、int、long、char、float、double、boolean(仅有true和false两值)和3种引用数据类型:数组、类、接口。Java把字符串作为对象实现。Java不支持无符号的整数,因此byte的范围为-128~127。类型转换:㈠自动类型转换:在满足a.两种类型是兼容的;b.目的类型比源类型大时发生自动类型转换(拓宽转换)。如:整数表达式包含byte、short、char和字面量数字,在进行计算之前,整个表达式被提升为int型(数组例外,不被提升)。比如,char a='a';char b='b';则int c=a+b;而不能char c=a+b(两整型变量相加有溢出的可能)。㈡目的类型比源类型小时(缩小转换)或两个不兼容类型之间的数据转换需要显示的强制转换,其一般形式如下:(target-type)value。可以利用各数据类型提供的parse()或parseInt()等方法来检验输入数据类型的有效性。如:通过捕获对出生日期的异常来检验输入日期类型的有效性Date d = sdf.parse(birth);㈢当一个浮点值被赋给一个整数类型时,将出现截断转换类型。㈣表达式的类型提升规则:所有的byte和short型的值被提升到int(char与int在一起也被提升到int);但如果有一个操作数是long型,则整个表达式将被提升为long型;如果有一个操作数是float型,则整个表达式将被提升为float型;如果有一个操作数是double型,则整个表达式将被提升为double型;null是一种特殊的数据类型,判断一个变量是否为null用==或!=,而不用equals(),因调用一个值为null的变量将会引发NullPointerException。另外注意:null与其它值相加等于其它值,null与null相加不等于null(1个)。⑶变量:在Java中,所有的变量必须在使用前声明。变量声明的基本形式:type identifier[=value] [,identifier[=value]...];其中:type是Java的数据类型,identifier是变量的名称,可以通过value值来初始化变量。块被包含在一对花括号中,一个块定义了一个作用域,在一个作用域内声明的变量对于作用域外的代码是不可见的(即:不可访问的)。对于嵌套的作用域,外部的作用域封装内部的作用域(即外部声明的对象对内部来说是可见的,反过来不成立)。⑷数组:是一组相同类型的变量,可以通过一个公共的名称引用,数组的一个元素通过下标来访问。数组的三种创建形式如下:
语法 |
语法 |
示例说明 |
语法 |
语法 |
datatype identifier[]; |
datatype identifier[]=new datetype[size]; |
double ch[]=new double[8]声明8个double类型数组,系统自动初始化为0.0。 |
Datetype identifier[]={value1,value2,…valueN}; |
Object[] params=new Object[] {“name”,”value”} |
在Java中,new是一个分配内存的特殊运算符,数组经new后将赋初值(参见数据类型初始化)。所有的数组都是动态分配的(即运行时分配)。Size指定数组中的长度。Length表示数组长度(元素个数)属性,仅用于数组对象。如,String[] args的长度可表示为:args.length,而不能表示为:args[].length。因为args为数组对象,args[]为数组元素。⑸多维数组:㈠二维数组声明(例):int towD[][]=new int[4][5];在Java中,多维数组实际上是数组的数组,如声明列数不同的一个二维数组:int twoD[][]=new int[4][];twoD[0]=new int[1];twoD[1]=new int[2];twoD[2]=new int[3];twoD[3]=new int[4];㈡在初始化多维数组时,只需简单地把每个维的初始化列表包括在它自已的花括号中。如double[][] m={{1.1,1.2,1.3}, {2.1,2.2,2.3}};
11、数据类型初始化:如果类属性(实例变量)没有进行初始化,则系统会按缺省值自动初始化。
类型 |
缺省值 |
类型 |
缺省值 |
类型 |
缺省值 |
类型 |
缺省值 |
byte、short、int |
0 |
long |
|
float |
|
double |
0.0D |
boolean |
false |
char |
‘\u |
引用数据类型(数组、类、对象) |
null |
Java中,八进制数值前导符O,十六进制OX。
数据结构:一般将数据结构分为两大类:线性数据结构和非线性数据结构。线性数据结构有线性表、栈、队列、串、数组和文件;非线性数据结构有树和图。
线性表的逻辑结构是n个数据元素的有限序列:(a1, a2 ,a3,…an) n为线性表的长度(n≥0),n=0的表称为空表。所有数据元素在同一个线性表中必须是相同的数据类型。线性表按其存储结构可分为顺序表和链表。将线性表中的数据元素依次存放在某个存储区域中,所形成的表称为顺序表;用链式存储结构存储的线性表称为链表。⑴一维数组就是用顺序方式存储的线性表。⑵栈(Stack)也是一种特殊的线性表,是一种后进先出(LIFO)的结构。栈是限定仅在表尾(栈顶top)进行插入和删除运算的线性表。栈的物理存储可以用顺序存储结构,也可以用链式存储结构。⑶队列(Queue)是限定所有的插入只能在表的一端(称为队尾Rear)进行,而所有的删除都在表的另一端(称为队头Front)进行的线性表。队列的操作是按先进先出(FIFO)的原则进行的。队列的物理存储可以用顺序存储结构,也可以用链式存储结构。
12、运算符:⑴在java中”+”有两种作用,一是加法运算,一是连接两个字符串(Char类型实质上是int类型的一个子集)。如:'a'+1结果是int 98,“ ”+'a'+1结果是char a1, “ ”+('a'+1)结果是char 98。⑵短路与&&(短路或||):当运算符的左侧为false(true)时,则不计算运算符的右侧,整个表达式的值为false(true),只有在运算符的左侧为true(false)时,才计算运算符的右侧。⑶将除法运算符应用于整型时,结果中将不包含小数部分(截断方式)。⑷模运算符%返回一个除法操作的余数,可应用于浮点类型和整型,如:int x=42;double y=42.25;则x%10==2,y%10==2.25。⑸位运算符(bitwise operator):适用于long、int、short、char、byte数据类型。位运算符的功能:
符号 |
结果 |
符号 |
结果 |
符号 |
结果 |
符号 |
结果 |
符号 |
结果 |
~ |
按位非(NOT) |
﹠ |
按位与(AND) |
| |
按位或(OR) |
∧ |
按位异或(XOR) |
>> |
有符号向右移位 |
>>> |
无符号右移 |
<< |
向左移位 |
&= |
按位与并赋值 |
|= |
按位或并赋值 |
∧= |
按位异或并赋值 |
>>= |
有符号右移并赋值 |
>>>= |
无符号右移并赋值 |
<<= |
向左移位并赋值 |
说明:无符号右移,左边空出的位以0填充;有符号右移,左边空位按高位值填充。 |
Java中所有的整数类型(除了char类型外)都是有符号的,用2的补码(two’s complement)来表示负数:即把一个正值的所有位取反,然后结果加1,为该正数的负数;要解码一个负数(首位为1的二进制),首先取反所有的位,然后加1,即为该正数值的负数。规定:-1的编码是所有位均为1。⑹运算符优先级:
最高 |
() |
++ |
* |
+ |
>> |
> |
== |
& |
∧ |
| |
&& |
|| |
?: |
= |
最低 |
[] |
-- |
/ |
- |
>>> |
>= |
!= |
|
|
|
|
|
|
0p= | ||
. |
~ |
% |
|
<< |
< |
|
|
|
|
|
|
|
| ||
同级 |
! |
|
|
|
<= |
|
|
|
|
|
|
|
|
Op=指算术赋值运算符:+=,-=,*=,/=,%=,|=,^=,>>=,>>>=,<<=。一元递增运算符++和递减运算符――用于表达式时要注意:位于变量之前是先自递增减后参与运算,位于变量之后是先参与运算后自递增减,如:float x=
13、程序控制语句:⑴switch语句的一般形式:
switch (expression){ //表达式expression必须是byte、short、int或char类型。
case value1: /*在case语句中指定的每个value值(枚举值)必须是和表达式兼容的类型。每case值必须是惟一的字面量(即它必须是一个常量,而不是变量)。不允许使用重复case值*/
//statement sequence
Break; //break语句是可选的,如果省略了break语句,程序将继续执行下一条case语句
case value2:
//statement sequence
Break;
…
default:
//default statement sequence
}
Switch语句的三个特征:㈠switch仅能用于离散型数值,而不能用于区间,if语句可用于任何类型的布尔表达式;㈡在同一个switch语句中不能有两个相同的case常量。当然,外部switch语句中的case常量可以和内部switch语句中的case常量相同;㈢switch语句通常比一组嵌套的if语句更高效。
⑵迭代语句(iterative statement):㈠while语句的一般形式:while(condition){//body of loop}。当控制表达式可以处理其本身的所有细节时,可以编写没有循环体的短循环代码(仅由一个分号组成:while(condition);)。㈡do-while语句的一般形式:do{//body of loop}while(condition);㈢传统for语句一般形式:for(initialization;condition;iteration){//body}。如果只有一条语句需要重复,大括号可以不要;初始化部分(initialization)只执行一次;当条件condition为假时,将跳出循环体;迭代部分通常是一个表达式,该表达式可增加或减小循环控制变量;在for循环内声明一个变量时,该变量的作用域限定在for循环体内。㈣for-each语句用于静态对象集合中(如数组),其语法的一般形式:for(type itr-var:collection){//statement block}。其中:type指定了迭代变量类型,itr-var指定了迭代变量名(iteration variable),该变量将集合(collection)的元素从头到尾依次接收。要注意的是:for-each语句的迭代变量是“只读”的,因为它仅与数组的下标相关。
⑶带标签的break语句一般形式:break label;其中:label是标识程序块的标签名称。要注意的是:该语句必须嵌套在带标签的程序块内。要指定一个标签块,只需把标签放在块的开始处即可。标签可以是任何有效的Java标识符,后再跟一个冒号。一旦给一个块加了标签,就可以把这个标签用做break语句的目标,程序会在带标签的块的下一条语句恢复执行。
⑷return语句:使用return语句可以从一个方法中显式的返回,即将程序控制转移回方法的调用者。对于main()方法中的return,程序将执行返回到Java的运行时系统。
14、Java类:Java中的所有代码都必须存在于类中,一个Java源程序中可以定义多个类,但是,具有public属性的类只能有一个,且与文件名完全一致。类是新的数据类型,可以在定义后使用它创建该类型的对象(object),对象也叫实例(instance),而类是对象的模板(template)。定义类的一般形式:
[修饰符] class className<T extends Person>{ //修饰符包括访问限定符(access-specifier)和类型修饰符。<>表示定义一个泛型类,方法、构造函数、方法的返回值也可以有泛型。
[修饰符] type instance-variable;[...n] //类的实例变量,为类的成员之一,成员属性
[修饰符] return-type methodName([type parameterName][,...n]){ //方法为类的成员
//body of method
}[...n] //return-type为该方法返回的数据类型,如果无返回值,则定义void
}
其中:type parameterName[,...n]为逗号隔开的参数列表对(为形式参数),注意:要有type类型定义。
欲返馈已知类(如:MyClass)的Class对象(类字面量),可以使用表达式Class clsObj=MyClass.class来获得。此方式也能够获得类、接口、基本类型、字符串和数组的类字面量(Class对象)。
创建类对象的一般形式:className class-variable=new className([argument-list][,...n]);
⑴它等效于:㈠className class-variable;//declare reference to object,声明后class-variable包含值null;㈡class-variable=new className([argument-list]);//作用:为对象动态分配内存(即运行时分配。类的对象的一个实际物理副本,含有类的成员)并把它赋给class-variable。类名后的括号()指定了类的构造方法(接口没有构造方法,因此不能用此形式产生接口的实例),argument-list为用逗号隔开的实际参数列表。⑵可以使用点.运算符来访问一个对象内的实例变量和方法。⑶当把一个对象引用变量赋给另一个对象引用变量时,并没有创建该对象的副本,而只是创建该引用的一个副本(地址)。如:Box b1=new Box();Box b2=b1;。
New是在运行时为对象动态分配内存,这种方法的优点是程序在运行期间可以根据需要创建对象,但由于内存是有限的,所以也可能出现因为内存不足而使new无法为一个对象分配内存的情况。如果出现这种情况,将会出现一个运行时异常。
构造方法(constructor)在创建对象时就对其初始化,以便使创建实例的代码有一个完全初始化的、立即可用的对象。特点:与类同名,没有返回值(因为一个类的构造方法隐含的返回类型是类类型本身)。两种构造方法:⑴默认的构造方法。如果不给类定义构造方法,则系统会为这个类创建一个默认的不带参数的构造方法;⑵带参数的构造方法。一旦定义了带参数的构造方法,则系统就不会创建默认的构造方法。
当一个类有可能产生子类且定义了带参数的构造方法之后,一般要另加一个不带参数的构造方法,以避免子类隐式调用出错。
方法有两种:构造方法和成员方法。
参数传递:把一个简单数据类型传递给方法时,使用按值调用(call-by-value),而对象传递则按引用传递(call-by-reference)。参数分常规参数和变长参数。
变长参数(variable-length arguments,简写varargs):一个变长参数由三个句点...来指定,如:static void vaTest(int ...v){//可使用for-each语句:for(int x:v)}。⑴在vaTest()内,v是作为一个可变长度的数组操作的(v引用);⑵调用vaTest()的时候,可带不同数目的整型参数,甚至可以不带参数,这些参数自动地被置入一个数组并传递给v;⑶一个方法既可以带常规参数,也可以带变长参数,但变长参数必须是该方法的最后声明的参数。如:void vaTest(int a,double c,int ...vals){;⑷方法内只能有一个varargs参数。如:int vaTest(int a,int ...vals,boolean ...seVals){//方法声明无效;⑸带varargs的方法重载可能带来模糊性而无法编译。如:void vaTest(int ...v){}与void vaTest(int n,int...v){} 方法的重载带来的非唯一性匹配的模糊性。
this关键字:在方法的内部使用,但不能在以static声明的类方法中使用。this 是一个对象的引用,指向当前的对象(谁调用这个方法,this就指向谁)。在一个类中,当局部变量和实例变量同名时,可以使用this来访问同名实例变量。
方法重写(覆盖method overwriting):是指子类中的方法与其超类中的方法具有同样的名称和类型声明(方法名、参数列表和返回类型均相同)。子类的对象在调用该方法的时候,就会调用重写以后的方法,而不再调用父类的方法了。但是父类的方法仍然存在。可以使用super.methodName()调用父类的方法。
方法重载(method overloading)与方法重写的区别:⑴重载是在一个类中,而重写是父类和子类两个类中;⑵重载只需要方法名一样,参数列表不一样。而重写是名称一样,列表也一样。
子类重写父类方法的时候,只能大于等于父类中的权限。
方法递归(recursion):调用自身的方法称为递归。当一个方法调用自身时,会给新的局部变量和参数分配堆栈中的存储空间,方法就带着这些新的变量从头执行。递归调用不会生成新方法副本,只有参数是新的。当递归调用返回时,旧的局部变量和参数从堆栈中被清除,然后从方法中的调用点重新开始运行。因为增加了额外的函数调用开销,所以许多递归版本的例程执行起来可能要比其迭代形式慢。对一个方法的递归调用可能会引起堆栈溢出,为避免递归调用溢出,对较多次数的递归可改为循环形式。编写递归方法时,必须有一条if语句以强迫方法返回。如:计算阶乘的递归:public class Factorial {
int fact(int n) { int result; //方法和变量声明不参与运行,仅分配内存空间
if (n == 1) return 1; //if语句强迫方法从fact(1)=1返回。否则,递归将永远不会返回
result = fact(n - 1) * n; //本语句为方法中的调用点。在递归调用返回前,程序执行方法开始处至本语句之前的代码块,以使参数n和fact(n-1)不断压入栈中;递归调用返回后,程序从本语句之后执行,遇到return语句或代码块结束点时,返回本语句,直至按后进先出法将旧的局部变量和参数依次全部出栈为止(即计算出factorial(n)的结果)。
return result; }
}
访问限定符(access-specifier)的可访问性(√表示可访问,×表示不可访问。适用于类及其成员):
|
private |
default |
protected |
public |
|
private |
default |
protected |
public |
同一个类 |
√ |
√ |
√ |
√ |
不同包子类 |
× |
× |
√ |
√ |
同包不同类 |
× |
√ |
√ |
√ |
不同包且非子类 |
× |
× |
× |
√ |
访问限定符可以限定:类、属性、方法(包括构造方法)。⑴当限定类的时候:㈠不要使用private、protected限定符;㈡当用public限定符的时候,类名一定要和java文件的文件名称一样。⑵类的成员属性(实例变量)一般用private来限定,类的外面要想访问该成员,可以通过公有的方法来间接访问(使用JBuilder工具来自动生成间接访问方法:定义完private属性后,在状态栏下选Beanàpropertiesà将getter和setter打上钩à点回source栏)。⑶方法体内的变量无需限定(因可见度仅限于方法内)。
类型修饰符:
类型 |
应用范围 |
限 制 条 件 或 说 明 | |
static静态 |
成员属性 |
也叫类变量,本质上是全局变量。静态变量不能是泛型。 | |
成员方法 |
也叫类方法。静态方法只能访问其他静态成员(方法、变量),不能使用this或super。 | ||
代码块 |
静态块仅在该类被加载时执行一次。一般用于初始化类的静态数据成员。 | ||
用static修饰的成员,只属于类,不属于任何对象。可以被它所属的类名直接访问,或使用对象访问。在同一个类里,静态方法可以直接引用。静态方法不能访问泛型。 | |||
用static修饰的语句在类被java虚拟机装载时就运行。static修饰的变量在内存空间里只有一份(无副本),只要类存在,它们就存在。而非static修饰的属性和方法要实例化之后才存在。 | |||
Final 最终 |
类 |
该类不能被继承。如果一个类为 final 类,那么它的所有方法都为隐式的 final 方法。 | |
变量 |
对成员和局部变量声明为final时,必须初始化且不能更改(等同常量)。该变量名全部大写 | ||
成员方法 |
该方法不能被重写。 | ||
对象 |
对象的引用不能更改,但它的值可以更改。 | ||
声明一个类不能既是abstract又是final,因为抽象类本身是不完整的。 | |||
abstract抽象 |
类 |
抽象类不能被实例化。带有抽象方法的类必须声明为抽象类。 | |
成员方法 |
父类中声明的abstract所有方法,子类必须重写,否则子类必须声明为抽象类。 | ||
抽象方法声明语法:abstract returnType methodName([type parameter][,...n]);参数列表为逗号隔开的形参。抽象方法只需要声明,不需要实现。构造方法和static方法不能声明为abstract。 | |||
abstract类不能有对象(即不能通过new直接实例化),但可以用来创建对象引用指向子类的对象。 | |||
⑴声明为final的方法有时能提高程序性能。因为正常情况下,Java运行时动态地解析对方法的调用,这称为后期绑定(late binding);然而由于final方法不能被重写,所以对它的调用可以在编译时解决,这称为早期绑定(early binding),编译器可以通过调用方法的编译代码直接内嵌(inline)来备份子例程的字节码,这样消除了与方法调用有关的昂贵开销。
一个类要被java解释器直接装载运行,这个类中必须有main方法。 Main方法寄生于类中,但又独立于类,它定义程序的起始点;由于java虚拟机要调用类的mian方法,所以该方法访问权限必须是public;Java虚拟机在执行main方法是不必创建对象,所以该方法必须是static的。Applet不需要main()方法。
Static变量及其代码块实例:
class TryInitialization {
static int[] values = new int[10]; //静态数组成员
static {
for(int i=0; i<values.length; i++)
values[i] = (int)(100.0*Math.random());
}
}
⑵使用静态方法创建类的唯一对象案例:
public class Student {private String stuName;
private static Student stu=new Student();//必须定义成静态变量.
private Student(){ }//将构造方法变为私有,类外将不能访问
public static Student getInstance(){return stu;}//通过创建getInstance()方法获取Student对象,由于非静态方法必须由类的对象调用,因此采用类的静态方法获得。
public String getStuName() {return stuName;}
public void setStuName(String stuName) {this.stuName = stuName; }}
public class Test {
public static void main(String[] args) {
Student stu=Student.getInstance();//通过类的静态方法创建唯一对象
stu.setStuName("张三"); System.out.println(stu.getStuName());}}
嵌套类(nested class):如果在一个类内定义另一个类,这种类称为嵌套类。Inner类(内部类,嵌套于内的类)可以访问Outer类(包围类),包括Outer类的private成员,但Outer类不能访问inner类的成员。Outer类外的代码不能实例化Inner类,因为Inner类仅在Outer类的作用域内是可知的。
可以在程序块的范围内定义内部类,也可以在方法体内定义内部类,或甚至在for循环体定义内部类。
匿名类(anonymous class):没有指定名称的类。多用于编写事件处理程序,如:用匿名内部类方法(方法内嵌套方法)实现的事件监听器(JBuilder的执行步骤:选择欲实现监听功能的Swing GUI上的组件,选择菜单栏的Project→Project Properties,打开Project Properties对话框→选择左面板中的Java Formatting内的Generated选项→在Event handling选项下,选择Anonymous adapter)。
15、继承:语法形式:class subclass-name extends superclass-name { //class-body }
注意:⑴没有extends,默认父类为Object。⑵只能有一个父类,即单一继承。⑶子类继承父类的全部成员(成员属性和成员方法),不含构造方法。如果父类的数据和方法声明为private性质后,子类则不能访问。⑷创建子类对象时,先调用父类的构造方法,然后再调用子类的构造方法。⑸子类中调用父类的构造方式有两种:㈠显式调用:使用super()方法,指定调用父类的哪个构造方法,而且必须为子类构造方法中的第一个语句。格式super(parameter_list)或super(),其中:形式参数列表前不加数据类型;㈡隐式调用:如果不使用super()方法,则调用父类的不带参数的构造方法。⑹super的第二种形式:super.member。其中member可以是一个方法,也可以是一个实例变量。这种形式多用于子类成员名被超类中同样的成员名隐藏的情况,如:super.methodname()调用重写的父类的方法。⑺在继承和多态中,决定可以访问什么成员的是引用变量的类型,而不是它引用的对象类型。也就是说,将一个子类对象的引用赋给一个超类引用变量时,只可以访问由超类所定义的那部分对象。
Object类:Object类是类体系结构的根,Java 系统中的每个类都是 Object 类直接或间接的子类,是sun公司为我们开发好的类。
16、多态polymorphism:多个子类重写了父类的方法形成多态。⑴多态时,Java应用动态方法调度(dynamic method dispatch,指运行时调用)。原理:当一个父类引用调用一个重写方法时,Java根据在调用时被引用对象的类型来决定执行哪个版本的方法(多态时形成的不同版本)。⑵一个父类的引用变量可以引用不同子类对象。比如,Student is a Person(is a 的关系)我们可以这样定义:Person p=new Student()。⑶父类的引用变量用于子类的方法,而父类没有定义此方法时则要在方法名前加子类名强制类型转换:(subClassName)superVariable.method。
17、接口(interface、implements):
接口定义一般形式:access interface interfaceName [extends superInterfaceName]{
Type static-final-varName1=value;
Type static-final-varName2=value;
Return-type methodName1(type parameterName[,..n]);
Return-type methodName2(type parameterName[,..n]);
……
} //access 是访问修饰符
接口访问的一般形式:access class className [extends superclassName] implements interfaceName [,interfaceName ...] { //class-body } //access 是访问修饰符;逗号分隔的接口用以实现多重继承。
⑴接口是一种特殊的抽象类,接口中的所有方法都是抽象的,因此接口没有构造方法。⑵接口是一种规范,可用于实现多重继承。⑶接口定义和接口访问中的access要么是public,要么是default。接口定义内的变量被隐含地声明为static和final(全局静态常量),这意味着它们不能由实现类来改变,也必须由常量值来初始化。如果接口本身被声明为public,那么其内的所有方法和变量都隐含地声明为public。实现接口的方法必须声明为public。⑷如果接口的实现类没有完全实现接口中的所有方法,那么这个类就是抽象类。⑸如果一个类实现了两个接口,而这两个接口声明了同一个方法,那么这个方法将被其中一个接口的客户使用。⑹接口类型的变量只可访问接口中声明的方法,而不能访问实现类的任何成员。如:变量c被声明为接口类型Callback,但它被赋与了Client实例(Callback c=new Client),这里使用c可以访问Callback()方法,但不能访问Client类的任何成员。⑺在Java中,接口可有属性,且该属性为常量;但在C#中,接口只有抽象方法,而不能有属性。
18、异常:Java中所有异常都是内置类Throwable的子类,它下面分Exception(异常)和Error(错误)两个子类。Exception下有一个RuntimeException(运行时异常)子类(见下图)。Error类异常(如断电、内存溢出、堆栈溢出、类方件格式错误等)指明与运行时环境本身有关的错误,通常是为响应灾难性故障而创建的,由Java虚拟机生成并抛出,而现在的程序通常无法处理这种灾难性故障。
异常处理块的一般形式:
try{ //每条try语句要求至少有一条catch或finally子句。
//Block of code to monitor for errors
[catch (ExceptionType1 exobj1){ //(异常类型1 异常变量1(或叫异常对象1)
//exception handler(处理程序) for ExceptionType1
}catch (ExceptionType1 exobj2){
//exception handler(处理程序) for ExceptionType1
}]...
[finally
{ //block of code to be executed before try block ends }]
⑴Java异常均是对象。异常产生的方式: JVM抛出或throw关键字手工抛出;异常处理方式:throws或try/catch语句;异常用finally关闭文件处理并释放资源(无论发生异常与否,此块必将执行。如果一个方法通过一个未捕获的异常或一条显式的返回语句从一个try/catch块内返回到调用者,finally子句会在方法返回之前执行)。
catch语句像只有一个参数且没有返回类型的方法定义,参数可以是类,也可以是接口。参数如果符合下列条件,则认为它与异常匹配:⑴是与异常相同的类;⑵是异常的父类;⑶如果该参数是一个接口,则异常类将实现接口。
⑵使用多重catch语句时,异常子类应该位于任何父类之前(Java对不可能到达的代码认为是一个错误)。Try块和catch语句形成了一个整体,Catch子句的作用域被限制在由其前面的try语句所指定的那些语句中,Catch语句不能捕获其他try语句所抛出的异常(除了嵌套的try语句以外)。
⑶用Throw显示地抛出异常的一般形式:throw <throwableInstance>
其中:throwableInstance必须是异常的实例(Throwable对象)或Throwable的一个子类。有两种方式获得一个throwableInstance:㈠在catch语句中使用一个参数;㈡用new ThrowableConstructedMethod()(//异常类构造方法)创建一个。如:throw new NullPointerException(“访问空值”);。
在throw语句后面,执行流会立即停止,其后面的语句将不再执行。然后检查距该语句最近的try块,查看是否有和异常类型相匹配的catch语句。如果找到了一个匹配,则将控制流送到那条语句。如果没找到匹配的catch,则默认的异常处理程序将停止程序并打印堆栈追踪。
⑷Java内置的很多运行时异常最少具有两个构造函数:一个不带参数;一个带有一个描述异常的字符串参数,当对象作为print()或println()的一个参数时,该字符串参数将被显示,也可以通过调用getMessage()来获得它。
⑸在方法中声明可能抛出的异常的一般形式:
return-type method-name([type parameterName][,...n]) throws ThrowableClassName[,...n]
⑹Java中的异常分为:㈠Java API(Application Programming Interface)定义的异常;㈡自定义异常。自定义异常应该继承Exception类。
⑺创建链式异常(chained exceptions)需要向Throwable添加:㈠构造函数Throwable(Throwable causeExc)或Throwable(String message,Throwable causeExc);㈡方法:ThrowableInstance.getCause()或ThrowableInstance.initCause(ThrowableInstance of causeExc)
其中:㈠causeExc是引起当前异常的异常,即异常出现的潜在原因;㈡getCause()方法返回引起当前异常的那个异常,如果没有此原因异常,将返回null;㈢initCause()方法把causeExc和调用异常关联起来并返回对该异常的引用。但原因和异常仅能设置一次,即仅可以为每个异常对象调用一次initCause()。如果原因异常由构造函数设置,就不能使用initCause()再设置它。
由于大多数Java的内置异常不定义额外的构造函数,因此,如果需要给这些异常添加异常链,将使用initCause()方法。
小技巧: 检验字符串对象是否无输入值时,可用"".equals(strObject)方法。如使用user.equls("")方法可能报NullPointException异常。
19、包(package):是类的容器,又是可见度控制机制。包名作为一个Java源文件的第一条语句,其一般形式:package pkg1[.pkg2[.pkg3]...];。在当前目录中Person.java源文件中含有package com.accp;包时,编译javac –d . Person.java时,要注意:⑴加参数-d即可生成与包名层次对应的目录结构;⑵在.后要加一空格(目录和文件名之间要有一空格。比如要在当前目录的上一目录下编译时,则为javac –d ..\classes Person.java命令);⑶系统编译时会自动在当前目录下生成.\com\accp\Person.class文件;⑷如果包目录存放位置转移,比如存在e:\project\classes目录中,则要指定环境变量:set classpath=.;e:\project\classes。
包名命名规范:com.ibm.item(域名倒置)。有两中命名方式:⑴通用按结构划分:如com.xaccp.gui、com.xaccp.db、com.xaccp.util、com.xaccp.control;⑵按功能划分:如com.xaccp.teacher、com.xaccp.student等。
当在命令行中运行Person类时,要使用完整名称:Java com.xaccp.Person。因为虚拟机要装载com.accp.Person类时,㈠会先找到classpath环境变量指定的目录,再在这些目录中,按照与包名层次相对应的目录结构查找.class文件;㈡类的全名跟路径名.\com\accp\Person.class是否匹配。
同一个包中的不同类,可以直接使用类名。不同包的类互相调用可以使用下面两种方式之一:⑴写类的全名;⑵通过关键字import导入包,如:import com.accp.Person或Import com.accp.*(*代表com.accp包中的所有的类和接口)。
类和包是封装和包含名字空间和变量、方法作用域的两种手段。包是类和其他从属包的容器,类是数据和代码的容器。
17、枚举、自动装拆箱和元数据(注释):
(一)枚举为一个类类型,枚举的声明放在其他类声明之前,声明的一般形式:
enum EnumTypeName{ //枚举类名及枚举常量首字母均大写,标识符的写法同类名。
enumTypeConstant1[(arg_list1)[,enumTypeConstant2[(arg_list)],...] //枚举常量被隐式
}声明为enumTypeName 的公有、静态枚举成员,这些常量被称为“自(指封闭)类型化的”。Arg_list为枚举定义的构造方法传递的实际参数值。
⑴枚举一旦被定义,就可以创建该类型的变量,但不能使用new实例化一个枚举。⑵两个枚举常量可以使用关系运算符“==”或equals()方法来比较其值相等性。⑶所有枚举类型自动包括两个预定义方法:㈠public static enumTypeConstants[] values(){。//返回包含所有枚举常量的数组。㈡public static enumTypeConstant valueOf(String str){。//str与返回的枚举常量相对应。⑷枚举可以有构造方法、方法、实例变量(也叫成员属性、成员变量)和实现接口。每一个枚举常量是它的枚举类型的一个对象,因此如果一个枚举定义了构造方法,则创建每个枚举常量时都要调用该构造方法;对此枚举类型定义的任何实例变量,每个枚举常量都具有这个实例变量的副本。⑸枚举常量的顺序值从0开始。⑹枚举不能被扩展(即不能是超类,也不能继承),但所有枚举会自动继承java.lang.Enum类,使用该类定义的方法。
(二)自动装拆箱:将一个值封装进一个对象的过程称为装箱(boxing),从一个类型包装器中提取值的过程称为拆箱(unboxing)。Java对基本数据类型和它的对应的包装类具有⑴对象赋值时;⑵方法的参数传递和返回时;⑶表达式运算中执行自动装拆箱功能。
(三)元数据(注释):将补充信息(注释)嵌入到源文件中,补多种工具使用,但不改变程序的操作,也叫程序注释工具。元数据的声明、保留策略及注释声明的一般形式(例子):
@Retention(RetentionPolicy.RUNTIME|CLASS|SOURCE) //保留策略指定三种之一,语句后不加分号。
@interface myAnno{ //声明注释名需要通过基于@interface接口的机制,@符告诉编译器为注释类型。
String str() [default “Testing”];//注释的两个成员(实例变量),所有的注释都只包括
Int val() [default 9000]; //方法,而不用提供方法的主体,因此变量名后加(),代表数据
} //类型域。Default表示如果在使用注释时,没有为注释成员指定值时,则使用其默认值。
@MyAnno(str=”abc”,val=100) //注释声明语句要放在关联语句块之前
public static void myMeth(){... //前面声明了MyAnno注释后,就可以使用MyAnno来注释声明。任何类型的声明(如:类、方法、值域、参数、枚举常量和注释本身)都可以加上一个注释。注释成员被赋值时,只使用它的名称,与值域类似,不加()。注释声明语句后不加分号,表示MyAnno注释链接了myMeth()方法。
⑴保留策略决定在哪个点上删除一个注释:㈠SOURCE的注释只在源文件中保留,在编译期间删除;㈡CLASS注释在编译期间存储在.Class文件中,但在运行时不能通过JVM来获得;㈢RUNTIME的注释在编译期间存储在.Class文件中,运行时可通过JVM来获得,因此可以反射性地读取。默认保留策略为CLASS。⑵注释不能包括extends子句,但所有的注释类型都能自动地扩展Annotation接口。Annotation是所有注释的超级接口,它在java.lang.annotation包中声明,应用时需要导入。注释声明的方法一定一带参数。注释不能是泛型。注释不能指定throws子句。⑶想获得已知类名MyAnno类型的Class对象(类字面量),可以用MyAnno.class表达式,通常,这种方法也能够获得类、接口、基本类型和数组的类字面量(如:int.class)。⑷想获得注释成员(如:val),须使用方法调用的语法:anno.val() (注意语法中有一对括号)。anno为MyAnno对象。如:MyAnno anno=m.getAnnotation(MyAnno.class))。⑸标记注释(marker annotation)是一种不包括成员的特殊的注释。⑹内置注释7个:@Retention、@Documented、@Target(注释可以运用的声明的类型)、@Inherted、@Override、@Deprecated、@SuppressWarnings。
(四)反射(reflection):反射是一种使类的有关信息在运行时被获得的特性。反射API被包含在java.lang.reflect包中。反射运用到注释的方法:⑴获得一个Class对象(Java内置类Class):用Object定义的getClass()方法来获得当前运行类的Class对象。⑵在得到一个Class对象后,可以使用它的方法来获得这个类声明的各项信息。获得注释信息的一般形式:Annotation getAnnotation(class anntype)。如果想获得在类中声明的与特定条目相关联的注释,必须首先获得代表该条目的对象,如:Class提供getMethod()getField()getConstructor()方法将分别获得方法、值域和构造方法的信息。
18、泛型(generic type):本质是参数化类型,用于类、接口、构造方法和方法。声明泛型类的语法(接口interface类似):
修饰符 class className<type_parameter_list>|<type_parameter extends superClass,...>{ }
创建泛型对象的语法:
Class className<type_argument_list> variableName=new className<type_argument_list>(constant_argument_list);
泛型方法语法:修饰符 <type_parameter_list> return-type methodName(type parameter[,...]){ }
泛型类(generic class)内里的方法使用通配符(wildcard)参数:⑴修饰符 return-type methodName(className<?> obj_par){ } ⑵将上式尖括号内改为:<?extends superClass>可为通配符建立上界。⑶改为:<?super subClass>可为通配符建立下界。通配符只是匹配任一有效的className对象。上、下界不同,参数类型不同。
其中:type_parameter_list表示用逗号隔开的形式参数列表;type parameter[,...]用逗号隔开的形式参数列表,其每个参数前要指明type类型;type_argument_list表示用逗号隔开的实际参数列表;形参和实参均用<>括起来;constant_argument_list表示用逗号隔开的对应的常量列表。
泛型方法的类型参数列表位于返回类型前(如:static<T,V extends T> boolean isIn(T x,V[] y))。在创建一个泛型的实例时,传递给类型形参的类型实参必须是类类型,如Integer、character、Double,不能使用int、char、double之类的简单类型。extends子句将type_parameter限制在只能由superClass或superClass的子类来替换(上界,有界类型bounded types)。泛型类层次的全部子类必须将泛型超类需要的类型参数沿层次向上传递。
如果一个类实现一个泛型接口,则此类必须也是泛型或者接受传递给接口的实参参数。如:interface MinMax<T extends Comparable<T>>{T min();T max();}//用于返回某个对象集的最小值和最大值的泛型接口,此接口必须扩展java.lang.Comparable接口,以实现对象的排序;Class Myclass<T extends Comparable<T>> implements MinMax<T>{}//实现类是泛型类,或者class MyClass implements MinMax<Integer>//实现类传递给接口一个实参参数<Integer>。
通过泛型,所有的强制转换都是自动和隐式的,对某种特定版本的泛型的引用,与对同一种泛型的另一种版本的引用是类型不兼容的,因此,编译时的这种类型检查确保了类型安全。Java编译器并不创建实际的不同的泛型版本,相反,编译器删除所有的泛型信息,按照指定的界限类型进行必要的强制转换(如果没有指定界限,则是Object)。
所有的静态成员都不能使用封闭类所声明的类型参数(泛型),静态方法也不能访问泛型对象(如下列错误的静态语句:class Gen<T>{static T ob;static T getOb(){return ob;} static void showOb() {System.out.print(ob);}}),但是可以声明静态泛型方法。
泛型数组和异常的局限:⑴不能实例化原始类型是类型参数的数组。如:T[] vals=new T(5);//T为泛型。⑵不能创建一个类型特定的泛型引用的数组,因为会损害类型安全,如:Gen<Integer>gens[]=new Gen<Integer>[10];//error!;但可以使用通配符,如:Gen<?>gens[]=new Gen<?>[10];//ok!⑶泛型类不能扩展Throwable,这意味着不能创建泛型异常类。
泛型应用案例(适用存放任何类型的实体类):
public class TypeFan {
public static void main(){
ArrayList<String> data=new ArrayList<String>();
data.add("张三"); data.add("李四"); //data.add(Student.getInstance); //非法类型。
//存取集合的方法有三: //其一:通过迭代器
Iterator<String> it=data.iterator();
while(it.hasNext()){
item=(String)it.next();//由于采用泛型,故在此不必强制转换为字符串.非泛型应为String。
String item=it.next(); System.out.println(item); }
//其二:通过for循环
for(int i=0;i<data.size();i++){ String item=data.get(i); //由于采用泛型,故在此不必强制转换为字符串.非泛型应为String item=(String)data.get(i); System.out.println(item); }
//其三:通过forEach循环.由于采用泛型,故在此直接定义字符串集合元素.非泛型应为for(Object itme:data){System.out.println((String)item);}
for(String item:data){System.out.println(item); }}}
19、面向对象程序设计思路过程:⑴首先需要抽取问题描述中实体也就是对象;⑵分析每个对象所具有的特征;⑶分析每个对象所发出的动作;⑷从这些对象的特征中,抽取类的属性和方法;⑸分析类之间的关系,画出类结构图。
二、java.lang包
提供利用 Java 编程语言进行程序设计的基础类和接口。java.lang是虚拟机默认的包,因此,它可以自动导入到所有的程序中。Java的基本数据类型出于高效的考虑不是对象,而是“常规”变量。
Object类位于Java.lang包中,是所有其他类的超类。它定义了clone()、equals()、getClass()、toString()、wait()等方法在每个对象上都是可用的。⑴toString()方法:用于将对象的内容作为字符串返回,对象无值的时候,返回对象的地址。也可以重写此方法。在对象调用print()和println()方法输出的时候,系统会自动调用该对象的toString()方法。⑵对象比较的两种方式:㈠使用比较符“==”:对于基本类型的变量比较的是值,对于引用数据类型比较的是地址;㈡使用equals()方法:这个方法比较的是对象中的内容是否相等。两个字符串的比较原则使用equals()方法。⑶clone()方法:用于创建调用它的对象的一个重复的副本,只有实现Cloneable接口的类才能够被复制(因为clone()在Object中声明为protected,意味着它必须在实现Cloneable接口的类所定义的方法中调中)。如果调用没有实现Cloneable接口的类的clone()方法,就会抛出一个CloneNotSupportedException异常。复制是一个具有潜在危险的行为。例如,如果被复制的对象包含obRef变量的引用,那么当完成复制后,副本中的obRef将引用与原来版本相同的obRef所引用的变量,如果副本改变了obRef引用的内容,那么原始对象所引用的内容也改变了。这种复制的负面效应有时很难发现(不安全),如果没有很好的理由,则不要实现任何类型的cloneable接口。⑷getCalss()方法:返回一个对象的运行时类。
Java.lang包括下面这些类:
Boolean |
Byte |
Character |
Class |
ClassLoader |
Compiler |
Double |
Enum |
Float |
Integer | |
InheritableThreadLocal |
Long |
Math |
Number |
Object |
Package |
Process |
short | |||
ProcessBuilder |
Runtime |
RuntimePermission |
SecurityManager |
StackTraceElement | ||||||
StrictMath |
String |
StringBuffer |
StringBuilder |
System |
Thread |
void | ||||
ThreadGroup |
ThreadLocal |
Throwable |
|
|
|
|
| |||
Java.lang定义了如下的接口:
Appendable |
CharSequence |
Cloneable |
Comparable |
Iterable |
Readable |
Runnable |
1、String类(final类):每个字符串都是String类型的对象,且创建后不可改变(StringBuffer和StringBuilder类可修改)。创建String实例的几种方式:⑴String str=”abc”;将str指向字符串池中字面量“abc”。特点:字符串池只保留一份相同字面量值,即不同字符串变量指向字符串池中的相同字面量时,则字符串变量指向相同。⑵String str=new String(“abc”);str指向堆内存字面量“abc”。特点:每new一次堆内存将重新分配存储空间,无论值是否相同。⑶使用字符数组String(char chars[])或字节数组String(byte asciiChars[])方式创建。
Java的字符串下标是从0开始的。
字符串可以使用+运算符和字符串或其他数据类型连接,当其他数据类型和String实例连接时,编译器就会将其他数据类型的操作数转换为它的字符串形式(通过调用valueOf()方法完成字符串的转换)。
当对String对象使用+运算符时,Java会自动将字符串实例的修改转化为对StringBuffer实例的修改,因此,一个连接实际上是调用StringBuffer对象的append()方法。在连接完成后,编译器插入对toString()的调用来把可修改的StringBuffer对象转换到常量的String对象中。
2、StringBuffer类(final类):
线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。
可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。
例如,如果 z 引用一个当前内容为 "start" 的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含 "startle",而 z.insert(4, "le") 将更改字符串缓冲区,使之包含 "starlet"。
通常,如果 sb 引用 StringBuilder 的一个实例,则 sb.append(x) 和 sb.insert(sb.length(), x) 具有相同的效果。
当发生与源序列有关的操作(如源序列中的追加或插入操作)时,该类只在执行此操作的字符串缓冲区上而不是在源上实现同步。
每个字符串缓冲区都有一定的容量。只要字符串缓冲区所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则此容量自动增大。从 JDK 5 开始,为该类补充了一个单个线程使用的等价类,即 StringBuilder。与该类相比,通常应该优先使用 StringBuilder 类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。
3、StringBuilder类(final类):StringBuilder的功能同StringBuffer。不同点:StringBuilder不是同步的,即不是线程安全的,但执行速度快。在使用多线程时必须使用StringBuffer。
4、简单类型包装器(type wrapper):包括Number、Byte、Character、Short、Long、Integer、Float、Double、Boolean类。
抽象类Number定义了一个包装各种数字类型类的超类,有6个具体的子类:Byte、Double、Float、Integer、Long和Short。数字类型的构造方法可以通过数字型或字符串形式来构造,通过字符串形式构造时引发NumberFormatException异常。
数字与字符串的相互转换:⑴字符串转换数字:使用parseInt()等方法,可以用BufferedReader br=new BufferedReader(new InputStreamReader(System.in));创建从System.in输入的字符存入缓冲区(引发异常IOException),然后使用readLine()方法返回字符串:str=br.readLine();最后用parseInt()方法解析返回整数值(引发NumberFormatException异常)。⑵数字转字符串:使用toString()、toBinaryString()、toHexString()和toOctalString()分别转换为十进制、二进制、十六进制和八进制。
J2SE 5补充了对32位Unicode字符的支持,现在Unicode字符范围是从0~10FFFF。代码点(codepoint)是在范围0~10FFFF之内的一个字符;代码单元表示一个16位字符;值大于FFFF的字符被称作追加字符(SupplementaryCodePoint)。J2SE 5处理扩展的Unicode的两个方法:⑴使用两个char来表示一个追加字符,第一个char称为高代理(HighSurrogate),第二个char称为低代理(LowSurrogate),提供新方法如codePointAt(),以便在代码点与追加字符间进行转换。⑵Java重载了几个原Character类中的方法,重载格式使用int而不是char类型。如:原方法static boolean isDigit(char ch),重载方法static isDigit(int codePoint)。
5、Class类(final类):封装对象或接口运行时的状态。当Java装载类时,会自动创建Class类型的对象。Class 类的实例表示正在运行的 Java 应用程序中的类和接口。Class定义的方法经常用在需要知道对象的运行时信息的场合,使用由Class提供的方法可以确定特定类的附加信息,如它的public构造函数、字段和方法,它的getName()方法以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
Class没有提供公共的构造方法,因此,不能显示声明一个Class对象,一般通过调用getClasss()方法来得到运行明Class对象。forName()方法返回给定字符串名相关联的类或接口的Class对象并将其装入内存。ClassName.class.getResourceAsStream(String fullPathName)方法是打开并读取一个参数指定的文件到系统内存中,返回一个InputStream流。
6、ClassLoader类(abstract类):定义了类是如何加载的。应用程序可以创建ClassLoader的扩展子类,实现它的方法。这样可以以某种其他的方式装载类,而不是由Java运行时系统正常地装载。
6、Void类(final类):Void 类是一个不可实例化的占位符类,它保持一个对代表 Java 关键字 void 的 Class 对象的引用。Void类有一个静态字段TYPE。
7、Process类(进程,abstract类):由ProcessBuilder.start()或Runtime.exec方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获取相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。
8、ProcessBuilder类(final类):提供一种启动和管理进程(即程序)的方法。若要使用ProcessBuilder创建一个进程,只需创建ProcessBuilder的一个实例,指定该程序的名称和所需参数,要执行此程序,调用该实例上的start()即可。
9、Runtime类(运行时): 每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。Runtime类封装了运行时的环境,应用程序不能创建自己的 Runtime 类实例,但可以通过静态方法Runtime.getRuntime()方法获取当前运行时Runtime对象的引用。一旦得到一个当前Runtime对象的引用,就可以调用几个控制Java虚拟机状态和行为的方法。当Applet和其他不被信任的代码调用任何Runtime方法时,常常会引起SecurityException 异常。
10、System类(系统,final类):
System 类封装了运行时环境的几个属性,可以获得当前时间以及系统相关的各种属性(如:对外部定义的属性和环境变量的访问,加载文件和库的方法,快速复制数组的一部分的实用方法)。它有一系列的静态方法和类字段,System类不能被实例化。System.out指标准输出,默认时指的是终端。System.in指标准输入,默认指键盘(默认时输入的字节存入键盘缓存区,直到按回车键才实际地送入程序)。System.err指标准错误流,默认时也指的是终端。System.in是InputStream类型的一个对象,System.out和System.err是PrintStream类型的对象,这些都是字节流,但它们常用于读写控制台的字符。利用System.currentTimeMillis()方法可以计算某段程序块运行的毫秒数。
11、Math类(数学,final类)和StrictMath类(精确数学,final类): 两个类均包含基本的数字操作,如指数、对数、平方根、三角函数、弧度数、随机数等。均定义了double类型的常量:E(自然对数的底数)和PI(园周率)。均为静态字段和静态方法。Math类中的方法有更大的宽容度,以提高性能。
12、Thread类(线程)、ThreadGroup(线程组)、ThreadLocal(本地线程)、InheritableThreadLocal(可继承的本地线程):用一封装执行线程的类。⑴Thread定义了三个静态字段MAX_PRIORITY、MIN_PRIORITY、NORM_PRIORITY分别表示线程具有的最高、最低和默认优先级,用start()方法开始线程的执行。⑵ThreadGroup提供了把线程组当做一个单元来管理的方法,这在想要挂起或恢复多个相关线程时特别有用。⑶ThreadLocal用于创建线程的局部变量,从而使每个线程都拥有自已的线程局部变量的副本。⑷InheritableThreadLocal创建可以被继承的线程局部变量。Runnable接口必须由一个可以启动单独的执行线程的类所实现。Runnable定义了一个抽象方法run(),它是线程的进入点。
13、Package(包类)、RuntimePermission(运行许可类)、Throwable(异常类)、SecurityManager(安全管理者,抽象类)、StackTraceElement(堆栈追踪元素数组类,Throwable类的getStackTrace()方法返回一个StackTraceElement数组。)、Enum(=enumeration枚举,抽象类)、CharSequence(定义了允许以只读方式访问字符序列的接口)、Comparable(可比较接口)、Appendable(可追加字符或字符序列接口)、Iterable(迭代接口。一个对象若要在for循环的for-each类型中使用,它的类必须实现Iterable接口)、Readable(用来指明一个对象可用作字符源的接口)。
14、java.lang子包:⑴java.lang.annotation(注释功能)。⑵java.lang.instrument(工具。允许 Java 编程语言代理监测运行在 JVM 上的程序的服务。)。⑶java.lang.management(可以对JVM和执行环境进行管理)。⑷java.lang.ref(可以对无用单元收集过程进行更加灵活的控制)。⑸java.lang.reflect(反射。提供了获取字段、构造方法、方法和类的修改器信息的能力,还允许动态创建和访问数组类:Array。)
三、java.util包
包含集合框架、遗留的 collection 类、事件模型、日期和时间设施、国际化和各种实用工具类(字符串标记生成器、随机数生成器和位数组)。
(一)集合框架(collections framework):
Java的集合框架为程序提供了一种处理对象组的标准方式。设计了一系列标准泛型接口:⑴Collection (集合)接口,扩展了Iterable接口,位于集合层次结构的顶部,因此所有的集合都实现Collection接口,并提供了iterator()方法来返回一个迭代器。用add()方法添加对象,remove方法()删除元素,clear()删除集合所有元素(size=0),contains()方法查看集合是否包含对象,toArray()方法返回集合元素数组,equals()方法比较两个集合是否相等,size()方法返回集合中元素的数目,isEmpty()判断集合是否为空,hashCode()返回调用集合的散列码,iterator()返回调用集合的迭代器。⑵List(列表)接口,扩展了Collection接口,存储一个序列的元素(基于0的索引),可以包含重复的元素,但不能有null值。获得特定位置的对象调用get()方法,用set()方法给特定位置元素赋值,用indexOf()或lastIndexOf()方法分别获得对象的第一个实例或最后一个实例所在的位置,subList()方法取子列表,listIterator()返回一个迭代器。⑶Set接口,扩展了Collection接口,该集合不允许存在相同的元素(包括唯一null值)。SortedSet接口,扩展了Set接口并声明自已是升序的集合。First()或last()方法分别获得第一或最后一个对象,subSet()获得子集,headSet()和tailSet()方法分别获得从头开始或直到未尾的子集。⑷Queue(队列)接口,扩展了Collection接口,并声明一个队列行为(FIFO,先进先出列表)。Offer()方法在队列尾插入元素。element()和peek()方法获得但不移除队列的第一个元素,如果队列为空,element()抛出NoSuchElementException异常,peek()返回null。poll()和remove()方法获得并移除队列的第一个元素,如果队列为空,poll()返回null,remove()抛出异常。⑸Comparator(比较器)接口,定义了两个方法:compare()和equals()方法,通过改写compare()方法,能够改变对象排序的方式。⑹Iterator(迭代器)接口、ListIterator(列表迭代器,可进行双向遍历)接口,一般来说,使用迭代器在集合中遍历时应遵循下面的步骤:㈠通过集合的iterator()得到一个指向集合开始处的迭代器:Iterator itr=collectionObject.iterator();㈡设置一个判断是否有下一个元素的循环:如while(itr.hasNext()){。㈢在循环中取出下一个元素:如Object element=itr.next();⑺RandomAccess(随机访问)接口。被ArrayList类和遗留的Vector类实现。⑻Map(映射)接口、Map.Entry (Map的嵌套类、内部类)接口、SortedMap(默认按key键升序排列的映射)接口。映射是将键映射到值的对象,一个映射不能包含重复的键;每个键最多只能映射一个值。Map接口提供三种collection 视图:键集、值集合或键-值映射关系集。映射不是集合,因为它们不实现Collection接口,但是可以通过使用entrySet()方法获得键-值映射关系的集合视图,或使用keySet()方法获得键的集合视图,使用values()方法获得值的集合视图。put()方法将值放入映射中,get()得到与键k相关联的值。SortedMap接口增加了获取子映射的headMap()、tailMap()、subMap()方法和获取首尾键的firstKey()、lastKey()方法。Map.Entry接口定义了获取键值的getKey()、getValue()方法和替换值的setValue()方法。
Collection集合的有序是Set,Map的有序是TreeMap。
异常:试图增加一个不兼容的对象到集合或映射中,将抛出ClassCastException;如果使用无效索引,抛出IndexOutOfBoundException;null不允许存在于集合或映射中,如果试图使用null对象,抛出NullPointException;当修改不可改变的集合或映射时,抛出UnsupportedOperationException;当调用下一个对象不存在时,抛出NoSuchElementException;
集合框架接口示意(父类∈子类):1、Collection∈⑴List,⑵Set∈SortedSet。2、Map∈SortedMap。
集合框架实现类示意(接口→实现类):1、List→⑴ArrayList,⑵LinkedList。2、Set→⑴HashSet,⑵LinkedHashSet。3、SortedSet→TreeSet。4、Map→HashMap。5、SortedMap→TreeMap。
1、Collections类:此类完全由在collection(集合框架定义的集合和映射)上进行操作或返回collection的一系列静态泛型方法和静态属性(字段)组成。如:checkedCollection()方法返回集合的运行时(动态)类型安全视图,frequency()返回一个元素出现的次数,disjoint()判断两个集合中有无相同的元素,addAll()将一个数组的内容添加到一个集合中,reverseOrder()返回一个倒序的Comparator。synchronizedMap()返回由指定映射支持的同步(线程安全)映射。unmodifiableList()返回不可修改的列表。Shuffle()方法随机化键表中的元素。
2、ArrayList泛型类:实现List、RandomAccess接口,是一个对象引用的变长数组(数组列表以初始长度创建,当长度超过时,集合自动增大;当删除对象时,集合自动变小)。也可以使用ensureCapacity()方法手动增加容量以提高性能,trimToSize() 方法使容量等于当前数组大小。相对LinkedList和Vector而言,ArrayList访问和遍历对象的性能更好(速度快),但Vector是线程同步。
3、LinkedList泛型类:扩展了AbstractSequentialList类(用于顺序而不是随机访问效果的元素),实现了List接口Queue接口。LinkedList提供了一个双向循环链表型的数据结构,可实现栈(stack)、队列、双向队列(double-ended queue)。相对于ArrayList而言,LinkedList添加和删除对象的表现更佳。
4、HashSet泛型类:扩展了AbstractSet并实现了Set接口,它创建一个使用哈希表存储的集合。散列法的特点是add()、contains()、remove()、size()等基本操作的执行时间保持不变(假定哈希函数将这些元素正确地分布在桶中。对此集合进行迭代所需的时间与 HashSet 实例的大小(元素的数量)和底层 HashMap 实例(桶的数量)的“容量”的和成比例),即使对于大的集合来说也是如此。
在Java语言中,通过负载因子(load factor)来决定何时对散列表进行再散列,即将所有元素存放到新的散列表中,原先的散列表将被删除。负载因子越高(越接近1.0),内存的使用效率越高,元素的寻找时间越长。负载因子越低(越接近0.0),元素的寻找时间越短,内存浪费越多。HashSet类的缺省负载因子是0.75。
LinkedHashSet泛型类:扩展了HashSet类,以元素插入的顺序来维护集合的链接表。
5、HashMap泛型类:实现Map接口,允许使用null键和null值。WeakHashMap实现“弱键”映射。LinkedHashMap泛型类:扩展了HashMap类,以元素插入的顺序来维护映射中元素的链表。IdentityHashMap泛型类:实现了Map接口,与HashMap相似,但在比较时使用引用的身份。
6、TreeSet泛型类:实现了SortedSet接口,该接口由 TreeMap 实例支持。此类使元素按照自然顺序排序(Comparable接口)或按照显示指定的比较函数Comparator排序。访问和遍历的时间很快。
TreeMap泛型类:实现了SortedMap接口,此类使元素按照自然顺序排序(Comparable接口)或按照显示指定的比较函数Comparator排序。访问和遍历的时间很快。
7、EnumSet泛型类:扩展了AbstractSet类并实现了Set接口,专门用于enum类型的键。EnumSet未定义构造方法且不允许使用null元素。此类的空间和时间性能应该很好,足以用作传统上基于int的“位标志”的替换形式,具有高品质、类型安全的优势。
EnumMap泛型类:实现了Map接口,专门用于enum类型的键。
8、PriorityQueue泛型类:扩展了AbstractQueue并实现了Queue接口,它是一个基于优先级堆的极大优先级队列。此队列根据构造方法决定元素的排序是自然顺序(默认Comparable接口,升序)还是由Comparator比较函数来显示指定。优先级队列不允许使用null元素,其容量可按需要自动增长。
9、Arrays泛型类:此类包含用来操作数组(比如排序和搜索)的各种静态方法。asList()返回受指定数组支持的固定大小的列表,列表和数组指向同一个地方。binarySearch()方法使用二分法来查找指定的值。这个方法必须用于排序的数组。
10、Java的标准集合类都不是同步的,但是所有的遗留类是同步的。Java.util定义的遗留类有:Dictionary (字典)泛型类,被映射取代。Hashtable(哈希表)泛型类,与HashMap近似,但不允许null作为键和值。Hashtable不直接支持迭代器,可使用Map定义的集合视图的方法(如:entrySet()和keySet()方法)得到哈希表的集合视图,然后从集合视图对象中获得迭代器(P375)。Properties(属性集)泛型类,是Hashtable的一个子类,用来维护键和值都是字符串的列表。Properties类的一个有用的功能是可以指定默认属性,如果没有与特定键关联的值,默认属性就被返回。另外,Store()和load()方法可以将一个Properties对象写到一个流中或者从流中读出。Stack(Vector子类),实现了标准的后进先出的椎栈。Vector(矢量动态数组)泛型类,与ArrayList相似,元素序列从0开始。遗留接口有:Enumeration(枚举)泛型接口:由Iterator取代,但它被遗留类定义的多个方法所使用,定义了两个方法:hasMoreElements()和nextElement()。
(二)其它工具类:
Java是按照格林威治标准时 (GMT=Greenwich mean Time) 定义的,格林威治标准时和世界时 (UT or CUT=Coordinated Universal Time协调世界时) 是相等的。
Java的日期和时间表示形式:⑴年份y由整数y - 1900表示;⑵月份M由从0至11的整数表示:0是一月、1是二月至11是十二月;⑶日期d(=DAY_OF_MONTH,月中天数)或D(=DAY_OF_YEAR,年中天数)从整数1开始,DAY_OF_WEEK表示这天是星期几(从SUNDAY、MONDAY至 SATURDAY分别用1,2至7表示),DAY_OF_WEEK_IN_MONTH表示当前月中的第几个星期;⑷小时由从 0 至 23 的整数表示。因此,从午夜到
1、Date类:封装了当前日期和时间,构造方法有:⑴Date()-默认;⑵Date(long millisec)。第一个构造方法使用当前的日期和时间初始化一个对象,第二个构造方法的参数等于从Calendar
类实现日期和时间字段之间转换,使用DateFormat
类来格式化和分析日期字符串,Date
中的相应方法已废弃,Date仅用于用指定的格式输出用Date表示的日期对象和将特定格式的日期字符串转换成一个Date对象。
可以利用各数据类型提供的parse()或parseInt()等方法来检验输入数据类型的有效性。如:通过捕获对出生日期的异常来检验输入日期类型的有效性Date d = sdf.parse(birth);
2、Calendar类(abstract类):主要用于完成日期字段之间相互操作的功能。具体实现Calendar类的直接子类GregorianCalendar
提供了世界上大多数国家使用的标准日历系统,并提供了Calendar类中所有的抽象方法的实现,同时它还提供了一些附加的方法,如:boolean isLeapYear(int year)方法——判断某年是否是一个闰年。
瞬间可用毫秒值来表示,它是距历元(即格林威治标准时间
Calendar是抽象类,不能用直接产生对象,但可以通过Calendar提供的getInstance()静态方法获得默认地域和时区的一个Calendar当前日期和时间的对象。如:Calendar calendarNow = Calendar.getInstance();。
Calendar有两种解释日历字段的模式:lenient(宽松) 和 non-lenient(非宽松)。⑴当 Calendar处于lenient模式时,它可接受比它所生成的日历字段范围更大范围内的值。例如,lenient 模式下的GregorianCalendar将MONTH == JANUARY、DAY_OF_MONTH == 32解释为February 1。⑵当Calendar处于non-lenient模式时,如果其日历字段中存在任何不一致性,它都会抛出一个异常。
Java中日历字段的默认组合(将使用由最近设置的单个字段所确定的最近组合):⑴ YEAR + MONTH + DAY_OF_MONTH;⑵YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK;⑶YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK;⑷YEAR + DAY_OF_YEAR;⑸YEAR + DAY_OF_WEEK + WEEK_OF_YEAR。对于时间字段:⑴HOUR_OF_DAY;⑵AM_PM + HOUR。
补充:DateFormat类(java.text包,extends Format,abstract类):是日期/时间格式化的抽象类,其直接具体子类SimpleDateFormat。在DateFormat类中使用静态 getDateInstance()方法来获得该国家的标准日期格式;静态getTimeInstance()方法可获得该国家的时间格式;静态getDateTimeInstance()方法可获得日期和时间格式。产生格式化日期对象后,调用其format()方法格式化输出时仅对Date或日期型对象有效,Calendar无效(参考instance目录下myDate)。
日期和时间格式由日期和时间模式 字符串指定。在日期和时间模式字符串中,未加引号的字母 'A' 到 'Z' 和 'a' 到 'z' 被解释为模式字母,用来表示日期或时间字符串元素。文本可以使用一对单引号 (‘ ‘) 引起来,以免进行解释。“''” 表示单引号。所有其他字符均不解释,只是在格式化时将它们简单复制到输出字符串,或者在分析时与输入字符串进行匹配。
3、TimeZone类(时区,abstract类):用于处理与GMT=Greenwich Mean Time(即CUT=Coordinated Universal Time)之间的时差,同时也计算夏令时。
通常,使用getDefault()方法来获得TimeZone对象,使用getID()获取TimeZone对象的名字,使用 getAvailableIDs() 方法来对所有受支持的时区 ID 进行迭代。也可以自定义时区ID,其语法是:⑴ GMT Sign Hours:Minutes;⑵GMT Sign Hours Minutes;⑶GMT Sign Hours。如:"GMT+10"和"GMT+0010" 分别意味着比GMT提前10小时和10分钟。TimeZone.getTimeZone("GMT-8").getID()返回"GMT-08:00"。
三字母时区 ID为了与 JDK 1.1.x 兼容,一些三字母时区 ID(比如 "PST"、"CTT"、"AST")也受支持。但是,它们的使用被废弃,这是因为相同的缩写经常用于多个时区(例如,"CST" 可以是美国的 "Central Standard Time" 和 "China Standard Time"),但是 Java 平台只可以识别其中一种。
SimpleTimeZone类是TimeZone的具体子类,它实现了TimeZone类的抽象方法并且保持一个相对GMT的偏移量,同时,可以设定夏令时安排的开始和结束规则。由于它仅为每一项保持单个值,因此它无法处理相对 GMT 的偏移量以及夏令时安排中的历史更改,除了setStartYear()方法可以指定开始实施夏令时安排的年份之外。
4、Locale类(地域,final类):Locale 对象表示了特定的地理、政治和文化地区,对语言环境敏感的需要,使用 Locale 为用户量身定制信息。Locale 类提供了一些方便的常量,可用这些常量为常用的语言环境创建 Locale 对象。例如,下面的内容为美国创建了一个 Locale 对象:Locale.US。
创建完Locale后,就可以查询有关其自身的信息。使用getCountry()可获取ISO国家代码,使用getLanguage()则获取ISO语言代码。可用使用getDisplayCountry()来获取适合向用户显示的国家名。同样,可用使用 getDisplayLanguage 来获取适合向用户显示的语言名。
Locale 是一种标识所要获取的对象种类 (NumberFormat) 的机制。但 locale 只是一种标识对象的机制,不是对象本身的容器。
5、Random类(伪随机数生成器):因为Random是均匀分布的序列,所以称之为伪随机数(pseudoRandom)。构造方法:⑴Random();——默认构造方法中使用当前时间为种子值。⑵Random(long seed)。Random方法可以提取7种基本数据类型的随机数。如int nextInt(int n)——返回一个介于0和n之间的整型(int)随机数,float nextFloat()/double nextDouble()——返回一个平均分布的0.0~1.0之间的float型/double型数据。
6、Currency类(货币,final类):封装了关于贷币的信息。该类的设计目标是:对于任何指定货币,从不会有多个Currency
实例。因此,没有公共的构造方法。可以使用 getInstance
方法获得 Currency
实例。
7、Formatter类(格式器,final类):提供格式转换,允许以任意格式显示数值、字符串、时间和数据。在使用Formatter来格式化输出之前,必须创建一个Formatter对象,创建之后,最常用的是format()方法:Formatter format(String fmtString,Object,…args),要注意:⑴此方法每种格式指定符(%开始)与其用逗号分隔符分开的相应参数类型匹配,否则会抛出一个IllegalFormatException异常;⑵此方法返回的Formatter对象被传递给println()时,它的toString()方法将被自动调用。
8、Scanner类(扫描器,final类):可用来读取来自磁盘文件、键盘、字符串或其他任何资源的各种类型的数值、字符串和其他类型的数据。Scanner默认读取的数据分隔定界符是空白符,也可以由useDelimiter()方法来设置(* 定界符表示零或多个空格)。
下面一行代码创建了一个读取标准输入(默认是键盘System.in,它是一个InputStream类型的对象):Scanner conin=new Scanner(System.in);
下面二行代码创建一个读取文件“Test.txt”内容的Scanner:FileReader fin=new FileReader(“Test.txt”); Scanner src=new Scanner(fin);
9、StringTokenizer类(字符串标记符类): 将字符串按标记分解,默认的分隔符集合包括空格、制表符、换行符和回车符。StringTokenizer 方法不区分标识符、数和带引号的字符串,它们也不识别并跳过注释。
StringTokenizer 是出于兼容性的原因而被保留的遗留类(虽然在新代码中并不鼓励使用它)。建议所有寻求此功能的人使用 String 的 split 方法或 java.util.regex 包。
10、BitSet类:创建一个特殊类型的数组,数组里面存储的是位值。此类实现了一个按需增长的位向量。位 set 的每个组件都有一个 boolean 值。用非负的整数将 BitSet 的位编入索引。可以对每个编入索引的位进行测试、设置或者清除。通过逻辑与、逻辑或和逻辑异或操作,可以使用一个 BitSet 修改另一个 BitSet 的内容。
默认情况下,set 中所有位的初始值都是 false。
除非另行说明,否则将 null 参数传递给 BitSet 中的任何方法都将导致 NullPointerException。 在没有外部同步的情况下,多个线程操作一个 BitSet 是不安全的。
11、Observable类(可观察的):用于创建可被程序的其他部分观察的子类(被观察对象)。正在被观察的对象必须遵循两条基本规则:⑴如果被观察者已经改变了,必须调用setChanged()方法;⑵必须调用notifyObservers()通知观察者方法,此方法将导致观察者对象(用Observer接口实现)的update()方法被调用。
12、Timer类(计时线程安排者)、TimerTask类(计时线程任务,abstract类):一种线程设施。Timer用于安排以后在后台线程中执行的任务,可安排任务执行一次,或者定期重复执行。为了安排一项任务,首先需要创建一个TimerTask类的对象,实现TimerTask的run()方法,然后使用Timer的一个实例安排它的执行。
如果新建了一个非守护类型的任务(守护线程:只要程序的其他部分仍在执行,它就一直保持执行状态的线程),那么应该在程序结束时调用cancel()方法来结束这个任务,如果不这样做,程序可能会“挂起”一段时间。
13、Java.util子包:⑴java.util.concurrent、java.util.concurrent.atomic、java.util.concurrent.locks用来支持并发安全程序;⑵java.util.jar提供读/写java归档文件的能力;⑶java.util.logging提供对和序活动日志的支持;⑷java.util.prefs提供对用户首选项的支持,典型情况下它用来支持程序配置;⑸java.util.regex提供对规则表达式的支持;⑹java.util.zip提供读/写现行ZIP和GZIP格式文件的能力。
四、java.io包
Java程序通过定义在java.io包中的类层次实现流(stream),数据连续不断进入内存称为输入流,数据流出内存为输出流,流是以先进先出的方式发送和接收数据的通道。Java定义了两种类型的流:字节流和字符流。⑴字节流(8位)。顶层是两个抽象类:InputStream(输入流)和OutputStream(输出流)。实现类(其子类): ㈠FileInputStream和FileOutputStream,这两实现类的子类:BufferedInputStream和BufferedOutputStream。用于写入诸如图像数据之类的原始字节的流。要读取字符流,使用 FileReader
。㈡DataInputStream和DataOutputStream用于读写二进制文件。⑵字符流(16位,Unicode)。顶层是两个抽象类:Reader(读取输入流)和Writer(写入输出流)。⑶System.in是InputStream类型的一个对象,System.out和System.err是PrintStream类型的对象,这些都是字节流,但它们常用于读写控制台的字符。⑷面向字符的读取控制台输入(国际化):㈠BufferedReader br=new BufferedReader(new InputStreamReader(System.in));通过System.in控制台创建一个与键盘相连的缓冲读取输入字符流。㈡通过使用BufferedReader类的read()方法一次读取一个字符(返回整数值,遇到流结束时将返回-1)或readLine()方法一次读取一个字符串。⑸面向字符的向控制台写输出(国际化):㈠PrintWriter pw=new PrintWriter(System.out,true);通过System.out控制台创建一个PrintWriter写输出字符流。这里的true表示每次调用println()方法时自动清空输出流。㈡通过使用PrintWriter类的print()、printf()或println()方法写入输出字符。
读写文本文件可以运用FileInputStream、FileOutputStream、FileReader、FileWriter、BufferedInputStream、BufferedOutputStream类实现。读写声像等原始字节流可以使用FileInputStream、FileOutputStream、BufferedInputStream、BufferedOutputStream类实现。读写二进制文件运用DataInputStream和DataOutputStream。
java.io.File类只能操作文件的属性,而不能操作文件内的数据。其即可以表示文件,也可以表示目录。其常用方法有:mkdir()创建目录、creatNewFile()创建文件、listFiles()返回目录下所有子目录及文件(如果该目录下含隐藏文件此方法不能很好地工作)、getName()获得文件名或目录名、isDirectory()是否是目录、isFile()是否是文件、exists()文件或目录是否存在。
例:/**
* 移动文件
* @param userFullPathFile 移动前原文件(绝对路径,全名)
* @param delFullPathFile 移动后文件(绝对路径,全名)
* @throws IOException
*/
private void moveFile(String userFullPathFile,String delFullPathFile) throws IOException{
File fullPathFile=new File(delFullPathFile);
//返回此抽象路径名的父路径名的路径名字符串。如果是含文件名的路径,则返回纯路径
String strPath=fullPathFile.getParent();
File filePath=new File(strPath+"/");
if(!filePath.exists()){
//创建此抽象路径名指定的目录,包括创建必需但不存在的父目录。
filePath.mkdirs();
}
//Java中没有直接对文件进行移动的方法,只有通过文件流的方式实现
FileInputStream fis=new FileInputStream(userFullPathFile);
BufferedInputStream bis=new BufferedInputStream(fis);
FileOutputStream fos=new FileOutputStream(delFullPathFile);
BufferedOutputStream out=new BufferedOutputStream(fos);
int temp;
while((temp=bis.read())!=-1){
out.write(temp);
}
bis.close();
fis.close();
out.close();
fos.close();
//经测试,删除文件必须放在流关闭后才有效
File userFile=new File(userFullPathFile);
userFile.delete();
}
四、JDBC(Java DataBase Connectivity)基础
作为应用程序和数据库通信的接口,目前常用的API=Application Programming Interface技术是:⑴JDBC=Java DateBase Connectivity;⑵微软提出的ODBC=Open DataBase Connectivity,Odbc不具备跨平台,只能在微软的操作系统上使用。
JDBC API定义了一组用于与数据库进行通信的接口和类,它们包括在java.sql包中。
Jdbc的驱动类型分:⑴JDBC-ODBC桥驱动;⑵本地纯Java驱动程序;⑶网络纯Java驱动程序;⑷纯Java驱动程序。
1、JDBC访问数据库的步骤:
Jdbc-Ojbc桥方式连接数据库步骤:⑴为数据库创建数据源(见下);⑵加载驱动程序(实质:驱动程序装入内存):Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”);桥驱动程序类名sun.jdbc.odbc.JdbcOdbcDriver由sun公司提供,返回此全名的Class对象将会使驱动程序载入内存中;⑶使用DriverManager创建连接(连接至URL中数据源的驱动程序):Connection conn=DriverManager.getConnection(“jdbc:odbc:mytest”,”sa”,“***”);其中:㈠三个参数分别表示:连接字符串,用户名,密码(用户名和密码为可选);㈡Jdbc-Ojbc桥连接的字符串url是:jdbc:odbc:mytest(格式为jdbc:subprotocol:subname ,mytest是所使用的odbc数据源名称,不区分大小写);㈢不同的数据库,连接字符串不一样,每一种字符串都是固定的格式;㈣由于是通过jdbc连接odbc的,所以在步骤⑴中配置了odbc数据源;⑷通过Connection 对象创建Statement接口实例:Statement stat=conn. createStatement();或通过Connection对象的prepareStatement()方法创建用于预编译的PreparedStatement对象(执行同一操作时可提高效率)。⑸通过statement对象执行executeQuery()等方法,得到ResultSet对象(更新数据库的executeUpdate()方法返回受该语句影响的行数int。ResultSet是一张二维表,列索引从1开始。默认情况下,游标指向第一条记录的上面。文件名和列名均不区分大小写):String sql=”select * from authors”;ResultSet rs=stat. executeQuery(sql)。⑹使用ResultSet接口的next()方法将当前指针指向下一条记录,使用get<type>()方法获取<type>类型的字段,使用close()方法从前到后分别关闭ResultSet对象、Statement对象、Connection对象。⑺为了确保正常退出,应设置捕获SQLException异常和finally语句块。
关于ResultSet结果集要注意:⑴每次执行SQL语句时,都会用新的结果。⑵ResultSet使用完后,应当关闭。当相关的Statement关闭时,ResultSet对象会自动关闭。⑶ResultSet接口中的get<Type>()方法可以直接访问结果集中的列,有两种形式:第一种接收列名作为其参数,另一种接收列索引号作为其参数。
为数据库创建一个ODBC数据源步骤:设置→控制面板→管理工具→数据源(ODBC)→系统DSN→添加(D)…→“创建新数据源”对话框选“SQL Server”,单击“完成”→在“创建到SQL Server的新数据源”标题中,输入:数据源名称、描述、服务器(本机选local或.),然后“下一步(N)”→在Microsoft ODBC SQL Server DSN配置中选择验证(如:使用用户输入登录ID和密码的SQL Server验证,登录名为sa,密码为空),然后“下一步”→从“更改默认的数据库为(D):”的下拉选项中选择所要连接的数据库名,然后“下一步(N)”→完成→[测试数据源,测试成功说明配置OK]→确定。数据源的名称应出现在“系统DNS”选项卡中(也可以参见录像)。
2、使用本地纯Java驱动程序直接连接数据库:每个数据库厂商发布它的数据库产品的时候,也发布了jdbc纯驱动程序,用于java程序直连数据库,可到数据库厂商的官方网站下载。Java纯驱动与jdbc-odbc连接方式不同点:⑴microsoft SQLServer数据库需要打上sp4补丁。⑵microsoft Sqlserver 的jdbc纯驱动是三个jar包(msbase.jar、mssqlserver.jar和msutil.jar),使用的时候,需要加入到classpath环境变量中(见下或参见视屏)。⑶驱动程序名改变:Class.forName(“com.microsoft.jdbc.sqlserver.SQLServerDriver”);⑷连接字符串改变:Connection con=DriverManager.getConnection(“jdbc:microsoft:sqlserver://localhost:1433;databaseName=mydatabase;”,“sa”,“ ”);其中:㈠SQLServer的路径url= jdbc:Microsoft:sqlserver://。㈡服务器名或IP地址:localhost。㈢SQLSever在windows系统中的端口号:1433。㈣数据库名:mydatabase。㈤用户名:sa。㈥密码:空。
将SQLServer三个驱动程序jar包加载到工程的classpath环境变量步骤:在JBuilder工程窗格中,右击工程名节点,选中properties...→选Required Libraries选项卡→Add...→在标题Add to project classpath的Libraries选项卡中点New...按纽→在标题New Library Wizard中,输入库名Name(如:db),Location选中User Home,Library paths框点击Add→找到Lib目录下的3个驱动程序.jar包选中后,按OK键,此时Library paths框中将显示三个jar包的完整目录名→OK返回后,在Libraries选项卡框的User Home目录中和Required Libraries选项卡框中的将显示刚定义的库名(db)→OK返回。
3、数据库链接的封装(本例以Jdbc-Odbc桥驱动为例,纯驱动只需修改DRIVERNAME和CONNECTIONSTRING所赋的值即可):
Public class DBManager{ //将每次对数据库的操作封装成一个类,这个类的名字可以随便启。
private static final String DRIVERNAME=” sun.jdbc.odbc.JdbcOdbcDriver”;//用来加载驱动程序名称
private static final String URL= "jdbc:odbc:mytest";//用来保存链接字符串
private static final String UID=”sa”; //用来保存数据库用户名
private static final String PWD=””;//用来保存数据库密码
private Connection conn=null; //数据库链接
Public DBManager(){ //构造方法,在该类被实例化的时候就去加载驱动,并创建链接对象。
Class.forName(DRIVERNAME );
conn=DriverManager.getConnection(URL, UID, PWD);
}
public void executeUpdate(String strSql) throws SQLException {
Statement stat=conn.createStatement();
stat.executeUpdate(strSql);
} //这个方法只需要传递一个sql语句,它会自动执行。该方法用于执行添加、修改和删除操作。
public ResultSet executeQuery(String strSql) throws SQLException {
Statement stat=conn.createStatement();
return stat.executeQuery(strSql);
} //这个方法需要传递一个查询语句,返回结果集,用于查询数据库。
public void closeConnection() throws SQLException {
if(conn!=null){
if(!conn.isClosed()) { conn.close(); }
}
} //关闭数据库链接,释放Connection对象,其余Statement和ResultSet对象均自动关闭。
4、Connection接口:负责连接数据库,设置数据库服务器,用户名,密码。
5、Driver接口:每个驱动程序必须实现的接口,一般数据库厂商提供实现类,程序员只需加载即可。DriverManager 会试着加载尽可能多的它可以找到的驱动程序,然后,对于任何给定连接请求,它会让每个驱动程序依次试着连接到目标URL。在加载某一Driver类时,它应该创建自己的实例并向 DriverManager 注册该实例。如用户可以通过调用以下程序方法加载和注册一个驱动程序:Class.forName("foo.bah.Driver")。
6、Statement接口:用于执行静态 SQL 语句并将结果返回到ResultSet对象中。在默认情况下,同一时间每个 Statement
对象只能打开一个 ResultSet
对象。如果读取一个 ResultSet
对象与读取另一个交叉,则这两个对象必须是由不同的 Statement
对象生成的。⑴该接口的void addBatch(String sql)方法:将给定的 SQL 命令添加到此 Statement
对象的当前命令列表中。⑵void cancel()方法:如果 DBMS 和驱动程序都支持中止 SQL 语句,则取消此 Statement
对象。⑶void close()方法:释放Statement
对象的数据库和JDBC资源。⑷void clearBatch()方法:清空此 Statement
对象的当前 SQL 命令列表。⑸boolean execute(String sql)方法:执行给定的 SQL 语句,如果第一个结果为 ResultSet
对象,则返回 true
;如果其为更新计数或者不存在任何结果,则返回 false
。⑹ResultSet executeQuery(String sql) throws SQLException方法:
执行给定的 SQL 语句,该语句返回单个 ResultSet
对象。⑺int executeUpdate(String sql) throws SQLException方法:执行给定 SQL 语句,该语句可能为 INSERT
、UPDATE
或 DELETE
语句,或者不返回任何内容的 SQL 语句(如 SQL DDL 语句)。返回的int为INSERT
、UPDATE
或 DELETE
语句的行计数;
7、PreparedStatement接口:该接口用于执行预编译的SQL语句。具有速度快和安全的特性。如String sql=”insert into table1 value(?,?)”; PreparedStatement pst=con.prepareStatement(sql);这里的?号只能适用于值,不能应用于关键字、数据库名和字段名。?号的顺序从1开始,如sql.setInt(1,101);sql.setString(2,”张三”)。
8、ResultSet接口:表示数据库结果集的数据表,通常通过执行查询数据库的语句生成,是一张二维表。返回的结果集默认情况下,游标指向第一条记录的上面。调用next() 方法时,游标将下移一条记录,如果超出结果集末尾,该方法将返回布尔值false。afterLast()移动到最后一条记录的后面;beforeFirst()移动到第一条记录的前面;first()移动到第一条记录处;last()移动到最后条记录处;previous()移到前一条记录处。
9、DatabaseMetaData接口:关于数据库的整体综合信息。
10、ResultSetMetaData接口:可用于获取关于 ResultSet
对象中列的类型和属性信息的对象。
11、CallableStatement接口:此接口包含用于执行SQL存储过程的方法。
12、DriverManager类:用于加载和卸载各种驱动程序并建立与数据库的连接。当我们给jdbc加载驱动程序以后,DriverManager就可以来管理驱动程序了。通过该类的static Connection getConnection(String URL,String user,String password,) throws SQLException等静态方法可以创建Connection对象(因为Connection是接口)。URL
是jdbc:
subprotocol:
subname 形式的数据库。
13、Date类:包含将SQL日期格式转换成Java日期格式的各种方法。
14、TimeStamp类:表示一个时间戳,能精确到纳秒。
15、SQL注入语句:1' or '1'='1。此语句用于用户名和密码时可绕过合法用户检查。解决办法:条件判断是否含有单引号“'”。如:⑴if(user.contains("'") || pwd.contains("'"));⑵if (name.indexOf("'") != -1 || pwd.indexOf("'") != -1)
五、Swing和AWT:
Java的图形用户界面的最基本组成部分是组件(也叫控件),组件是一个可以以图形化的方式显示在屏幕上并能与用户进行交互的对象,如一个按钮,一个标签。
1、java.awt(Abstract Window Toolkit抽象窗口工具包):Component抽象类是所有java GUI组件的共同父类,它规定了所有GUI组件的基本特性,该类中定义的方法实现了作为一个GUI组件所应该具备的基本功能。重量级的Awt工具包中有些组件不是纯java编写,而且依赖于具体的平台;轻量级的Swing工具包只有JFrame,JDialog,JWindow,JApplet不是纯java所写,所以可移植性强。
2、Swing包体系结构:
包括javax.swing包及其子包是新的GUI组件库。由于Swing 组件是基于AWT构建,包含了AWT可视化组件的替代组件,也包含复杂组件——树和表,因此,Swing独立于AWT又继承AWT。AWT不是纯Java组件,Swing是纯Java组件,即Swing组件包含可改变的外观,使所有的应用程序在不同的平台上运行时具有本机外观和相同的行为。Swing类体系结构主要根是javax.swing.JComponent类,除了AbstractButton类以外均以J开头,JComponent继承于java.awt.Container容器类,Container类继承于java.awt.Component类。
Swing中的容器有两类(可以添加别的Swing组件的区域叫容器):⑴顶级容器(也叫主窗口:JFrame、JApplet、JDialog);⑵中间容器(也叫内容面板:JPanel、JScrollPane、JTabbedPane、JToolBar,默认JPanel)。
Javax.swing包常见容器:⑴JFram:㈠扩展java.awt.Frame类,㈡用于在Swing程序中创建窗口,㈢包含边框、标题和用于关闭和图标化窗口的按钮。⑷JFrame 包含一个 JRootPane 作为其惟一的子容器,根据规定,根窗格所提供的内容窗格应该包含 JFrame 所显示的所有非菜单组件。⑵JPanel:㈠用于将较小的轻量级组件组合在一起,㈡与内容窗格相似,面板在默认情况下不透明。⑶JScrollPane:管理视区、滚动条及可选的行和列的标题视区。⑷同一组单选按纽要放在ButtonGroup容器中。
Container(容器)对象可用于将组件组合在一起。
布局管理器:是一组实现java.awt.LayoutManager接口的类,用于自动管理Swing的可视化组件在容器中的具体的位置和大小。Java中基本的布局管理器分为:⑴BorderLayout(边界布局管理器),是窗口、框架、和对话框类型的对象的默认布局管理器。BorderLayout把容器划分成东西南北中五个方位,也就是说容器中最多存放5个组建。如果我们想在窗口上放置更多的组件,可以将若干组件添加到一个中间容器JPanel上,然后将这个JPanel作为一个组件放置到窗口上。如果JFrame为borderLayout布局时,放置其上的容器一般需要居中设置(将constraints设置为center),其上容器才能布满JFrame并能得到很好的显示。⑵FlowLayout(流布局管理器),中间容器(JPanel)默认的布局管理器,把组件依次放置到容器中,当每行存放不下的时候,就换行。⑶GridLayout(网格布局管理器),将容器平均划分成指定行和列的等宽等高网格。⑷Null(空布局),可以使用绝对定位。
容器中的组件根据特定布局排列。
开发一个图形窗口只需要创建JFrame对象或继承JFrame类。
常用的几个方法:
JFrame jf=new JFrame("BorderLayoutFrame");//创建标题为 BorderLayoutFrame的顶级容器(窗口)。 |
Container contendPanel=this.getContentPane();//创建一个Container类型的容器,this代表JFrame对象。 |
contendPanel.setLayout(new GridLayout(5,4));//顶级容器和中间容器都用这个方法设置布局管理器 |
contendPanel.add(new JButton("北按钮"), BorderLayout.NORTH ); //每个容器都有add方法以添加组件,组件可以是按钮,文本框等等,也可以是中间容器。 |
jPanel1.setBorder(BorderFactory.createTitledBorder("登陆")); //给容器或组件加边框 |
this.setTitle("我的第一个窗口");//设置窗口的标题, this代表JFrame对象。 |
this.setBounds(100,200,400,300);//设置窗口出现的位置、大小,参数代表窗口左上角的x坐标,y坐标,窗体宽度,高度。 this代表JFrame对象。 |
this.setSize(500,400);this.setLocationRelativeTo(Component c)设置此窗口相对于指定组件的位置(如父窗体super.getOwner()的中央)。如果此组件当前未显示,或者 |
this.setDefaultCloseOperation(EXIT_ON_CLOSE);//设置窗口点击关闭按钮之后退出应用程序。默认情况下,该值被设置为 HIDE_ON_CLOSE。 |
Image img=Toolkit.getDefaultToolkit().createImage("d:/aa.jpg"); this.setIconImage(img);//设置窗口左上角图标 |
this.setVisible(true);//设置窗口可见,this代表JFrame对象。 |
mnuItemExit.setIcon(new javax.swing.ImageIcon("img/Quit.gif"));//给菜单加上图标。 |
dlgMessage.showMessageDialog(this,"非法用户名或密码 ","系统提示",JOptionPane.ERROR_MESSAGE);//显示标题为“系统提示”,提示信息为“非法用户名或密码”的错误消息。(更多见下面“5、对话框”) |
this.setUndecorated(true);//禁用dialog或frame的装饰(无最大化、最小化及关闭框)。 |
frmObject.setSize( Toolkit.getDefaultToolkit().getScreenSize());//使窗体占满整个屏幕 |
String user=this.txtUser.getText();//获得name=”txtUser”文本框的字符串内容。 |
String pwd=new String(this.txtPassword.getPassword());//获得name=”txtPassword”密码框的内容。出于安全原因,JPasswordField的getPassword()方法返回char[],所以用String的构造方法来获取字符串。 |
txtNotepad.setFont(this.getFont().deriveFont(15));//将文本字体改为15dt。 |
public void txtName_keyPressed(KeyEvent e){char key=e.getkeychar();if(key= =’\n’)btnOk_actionPerformed(null)}此方法获取文本框里显示的键盘输入的字符(事件源为e),按回车键以后将调用Ok按纽处理事件。 |
|
组件编码规范:⑴标签JLabel,前缀lbl。⑵文本:JTextField (单行),前缀txt;JTextArea (多行),前缀txa。⑶按钮JButton,前缀btn。⑷选框:JRadioButton(单选框),前缀rad; JCheckBox(复选框), 前缀chk; JComboBox(下拉框),前缀cbo。⑸容器:JPanel(普通中间面板容器),前缀pnl;JScorllPane(带滚动条的中间容器),前缀scp。⑹菜单: JMenuBar(菜单容器),前缀mnuBar;Jmenu(顶级菜单),前缀mnu;JmenuItem(菜单项),前缀mnuItem。⑺对话框:JOptionPane(模式)和JDialog(非模式),前缀:dlg。⑻窗体定义:JFrame(窗口容器类),前缀Frm。⑼JTable:前缀tab。TableModel:功能+Model,如StudentModel。
3、事件:我们把程序从操作系统接收到的作为用户操作结果的信号称为事件。发生事件的地方,也就是发生事件的GUI组件,成为事件源。监听器通常是一个监听和处理事件的类对象,该对象实现一个或一组相应的监听器,以便应用程序能处理事件。监听器对象还可以是另一个实现了一个或多个监听器接口的Swing组件。
实现GUI组件上的<EventType>Event事件的编写过程(例:按下jButton1按钮):⑴写一个类去实现监听器接口。如public class MyListener implements ActionListener { public void actionPerformed(ActionEvent e) {System.out.println("按钮被点击了"); }};也可以在该实现类中重写的方法不写任何代码,而只调用事件处理器,在事件处理器(方法)中专门写事件处程程序。⑵实例化一个监听器对象:MyListener mylistener=new MyListener();⑶将事件源注册到监听器对象上:jButton1.addActionListener(mylistener);⑷在MyListener中实现事件处理:如⑴中System.out.println("按钮被点击了");。这里<EventType>可以是各种不同的事件类型,如Window、Mouse、Key、Action。
每个事件源都被映射至一个或多个事件监听器,发生事件时需要调用这些事件监听器。而触发这一事件的每一种情况,都对应着事件监听器对象中的一个不同的方法。某种事件监听器对象中的每个方法名称必须是固定的,事件源才能依据事件的具体发生情况调用不同的方法。
监听器通过实现 java.awt.event 包中定义的一个或多个接口来创建。
常用事件类:⑴MouseEvent类对应鼠标事件,包括㈠鼠标事件(MouseEvent):⑴按下鼠标按键Mouse_Pressed,⑵释放鼠标按键Released,⑶单击鼠标按键(按下并释放)Clicked,⑷鼠标光标进入组件几何图形的未遮掩部分Entered,⑸鼠标光标离开组件几何图形的未遮掩部分Exited;㈡鼠标移动事件(MouseMotionEvent):⑴移动鼠标Moved,⑵拖动鼠标Dragged。⑵WindowEvent类对应窗口事件,包括⑴打开Window_Opened,⑵关闭Closed,⑶正在关闭Closing,⑷激活Activated,⑸停用(不再是活动Window时)Deactivated,⑹图标化(最小化)Iconified,⑺取消图标化(从最小化变为正常状态时)Deiconified,⑻获得焦点Gained_Focus,⑼失去焦点Lost_Focus,⑽窗口状态改变State_Changed。⑶ActionEvent对应一个动作事件,它不代表一个具体的动作,而是一种语义,如按钮或者菜单被鼠标单击。可以这样来理解ActionEvent事件,如果用户的一个动作导致了某个组件本身最基本的作用发生了,这就是ActionEvent事件。
事件 |
事件监听器接口 |
适配器类 |
事件监听器接口定义的方法 |
ActionEvent |
ActionListener |
ActionAdapter |
actionPerformed发生操作时调用 |
AdjustmentEvent |
AdjustmentListener |
AdjustmentAdapter |
adjustmentValueChanged可调整值更改时 |
ComponentEvent |
ComponentListener |
ComponentAdapter |
componentResized组件大小更改时调用 componentMoved组件位置更改时调用 componentShown组件变得可见时调用 componentHidden组件变得不可见时 |
|
ContainerListener |
ContainerAdapter |
componentAdded将组件添加至容器时 componentRemoved从容器中移除组件时 |
FocusEvent |
FocusListener |
FocusAdapter |
focusLost组件失去键盘焦点时调用 focusGained组件获得键盘焦点时调用 |
ItemEvent |
ItemListener |
|
itemStateChanged选定或取消选定某项时 |
KeyEvent |
KeyListener |
KeyAdapter |
keyPressed按下某个键时调用 keyReleased释放某个键时调用 keyTyped键入某个键时调用 |
MouseEvent |
MouseListener, |
MouseAdapter, |
mouseClicked单击(按下并释放)组件时 mouseEntered鼠标进入到组件上时凋用 mouseExited鼠标离开组件时调用 mousePressed鼠标按键在组件上按下时 mouseReleased鼠标按钮在组件上释放时 |
MouseMotionListener |
MouseMotionAdapter |
mouseDragged在组件上按下并拖动时 mouseMoved鼠标光标移动到组件上但无按键按下时 | |
TextEvent |
TextListener |
|
textChanged |
WindowEvent |
WindowListener |
WindowAdapter |
WindowListener方法由下框定义 |
⑴windowActivated将Window设置为活动Window时;⑵windowClosed因对窗口调用dispose而将其关闭时;⑶windowClosing用户试图从窗口的系统菜单中关闭窗口时;⑷windowDeactivated当Window不再是活动 Window时;⑸windowDeiconified窗口从最小化状态变为正常状态时;⑹windowIconified窗口从正常状态变为最小化状态时;⑺windowOpened窗口首次变为可见时。 |
4、菜单:Swing菜单包含JMenuBar(菜单容器)、JMenu(顶层菜单)和JMenuItem(菜单项),均继承JComponent。JMenuBar组件可添加至容器,但它只在JFrame、JWindow或JInternalFrame作为其根窗格时添加。JMenu可包括标准菜单项,如JMenuItem、JCheckBoxMenuItem(实现菜单栏中的复选框)、JRadioButtonMenuItem(实现菜单栏中的单选按钮)、JSeparator。另外,与JMenu并列的弹出式菜单JPopupMenu可显示在屏幕的任何地方,它通常是由单击鼠标右键触发的,并依赖于上下文。
JBuilder图形化创建菜单时注意:在Design设计选项卡下,UI设计视图添加JMenuBar容器,Menu设计视图添加JMenu、JMenuItem等菜单。窗口布局为BorderLayout。
JBuilder创建菜单栏的快捷键方法:⑴顶层菜单(如:文件(F)的快捷键alt+F):在顶层菜单“文件”后中手工键入(F),然后在查看器中将mnemonic的0改为F。⑵菜单项(如:新建 ctrl-N):选中“新建”菜单项→在查看器中选accelerator参数后的...,打开accelerator框→在select event type选key pressed,在Type any keystroke combination文本框中同时按下ctrl和n→按ok返回。
在JMenuItem中除了可以添加字符串外,还可添加图标,JMenuItem通过重写actionPerformed()方法处理ActionEvent事件。
工具按纽(快捷键)创建,在UI设计视图添加JToolBar容器,在此容器中添加button按纽,将constraints设为North。
状态栏创建,在UI设计视图添加JPanel容器,在此容器中添加JLabel组件,将constraints设为South。将布局管理器设为GridLayout。
要使多行文本框具有输满内容时自动加载滚动条,须把文本框放置在JScorllPane容器内,水平自动换行将文本框JTextArea的lineWrap属性改为true。
5、对话框:Java中的对话框是JFrame和JPanel等容器的子容器。每个对话框都依赖于父容器,如果父容器被消毁,则对话框也会被消毁;父容器变为小图标,依赖于它的对话框也会消失。JOptionPane类默认提供模式对话框,以提示用户输入信息或向用户通知消息,当显示模式对话框时,将阻止向所有其他窗口进行输入。JDialog类默认创建非模式对话框,也可以指定model为true来创建模式对话框。
JOptionPane类的静态showXxxDialog()方法是显示模式对话框常用的方法。主要有:⑴showConfirmDialog()方法,用于询问一个确认问题,如 yes/no/cancel。⑵showInputDialog()方法,提示要求某些输入。⑶showMessageDialog()方法,告知用户某事已发生并等待用户单击OK。如public static void showMessageDialog(Component parentComponent,Object message,String title,int messageType,Icon icon)⑷showOptionDialog()方法,显示一条消息并得到用户在一组选项中的选择。如public static int showOptionDialog(Component parentComponent,Object message,String title,int optionType,int messageType,Icon icon,Object[] options,Object.initialValue)。
这里的参数遵守一致的模式:⑴parentComponent指父容器。⑵Object类型的message:对话框中的描述消息。⑶title:对话框的标题。⑷optionType定义在对话框的底部显示的选项按钮的集合:DEFAULT_OPTION、YES_NO_OPTION、YES_NO_CANCEL_OPTION、OK_CANCEL_OPTION,用户也可以提供想使用的任何按钮。⑸messageType消息类型。对话框的外观可能因此值而异,并且往往提供默认图标。可能的值为:ERROR_MESSAGE、INFORMATION_MESSAGE、WARNING_MESSAGE、QUESTION_MESSAGE、PLAIN_MESSAGE。⑹Icon对话框中的装饰性图标被包装在JLabel中显示,图标的默认值由messageType参数确定。⑺initialValue默认选择(输入值)。⑻当其中一个 showXxxDialog 方法返回整数时,可能的值为:YES_OPTION、NO_OPTION、CANCEL_OPTION、OK_OPTION、CLOSED_OPTION。
例如:dlgMessage.showMessageDialog(this,"非法用户名或密码 ","系统提示",JOptionPane.ERROR_MESSAGE);//显示标题为“系统提示”,提示信息为“非法用户名或密码”的错误消息( dlgMessage可为 JOptionPane)。
对文件操作的对话框在JFileChooser类中定义,选择组件面板的Swing Containers页中的JFileChooser组件,单击结构窗口组件树中的UI文件夹,名为JFileChooser1的组件即被添加至树的UI部分。将JFileChooser1更名为fcFile,即可创建JFileChooser对象。⑴int showOpenDialog(Component parent)方法弹出一个 "Open File" 文件选择器对话框。⑵int showSaveDialog(Component parent)方法弹出一个 "Save File" 文件选择器对话框。⑶int showDialog(Component parent,String apporveButtonText)方法弹出具有自定义approve按纽的文件选择器对话框。如,自定义打印对话框:fcFile.showDialog(this,"打印");。
6、图像:抽象类java.awt.Image
是表示图形图像的所有类的超类,必须以特定于平台的方式获取图像。创建图像一般使用javax.swing.ImageIcon类,此类实现了Icon接口,有多种构造方法,支持图像格式(比如 GIF、JPEG 或从 1.3 版本开始的 PNG)的图像文件。
7、javax.swing.JTable类:用来显示和编辑规则的二维单元表,获取二维表中相关信息。JTable不存放数据,它只提供数据的呈现方式,允许用户对其进行编辑。JTable的滚动需要JScrollPane组件的支持(如果JFrame为borderLayout布局时,JScrollPane放在JFrame上,需要将JScrollPane居中设置[将constraints设置为center]),只有把表格组件包含在滚动面板中,表格组件才会显示表头和滚动条。JTable的构造方法有多种,与数据库连接的多用TableModel模型的方式创建,也可以使用Public JTable(Vector rowData,Vector columnNames)[建立一个以Vector为输入来源的数据表格,可显示行的名称]。
TableModel接口来自于javax.swing.tabel包,该包提供用于处理JTable的类和接口。java提供了两个类实现TableModel接口:⑴AbstractTableModel抽象类。该类除了public int getRowCount();public int getColumnCount();public Object getValueAt(int row,int column)这三个方法外没实现外,其余均实现。⑵DefaultTableModel实现类实现了TableModel接口的所有方法。DefaultTableModel内部使用Vector来使用表格的数据。在创建子类时使用 AbstractTableModel 作为基类,在不需要创建子类时则可以使用 DefaultTableModel。
TableModel默认调用String getColumnName(int columnIndex)方法来初始化列表头,该表头名为“A、B、…Z、AA、AB…”。如果重新定义表头名,需重写该方法。
JTable的内容做了更新后,要使用fireTable***()等方法,通知所有侦听器,表的有关内容已做更新,JTable 应该从头开始重新绘制该表。
8、javax.swing.JDesktopPane类:用于创建多文档界面或虚拟桌面的容器,通常用作 JInternalFrames 的父类,JDesktopPane 不支持边界。用JDesktopPane在主窗体类里使用匿名内部类方法添加桌面背景图片的方法:JDesktopPane desk = new JDesktopPane(){
Image img = Toolkit.getDefaultToolkit().createImage("image/leaf.jpg");
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(img,0,0,this.getWidth(),this.getHeight(),this);
}
};