MATH FUNCTIONS IN JAVA
Java中的数学函数
(此文原文有较多错误,所有错误已在译文中改正,但原文中的错误,如希腊字母不能正确显示,许多前后单字间还缺少空格等,因工作量太大未全部改正。如果你阅读原文,要注意一些才是。)
334 Getting the Absolute Value ofa Number
334 求数的绝对值
Javas java.lang.Math class provides avariety of static methods for exponentiation, floating-point trigonometry, minand max functions, as well as other operations. Because they are all staticmethods, your programs can reference them by the class name without having tocreate an instance of the class. Several of the following Tip discuss thesemathematical methods in detail.
Java的java.lang.Math类为我们提供了多种类型的静态方法,可用来实现指数、浮点三角函数、最大和最小、以及其它运算。由于它们都是静态方法,在程序中你可通过类名来引用它们,无需创建类的实例。以下诀窍详细讨论这些数学方法。
To return the absolute value of a number, the Math classprovides four overloaded methods all named abs. The methods support the fournumeric types, int, long, float, and double:
为了返回一个数的绝对值,由Math类提供了四个都叫abs()的相同方法,分别用来支持int、long、float以及double四种数据类型:
public static intabs(int a);
public static longabs(long a);
public static floatabs(float a);
public static doubleabs(double a);
For example, to return the absolute value of a float, you canuse the abs method, as shown:
例如,为了返回一个浮点数的绝对值,你可按下面的方式使用abs()方法:
float num = -5.8F;
num =Math.abs(num); // Assigns the value 5.8F
335 Using the sqrt Method
335 sqrt方法的使用
When your programs perform arithmetic operations,there will betimes when you will need to take the square root of a value. In such cases,your programs can use the Math class sqrt method. The format of the sqrt methodis as follows:
当你的程序在执行算术运算时,有时需要计算一个数的平方根。这时,你的程序可使用Math类中的sqrt方法。sqrt 方法的格式如下:
public static doublesqrt(double a) throws ArithmeticException;
The following statements, for example, use the Math class sqrtmethod to return the square root of the value 7.9:
例如,以下语句是利用Math类中的sqrt方法来返回数7.9的平方根:
float num = 7.9F;
num = (float) Math.sqrt(num); // return the square root value
// 返回平方根值
Notice that this statement uses an explicit cast to assign thereturn value to a float because the sqrt method returns a double. In this case,the variable num will have a value of 2.81069 after the assignment.
注意,这一语句用强制类型转换方式指定返回数值为float型,因为在缺省时sqrt方法返回的值为double型。在本例中,变量num在赋值后所得到的值将是2.81069。
336 Using the cos Method
335 cos方法的使用
For a triangle, the cosine of an angle is the ratio of the angles adjacent edge to the hypotenuse. The Math class cos method returns thecosine of an angle expressed in radians. The declaration of the cos function isas follows:
在一直角三角形中,一个角的余弦(cosine)就是此角的邻边与斜边的比。Math类中的cos方法返回用弧度表示的角的余弦值。cos函数的说明如下:
public static doublecos(double a);
To return the cosine of an angle, you can use the cos method, asshown:
要得到一个角的余弦,你可按以下形式来使用cos方法:
double num, angle =0.785398D; // angle in radians , 角的弧度值
num =Math.cos(angle); // return thecosine of the angle,返回角的余弦
In this case, the statements will assign the variable num thevalue of 0.707107。
在本例子中,语句将把0.707107赋给变量num作为其值。
337 Using the sin Method
337 sin方法的使用
In a triangle, the sine of an angle is the ratio of the angles opposite edge to the hypotenuse. The Math class sin method returns the sine ofan angle expressed in radians. The declaration of the sin method is as follows:
在一个直角三角形中,一个角的正弦(sine)就是此角的对边与斜边的比。Math类中的sin方法返回用弧度表示的角的正弦值。方法sin的说明如下:
public static doublesin(double a);
To return the sine of an angle, you can use the sin method, asshown:
要得到一个角的正弦,你可按如下所示来使用方法sin:
double num, angle =0.785398D; // angle in radians, 1/4
num =Math.sin(angle); // return thesine of the angle
In this case, the statements will assign the variable num avalue of 0.707107.
在本例子中,语句将把0.707107赋给变量num作为值。
338 Using the tan Method
338 tan方法的使用
In a triangle, the tangent of an angle is the ratio of theangles opposite edge to the adjacent edge. The Math class tan method returnsthe tangent of an angle expressed in radians. The declaration of the tan methodis as follows:
在一个直角三角形中,一个角的正切(tangent)就是此角的对边与邻边的比。在Math类中的tan方法返回用弧度表示的角的正切值。tan方法的说明如下:
public static doubletan(double a);
To return the tangent of an angle, you can use the tan method,as shown:
要得到一个角的正切,你可使用tan方法,如下所示:
double num angle =0.785398D; // angle in radians,1/4 (角的弧度值,等于1/4)
num =Math.tan(angle); // return thetangent of the angle (返回角的正切)
In this case, the statements will assign the variable num thevalue of 1.0.
在本例中,语句将把1.0赋给变量num作为值。
339 Using the acos Method
339 acos方法的使用 【译注:以下一段原文有概念错误,把邻边/斜边之比(即cos(x)的倒数)当成反三角函数acos,但这应改仍是一个三角函数sec(x)。 译文未译此句,另作解释】
The arccosine is theratio between the hypotenuse of a right triangle and the leg adjacent to a given angle; the inverse of the cosine of an angle. If y is the cosine of x, then x is the arccosine of y. The Math classacos method returns the arccosine of an angle specified in radians. Thedeclaration for the acos function is as follows:
一个角的余弦函数cos(x)是与此角邻边与斜边的比,而反余弦函数acos(x)是余弦函数的逆,即: 如果y是角a的余弦,则角a就是y的反余弦。在Math类中,acos方法返回用弧度表示的反余弦值。acos函数的说明如下:
public static doubleacos(double a);
To return the arccosine of a number, you can use the acosmethod, as shown:
要得到一个数的反余弦,你可使用acos方法,如下所示:
float num = 0.707107F;
num = (float)Math.acos(num); // 返回反余弦
Notice that these statements use an explicit cast to assign theresult to a float because the acos method returns a double. In this case, numwill have a value of 0.785398 radians after the assignment.
注意,语句用强制类型转换方式指定返回的结果为float型,因为acos方法缺省情况下返回
double型。在本例中,变量num在赋值后所得到的值将是0.785398。
340 Using the asin Method
340 asin方法的使用【译著:以下一段原文同样有概念错】
The arcsine is the ratio between the hypotenuse of a right triangleand the leg opposite a given acute angle; the inverse of the sine of an angle.If y is the sine of (, then ( is the arcsine of y. The Math class asin methodreturns the arcsine of the number as a double. The declaration of the asinmethod is as follows:
一个角的正弦 sin(x)是与此角的对边与三角形的斜边的比,而反正弦asin(x)是一个角的正弦的逆(不是倒数),即: 如果y是角a的正弦,则a就是y的反正弦。在 Math类中,asin方法返回用弧度表示的反正弦值。asin函数的说明如下:
public static doubleasin(double a);
To return the arcsine of a number, you can use the asin method,as shown:
要得到一个数的反正弦,你可使用asin方法,如下所示:
float num = 0.707107F;
num = (float)Math.asin(num); // return the arcsine
Notice that these statements use an explicit cast to assign thereturn to a float because the asin method returns a double. In this case, numwill have a value of 0.785398 radians after the assignment.
注意,语句用强制类型转换方式指定返回结果为float型,因为asin方法在缺省情况下返回的值为double型。在本例中,变量num在赋值后所得到的值将是0.785398。
341 Using the atan Method
341 atan方法的使用【译著:以下一段原文也有错,见红字部分。译文重写纠正了】
The arctangent is the ratio between the leg adjacent to a givenacute angle and the leg opposite it in a right triangle; the inverse of thetangent of an angle. If y is the tangent of (, then ( is the arctangent of y.The atan method in the Math class returns the arctangent of the number as adouble.The declaration of the atan method is as follows:
一个角的正切是与此(锐)角的对边与邻边之比,而反正切是一个角的正切的逆,即:如果y是角a的正切,则a就是y的反正切。在Math类中,方法atan返回用弧度表示的双精度反正切值。atan函数的说明如下:
public static doubleatan(double a);
To return the arctangent of a number, you can use the atanmethod, as shown:
要得到一个数的反正切,你可使用atan方法,如下所示:
double num = 1.0D;
num = Math.atan(num); // 返回反正切
342 Converting RectangularCoordinates to Polar Coordinates
342 将直角坐标转换成极坐标
In the rectangular coordinate system, the coordinates (x, y)locate a point x units along the x-axis and y units along the y-axis. In thepolar coordinate system, the coordinates (r, () locate a point r units from theorigin and at an angle ( measured from a reference line. If you have the (x, y)rectangular coordinates and would like to convert them to polar coordinates (r,(), you can use the following equations:
在直角坐标系统中,坐标(x,y)在平面上确定了这样一个点,它沿x轴的分量是x单位,而y轴的分量是y单位。而在极坐标系统中,坐标(ro,thita)在平面上确定了这样一个点,它离原点的距离是ro单元,而与参考线的夹角为thita弧度。如果你已知直角坐标系统中坐标(x,y),想把它们转换成极坐标(ro,thita),则你可用以下两个方程式:
ro = sqrt(x2 + y2)
thita = arctan(y/x)
To implement these equations in Java, use statements similar tothe following:
在Java中要实现这两个方程,可使用以下语句:
float x = 10F, y =20F;
float r = (float)Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
float theta = (float)Math.atan(y/x);
System.out.println(r +", " + theta);
343 Rounding a FloatingPoint Value Up or Down
343 浮点数的舍入和舍出
The Java Math class provides two methods for rounding a number.The first rounds values of type float to int, and the second rounds values oftype double to long:
Java的Math类提供了两个方法进行数的舍入。第一种方法是把float型浮点数舍入后转换成int型整数,第二种方法则是把double型的双精度数转换成long型长整数:
public static intround(float a);
public static longround(double a);
The following statements illustrate the use of the round method:
以下四个语句示范了舍入方法的使用:
float f1 = 3.8F, f2 =3.2F;
int i, j;
i = Math.round(f1);
j = Math.round(f2);
These statements assign the variable i the value 4, and thevariable j thevalue 3.
这些语句将变量i的值赋为4,而变量j的值赋为3。
344 Finding the LargestWhole Number Less Than or Equal to a Floating-Point number
344 寻找小于等于某一浮点数的最大整数
When you work with floating-point numbers, you may need to rounddown the value to the next lower integer. For such cases, the Java Math classprovides the floor method whose format is as follows:
当你利用浮点数工作时,有时要把数值舍成比此数小的那个整数值。对于这种情况,Java的Math类提供了一个floor方法,它的格式如下:
public static doublefloor(double a);
Unlike the round methods which round up or down to an integer,the floor method rounds down the floating-point number and returns a type thatis also a floating point. For example, the following statements illustrate theuse of the floor method:
floor与round的舍入方法不同,round方法舍进或舍出后变成了integer型整数,而floor
方法是对float型浮点数进行舍出,并且舍去小数后仍然是一个float型实数。例如,以下
的语句示范了floor方法的使用:
float ff = 3.8F;
float jj = (float)Math.floor(ff);
System.out.println(ff+ " after floor is --> " + jj);
These statements will display the following output:
这些语句将显示以下输出:
3.20000 after floor is--> 3
345 Finding the SmallestWhole Number Greater Than or Equal to a Floating-Point number
345 寻找大于等于某一浮点数的最小整数
When you work with floating-point numbers, you may need to roundup the value to the next higher integer. For such cases, the Java Math classprovides the ceil method, the format of which is as follows:
当你利用浮点数工作时,你可能要把数值舍进成比此数大的那个整数值。对此情况,Java的Math类提供了一个ceil方法,它的格式如下:
public static doubleceil(double a);
Unlike the round methods which round up or down to an integer,the ceil method rounds up the floating-point number and returns a type that isalso a floating point. The following statements illustrate the use of the ceilfunction:
ceil与round的舍入方法不同,round方法舍进或舍出后变成了integer型整数,而ceil方法是对float型浮点数进行舍入,并且返回所得仍然是一个float型实数。以下语句说明了ceil函数的使用:
float ff = 3.2F;
float jj = (float)Math.ceil(ff);
System.out.println(ff+ " after ceil is --> " + jj);
In this case, because the ceil method returns the type doubleand the statements use a variable of type float, the statements use an explicitcast. The statements will display the following output:
在这一例子中,由于ceil方法返回的是double型实数,而语句使用了一个float型的实型
变量,所以在调用的函数表达式之前要加(float)来实行强制类型转换。本语句将显示如下的结果:
3.20000 after ceil is--> 4
346 Rounding a FloatingPoint Value Up or Down to Another Floating Point Value
346 将一浮点数舍入或舍出成为另一浮点数
As you learned in Tip 342, Javas round method will round afloating-point number to an integer. Depending on your programs purpose, youmay want to round the number to another floating-point value. To obtain afloating-point value from the round method, you simply use an explicit cast toa value of type float or double, as shown:
你在诀窍 342 中已了解,Java的round方法在作舍入转换时将把浮点数转成一个整型数。根据你的程序用途的差别,你有时可能需要在舍入运算后把浮点数转换成另一浮点数。为了由舍入方法得到一浮点数,你只要使用float型或double型的强制类型转换,如:
float f = (float)Math.round(3.8F);
double d = (double)Math.round(3.2F);
These statements will assign the variable f the value 4.0 andthe variable d the value 3.0.
这些语句把变量f赋值为4.0,而把变量d赋值为3.0.
347 Working withExponentials
347 指数函数的利用
When your programs perform complex mathematical operations,there may be times when you need to calculate the exponential of ex。In such cases,your programs can use the Math class exp method. The following statementillustrates the use of the exp function to determine the result of e0.4:
当你的程序在执行复杂数学运算时,你有可能需要计算以e为底的指数。这时你的程序就可使用Math类中的exp方法,以下这一条语句说明了exp函数的用法,并得到e的0.4次的指数值:
double value =Math.exp(0.4); // computes to 1.49183
double value =Math.exp(0.4); // 计算结果为1.49183
348 Getting the Value of eor pi
384 获得常数e和pi的值
Javas java.lang.Math class provides two predefined constants.One for e and the other for PI. To obtain these values, specify the Math classname followed by the name of the constant, as shown:
Java的类java.lang.Math提供两个预定义的常数。一个是e,而另一个是pi。为了得到这些值,只要在数学类名Math之后跟随所需常量名即可,如:
System.out.println(eis: + Math.E);
System.out.println(PIis: + Math.PI);
These statements, for example, will display the following output:
这两个语句将分别显示以下的结果:
e is: 2.71828
PI is: 3.14159
349 Finding the Remainderof a Floating-Point Division with IEEEremainder
349 寻找带有IEEE余数(IEEEremainder)的浮点除法的余数
As you have learned, the modulo operator (%) returns theremainder of an integer division. Depending on your programs purpose, you maywant to know the remainder of floating-point division. In such cases, the Mathclass provides the IEEEremainder method to divide two floating-point values,returning the remainder as a floating-point value. The form of theIEEEremainder method is as follows:
你已知道,求模操作(%)能返回整数除法的余数。根据你的程序的用途,你有可能需要计算浮点除法的余数。这时你的程序就可使用Math类中的IEEE余数方法,它对两个浮点数进行相除,并返回浮点的余数。IEEE余数方法的形式如下:
public static doubleIEEEremainder(double f1, double f2);
For example, if you invoke IEEEremainder with the values 10.0and 3.0, the function will return the value 1.0 (10 divided by 3 is 3 with aremainder of 1). The following statements, for example, will display thefloating-point remainder to the screen:
例如,如果你调用IEEE余数,并以10.0和3.0作为两个参数,则此函数将返回值1.0(10除以3得3,余数为1)。例如以下这些语句在屏幕上将显示上述浮点余数:
double n = 10.0;
double d = 3.0;
System.out.println(Math.IEEEremainder(n,d));
350 Calculating Natural Log
350 计算自然对数
The natural logarithm of a number is the power to which thevalue e must be raised to equal the given number. To help your programsdetermine the natural log, the Math class provides the log method, whichreturns the natural logarithm of a floating point value. The followingstatement illustrates the use of the log function:
一个数的自然对数是一个幂(power),e的这一次方幂就等于已给的那个数。为了帮助你的程序计算自然对数,Math类提供了log方法,它返回一个数的自然对数。以下语句说明了log函数的用法:
double d =Math.log(7.0); // returns 1.94591
351 Determining Maximum andMinimum Values
351 确定最大最小值
When your programs compare two numbers, there will be times whenyou will want to know the minimum or maximum of two values. For such cases, theMath class provides the min and max methods. You can use these methods tocompare values of type int, long, float, and double. For example, the followingstatements use the min and max functions to determine the minimum of two valuesof type float and the maximum of two values of type double:
当你的程序在比较两个数的时候,你有时会想要知道两个数中最大或最小的那个数。在这种情况下,你可使用Math类提供的方法min和max。利用这两个方法你就可以比较数的大小,包括int、long、float、double四种类型。例如,以下利用函数min和max的两行语句分别确定两个float型数的最小值和double型数的最大值:
float min =Math.min(3.5F, 4.8F); // Assigns thevalue 3.5F
double max =Math.max(Math.PI, 3.0); // Assigns thevalue Math.PI
float min = Math.min(3.5F, 4.8F); // 赋以数值 3.5F
double max = Math.max(Math.PI, 3.0); // 赋以数值 Math.PI
352 Calculating the Resultof Xn
352 计算x的n次幂
One of the most common mathematical operations your programswill perform is to raise a value to a given power. For such cases, the Mathclass provides the pow method, which returns the result of a value raised to agiven power. The format of the pow method is as follows:
你的程序要执行的最普通的数学运算之一是求一个数的n次升幂。为此, 你可使用Math类提供的方法pow,它返回一个数的n次升幂的结果。pow方法的格式如下:
public static doublelog(double a, double b) throws ArithmeticException;
If the result of the value raised to the given power results inoverflow, Java will throw an exception of type ArithmeticException. The powmethod takes two doubles as parameters the first parameter is the base value and the second is thepower to which the method raises the base. The following statement illustratesthe use of the pow function:
如果已知数的n次升幂的结果产生溢出,Java将抛出一个类型例外(exception of type),叫算术例外(ArithmeticException)。pow方法以两个double型实数作为参数,其中第一个是底(base),第二个是底数需要上升的幂。以下语句示范了pow函数的用法:
double ans =Math.pow(3, 2); // returns 3 to the 2,or 9
double ans =Math.pow(3, 2); // 返回 3 的 2 次幂, 即 9
353 Creating RandomFloating-Point numbers Using the Math Class
353 利用Math类创建随机浮点数
Depending on your programs purpose, you may need to generate oneor more random numbers. In such cases, your programs can use the Math classrandom function. The format of the random function is as follows:
根据你程序的用途不同,你可能需要生成一个或多个随机数。在这种情况下,你可使用Math类提供的random方法。random的格式如下:
public staticsynchronized double random();
The following statements illustrate the use of the random method:
以下语句示例说明方法random的用法:
double rand;
rand = Math.random();
{kaj verify this statementdoes not seemright}
The random function returns a value in the range 0 to 1.0. Bymultiplying the functions result by a value such as 100 or 1000, your programscan change the range of values.
随机函数返回的值是在0到1.0范围之内的。将所得函数值乘以100或1000,你就可以改变
所得的结果的范围。
354 Understanding PseudoRandom Versus True Random
354 弄清伪随机数与真随机数
When Java, or most other computer languages, needs to produce arandom number, a special calculation is made based on a given input valuecalled a seed number. The calculation will always produce the same number whenthe same seed number is given. Because the functions result is alwayspredictable, it is called a pseudo-random number. A true-random number is notpredictable.
The fact that the pseudo-random number is predictable does notmean that it cannot make a good random number. The seed number in Java is 64bits long and the algorithm which uses it to create a random number produces agood distribution of values.
A big advantage of pseudo-random numbers is that your program iseasier to debug when it uses the same sequence of random numbers. After yourelease your software to users, you can ensure good randomness by using adifferent seed for each program run. For example, the seed could be based onthe time, user keystrokes, network activity, or any other random phenomena.
当Java,或其它计算机语言,需要产生一随机数时,就要利用一个称作种子(数)的已知输入数来进行一种特殊的计算。当给出的是同一种子时,则计算的结果也永远是相同的一个数。这是因为,函数的计算总是确定的,其结果也就总是可以预测的。所以,这样的随机数叫伪随机数。真随机数则应该是不确定的,不可预测的。
伪随机数的可预测性并不意味它不能造就出一个好的随机数。Java的种子数是64位的长整数,算法利用它来产生随机数就能获得优良的值的分布。
伪随机数的一个很大优点在于它可以使程序容易调试,因为它可以使用相同序列的一串数。当你把你的软件交给用户使用后,你可以让每一次运行使用不同的种子以保证产生很好的随机性。例如,你可以根据当时时间、用户的击键次数、上网作业的次数,或其它随机现象来计算种子的数值。
355 Seeding a Random NumberGenerator
355 随机数生成器
Java provides the java.util.Random class which facilitates yourprograms implementation of a pseudo-random number generator. By default, theclass methods uses the current time as the seed value. However, you can use thesetSeed method or the class constructor to specify a seed value of your own.You may want to do this when, for example, you need to debug code which usesrandom numbers, and you need a repeatable sequence of numbers. For example, youcan use the Random class and set a starting seed value as follows:
Java提供了一个类java.util.Random,它能简化你的程序实现伪随机数的生成。当缺省时, 该类方法使用当时时间作为种子值。但是,你可以利用方法setSeed或类构造函数(class constructor)来指定你自己的种子值。例如,当你需要调试一个包含随机数的程序时,你就可能需要这样做,你可能需要一个可重复的数的序列。这时,你就可以使用类Random,并按以下方法来设置一初始的种子值:
import java.util.*;
class Randomize {
public static void main(String args[])
{
Random r = new Random(123456); // set aninitial seed 设种子初值
System.out.println(Random 1 is + r.nextInt());
r.setSeed(654321); // reset the seed to something else
将种子改成其它某个值
System.out.println(Random 2 is + r.nextInt());
}
}
The program first sets a seed when it creates the Random classobject. Next, within the call to the System.out.println function, the programcalls the nextInt method, which returns the next integer in the random number sequence.Normally,you do not need to set a new seed more than once within your programs. However,should you need to do so, you can call the setSeed method, as shown. Thisprogram produces the following output:
本程序在创建对象Random类时首先设置了种子数。然后在函数System.out.println的调用中,程序又调用了方法nextInt,后者返回随机数序列中的下一个整数。通常在你的程序种,除了第一次外,你无需再设置新的种子。但是假如你要这样做,你可以用所示形式来调用setSeed方法。本程序产生以下输出结果:
Random 1 is 1774763047
Random 2 is 129127415
356 Creating RandomFloating-Point Numbers
356 创建随机浮点数
As shown in TIP 358, you can generate random numbers by using aninstance of the Random class. You also learned that the nextInt functionreturns the next integer in a range of random numbers. In a similar way, theRandom class contains a method called nextFloat, which produces a new randomfloating-point number for each call. The following statements illustrate theuse of the nextFloat method:
如诀窍 358所示{354?}, 你可以利用类random的一个实例来生成随机数。你也知道, 函数nextInt返回的是随机数范围中的下一个整数。用类似的方法,Random类包含一个称作NextFloat的方法,它为每一次调用产生一个新的随机浮点数。以下语句说明nextFloat的用法:
Random r = new Random(); // use a default initial seed
// 利用缺省初始种子
System.out.println(Randomfloat is + r.nextFloat());
357 Creating Random Numberswith Gaussian Distribution
357 创建Gause分布随机数
When you create random numbers, you may need better control overthe range of numbers that the random number generator creates. As it turns out,you can produce a set of random numbers based on a Gaussian distribution, thatis, a distribution having a mean of 0.0 and a standard deviation of 1.0. To getnumbers based on the Gaussian distribution, you use the Random classnextGaussian method, as shown:
当你创建随机数时,你可能需要更好地控制随机数生成器所生成的随机数的范围。当出现这种情况时,你可以利用Gause分布来生成随机数集,Gause分布是这样的一个分布,它的平均值是0.0,而标准偏差是1.0。要获得基于Gause分布的数, 你可以使用随机数类Random的nextGaussian方法, 如下所示:
Random r = newRandom(); // use a default initial seed
// 利用缺省初始种子
System.out.println(Random1 is + r.nextGaussian());
358 Controlling the Rangeof Random Integers
358 控制随机数的范围
As you have learned, Java programs can generate random integersby using an instance of the Random class. The Random class contains a methodcalled nextInt, which produces a new random int for each call. Depending onyour programs purpose, you may need to produce random numbers in a specificrange. To control the range of integer values a random-number generatorcreates, you can use the modulus operator (%). For example, if you need numbersin the range -100 to 100, you can get the remainder of the random
number divided by 100, as shown:
你已了解, Java程序利用random类的一个实例来生成随机数。random类中包含一个称作NexrInt的方法,它为每一次调用产生一个新的随机整型数。按照你的程序的用途,你可能需要产生某一范围内的随机数。为了控制一随机数建立的整数范围,你可以使用取模运算符(%)。例如,如果你要-100到100范围中的数,你可用100来除随机数而取其余数,如下所示:
Random r = newRandom(); // use a default initialseed
利用缺省初始种子
System.out.println(Random int is + r.nextInt() % 100);
Likewise, if you need to restrict the range of numbers topositive values, say 0 to 100, your programs can use the Math class absfunction, as shown:
同样,如果你要把数值限制在正数范围之内,例如0到100,则你可以在程序中使用Math类的abs函数,如下所示:
Random r = newRandom(); // use a default initialseed
利用缺省初始种子
System.out.println(Randomint is + Math.abs(r.nextInt() % 100));
359 Creating RandomIntegers for a Specific Range
359 在一指定范围中创建随机数
The Random class methods for generating random numbers producevalues in the ranges indicated in Table 359:
生成随机数的Random方法所产生的数值其范围如表359所示:
Method name Range of output
方法名 输出范围
------------------------------------------------------------------------
nextFloat 从 0.0到 1.0
nextDouble 从 0.0到 1.0
nextInt 从-2147483648 到 2147483647
nextLong 从-9223372036854775808 到 9223372036854775807
------------------------------------------------------------------------
Table 359 Range of random numbers.
表359 随机数的范围
As you learned in Tip 360, by performing simple math operations,you can manipulate the random numbers to produce a desired range. The followingexample shows you how you might limit the range of floating-point randomnumbers from 0 to 100:
你在诀窍 360中已了解, 通过简单的数学运算,你就可控制随机数产生在某一个所希望
的范围内。以下例子向你展示怎样把浮点随机数的范围限制在0到100之内:
Random r = newRandom(); // create a Random object
创建对象Random
float f =r.nextFloat(); // get a random value(0.0 to 1.0)
获得0.0-1.0的随机值
float v = (f *100); // multiply by a factor to get0 to 100
乘上一因子得到0-100的随机值
1001 Java 诀窍
PAGE 29 of numpages 35
filename jt0375_a
TIME \@ "MMMM d, yyyy"
November 24, 1996
a
Date Functions in Java
java中的日期函数
360 Getting the Current Date with the Date Class
360 利用Date类获得当前时间
Within your programs, there may be times when your programs willneed to work with the current date and time.As it turnsout, Javas Date class,java.util.Date, provides various methods to representand manipulate dates and times.If your program callsthe Date constructor with no arguments, a Date instanceis initialized with the current date and time.Becausedifferent parts of the world represent dates in different formats, the Date class provides a convenient method which formats thecurrent date into the local style.The toLocaleStringmethod will take the date information in the instance and create a Stringobject.For example, thefollowing statements use the Date class methods to display the current date andtime within the United States:
在你的程序中有时会要求程序在当前日期和当前时间进行工作。当发生这种情况时,你可利用Java的Date类java.util.Date。这一类中包含了许多有关日期与时间的表示和控制的方法。如果你的程序不带参数调用Date构造函数,则一个Date实例就会以当前日期和时间进行初始化。
由于世界不同地区采用不同的格式表示时间,Date类提供了一种将当前时间格式化成地区性时间的方便方法。toLocaleString方法将会在实例中取到日期信息,并创建一个 String对象.例如,以下语句利用Date方法在美国国内显示当前日期和时间:
class PrintTheDate {
public static void main(String arg[] )
{
Date today= new Date();
System.out.println(today.toLocaleString());
}
}
The above code will print the date and time, for example:
以上程序将打印类似以下形示的日期和时间:
Tuesday, 26November, 1996 10:02:17 PM
361 Beware of Specifying Dates beyond 2000
361 注意说明2000年后的日期
When your programs work with dates, you need to be careful with dates beyond2000.When you use the setYear method or any of theconstructors that take a year, you are indicating ayear by the number of years since 1900rather than the centurys last two digits.Therefore, to set the date to the year 2000, you would use the value 100, as follows:
当你的程序利用日期工作时,必须小心日期是否超出2000年。当你使用setYear方法或其它任何带有年份的构造函数时,你常常是指从1900年开始计算的数字,而不是世纪的后两位数字。因此,把日期设定为2000年,你应如下那样使用数值100:
Date future_date= newDate(100, 2, 29);
Note: Some versions of the Java compiler may have a problemrepresenting years beyond 2035.You may want to test your compilers ability toprocess years beyond 2035.
注意: Java编译器的某些版本在表示超过2035年的各个年份时可能会遇到问题。你可能需要测试一下你的编译器处理超过2035年年度的能力。
362 Creating Your Own Date/Time with the Date Class
362 利用Date类建立你自己的日期和时间(以下原文有错!)
Within your programs, you can construct a Date class objectusing the Date method either with parameters (to get the current date and time), or without parameters.If you call the Dateconstructor with parameters, you may set a specificdate and time.You may also set a particular date andtime after the Date instance is created by calling a specific series of Dateclass methods.
在你的程序中,你可以使用不带参数的Date方法来构造一个Date类对象(这时你将得到当前的日期和时间),也可以使用带有参数的Date方法来构造Date类对象(这时你是用来设置日期和时间).当你调用了一系列Date类方法创建了Date实例之后你可能还要设置特殊的日期和时间。
You may want to create a Date object with a date or timedifferent than the current date or time for a variety of situations.For example, you may need to store dates for specific items in a database, or perhaps you may need to compare two dates.In any case, the Date class offers severalmethods your programs can use to change dates and times, as shown in Table 362:
你可能要创建一个带有和当前日期和时间不同的日期和时间的Date对象。例如,你可能要为一数据库某指定项存入数据,也或许是要比较两个日期。在任何情况下,你的程序可利用Date类提供的用来改变日期和时间的几个方法, 如表362所示:
方法 用途
---------------------------------------------------------------------------
setDate(int date) 设置日期 (day of the month)
setHours(int hours) 设置小时
setMinutes(int minutes) 设置分
setMonth(int month) 设置月份数减1(从0开始计月份)
setSeconds(int seconds) 设置秒
setTime(long time) 设置从1/1/1970开识计算的毫秒数
setYear(long year) 设置从1900年开始的年份数
Table 362 Summary of methods for changing date andtime.
表362 改变日期和时间的方法一览表
For example, to create a Date object with the date, May 31, 1997, youwould use the following statement:
例如,为了建利带有日期1997年5月31日的Date类,你可利用以下的语句:
Date start_date= newDate(97, 4, 31);
363 Using the Date Class to Find the Day of the Week
363 利用Data类计算某年某月某日是星期几
After you create a Date object, either with the current date and time, or with some other date and time, you canobtain the day of the week using the getDay method.TheDate class represents the day of the week as a zero-based number, with Sunday equal to zero and Saturday equal to six.The following statements will display the day of the week thatcorresponds to the date, May 31, 1997which turns out to be 6 (a Saturday):
在你建立了带有当前日期和时间或其它日期和时间的Date对象之后,利用getDay方法,你即可算出星期几.Date类表示星期几是从0开始算的,即0代表星期天,而6代表星期六.以下语句将显示对应于1997年5月31日是星期几,它应是星期6:
Date start_date = newDate(97, 4, 31);
System.out.println(start_date.getDay());
364 Be Aware that the Day of the Week and Month in theDate Class is
Zero-Based.
364 注意Date类中星期几或几月、几号的计算都是从零为开始算起的
The Date class provides several functions you can use to get orset the current date.When you use the getDay, getMonth, setDay, or setMonth methods, be aware that these methods use zero-based dates.In other words, the first day of the weekand the first month of the year use the number 0.Forexample, the first day of the week, Sunday, is represented by a 0.The first month of the year, January, is also represented by a 0.Likewise, the last day of the week, Saturday, is represented by a 6 and the last month,December, is 11.
Date类提供了几种可用来获得或设置当前日期的功能.包括getDay、 getMonth、setDay、或setMonth 等.注意,这些方法在计算时都是从零开始算起的.也就是说,一个星期的第一天、一个月的第一天、以及一年的第一个月,都使用了0.这样,星期天是星期0,每个月的一号是0号,正月是0月,12月则是11月,等。
365 Getting the Current Time with the Date Class
365 利用Date类来计算当前时间
Within your programs, there will be many times when you need todetermine the current time.If your program calls theDate constructor with no arguments, the constructorwill initialize the Date object with the current date and time.To determine the current time using the Date class, you can use several different techniques.Forexample, the following statements display the currenttime using the toGMTString (to Greenwich Mean Time) getHours, and getMinutes methods:
你的程序中将会有很多时候需要确定当前的时间.如果你调用Date构造函数时不带参数,则此构造函数将用当前日期和时间来初始化.要利用Date类来确定当前时间,你可以使用几种不同的技术.例如,以下这些语句是利用toGMTString(格林威治平均时间) getHours和getMinutes方法显示当前时间:
class PrintTheTime {
public static void main(String arg[])
{
Date now= new Date();
System.out.println(now.toGMTString().substring(12));
System.out.println(now.getHours() +":" + now.getMinutes());
}
}
The toGMTString method uses the current Date information toreturn a String representing the Greenwich Mean Time.By using thesubstring method, you can chop off the date informationand just report the time, as shown here:
以上方法toGMTString利用Date信息来返回代表格林威治平均时间的一个字符串.借助于子字符串方法,你可以由此截取日期信息和报告当前时间,如:
06:37:16 GMT
To display the current time using a 24-hour format, your programcan concatenate the result of the getHours and getMinutes methods.For example, the previous statements willdisplay the following output:
要使用24小时制显示当前时间,你的程序可把getHours和 getMinutes方法的结果合在一起.例如,以上语句将产生以下的输出:
23:41
366 What Is the Epoch Date?
366 什么是时代日期(Epoch Date)?
Within a Java program, you can create a Date object by specifyinga year, month, date and, optionally, the hour, minute, and second as parameters to theconstructor function.You can also create a Date objectwith no arguments to the constructor, in which case theDate object will contain the current date and time.Finally, you can create a Date object by specifying the number ofmilliseconds since the epoch date, which is midnightGMT, January 1, 1970.The Date class uses the epoch date as a reference point which letsyour programs refer to subsequent dates in terms
of a single long integer.You cannot set a year before 1970.
在Java程序中,你可以利用对年、月、日,或者再加上对时、分、秒的说明,来创建一Date对象.你也可创建一个在构造函数中不带参数的Date对象,这种情况下,Date对象将包含当前的日期与时间。最后,你可以用指明从时代日期以来的毫秒数的办法,来创建一Date对象。时代日期是指1970年1月1日格林威治午夜12点。利用以时代日期作为参考点的Date类使你的程序可以使用单个的长整数来谈论其后的时间,但不能设置1970年以前的年份。
367 Getting Current Time in Milliseconds with thegetTime Method
367 利用getTime方法来获得用毫秒表示的当前时间
Within your programs, there will be times when you need tocompare two dates.One way to compare dates is toconvert the dates to milliseconds since a specific date, such as seconds since the epoch date (discussed in Tip 366).The Date class getTime method returns the number of millisecondssince the epoch date, midnight GMT, January 1st, 1970.Thefollowing statements illustrate how you can use the getDate method to comparetwo dates:
在你的程序中有时会要求比较两个日期或时间.比较时间的一种办法是将这些时间通统转换成某一时刻后的毫秒数,例如诀窍366中讨论的时代日期时间.Date类中的getTime方法就是能返回从1970年1月1日格林威治午夜12点以来的毫秒数.以下语句示范了怎样用getDate方法来比较日期:
class CompareDates {
public static void main(String arg[])
{
Date now = new Date();
Date later = new Date(97, 3, 15);
long difference = later.getDate() -now.getDate();
System.out.println(Current date: + now.getHours() +
":" + now.getMinutes());
System.out.println(Future date: + future.getHours() +
":" + future.getMinutes());
System.out.println(Difference (ms): + difference);
}
}
368 Measure Code Execution Speed with the getTimeMethod
368 利用getTime方法来检测程序的执行速度
As you examine your programs performance, there may betimes when you want to time a particular section of your code.You can time blocks of code within your programs simply by using thegetTime method before and after the section of code you want to time.For example, the following statements usethe getTime method to determine how much time the for loops processingconsumes:
当你要检查你的程序的性能时,有时会想要算一算运行程序中某一段代码所需的时间。为此你只需把getTime方法插在你所想考察的那一段代码之前和之后。例如,以下语句是利用getTime方法来确定For循环所耗用的时间:
Date now = newDate();
long startTime=now.getTime(); // begin time count 开始时间计数
for (long m=0; m <1000000; m++)
; // do whatever time consuming task
now = new Date();
long endTime =now.getTime(); // end the time count 结束时间计数
System.out.println(Milliseconds=+ (endTime-startTime));
These statements will display the time it takes the program toperform thefor loop, as follows:
这些语句将显示程序执行循环所用去的时间,如下:
Milliseconds=1616
369 Comparing Dates with after, before, and equals Methods
369 利用after、before、和 equals方法来比较日期
Java provide several methods to compare two Date objects: after, before andequals.The following statements create two Date objects, each with a different date.The statementsthen determine if one date is before or after the other, or whether they are the same date:
Java提供了比较两个Date对象的几种方法: after、before、equals。以下语句创建两个有不同日期的Date对象,然后再确定一个对象是否在另一对象之前或之后,或者它们是同一个日期:
Date startDate= newDate();
Date endDate= newDate(120, 4, 31);
System.out.println(startDate.toLocaleString());
System.out.println(endDate.toLocaleString());
System.out.println(Isstart date after +
startDate.after(endDate));
System.out.println(Isstart date before +
startDate.before(endDate));
System.out.println(Aredates equal +startDate.equals(endDate));
These statements will display the following output:
这些语句将产生下列的输出:
Saturday, 31August, 1996 01:10:39 AM
Sunday, 31May, 2020 12:00:00 AM
Is start date afterfalse
Is start date beforetrue
Are dates equal false
370 Converting String to Date
370 将字符串转换为日期
The Date class provides a very convenient constructor that takesa String representation of a date and converts the string into a Date object byassigning values to the various time and date fields.The followingstatements illustrate the use of the Date class String-based constructor:
Date类提供了一个非常方便的、用字符串表示日期的构造函数,利用对各种日期和时间域的赋值,可以将字符串转变成Date对象。以下语句说明了Date类的这种字符串型构造函数的用法:
Date someDate= newDate("Dec 25, 1996");
System.out.println(someDate.toLocaleString());
someDate= newDate("Dec 25, 1996 1:56 PM");
System.out.println(someDate.toLocaleString());
In this case, the statements successfully convert the twoStrings into Date objects and display the following dates:
这里,语句将字符串转换成Date对象,并显示下面这样的日期:
Wednesday, 25December, 1996 12:00:00 AM
Wednesday, 25December, 1996 01:56:00 PM
{ kaj what if conversion error occurs ???}
371 Creating a daysBetween Function
371 建立一个计算间隔天数的函数
Because the Date class lets your programs express dates in termsof milliseconds from a known epoch date, you can determine the number ofmilliseconds between two dates very easily.After youhave the number of milliseconds between dates, you candetermine the number of days between those dates.Thefollowing statements, for example, convert milliseconds to days by dividing the milliseconds by86400000, that is, the numberof milliseconds per day:
由于Date类使你的程序在表示日期时是从一已知的时代日期算起的毫秒数,你可以很容易地确定处于两个日期之间的毫秒数。而有了两个日期之间的毫秒数之后,你就可计算这两个日期之间的天数。为此,只要用一天的毫秒数(86400000)来除两个日期之间的毫秒数就可以了。以下语句说明了这一方法:
import java.applet.*;
import java.awt.*;
import java.util.*;
public class Testextends Applet {
public long days(Date startDate,Date endDate)
{
return(Math.abs(endDate.getTime()
startDate.getTime())/86400000);
}
public void init()
{
Date startDate = new Date(96, 8, 4);
Date endDate = new Date(96, 8, 6);
System.out.println(Diffence = + days(startDate,endDate));
}
}
In this program, the days method takes two Date objects andreturns the number of days between them.
在此程序中,days方法用了两个Date对象,返回的是这两个date之间的天数。
372 Creating a daysInMonth Method
372 建立一个计算一月中天数的方法,daysInMonth
Within your programs, you can use the Date class to determinethe number of days in any month.The followingDaysInMonth method takes a Date object and returns the number of days in thedates month.The method works by determining how manydays there are from the specified date to the first of the following month.
{以上原文有错!}
在你程序中,你可使用Date类来确定任何一个月的天数。以下的daysInMonth方法以一个Date对象作为输入参数,返回的是这一指定月份所包含的天数。这一方法的实现是计算从包含指定日期的月份的第一天到下一个月的第一天之间有多少天数。
short DaysInMonth(DatethisDate)
{
long diff;
Date tempDate = new Date();
tempDate.setTime(thisDate.getTime()); // copy the date 拷贝日期
if (thisDate.getMonth()!= 11)
{
tempDate.setMonth(thisDate.getMonth() +1);
}
else
{ // special case of December 12月份为特殊情况
tempDate.setMonth(0);
tempDate.setYear(thisDate.getYear() +1);
}
tempDate.setDate(1);
diff=Math.abs(tempDate.getTime()-thisDate.getTime())/86400000;
diff+= thisDate.getDate();
return((short)(diff-1));
}
373 Understanding Different Date Standards
373 弄清不同的日期标准
The basis for standard time throughoutthe world is the meridian at Greenwich, England.You can specify the time for any location in the world in terms ofthe number of hours from Greenwich Mean Time, or simplyGMT.Java uses midnight GMT,January 1st, 1970 for its epoch date.Java provides methods you can use to express the time based on twotime locations: the time at Greenwich and your local time.Of course, the classes determine the timebased on your computers clock and time-zone settings.Thus, you must make sure that both your systems time and time-zonesettings are correct.When you need to express the timeand date in terms of GMT, you can use the Date classtoGMTString method.If you need the time expressed inthe local time, use Date class toLocaleString method.The Date class getTimezoneOffset method determines the localtime-zone offset, which is the number of minutes yourprogram must add to Greenwich Mean Time to give the local time zone.This value includes the correction,ifnecessary, for daylight savings time.
全世界的基本标准时间是英国格林威治子午线时间。你可以用从格林威治平均时间(简记为GMT)开始算起的时数来表示世界上任何一个地区的时间。Java用1970年1月1号午夜12点(GMT)作为时代时间。Java为你提供了两种时间位置表示时间的方法,即格林威治时间和你的局部地区时间。当然,实际的计算还决定于你的计算机的时钟和时区的设置。因此,你必须保证你的系统时间和时区的设置都正确无误.当你需要用GMT标准表示时间和日期时,你可使用Date类的toGMTString方法,如果你想得到局部地区时间,则你可使用Date类中的toLocaleString方法。Date类中的getTimezoneOffset方法则用来设置时区,它代表你所在的局部地区时间与GMT时间之间相差的分数,在你的程序中只要把这一分数加到GMT时间上,就可得到你所在的局部地区时间。
1001 Java Tips
PAGE7 of numpages 35
Filename jt0375_a
November 24, 1996
b
Date Class
Date类(日期类)
374 Beware When Relying on Date Formats
374 留心与Date格式有关的事情
When you work with the Date class object, be aware that Sun hasreported several bugs in the Date class. One bug involves the toString method,which gives different output on different platforms. If your program parses thestring or relies on the presence of specific fields, you should carefullyverify that the strings contain the text you expect. For example, on a SunSolaris computer, calling the Date class toString method will result in thisoutput:
当你利用Date类对象工作时,必须留心Sun公司已报告的Date类中的几个疏忽。一个疏忽包含在toString方法中,它在不同的平台上会有不同的结果。如果你的程序要分析所得的string,或者依赖于所得string的某些域,则你必须小心验证你所期望的文本字符串。例如,在Sun的Solaris计算机上,调用Date类的toString方法将产生以下结果:
Tue Sep 10 12:22:56PDT 1996
On Microsoft Windows NT and Windows 95, the toString methodproduces the
following date string:
而在Microsoft Windows NT 和 Windows95上,toString方法将生成以下日期字符串:
Tue Sep 10 12:22:561996
375 Using the DOS TZ Environment Variable
375 使用 DOS 环境变量 TZ
If you use a Windows-based system, you can set the time-zonevariable, TZ, by placing a SET command within your systems AUTOEXEC.BAT file.The format of the TZ entry is as follows:
如果你使用基于Windows的系统,你可在AUTOEXEC.BAT中利用SET命令之后加上时区变量TZ来设置时区。TZ的输入格式如下:
SETTZ=SSS[+/-]h[h][DDD]
The SSS field contains the standard time zone name (such as ESTor PST), and the [+/-]h[h] specifies the difference in hours between thestandard time zone and GMT. Finally, the DDD field specifies the name of thedaylight savings time zone (such as PDT). The following entry sets the time zonefor the West Coast when daylight savings time is active:
SSS 域中包括标准时区名(如EST 或 PST)和选项[+/-]h[h],后者用来指示标准时区与GMT的时数差。最后,DDD域用来指示夏令时时区名,如PDT。当夏令时生效时,以下参数可用来为西海岸设置时区:
SET TZ=PST8PDT
When daylight savings time is not active, omit the time zonename, as shown:
如果未设置夏令时,则可省去时区名,如:
SET TZ=PST8
If you do not specify a TZ entry, the default is EST5EDT.
如果你不指定TZ参数,则使用的缺省值为 EST5EDT(美国东部时区)。
376 Understanding Arrays
376 了解数组
Throughout this books tips, you have learned how to createvariables for individual objects. Sometimes, however, you will need tomanipulate a series of related objects within an array object. To do this, youcan use aArrays let your programs work conveniently with a group of relatedobjects. In short, an array is simply a waylets you to store and access a setof objects of the same type within the same variable. For example, you can usean array to keep track of grades for fifty students or to store a series offilenames.
Even though Java arrays are similar in syntax to C/C++ arrays,they have subtle differences. In Java, an array is an actual basically anobject that points to a set of other objects or primitive data types. The onlyvisible difference between arrays and objects is that arrays have a specialsyntax to make them behave like the arrays found in other languages. Unlike Cand C++, however, Java arrays cannot change in size, and also cannot benor cana program use an out-of-bounds index with a Java array. Also, you declare andcreate arrays in Java very differently than in C/C++. The following tips describehow to create and use arrays in Java.
通过本书前面的诀窍你已知道怎样为单个对象创建变量。但是,你有时必需同时处理相关的一系列对象。为了实现这一事情,你可以利用数组,它可使你的程序方便地处理相关的一系列对象。一个数组,简单地说,就是能在同一个变量中存放和引用相同类型的一组对象的方法。例如,你可利用一个数组来保存50个学生的成绩,或存放一系列文件的名称。
Java的数组在语法上和C或C++数组类似,但它们有着微妙的差别。在Java中,一个数组从根本上说就是一个指向一组对象或一组原始数据类型的实际对象。数组对象与原始对象之间可以觉察的唯一差别在于,数组具有一种特殊的语法,使它们的行为看上去和其它语言中的数组一样。但与C或C++不同,Java中的数组不能改变大小,而且在程序中使用时也不允许下标超越它的范围。另外,你在Java中说明和建立数组的方法和C或C++中所用的也很不相同。以下几个诀窍将描述怎样在Java中建立和使用数组。
377 Declaring an Array in Java
377 在Java中说明(声明)一个数组
As you have learned, creating an object is a two-step process.To start, you must first declare the object. Then, you must make an instance ofthat object. In Java, arrays are objects. Therefore, you must first declare anarray, and then create it. In Java, you can declare an array in two ways. Thefirst syntax places the bracketbraces [][] on the variable name. The followingcode demonstrates an integer array declaration:
你已知道了,创建一个对象是一个两步的过程。开始,你必须首先说明这个对象。然后,你必须为此对象制造一个实例。在Java中,数组也是对象,所以你必须先要说明一个数组,然后再创建它。在Java中,说明一个数组可以用两种办法。第一种方法是在变量名后加一对或几对括号[]。以下语句是(一维)整型数组的说明方法:
int myarray[];
The alternative declaration syntax places the bracketbraces []on the variable data type. The following code demonstrates the type name:
另一种句法是在变量数据类型后加对括号[]。以下语句是采用这种句法的说明:
int[] myarray;
Notice that the size of the array is not part of thedeclaration. You define an arrays size when you create the array.
注意,数组的大小不属于说明的一部分内容。你必须在以后创建数组的实例时再来定义数组的大小。
378 Creating an Array of Primitive Data Types
378 创建一个原始日期类型(Primitive Data Types)数组
In Tip 377, you learned how to declare an array. Your next stepis to create the array object. As you have learned, in Java you create objectswith the new keyword. When you create an array, you follow the new keyword withthe object type followed by the size of the array in bracketbraces. A primitivearray is an array of one of the primitive numeric, char, or boolean types. Thefollowing statements demonstrate how to create various primitive arraysan arrayof 100 integers.
在诀窍377中,你已知道怎样说明一个数组。你的下一个步骤就是要创建一个数组对象。正如你已所了解的,在 Java中,要建立一个对象要使用新的关键字(keyword)。当你创建数组时,你应在对象类型的新关键字后的一对括号中填写数组的大小。一个原始数组是指由单个数值或字符或布尔类型组成的数组。以下语句说明了怎样创建包含100个元素的不同类型的数组:
int myarray1[] = newint[100];
double myarray2[] =new double[100];
boolean myarray3[] =new boolean[100];
In this case, the statements do not initialize the contents ofthe arrays. However, by default, Java initializes the primitive numeric datatype arrays to zero and boolean arrays to false.
在本例中,语句没有对数组的内容初始化。但是,按照约定,Java将原始数值数据类型初始化为0,而将Boolean数组初始化为false。
379 Initializing an Array of Primitive Data Types
379 初始化一个原始数据类型数组
Just as with C/C++ and other programming languages, you caninitialize numeric arrays when you declare the arrays. When you specify initialvalues within an array declaration, Java performs the new operation and definesthe array size for you. The following statements demonstrate the declarationand initialization of a numeric array and a boolean array:
如同C或C++以及许多其它程序设计语言一样,你可以在数组的说明中来初始化数组。当你在数组的说明中指定数组的初值时,Java执行这一新操作,并且为你确定数组的大小。以下语句说明了一个数值数组和一个布尔数组的说明和初始化方法:
int myarray1[] = { 1,2, 3, 4, 5 };
boolean myarray2[] = {true, false, true };
In these examples, Java creates onean array object that holdsfive integers and a second array that holds three boolean values. Java alsoinitializes the arrays with the specified values. Notice that you surround thearray values with braces {}, and separate each value with a comma.
在这一例子中,Java 建立了具有五个整型数的数组对象和具有三个布尔量的另一个数组对象。Java同时用所给出的值来初识化数组。注意,数组元素要用括号{}括起来,相互之间用一逗号分开。
380 Understanding Array Indexing
380 了解数组的下标记法
Each value of an array is called an array element. To access anarray element, you specify the name of the array with the index of that elementplaced between bracketbraces []. Java array indexing is similar to that ofC/C++. The following code demonstrates a loop that cycles through all theelements of an array and displays each value to the screen:
数组中的每一个数据叫数组元素。要存取一个数组的元素,你应指出该数组的名字,并在其后面的一对括号中填入所需元素的索引号(即下标)。Java数组的下标形式和C或C++类似。以下语句是一个循环程序,它依次引用一个数组中的每一个元素,并在屏幕上显示了每一个元素的值:
int myarray[] = { 1,2, 3, 4, 5 };
for (int index = 0;index < 5; index++)
{
System.println(myarray[index]);
}
In this example, the size of the array is five. In Java, theindex of the first element of an array is zero, and the last location is thesize of the array minus one. Therefore, to loop through all the members of thearray, the program uses the loop variable values 0 to 4.
When you index a Java array, Java checks that the index value isgreater than or equal to zero and less than the size of the array. If the indexis less than zero or greater than or equal to the size of the arrayout of thisrange, then Java will generate an IndexOutOfBoundsException error and terminate your program. (Anexceptions is how Java flags an error conditions. You will learn about theexceptions in later tips. )
在本例子中,数组的大小是5。在Java中,数组的第一个元素的下标为0,而最后一个元素的下标是数组的大小减1。因此,循环要遍历所有元素,程序的循环变量的取值应是0到4。
当你用下标引用Java数组时,Java将检查所用下标是否大于、小于或等于数组的大小。如果下标小于0,或大于或等于数组的尺寸,则Java将产生一个指示下标已溢出数组范围的错误:IndexOutOfBoundsException,并终止你的程序。Exception(例外)是Java用于说明各种出错情况的标志。你在今后的一些诀窍中会学到有关的各种Exception。
381 Assigning an Array Element
381 为数组元素赋值
You have learned how to access an array element. Within yourprograms, you can use an array element just like any other variable. For example,you can use the assignment operator to change the array elements value anywhere within the class that defines the array. Likewise, you can access theelements value from any location within the class. The following statementsdeclare the array myarray to store five integer values. Then, within the forloop, the program assigns values to the array elements and then accesses (uses)the elements value within the System.out.println function call:
以上你已了解了怎样存取数组元素。在你的程序中,你可以象使用其他变量一样来使用一个数组元素。例如,你可以在定义数组类的任何地方用赋值操作来改变数组元素的值。以下语句说明了数组myarray要存放5个元素,然后,在For循环中,程序为每一数组元素进行赋值,并在System.out.println函数中使用了元素的值。
int myarray[] = newint[5]; // Initializes array to allzeros
数组数据全初始化为0
for (int index=0;index < myarray.length; index++)
{
marray[index] = index + 1; // Assign a new value
赋以一个新值
System.out.println(myarray[index]); // Usethe value 使用此新值
}
382 Finding the Length of an Array
382 确定数组的长度
In Java, an array is an object. The only member variable of anarray object is the length variable which contains the size of the array. Youwill find the array object length variable useful for looping through theelements of anthe array. The length variable is read only because the size ofan array object cannot change after you create the array. The following codedemonstrates the use of the length variable within a for loop that cyclesthrough all the elements of an array:
在Java中,一个数组是一个对象。数组对象中唯一的成员变量是长度变量,它的值就是数组的大小。你将发现,数组对象的长度变量在访问每一数组元素的循环程序中有用。长度变量是一个只读变量,因为一个数组的大小在你建立了之后就不能改变。以下的程序说明了长度变量在一For循环中的用法,这个循环经历了一个数组的所有元素:
int myarray[] = { 1, 2, 3, 4, 5};
for (int index=0; index
{
System.out.println(myarray[index]);
}
383 Understanding Array References
383 了解数组的引用
As you have learned, Java uses references to point to an object.Array references are no different thant those that you use for other types ofobjects. For example, you can point to one array object with an arrayreference, and later point to another array object using the same reference.The following statements use the myarray reference to access two differentarrays:
你已了解,Java靠引用来指向一个对象。数组的引用和其它对象类型的引用没有什么不同。例如,你可利用一个数组的引用来指向一个数组元素,然后利用同样的引用来指向数组其余的元素。以下语句利用数组myarray的引用来访问了2个不同数组:
public class arrayReference {
static public void main(String args)
{
int myfirst[] = { 1, 2, 3, 4 };
int mysecond[] = { 5, 6, 7, 8, 9, 10 };
int myarray[];
myarray = myfirst;
System.out.println("FirstArray:");
for (int index=0; index { System.out.println(myarray[index]); } myarray = mysecond; System.out.println("SecondArray:"); for (int index=0; index { System.out.println(myarray[index]); } } } 384 Creating an Array of Objects 384 创建一个数组对象 In Tip 377, you learned how to create arrays of primitive datatypes. As your programs become more complex, there will be many times when youwill want to create an array of objects, such as an array of String objects.The first two steps of creating an array of objects are the same as creating anarray of primitives. The following statement, for example, creates an array ofRectangle objectsthis: 在诀窍 377中你已了解怎样创建原始数据类型数组。当你的程序变得愈来愈复杂时,你很多时候需要创建其它对象的数组,例如String对象数组。创建对象数组的前两个步骤仍然和创建原始类型数组一样。例如,以下语句创建了一个矩形数组: RectangleIntegermyarray[] = new RectangleInteger[520]; When you create an array of primitive types, Java initializesthe array to all zeros. However, when you create an array of objects, Javainitializes the array to nNull to indicate that the array does not yet containany objects. You must create the members of the array and assign them to theproper array element. The following code demonstrates how to assign Rectangleobjects to an array:create an array of objects: 当你创建原始类型的数组时,Java把每个元素的初值置成0。但当你创建一对象数组时,Java把数组置为NULL,以指示数组还没有包含任何对象。你必须创建数组的成员,并为它们指定应有的数组元素。以下这些语句示例说明怎样把矩形赋给一个数组来建立一个对象数组: RectangleInteger myarray[] = new RectangleInteger [520]; for(int index=0; index < myarray.length; index++) { myarray[index] = new RectangleInteger(0,0,10,10index); // call constructor // 调用构造函数 } 385 Understanding Multidimensional Arrays 385 了解多维数组 Each of the arrays you have created in the preceding tips havecontained a single list of array elements. Sometimes, however, you will find itconvenient to use multidimensional arrays to organize data that is indexed bytwo or more parameters. You can visualize a two-dimensional array as arow-column table. You access elements within the table by specifying aparticular row and column. Think of a three-dimensional array as a stack oftables, each on a different piece of paper. You access elements within thethree-dimensional array by specifying a page, row, and column. Figure 385illustrates ways you can visualize multidimensional arrays. 在前面的诀窍中所创建的数组都只包含一个数组元素表。但有时你将会看到使用包含2个或多个下标的多维数组来组织数据会更方便些。你可以把一个2维数组直观地看作一个行列表。你用指明某个特殊行和特殊列的办法来访问表中的元素。而三维的数组则可以想象成为一大叠表,每一张表都画在不同的纸片上。你访问三维数组中的元素时要指出某页,某行和某列。图385形象地画出了你能看清楚的多维数组。 Production: Place figure - multidimensional arrays - SG Figure385 Multidimensional arrays. 图385多维数组 386 Declaring Multidimensional Arrays 386 说明多维数组 Tip 385 discussed multidimensional arrays. To declare amultidimensional arrays within a Java program, you simply specify additionalsets of bracketbraces. For example, to declare a two-dimensional array, youdeclare the array with two sets of bracketbraces, as shown: 诀窍385讨论了多维数组。要在Java程序中说明多维数组,你只需写出更多对的括号。例如,要说明两维数组,你只需写出两对括号,如下: int TicTacToe[][]; You can also use the alternative declaration syntax that youlearned in Tip 377 to declare multidimensional arrays by placing the extrabracketbraces after the primitive or object type. The following codedemonstrates an alternative declaration of a two-dimensional array: 你同样可以利用诀窍377中所介绍的句法来说明多维数组,把附加的括号对放在基本类型或对象类型之后。以下语句示范了说明2维数组的另一种方法: int[][] TicTacToe; You may even mix the two types of declarations., as demonstratedby Tthe following code: demonstrates how to do this: 你甚至可以把两种说明的形式混起来使用,如以下语句所表示的那样: int[] TicTacToe[]; Each of these examples declares an equivalent two-dimensionalarray reference. 以上每一个例子都是说明了相互等价的一个2维数组. 387 Creating Multidimensional Arrays 387 创建多维数组 In Tip 377, you have learned how to create single-dimensionalarray objects. To create a multidimensional array object, you simply specify anadditional array bracketbraces that specify the dimensions size information.For example, to create an array to keeptrack of fifty students grades for five tests, you can create a 50x5 array. Thefollowing statement demonstrates how to create a multidimensional array: 在诀窍377中你已知道了怎样创建一维的数组对象。要创建多维的数组对象,你只需再加一对括号来指明另一维数的大小即可。例如,要创建一个包含50个学生5次考试成绩的数组,你可以创建一个50*5的二维数组。以下语句说明了怎样创建一个多维的数组: Integer myarray[][] =new Integer [50][5]; As you have learned, because this statement defines an array ofInteger objects, this code only initializes the array elements to null. Tofinish making the array, you must create the members and assign values them tothe proper array elements. 正如你所了解的,由于这一语句定义的是整型对象的数组,所以Java只把数组元素初始化为NULL。要完全建成这个数组,你必须创建其中的各个成员,并为它们赋以固有的数组元素值。 388 Looping through Multidimensional Arrays 388 多维数组的循环 In Tip 380, you learned how to use a for statement to loopthrough a single-dimensional array. To loop through a multidimensional arrays,you can use a for loop for each array dimension. For example, to cycle throughall the members of a two-dimensional array, you use two for loops. The innerfor loop executes once (in its entirety) for each iteration of the outer forloop. The following statements demonstrate how you loop through atwo-dimensional array: 在诀窍380中,你已了解怎样使用For语句来组成一个能走遍一维数组的循环。要走遍一个多维的数组,则你必须为每一维组织一个For循环。例如,要走遍二维数组中所有的元素,就要用两个For循环,一个是外层循环,一个是内层循环。对外层For循环每一迭代,内层的For循环读要从头执行一遍。以下语句告诉你怎样组织循环来通过一个二维数组: public classarrayLooping { static public void main(String args) { Integer myarray[][] = new Integer[50][5]; for (int i=0; i < myarray.length; i++) { for (int k=0; k { myarray[i][k] = new Integer(i*10+ k); System.out.println(myarray[i][k]); } } } } The outer for loop, in this case, loops through the 50 rows ofthe array. The inner for loop, on the other hand, loops through the arrays 5columns. Notice that the outer loop determines the number of rows in the arrayusing myarray.length. Likewise, the inner loop determines the number of columnsin each row using myarray[i].length, where the index i corresponds to thecurrent row. 在本例中,外层For循环依次通过数组的50行,而内层For循环则通过数组的5个列。注意,外层For循环利用myarray.length来确定数组的行数。同样,内层For循环则是利用myarray[i].length来确定数组每一行中的列的数目,这里的下标i是当前行号。 389 Understanding Unbalanced Arrays 389 了解非平衡数组 So far, the two-dimensional arrays that you have created havebeen rectangular. Rectangular arrays are like tables. All of the rows are ofthe same length, and all of the columns are of the same length. Javasmultidimensional arrays are actually arrays of arrays. You do not have to haveEeach dimension does not have to be of a fixed length,. but dimensions must bespecified left to right. For example, the following declaration is legalbecause the elements are specified from left to right: 在此之前,你建立过的二维数组是矩形数组。矩形数组象表一样。所有的行有同样的长度,所有的列也有同样的长度。Java的多维数组实际确是数组的数组,但并不一定要将每一维数组的大小都设成固定长度。但维数必须从左到右依次说明。例如,以下的说明是合法的,因元素的数目是从左到右说明的: /* legal dimension specification */ /* 合法的维数说明*/ boolean legal_ex[][] = newboolean[2][]; On the other hand, this array declaration is illegal because itspecifies elements from right to left: 相反,以下的说明是不合法的,因元素的数目是从右到左说明的: /* illegal dimensionspecification */ boolean illegal_ex[][]= new boolean[][5]; Consider an example of a two-dimensional unbalanced array. For example,sSuppose, for example,d you use a two-dimensional array to keep track of a setof bowling pins. Each row has a different number of pins. So, the size of thearray for each row is different, and the array is triangular instead ofrectangular. To create a triangular array like this, you first must declare it.For a set of bowling pins, Tthe first dimension will be 4, representing thenumber of rows:. The second dimension will be unspecified. The following codedemonstrates this: 考虑一个二维不平衡数组的例子。例如,假如你要使用一个二维数组来保存一组滚轴 (bowling pins)的轨迹(track)。而每一行有不同的轴的数目。这样,为每一行设置的数组大小是不一样的,这时的数组形状就要用三角形来代替长方形。要建立这种样子的三角形数组,你首先要说明它。对于一组滚轴,第一个数组大小是4,它表示行数。而第二个大小将不指定。以下程序说明了这一情况: /* declare only thefirst dimension */ /* 仅说明第一个维数*/ boolean down_pins[][]= new boolean[4][]; Note: You should not specify a dimension on the right and leavea dimension on the left unspecified. This will lead to a compile error. 注意: 你不应该指定右边的维数大小而不先给出左边的维数大小,这会导致一个编译错误。 After you declare the array, you then create an array for eachrow. The following code demonstrates how to create a triangular array: 当你说明了这个数组后,你就可以为每一行创建一个数组。以下语句说明怎样建立一个三角形的数组: public class arrayPins{ static public void main(String args) { /* declare only the first dimension */ /* 仅说明第一个维数*/ boolean pins_fell [][] = newboolean[4][]; /* create the second dimension */ /* 创建第二个维数*/ for (int i=0; i< pins_fell.length;i++) { pins_fell [i] = new boolean[i + 1]; } /* print the contents of the array tothe screen */ /* 在屏幕上打印数组内容 */ for (int i=0; i< pins_fell.length;i++) { for (int k=0; k { System.out.print(pins_fell[i][k]+ " "); } System.out.println(""); } } } As you can see, the program allocates columns for each row ofthe array. Later, the program displays the contents of the two-dimensionalarray. When you compile and execute this program, your screen will display thefollowing output: 可以看出,程序为数组的每一行分配一个列。然后,程序显示二维数组的内容。当你编译和执行这一程序时,你的屏幕上将出现以下的输出结果: false false false false false false false false falsefalse 390 Initializing Multidimensional Arrays 390 初始化多维数组 As you have learned, when you create a single-dimensional array,you can initialize the array by placing the values between right and leftbraces {}. In a similar way, you can initialize a two-dimensional array at itsdeclaration by using additional braces {} to distinguish each dimension. Forexample, the following code demonstrates how to initialize a two-dimensionalarray of integer values: 你已了解了,当你创建一维数组时,你可以用在括号{}内给出每一数组元素值的办法来初始化这个数组。同样,对于一个二维的数组,你可以在说明这一数组时,来初始化这个数组。为此,需要增加一重括号{}来区别不同的维数。例如,以下程序说明了怎样初始化一个二维整型数组: int myarray[][] = {{1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }}; Notice that the statements separate each row with a comma. Inaddition, the declaration does not specify an array size. Instead, the Javacompiler determines the array size of the arrays based on the values youspecify.You can also initialize unbalanced multidimensional arrays at their declaration.For example, the following code demonstrates how to initialize a triangulararray of integers: 注意语句用一逗号来分隔每一行,并且说明中不指出数组的大小。Java能根据你指定的值由编译器来确定数组的维数大小。你同样可以在说明一不平衡多维数组时来初始化这个数组。例如,以下程序说明了怎样初始化一个三角形整数数组: int myarray[][] = {{ 1}, { 2, 3 }, { 4, 5, 6 }, { 7, 8, 9, 10 }}; 391 Searching an Array for a Specific Value 391 在一数组中搜索一特殊值 You have learned that arrays allow you to access a set ofobjects of the same type. One operation your programs will commonly perform onarrays is to search for a specific value. There are two classic types of searchtechniques, sequential and binary. In aA sequential or linear search, yousearch is simply going though the array elements one by one, starting from thefirst location until you find a match. You can easily implement a sequentialsearch with a for loop. The following program code, for example, demonstrateshow you would perform a linear search: 你已知道,数组能使你访问一组相同类型的对象。程序在一数组上共同完成的一种操作是搜索一个特殊的数值。有两种典型的搜索方法,即顺序搜索和二分法搜索。在一顺序搜索或线性搜索中,搜索需要一个接一个地考察数组中的每一个元素,从第一个位置开始,直到找到那个匹配的元素位置为止。你很容易用For循环的方法来实现。以下程序就是实行了按线性顺序的搜索: public classarrayLinear { public static int lsearch(int array[], intvalue) { for (int i=0; i < array.length; i++) { if (array[i] == value) return(i); // return index; 返回下标值 } return(-1); } public static void main(String[] args) { int array[] = new int[100]; for (int i=0; i < array.length; i++) { array[i] = i; } System.out.println("Result " +lsearch(array, 67)); System.out.println("Result " +lsearch(array, 33)); System.out.println("Result " +lsearch(array, 1)); System.out.println("Result " +lsearch(array, 1001)); } } As you can see, the lsearch method loops through the arrayelements until it locates a matching value. If your search does not find amatch, the method returns the value -1. If your search successfully locates thevalue, the method returns the index value that corresponds to the valueslocation within the array. 可以看出,lsearch方法从数组的第一个元素开始循环,直到匹配的数值处停止。如果你的搜索没有找到匹配的数值,方法将返回数值-1。如果你的搜索找到匹配的数值,方法将返回对应于这一数值数组下标值。 392 Understanding the Binary Search 392 了解二分法搜索 In the previous tip, Yyou have learned that you can find anelement in an array by searching each element of the array one by one.Unfortunately, sequential searches are very inefficient for large arrays. Ifyour array is sorted, you can use a binary search instead to locate a valuewithin the array. A binary search repeatedly is able to subdivides the arrayuntil it finds your desired element. For example, the element you are searchingis found. you have undoubtedly searched for a word in a dictionary. Asequential search is equivalent to searching each word one by one, startingfrom the very first word. If the word is much past the first page, this type ofsearch is a very inefficient process. It should be obvious how inefficient thiswould be. 在前面的诀窍中你已知道,可以用一个一个依次搜索每一数组元素的办法来找到数组中的一个元素。不幸的是,对于大型数组来说,顺序搜索方法效率极低。如果你的数组已排序,你可以改用二分法搜索,而不是依次搜索数组中每一个元素,直到找到匹配位置。二分法搜索对数组重复地进行分划,直到找到需要的元素为止。例如,假如你搜索的是一个新的单字,则你无疑会去查字典。顺序搜索等价于从字典的最前面的一个单字开始一个一个查阅。如果所查的单字离开首页很远,这种类型的搜索将是一个极为无效的过程, 多么无效是显而易见的。 A binary search is equivalent to opening a dictionary in themiddle, and then deciding if the word wasis in the first half or second half ofthe book. You then open the next section in the middle and then decide if theword is in the first half or second half of that section. You can then reYourpeat this process of dividing the book in half until you find the word forwhich you are looking. If you have never tried, pick a word and try to find itin a dictionary using a binary searchwith this technique. You wouldmight be surprised at how few divisions it takes to getvery close to the word you are looking for. A binary search is very efficient.However, the array must be in a sorted for it twoto work. 二分法搜索相当于从中间翻开一本字典,然后判别单字是在前面一半中还是在后面的一半中。然后再在确定的一半的中间再翻开来,并再判别所要找的单字是在这一半的前面一半还是后面一半中。你对字典重复这个一半一半的分划过程,直到找到你想找的那个单字。如果你从来没有试过,不妨任意检一个单字在一本字典上用二分法去试找一下。你一定会惊讶在如此少的几次分划后就会非常接近你所要找的那个单字。二分法是非常有效的,但它所用的数组必须是已排序的。 393 Using a binary search 393 使用二分法搜索 You have learned that aA binary search is an efficient algorithmfor searching through a sorted array. The technique of how to implement thebinary search is best demonstrated with an example. To demonstrate the binarysearch technique, Tthe following program looks throughsearches an array of integersfor various values. AsWhen you execute the program executes, it prints messagesare printed to the screen that describe the process of the search. Also, at theend of the search, the program displays the number of steps it required to findthe desired valueby the binary search: to the screen: 你已知道二分法搜索是对已排序的数组的一种非常有效的搜索算法。怎样实现二分法搜索的过程最好是通过一个例子来说明。以下程序通过对一个整型数组寻找某个值来说明二分搜索法。当此程序执行时,描述搜索过程的信息将在屏幕上打印出来。并且,在搜索完毕后,程序将在屏幕上显示用二分法找到所找数值所需的步数: public classarrayBinary { public static int bsearch(int array[], intvalue) { boolean found = false; int high = array.length - 1; int low = 0; int cnt = 0; int mid = (high + low)/2; System.out.println("Looking for" + value); while (!found && (high >=low)) { System.out.print("Low " +low + " Mid " + mid); System.out.println(" High" + high); if (value == array[mid]) { found = true; } else if (value < array[mid]) high = mid - 1; else low = mid + 1; mid = (high + low)/2; cnt++; } System.out.println("Steps " +cnt); return((found) ? mid: -1); } public static void main(String[] args) { int array[] = new int[100]; for (int i=0; i < array.length; i++) { array[i] = i; } System.out.println("Results " +bsearch(array,67)); System.out.println("Results " +bsearch(array,33)); System.out.println("Results " +bsearch(array,1)); System.out.println("Results " +bsearch(array,1001)); } } From this programs output, you can see how a binary searchsub-divides an array. The program uses the high, mid, and low variables to keeptrack of the ranges for each step of the search. The following tips describehow to sort an array, so that you may use the binary search technique. 从此程序的输出你可看到二分法搜索是怎样分划一个数组的。程序利用了high,mid和 low 三个变量来保存每一步搜索的范围。以下程序描写了怎样为数组排序,这样你就可以使用二分搜索法了。 394 Sorting an Array 394 数组的排序 You have learned that arrays let your programs manipulate aseries of objects of the same type. One operation your programs may often needto perform is sorting the arrays objects. A program can sort an array. an arrayof numbers from smallest to largest (ascending order) or largest to smallest(descending order). In a similar way, a program can Even asort an array ofStrings alphabetically. In fact, any array with objects that can be comparedwith a greater, equal, or less than result can be sorted. Your program can usemany techniques to sort an array. Each technique makes a trade-off betweencomplexity and efficiency. The following tips describe some useful array-sorting techniques. 你已知道,数组使你的程序能处理相同类型的一系列对象。你的程序可能经常需要执行的另一种操作是数组对象的排序。一个程序可以对一个数值数组进行排序,使它排成由小到大的顺序(升序),或排成由大到小的顺序(降序)。用类似的方法,一个程序也可以对一个字符串数组进行排序,使它们排成字典顺序或逆字典顺序。事实上,凡是可以用大于、等于、和小于来比较的任何一种对象数组都可以被排序。你的程序可以用许多办法来对数组进行排序。每一种方法都要在复杂性和有效性方面进行合理的选择。以下几个诀窍描述了几种可用的数组排序方法。 395 Understanding the Bubble Sort 395 了解冒泡法排序(Bubble Sort) Just as Hello, World is the first program many programmerswrite, the bubble sort is the first sorting technique most programmers learn.BecauseBecause it is simple, the bubble sort is not very efficient. For largearrays, the bubble sort can be very slow. However, for small arrays of 30 orless elements, it performs adequately. 正象 Hello,World是许多程序员写的第一个程序那样,冒泡法排序是许多程序员学习的第一种排序方法。由于这种排序方法简单,效率也就不高。对于大数组,用冒泡法排序可以非常慢。但对于30个元素或30个元素以下的数组来说,它已足够用了。 To use a bubble sort to place array values in ascending order(smallest to largest), the bubble sort works throughtraverse the array andmoves the largest value to the top of the array. It repeats this process untilno more values are left. For example, suppose you have three children that mustbe lined up by height for school pictures. To start, you can compare the firstto second children and switch them if necessary. Then, you compare the secondto third, again switching if necessary. After this first pass, the tallest child will be third. You then compare thefirst to the second and switch if necessary. That is it. The children will bein the correct order. Figure X. illustrates the bubble sort technique for anarray of integers. 为了利用bubble sort将数组排成升序(由小到大的次序),bubble sort搜索整个数组,并将最大的元素搬到数组的顶部(即作为下标最大的元素)。它重复这一个过程,直到用完所有的数值。例如,假设你有三个孩子要按高矮个子排队,高的排在后面。开始,你比较第一个和第二个孩子,并当必要时交换他们的次序。然后你比较第二个和第三个孩子,同样在必要时交换他们的次序。做完这些后第一遍结束,最高的孩子已到了最后。然后你再比较第一个和第二个孩子,并在必要时交换他们的次序。这样就结束, 孩子们已排成正确的次序。图395说明了一个整型数组bubble sort法。 Production: Place figure - bubble sort - SG Figure 395 Iterations of a bubble sort. 图 395冒泡法排序的叠代过程 396 Putting the Bubble Sort to Use 396 应用冒泡法排序 In the previous tip, you learned that the bubble sort is asimple sorting technique that can be used on small arrays. The following code,arrayBubble.java, demonstrates the use of a bubble sort to sort an array of 30random integers: 在以上诀窍中你已了解冒泡排序是一中简单的排序方法,它只能用在小的数组的排序。以下程序arrayBubble。java是利用冒泡排序法对包含30个整数的数组进行排序: public classarrayBubble { public static void bubble_sort(int array[]) { inti = array.length; while (--i >= 0) { for (int j = 0; j < i; j++) { if (array[j] > array[j+1]) { /* swap values */ int temp = array[j]; array[j] = array[j+1]; array[j+1] = temp; } } } } public static void main(String[] args) { int array[] = new int[30]; System.out.println("BeforeSort"); for (int i=0; i { array[i] = (int)(Math.random() *30.0); System.out.println(array[i]); } bubble_sort(array); System.out.println("AfterSort"); for (int i=0; i { System.out.println(array[i]); } } } The bubble sort is only suitable for small arrays. The next tipcovers a more sophisticated sorting technique that is much more processorefficient. 冒泡法排序仅适用于小数组。下一诀窍将介绍一个远为复杂的排序方法,但也有高得多的处理效率。 397 Understanding Quick Sort 397 弄懂Quick Sort(快速排序) For large arrays, you need an efficient sorting technique. Oneof the most efficient techniques is the quick sort. The quick sort techniquetakes the middle element of an array and sub-divides the array into two smallerarrays. One array will contain elements greater thant the middle value of theoriginal array. Conversely, the other array will contain elements that are lessthan the middle value. The quick sort will repeat this process for each newarray until the final arrays contain only a single element. At this point, thesingle element arrays are in the proper order, as shown in Figure 397. 对于大的数组,你必须寻找一种有效的排序方法。Quick sort 就是最有效的排序方法之一。Quick sort 方法计算了位于数组中心的元素,并用它把数组分成两个较小一点的数组,其中一个包含了比中心元素大的元素,而另一个则包含了比中心元素小的元素。Quick sort重复以上过程,直到最后,小数组只包含一个元素。到此时,单元素的数组就是排好序的数组,如图397所示。 Production: Place figure - quick sort - SG Figure 397 Iterationsof a quick sort. 图397Quick sort的叠代过程 398 Putting the Quick Sort to Use 398 应用快速排序 In the previous tip, you learned that the quick sort is anefficient technique that you can use to sort an array. The following codedemonstrates how to quick sort an array of 1,000 random integers. 在以上诀窍中,你已知道了quick sort是一种可用来对一数组进行排序的有效方法。以下程序说明了怎样为1000个随机整型数数组进行排序: public classarrayQsort { static void qsort(int array[], int first, intlast) { int low = first; int high = last; if (first >= last) return; int mid = array[(first + last)/2]; do { while (array[low] < mid) low++; while (array[high] > mid) high--; if (low <= high) { int temp = array[low]; array[low++] = array[high]; array[high--] = temp; } } while (low <= high) ; qsort(array, first, high); qsort(array, low, last); } public static void main(String[] args) { int array[] = new int[1000]; System.out.println("BeforeSort"); for(int i = 0; i < array.length; i++) { array[i] = (int)(Math.random() *1000.0); System.out.println(array[i]); } qsort(array, 0, array.length-1); System.out.println("AfterSort"); for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } } Note: The previous quick sort function sorts an array fromlowest to highest. To change the order of the sort, you simply change thecomparisons in the while loops, as the following code illustrates: 注意: 以上的quick sort函数由低到高地为一数组进行排序。如果要改变排序的次序,你只需改变循环中的比较方法,如下: while (array[low] >mid) low++; while (array[high]< mid) high--; 399 Using arraycopy on an Array of Primitive DataTypes 399 对原始数据类型数组使用数组复制(arraycopy) As you work with arrays, you may sometimes need to copy thearrays contents. To help simplify an array copy operation, Java provides thearraycopy method. You have learned that creating an array of primitive datatypes is slightly different than creating an array of objects. You will findthat arraycopy also works somewhatslightly differently for arrays of primitivedata types and objects. 当你用数组工作时,你有时需要复制数组的内容。为了帮助你简化数组的复制操作, Java提供了一个数组复制方法。你已了解,创建一个原始数据类型的数组和创建一个对象的数组是有差别的。你将发现,原始数据类型的数组复制和对象数组的复制也是有差别的。 When you copy an array of primitive data types, arraycopy worksas you would expectthe method copies the entire array to a different array. Thetarget array must have been created already exist, and. Also, it must be large enough to hold thecopy. After the copy, the two arrays are independent. Figure 399 illustrateshow to visualize an arraycopy of primitive data types. 当你复制原始数据类型的数组时,arraycopy正象你期望的那样工作,它把整个数组复制成另一个数组,但目标数组必须先要创建好、已存在,并且,还必须足够大,以保证这种复制的完成。在复制后,两个数组是独立的。图399是原始数据类型数组的复制的形象化说明。 Production: Place figure - arraycopy primitive data types - SG Figure 399 Copying an arrayof primitive data types. 图399 一个原始数据类型数组的复制 The following code, arrayCopyPrim.java, demonstrates how to usethe arraycopy method to copy an array of integers. 以下的arrayCopyPrim.java程序说明怎样用arraycopy方法来复制一整型数组。 public classarrayCopyPrim { public static void main(String[] args) { int array1[] = { 0, 1, 2, 3, 4 }; int array2[] = new int[5]; System.arraycopy(array1, 0, array2, 0,array1.length); array2[2] = 200; // modify second array 修改第二个数组 System.out.print("Array 1: "); for (int i = 0; i < array1.length;i++) System.out.print(array1[i] + ""); System.out.println(); System.out.print("Array 2: "); for (int i=0; i System.out.print(array2[i] + ""); System.out.println(); } } When you compile and execute this program, your screen willdisplay the following output. 当你编译和执行这一程序后,在显示器上将出现以下结果: Array 1: 0 1 2 3 4 Array 2: 0 1 200 3 4 In this example, after the program copies the array, the programmodifies the third element of the second array. When the program later displaysthe contents of both arrays, notice that the first array is unchanged. In otherwords, after you use the arraycopy method, the arrays are independent. Withinyour programs, you do not have to copy an entire array with the arraycopymethod. If you examine the arguments to the arraycopy method, you will findthat it lets you can copy a range of elements into another array. 在本例中,当程序复制完数组后,程序修改了第二个数组的第三个元素。当程序在以后再显示这两个数组的内容时,可发现第一个数组没有变。换言之,在你使用了数组复制方法arraycopy之后,两个数组是独立的。在你的程序中,你并不必须用arraycopy方法来复制整个数组。如果你查看一下arraycopy方法的自变量,你将发现它能使你把一个范围的元素复制到另一个中。 400 Using arraycopy on an Array of Objects 400 对Object数组使用数组复制 You learned in the previous tip that when you copy an array ofprimitives, the copy is physically different from the original. However, Wwhenyou copy an array of objects, only the object references are copied to the newarray. The objects that make up the elements of the source array are notduplicated. When you modify an object that is an element of one array, youactually modify the corresponding element of the other array. Figure 400illustrates how to visualize an arraycopy of objects. 你在前面的诀窍中已知道,当你复制一个原始数组时,复制所得数组的与原始数组实际不同。但是,当你复制一个对象数组时,只有对象的引用被复制到新的数组中。组成原有数组元素的对象是不复制的。当你修改一个数组元素对象时,你实际是修改了另一数组的对应元素。图400说明了怎样把对象的数组复制弄的更形象化。 Production: Place figure - arraycopy objects - SG Figure 400 Copying an arrayof objects. 图400 对象数组的COPY The following code demonstrates how to copy an array of objects: 以下程序说明怎样复制一个对象数组: public classarrayCopyObject { public static void main(String[] args) { StringBuffer array1[] = newStringBuffer[5]; StringBuffer array2[] = newStringBuffer[5]; for (int i=0; i array1[i] = newStringBuffer(Integer.toString(i)); System.arraycopy(array1, 0, array2, 0,array1.length); array2[2].append("00"); //modify second array 修改第二个数组 System.out.print("Array 1: "); for (int i=0; i System.out.print(array1[i] + ""); System.out.println(); System.out.print("Array 2: "); for (int i=0; i System.out.print(array2[i] + ""); System.out.println(); } } When you compile and execute this program, your screen willdisplay the following output. 当你你编译和执行这一程序时,屏幕上将出现以下的输出结果: Array 1: 0 1 200 3 4 Array 2: 0 1 200 3 4 In the previous example, after the program copies the array, theprogram modifies the third element of the second array. After the programdisplays the contents of both arrays, notice that the both arrays have beenmodified. Clearly, both arrays point to the same list of objects. 在以上例子中,当程序复制了数组后,程序修改了第二个数组的第三个元素。但当你的程序再显示两个数组的内容时,可以发现,所有两个数组都已被改变了。很明显,两个数组是指着同一个对象表。 401 Storing Different Objects in an Array 401 在一数组中存放不同的对象 The arrays you have created in the previous tips only contain asingle type of object. As it turns out, you can also create arrays that hold manydifferent types of objects. The most generic array that you can declare in Javais of type Object. Every Java object is a subclass of the Object class. Withinan array, you can store any Java objects reference. However, to retrieve anduse an object from an Object array, you must use the instanceof operator. Thefollowing code demonstrates how you can store images and rectangles in a single array: 前面你所创建的各种数组仅包含单种类型的对象。当需要时,你也可以创建包含多种对象类型的数组。在Java中,你可以说明的最根本的数组是Object型数组。每一个Java对象是Object类的子类。一个数组可以用来存放任意的Java对象的引用。但是,为了从Object数组中抽取(retrieve)和使用(use)一个对象,你必需使用instanceof函数。以下这些语句说明了怎样在单一的数组中存放图象和矩形: import java.awt.*; importjava.awt.image.*; import java.applet.*; public classarrayOfObjectsApplet extends Applet { Object array[] = new Object[4]; public void init() { array[0] = getImage(getCodeBase(),"a.gif"); array[1] = getImage(getCodeBase(),"b.gif"); array[2] = new Rectangle(0,26,26, 26); array[3] = new Rectangle(26,0,26, 26); } public void paint(Graphics g) { g.setColor(Color.black); for (int i = 0; i < array.length; i++) { if (array[i] instanceof Image) { Image img = (Image) array[i]; g.drawImage((Image)array[i],i*26,i*26,this); } else if (array[i] instanceofRectangle) { Rectangle r = (Rectangle)array[i]; g.fillRect(r.x, r.y, r.width,r.height); } } } } As you have learned, Java applets useinterfaces to allow one class to access the data and methods of another.Sometimes, you will find it more convenient to create an interface that allobjects in an array implement. In this way, you can then call the methods ofthe interface without having to know what the objects are. 正如你所见到的,Java小应用程序利用接口使一个类能访问另一个类的数据和方法。有时,你会发现建立一个接口把所有对象都放在一数组工具中将更方便。这样,你不需要知道对象是什么就可以调用接口方法。 1001 Java Programming Tips Page 18 of numpages 12 filename jtip050b.doc August 11, 1996 事件驱动编程 402 Understanding Event-Driven Programs 402 了解事件驱动程序 TheHello World program is an example of a simple Java program. The program hasjust one purpose: to display a string to the screen. As you will learn, mostJava programs are much more complex and must respond to a variety of events. Anevent-driven program is a program that waits for someone (or something) to tellit to do something. For example, assume the program resizes the applet window.The browser, in turn, will generate an event that tells the applet to resizethe window. The applet, in turn, will call the paint function to redraw thewindow. Hello world 是Java程序的一个简单例子. 这一程序只有一个用途:在屏幕上显示一个字符串. 你将会看到,大多数Java程序都比它远为复杂,并且要响应大量的事件. 一个事件驱动编程是这样的一种程序,它等待某些事件的发生,来告诉它需要做什么. 例如,假设程序是重定应用块的窗口. 则浏览器将产生一个事件告诉应用块要重定窗口,而应用块则又将告诉paint函数要重定这一窗口. As you will learn, a user, the operating system,or other programs can generate events. When an event-driven program doessomething in response to an event, the program is said to have handled theevent. For example, suppose you want your program to quit when a user pressesthe Q key. You would write your program so that it detects and handles allkeydown events. If the user presses the Q key, you can end the program. As yourJava programs become more complex, they will make extensive use of events. Tosimplify your programming, Java predefines an Event class. 你将会看到,一个用户,或者是操作系统,或者是其它的程序,都会生成事件. 当一事件驱动程序在响应某个事件而做什么事情的时候,我们就说该程序是在处理事件. 例如,假设你要你的程序在用户按了 Q 键时退出程序, 则你的程序必须能检测并处理每一个按键事件. 如果用户按的是Q键,则你应终止你的程序. 当你的Java程序变成非常复杂时,它们将会经常应用事件. 为了简化你的程序设计, Java已预定义事件类,Event class. 403 Understanding the Event Class 403 了解事件类(Event class) As you will learn, Java generates an Event objectwhen something happens (an event occurs) for which the applet must respond. AnEvent object is an instance of the Event class, and stores information aboutthe event. For example, when you click the mouse, Java generates an eventobject that contains the mouse screen coordinates. Likewise, when you press akeyboard key, Java generates a keyboard event that contains the keys ASCIIcode. When an event occurs, Java calls a series of methods based on the eventtype. Table 403 shows some of the information stored in the Event object. 你将会知道,当应用块必须响应的某种事情发生时,Java就会生成一个Event类. Event对象是Event类的一个实例,它保存着有关事件的信息. 例如,当你在鼠标器上击键时,Java将产生一个事件,用来保存鼠标的屏幕坐标. 同样,当你在键盘上按下一个键时,Java将产生一个键盘事件,用来保存按键的ASCII码. 当一事件发生时,Java将根据事件的类型而调用一系列的方法. 表403指出了存于Event对象中的几种信息. Type Name Description ------------------------------------------------------------------------- int id Contains the event type identifier Object target Object where eventoccurred int clickCount Multiple mouseclick flag int key Key code for keyboard events int modifiers Modifier keys statewhen event occurred long when Time when eventoccurred int x,y Coordinates of mouse events ------------------------------------------------------------------------- Table 403 Event classvariables. 类型 名称 说明 ------------------------------------------------------------------------- int id 包含事件类型标识符 Object target 事件发生的对象 int clickCount 鼠标重击标志 int key 键盘事件的击键码 int modifiers 事件发生时变动键的状态 long when 事件发生的时间 int x,y 鼠标事件的光标位置 ------------------------------------------------------------------------- 表403 事件类变量 Not all events have valid data for all thevariables in the Event object. For example, it does not make sense to check theclickCount variable for a keydown eventthe clickCount variable corresponds tomouse double-click operations. The following tips will show you how to use theEvent class data. 在Event对象中,并不是所有变量都产生有用的数据. 例如,检测击键事件的clickCount变量是没有意义的. clickCount变量仅用于区别鼠标的单击和双击. 以下TIP将向你显示怎样使用Event类数据. 404 Understanding Convenience Methods 404 了解Convenience方法 In most event-driven programming languages, theprogram sits in a loop waiting for events to occur. Within this event loop, youplace code that decides which part of your program should receive the event.Based on your code, the program dispatches events by calling appropriatemethods.Within a Java applet, Java provides this event-processing loop behindthe scenes for you. Also, Java defines a set of convenience methods to helpyour program distinguish between events. A convenience method is how Java tellsyour program that a particular type of Event has occurred. For example, if auser clicks the mouse, Java will call the mouseDown convenience method. 在大多数事件驱动程序设计语言中,程序处在一循环中等待事件的发生. 在这事件循环中, 你加入了一段代码来确定你的程序的哪一部分应接收事件. 根据你的代码,程序调用不同的方法来处理事件. 在Java应用程序中,Java在后台为你提供了这种事件处理循环. 同样,Java定义了许多能帮助你的程序区别不同事件的Convenience方法. 其中一个Convenience方法是Java怎样来告诉你一种特别类型的事件已发生. 例如, 如果用户按下了mouse键,Java将调用mouseDown方法. Java declares convenience methods in the Componentclass. You will learn the details of the Component class in later tips. Fornow, you just need to know that the Applet class is a subclass of the Componentclass which defines many of component objects every program needs (such as theconvenience methods). Consequently, you can use the convenience methods in anyclass you extend from the Applet or Component classes. Java在Component类中声明Convenience方法. 你将在今后的TIP中学习Component类的细节.现在,你只需知道Applet类是Component类的一个子类,它定义了许多每一个程序都要用的Component对象(例如Convenience方法). 因此, 你可以在由Applet类或Component类扩充而得到的任何类中使用Convenience方法. Within your applet, you can have more than oneobject that extends from the Component class. Each of these objects can haveits own convenience methods. Java will call the correct methods based on thetype of event that occurred. 在你的应用程序中,你可以有多个由Componet类扩充而来的对象. 这些对象每一个都可以有自己的Convenience方法. Java将根据发生的事件的类型来调用正确的方法. 405 Using the mouseDown Method 405 使用mouseDown方法 As your applets become interactive, they will needto respond to mouse and keyboard events. One of Java's convenience methods isthe mouseDown method, which your programs can use to detect when a user hasheld down the mouse button. The following program, mouseDownApplet.java,displays the mouse-screen coordinates every time the user clicks the mouse(causing Java to call the mouseDown method): 当你的程序是交互式程序时,它们必需响应鼠标事件和键盘事件.Java的Convenience方法之一是mouseDown方法,你可以用它来检测何时用户按下了Mouse键. 以下这一程序,mouseDownApplet.java,在每当用户点击鼠标(导致Java调用mouseDown方法)显示mouse 的屏幕坐标. kaj test this import java.awt.*; import java.applet.*; public classmouseDownApplet extends Applet { public boolean mouseDown(Event evt, int x,int y) { System.out.println("Mouse Down(" + x + "," + y + ")"); return(true); } } The mouseDown methods first argument is the Eventobject. The second and third arguments are the (x and y) screen coordinates ofthe mouse pointer at the time the user clicked the mouse. The screencoordinates specify the distance in pixels from the upper-left corner of thedisplay to the mouse pointers location. In the previous example, the applet windowsupper-left corner is location (0, 0). mouseDown方法的第一个自变量是Event变量.第二和第三个自变量(x,y)是用户点击mouse时的mouse光标的屏幕坐标. 屏幕坐标指示mouse光标与显示器左上角的距离,用pixel为单位来计算. 在前一例子中,applet窗口左上角的位置是(0,0). Note that the mouseDown method returns true. Whenyou create an event handler within your applets, your method should return thevalue true to tell Java that you have handled the event. If Java receives thetrue value, Java will not call any other convenience methods to handle theevent. If your event handler returns false, Java will call another eventhandler to process the event. 注意,这里mouseDown方法返回的是true.当你在你的applet中创建一个事件句柄(event handler)时,你的方法必须返回true值以通知Java你已取得了事件信息. 如果Java接受了true值,Java就不再调用其它的convenience方法来处理事件. 如果你事件句柄返回了false,则Java将会调用其它的事件处理程序来处理事件. 406 Using the mouseUp method 405 使用mouseUp方法 In the previous tip, you learned about themouseDown event which Java calls when the user holds down the mouse button.Conversely, Java provides the mouseUp event when the user releases the mousebutton. If you are not familiar with writing graphical user interfaces, you maywonder why there are two mouse-click events. A common use of the mouse-downevent is to highlight a control, such as a button, that the user has selected.If the user releases the mouse button over the control, the program knows theuser has accepted the button. However, if the user moves the mouse off thecontrol before the mouse is released, the program knows the user did not selectthe button. 在以上TIP中,你已知道了mouseDown方法是用户按住mouse按钮时Java所调用的. 相反地, Java也提供一个mouseUp方法是用户释放mouse按钮时产生的. 如果你不熟悉用图形用户接口编程, 你可能对为什么要两个mouse击键事键感到奇怪. mouseDown方法的普通用途是强调显示(highlight)用户选择的一个控制,如button(按钮). 如果用户在控制上释放了mouse按钮,程序知道用户是接受了button.如果用户在mouse释放之前把mouse移开了控制,程序将知道用户没有选择此button. The following program, mouseUpApplet.java,displays a message to the screen every time the user holds down the mousebutton and also when the user releases the button. The program also displaysthe mouse-screen coordinates for each event: 以下的mouseUpApplet.java程序在每当用户按着mousebutton和释放mouse button时在屏幕上显示一个消息. 程序同时也为每一事件显示mouse光标的屏幕坐标: import java.awt.*; import java.applet.*; public classmouseUpApplet extends Applet { public boolean mouseDown(Event evt, int x,int y) { System.out.println("Mouse Down(" + x + "," + y + ")"); return(true); } public boolean mouseUp(Event evt, int x, inty) { System.out.println("Mouse Up(" + x + "," + y + ")"); return(true); } } Take time now to run this applet. Next, move andclick the mouse both from within and outside of the applet window to learn howJava responds to such mouse operations. 现在来运行这一应用程序.然后移动mouse,并在应用块窗口的内部和外部点击mouse键,以了解Java是怎样响应这些mouse操作的. 407 Using the mouseDrag method 407 使用mouseDrag方法 In the previous tips, you have learned how todetect and respond to mouse-down and mouse-up events. There may be times, however,when you need to track how a mouse moves between mouse-down and mouse-upeventsin other words, how the user drags the mouse. For example, many graphicalprograms use a bounding box which shows users the screen area they areselecting. To help your programs process mouse-drag operations, Java providesthe mouseDrag convenience method which lets the applet track the mouse from themouse-down event to the mouse-up event. 在以上的TIP中,你已知道了怎样检测和响应mouse-down和 mouse-up 事件. 但有时你还需探索mouse是怎样在mouse-down和 mouse-up事件之间移动的,也就是说,了解用户是怎样拖动mouse的. 例如,许多图形软件使用一个矩形框向用户指示他们正在选取的屏幕范围. 为了帮助你的程序处理mouse拖动操作,Java提供一个convenience方法,叫mouseDrag方法,它使应用程序可在mouse-down到mouse-up事件之间拖动mouse. The following program, mouseDragApplet.java, doesthree things. First, the applet displays a message to the screen every time theuser holds the mouse button down. Next, the applet displays a message as theuser moves the mouse. Finally, the applet displays a message when the userreleases the mouse button. 以下的程序mouseDragApplet.java做了三件事. 首先,它在用户按下mouse button时在屏幕上显示一个消息; 然后,当用户移动mouse时程序又显示一个消息; 最后, 当用户释放mousebutton时再显示一个消息. import java.applet.*; import java.awt.*; public classmouseDragApplet extends Applet { public boolean mouseDown(Event evt, int x,int y) { System.out.println("mouseDown:(" + x + "," + y +")"); return(true); } public boolean mouseUp(Event evt, int x, inty) { System.out.println("mouseUp:("+ x + "," + y + ")"); return(true); } public boolean mouseDrag(Event evt, int x,int y) { System.out.println("mouseDrag:(" + x + "," + y +")"); return(true); } } When you run this applet, do not expect equal timeintervals between calls to the mouseDrag method. The frequency Java uses tocall the mouseDrag method depends both on the operating system and the machinesspeed. 当你运行这一应用程序时, 不能期望在调用mouseDrag方法时有相同的间隔时间. Java在调用mouseDrag方法时所使用的频率既和操作系统有关,也和机器的速度有关. 408 Using the mouseMove Method 408 使用mouseMove方法 In the previous tips, you have learned how todetect and respond to mouse-down and mouse-up events. There may be times,however, when you need to track how a mouse moves between mouse-down andmouse-up eventsin other words, how the user drags the mouse. For example, manygraphical programs use a bounding box which shows users the screen area theyare selecting. To help your programs process mouse-drag operations, Javaprovides the mouseDrag convenience method which lets the applet track the mousefrom the mouse-down event to the mouse-up event. 在以上的TIP中,你已知道了怎样检测和响应mouse-down和 mouse-up 事件. 但有时你还需探索mouse是怎样在mouse-down和 mouse-up事件之间移动的,也就是说,了解用户是怎样拖动mouse的. 例如,许多图形软件使用一个矩形框向用户指示他们正在选取的屏幕范围. 为了帮助你的程序处理mouse拖动操作,Java提供一个convenience方法,叫mouseDrag方法,它使应用程序可在mouse-down到mouse-up事件之间拖动mouse. {以上看来有错,drag,还是move?待纠!,408段都有问题!} The following program, mouseDragApplet.java, doesthree things. First, the applet displays a message to the screen every time theuser holds the mouse button down. Next, the applet displays a message as theuser moves the mouse. Finally, the applet displays a message when the userreleases the mouse button. 以下的程序mouseDragApplet.java做了三件事. 首先,它在用户按下mouse button时在屏幕上显示一个消息; 然后,当用户移动mouse时程序又显示一个消息; 最后, 当用户释放mousebutton时再显示一个消息. import java.applet.*; import java.awt.*; public classmouseDragApplet extends Applet { public boolean mouseDown(Event evt, int x,int y) { System.out.println("mouseDown:(" + x + "," + y +")"); return(true); } public boolean mouseUp(Event evt, int x, inty) { System.out.println("mouseUp:("+ x + "," + y + ")"); return(true); } public boolean mouseDrag(Event evt, int x,int y) { System.out.println("mouseDrag:(" + x + "," + y +")"); return(true); } } When you run this applet, do not expect equal timeintervals between calls to the mouseDrag method. The frequency Java uses tocall the mouseDrag method depends both on the operating system and the machinesspeed. 当你运行这一应用程序时, 不能期望在调用mouseDrag方法时有相同的间隔时间. Java在调用mouseDrag方法时所使用的频率既和操作系统有关,也和机器的速度有关. In Tip 407, you learned that the mouseDrag methodlets your applets track mouse movement when the user is holding down the mousebutton. However, there may be times when you will need to track mouse movementswhen the user is not holding the mouse button down. For example, suppose youwant to display the mouses screen coordinates as the user moves the mousearound a drawing area. For such cases, you can use the mouseMove method todisplay the coordinates. The following program, mouseMoveApplet.java,demonstrates how to track the mouse movements using the mouseMove method: 在TIP 407中,你已知道了mouseDrag方法使应用程序在用户按下mouse button时能拖着mouse移动. 但是,有时你也需要在用户不按mouse button时来移动mouse. 例如,当用户在作图区域中移动mouse时,你的程序要显示mouse的屏幕坐标. 在这种情况下,你可使用mouseMove方法来显示坐标. 以下的mouseMoveApplet.java程序说明了怎样用mouseMove方法来拖着mouse移动. import java.applet.*; import java.awt.*; public classmouseMoveApplet extends Applet { public boolean mouseDown(Event evt, int x,int y) { System.out.println("mouseDown:(" + x + "," + y +")"); return(true); } public boolean mouseUp(Event evt, int x, inty) { System.out.println("mouseUp:("+ x + "," + y + ")"); return(true); } public boolean mouseMove(Event evt, int x,int y) { System.out.println("mouseMove:(" + x + "," + y +")"); return(true); } } As was the case with the mouseDrag method, youcannot expect equal intervals between calls to the mouseMove method. However,you can expect that Java will call the method often enough to give the user anadequate response. 和mouseDrag方法的情况一样, 你不能期望在调用mouseMove方法时有相同的间隔时间.但是,你可以期望Java调用mouseMove方法是足够经常的, 它能给用户充分的响应. 409 Detecting Double-Clicks with clickCount 409 利用clickCount检测Double-Clicks状态 ** kaj better define what the variable containshowdoes it get reset? In the previous tips, you have learned how to detect whenthe user has pressed the mouse button. In many cases, your programs mustrespond to a mouse double-click operation, which is simply two quick clicks ofthe mouse. As you have learned, the Event class contains information about anevent. One piece of information the Event class contains for mouse events isthe clickCount variable. Your applets can use the clickCount variable to detectdouble-click operations. The following program, doubleClick.java, displays amessage to the screen each time the user double-clicks the mouse: 在以上的TIPS中,你已知道了怎样测出用户是在按mouse button. 在很多情况下,你的程序还必须能检测mouse的double-click(双击)操作, 也就是很快地点击两次mouse键.正如你所了解的那样, Event类包含着事件的信息. Event类为mouse事件提供的信息之一是clickCount(击键数). 你的程序可以利用clickCount变量来检测double-click操作. 以下的doubleClick.java程序在每当用户双击mouse时就会在屏幕上显示一个消息. import java.applet.*; import java.awt.*; public classdoubleClick extends Applet { public void init() { resize(400, 300); } public boolean mouseDown(Event evt, int x,int y) { if (evt.clickCount == 1) System.out.println("mouseDown:single click"); else if (evt.clickCount == 2) System.out.println("mouseDown:double click"); else if (evt.clickCount == 3) System.out.println("mouseDown:triple click"); else if (evt.clickCount > 3) System.out.println("mouseDown:many clicks"); return(true); } } 410 An Alternative Way to Detect Double-Clicks 410 检测Double-Clicks的另一种方法 In Tip 409, you learned how to detect double-clickoperations using the Event class clickCount variable. Unfortunately, dependingon your release of Java, you may find that clickCount does not always containthe correct value. An alternative way to detect double-click mouse operationsis to determine the time interval between clicks yourself. To do this, you cancheck the Event class when variable. If two mouse clicks occur within aspecific interval of time, your applet can treat the mouse clicks as adouble-click operation. The following program, altDoubleClick.java,demonstrates how you might check the interval between mouseDown events usingthe when variable: 在TIP 409中,你已知道了怎样利用clickCount变量来检测double-click操作. 不幸的是,利用clickCount变量来检测double-click操作,在不同的Java版本下,并不总是提供可靠的值. 检测double-click操作的另一种方法是由你自己来确定击键的时间间隔. 为了做这一事,你可检测Event类. 如果两次mouse 点击事件出现在一个指定的时间间隔内,你的程序就可把它当作一个double-click来处理. 以下的altDouble-Click.java程序将告诉你怎样利用when变量来检测两次mouseDown事件之间的时间间隔: import java.applet.*; import java.awt.*; public classaltDoubleClick extends Applet { static int lastclick = 0; static long maxdelay = 100; static int doubleclick = 0; public void init() { resize(400, 300); } public boolean mouseDown(Event evt, int x,int y) { long delay = evt.when - lastclick; if ((delay > maxdelay) ||(doubleclick == 0)) doubleclick = 1; else doubleclick++; if (evt.clickCount == 1) System.out.println("mouseDown:single click"); else if (evt.clickCount == 2) System.out.println("mouseDown:double click"); else if (evt.clickCount == 3) System.out.println("mouseDown:tripple click"); else if (evt.clickCount > 3) System.out.println("mouseDown:many clicks"); return(true); } } On most operating systems, a user can set thesensitivity for double clicks. However, the when variable technique in this tiphas no way to adjust sensitivity based on the operating-system settings. 在大多数操作系统中,用户可以设置double clicks的灵敏性. 但是,对本TIP中使用的when变量没有办法利用操作系统的设置来调整灵敏度. 411 Detecting Mouse Click Modifier Keys 411 检测鼠标点击修饰键 From the time of the first graphical-userinterface, there have been mouse-click and key combinations that users performfor special purposes. For example, in many graphical programs, drawing with theShift key depressed causes an oval tool to draw circles. 为了实现特殊的用途,自从第一个图形用户接口诞生时起,就有把鼠标键和键盘键组合在一起的用法. 例如,在大多数图形程序中, 如果鼠标作图时同时按下了Shift键,将使椭圆工具(ovaltool)画成圆. To detect a mouse-click modifier key within a Javaapplet, you check the Event class modifiers variable. Java defines a set ofconstants in the Event class that your programs can use to check for a specificmodifier key such as SHIFT_MASK, CTRL_MASK, and ALT_MASK. To determine if theuser has pressed a specific key, you perform a bitwise AND operation of thecorresponding constant and the modifier variable. The following program,singleModifier.java, demonstrates how your programs detect if a user modifiedthe mouse operation by holding down the Shift key: 在Java应用程序中,为了检测鼠标点击修饰键,你可检查Event类的modifiers变量. Java在事件类中定义了一组供你用来检测特殊修饰键的常量,如SHIFT_MASK, CTRL_MASK,和 ALT_MASK. 为了检测用户是否已按下某个特殊键,你可以对modifiers变量和对应的常量实行按位乘(AND)运算. 以下的singleModifier.java程序告诉你怎样检查用户在利用mouse操作时是否同时按下了Shift键. import java.awt.*; import java.applet.*; public classsingleModifier extends Applet { public boolean mouseDown(Event evt, int x,int y) { if ((evt.modifiers &Event.SHIFT_MASK) != 0) System.out.println("mouseDown andShift key pressed"); else System.out.println("mouseDown"); return(true); } } 412 Understanding the Multi-Button Mouse Problem 412 了解多按钮(Multi-Button)鼠标问题 In the previous tips, you have learned how todetect when the user clicks the mouse. On some platforms, the mouse has morethan one button. Unfortunately, Java does not provide a clear way todistinguish between mouse buttons. In fact, to date, only undocumentedtechniques existwhich might not work in future versions of Java. Also, if youcreate a program that requires more than one mouse button, your program will beplatform dependent. Until a solution is built into the language, we recommendthat you just assume that there is only one mouse button. With that said, thefollowing program, multiMouse.java, will now demonstrate an undocumentedtechnique for detecting the second and third mouse button: 在前面的TIP中,你已知道了怎样检测用户是否已按下mouse键. 在有的平台上,mouse可以有多个button. 不幸的是, Java不提供区别mouse button的确切方法. 事实上,到目前为止,只有不成文的技术在用, 它们对今后的Java版本有可能不使用. 同样,如果你创建一个要使用更多button的程序,你的程序就可能和平台有关. 这个问题在语言中的解决方案出来之前,我们建议你就假设只有一个mouse button. 据此, 以下的这一个程序, multiMouse.java, 现在只是用来检测第二和第三个mousebutton的一种不规范的方法: import java.applet.*; import java.awt.*; public classmultiMouse extends Applet { public void init() { resize(400, 300); } public boolean mouseDown(Event evt, int x,int y) { if ((evt.modifiers & Event.ALT_MASK)> 0) System.out.println("mouseDown:middle button"); else if ((evt.modifiers &Event.META_MASK) > 0) System.out.println("mouseDown:right button"); else System.out.println("mouseDown:left button"); return(true); } } As you can see, the program detects the othermouse buttons by checking the modifier keys. Currently, the other mouse buttonsare equivalent to a standard mouse click with a modifier key pressed. Remember,however, these techniques may not work in future versions of Java. 你可看到,程序检测其它的mouse button 是利用了modifier键. 这里,其它的mousebutton等价为点击mouse同时按下了一个modifier键. 但要记住, 这些方法在今后的Java版本中可能不使用. 413 Using mouseEnter and mouseExit 413 使用mouseEnter和mouseExit You have learned that your applets can handlemouseMove events when a user moves a mouse around the screen. Within yourprograms, you can use the event coordinates to manually check when a mouseenters a window or control. However, Java has two functions that can do this foryou: mouseEnter and mouseExit. Java calls the mouseEnter when a mouse enters acomponent. Likewise, Java calls the mouseExit when the mouse leaves thatcomponent. For example, you might use these methods to display a pop-up helpmessage that tells a user about a particular control or button. The followingprogram, mouseEnterExit.java, demonstrates how your programs can detect when amouse enters and leaves an applet window: 你已知道了,当用户利用mouse在屏幕上移动mouse光标时,你的应用程序是怎样来处理mouseMove事件的. 在你的程序中,你可以利用mouse事件的坐标来检测一个mouse是进入一个窗口或者是一个控制对象图标. 但是,Java有两个供你使用的功能:mouseEnter和 mouseExit. Java在mouse进入某一成员范围时调用mouseEnter,同样, Java在mouse离开某一成员范围时调用了mouseExit. 例如,你可以用这些方法来显示一个弹出式消息,告诉用户有关的特殊控制或按钮. 以下的mouseEnterExit.java程序说明了你的程序怎样来检测mouse何时进入/退出一个应用程序窗口: import java.awt.*; import java.applet.*; public classmouseEnterExit extends Applet { public boolean mouseEnter(Event evt, int x,int y) { System.out.println("mouseEnter"); return(true); } public boolean mouseExit(Event evt, int x,int y) { System.out.println("mouseExit"); return(true); } } The first message will cause the status window(the window that displays the message "mouseEnter") to be in front ofthe applet. For the mouseEnter and mouseExit methods to work, you must clickthe applet so that it becomes the front-most window. 这里的第一个消息将使状态窗口(显示消息"mouseEnter"的窗口)变为应用程序的front窗口. 为使mouseEnter 和 mouseExit 方法工作,你必须点击你的应用程序,使它成为最前端的那个窗口. 414 Understanding Keyboard Events 414 了解键盘事件 In the previous tips, you learned about the eventsthat are generated by the mouse. As you will learn, another set of importantevents is generated from the keyboard. When Java generates a keyboard event, itpasses an Event object that contains information about the key pressed. Javarecognizes normal keys, modifier keys, and special keys. For normal keys, theevent object contains the keys ASCII value. For the function, arrow, and otherspecial keys, there are no ASCII codes, so Java uses special Java-definedcodes. In Tip 411, you learned how to detect modifier keys. The modifier keysare stored in the modifiers variable in the Event object. The following tipsdescribe how to handle various keyboard events. 在以上的TIP中,你已知道了由mouse生成的有关事件. 你将会了解,另一类重要的事件是由键盘产生的.当Java产生一键盘事件时,它传递了包含有关按下键信息的事件对象.Java将辨识出所按的一般的键还是修饰键,或者还是特殊键. 对于功能键,光标移动用的箭头键,以及另一些特殊键,它们是没有自己的ASCII码的,所以Java使用了由自己定义的专用代码.在TIP 411中你将知道怎样检测修饰键. 修饰键存储在Event对象的修饰字变量(modifiers variable)中. 以下的TIPS描述了怎样处理各种键盘事件. 415 Using the keyDown Method 415 使用键盘事件 As you have learned, Java provides conveniencemethods that make capturing mouse events easy. For example, when the user holdsdown the mouse button, Java will call the mouseDown method. Similarly, when theuser presses a keyboard key, Java will call the keyDown convenience method. Thearguments to the keyDown method are the Event object and a key code. Thefollowing program, keyDownApplet.java, demonstrates how to capture key strokesand display them within the status window: 正如你所了解的那样,Java提供的convenience方法使得事件的捕捉变得容易. 例如,用户按下mouse键时,Java将调用mouseDown方法.类似地,当用户按键盘上的键时,Java将调用keyDown方法. keyDown方法的自变量是Event对象和所按键的代码. 以下keyDownApplet.java程序说明了捕捉按键并将它们显示在状态窗口中: import java.applet.*; import java.awt.*; public classkeyDownApplet extends Applet { public boolean keyDown(Event evt, int code) { System.out.println("keyDown:"+ (char)code); return(true); } } 416 Using the keyUp Method 416 使用keyUp方法 As you have learned, Java provides separate eventsfor mouse-down and mouse-up operations. Thus, it should not surprise you thatJava provides separate events for key-down and key-up operations. When the userreleases a keyboard key, Java calls the keyUp convenience method. The argumentsto the keyUp method are the Event object and a key code. The following program,keyUpApplet.java, demonstrates how to detect a key up event: 正如你所了解的那样,Java为mouse-down和mouse-up操作独立地提供了事件. 因此,你也不会奇怪Java为key-down和key-up操作提供两类不同的事件. 当用户释放某个键时,Java调用了key-Up convenience 方法. key-Up方法的自变量是Event对象和所按键的代码. 以下keyUpApplet.java程序说明了怎样检测按键的释放事件: import java.applet.*; import java.awt.*; public classkeyUpApplet extends Applet { public boolean keyDown(Event evt, int code) { System.out.println("keyDown:"+ (char) code); return(true); } public boolean keyUp(Event evt, int code) { System.out.println("keyUp:" +(char) code); return(true); } } 417 Detecting Multiple Modifier Keys 417 检测多重变动键 In Tip 414, you learned that Java supports threetypes of keyboard characters. The first type are normal keys, which you learnedto handle in the previous two tips. Another type of keys are the modifier keys.In Tip 415, you learned how to detect if the user has pressed a modifier keyduring a mouse click. Now, you will learn how to detect if multiple modifierkeys were pressed at the same time. 在TIP 414中,你已知道了Java支持三种类型的键盘字符. 第一种类型是正常的键,这一种类型你已在前两个TIP中学过了.另一种类型的键是修饰键,TIP 415中你已学过了怎样检测用户在击mouse键时按下了一个修饰键. 现在,你将学到怎样检测用户是否同时按下多个修饰键. The Event class modifiers variable is a bit fieldthat lets a variable contain multiple flags. Within the modifiers variable,Java sets one bit for each of the Shift, Ctrl, and Alt keys. Within yourprogram, you can test which modifiers are set by performing a bitwise ANDoperation of the modifier constant and the modifiers variable. The followingprogram, multipleModifier.java, demonstrates how to detect the Shift and Ctrlmodifier keys when a normal key has been pressed: Event类的modifiers(修饰键)变量是一个bit域,这样在一个变量中可容纳多个标记.在modifiers变量中,Java为Shift, Ctrl 和 Alt三个键分别设置一个bit. 在你的程序中,你可以对modifiers变量和modifiers常量实行按位乘(AND)操作,来检侧哪一个modifiers(修饰键)被设置了. 以下的程序multipleModifier.java说明怎样来检测用户在按正常键的同时也按下了Shift和Ctrl修饰键: import java.applet.*; import java.awt.*; public classmutitipleModifier extends Applet { public void init() { resize(400, 300); } public boolean keyDown(Event evt, int key) { if (((evt.modifiers &Event.SHIFT_MASK) > 0) && ((evt.modifiers &Event.CTRL_MASK) > 0)) System.out.println("SHIFT andCTRL pressed"); return(true); } } 418 An Alternative Way to Detect Keyboard ModifierKeys 418 检测键盘变动键的另一种方法 In the previous tip, you learned how to detectkeyboard modifier keys by examining the Event class modifiers variable. Analternative way to check for modifier keys is to use the methods built into theEvent class: controlDown, metaDown, or shiftDown. You can use these methodsinstead of performing a bitwise AND operation of the modifier constants withthe modifiers variable. The following program, altModifierKey.java,demonstrates how to check for modifier keys using the built-in Event classmethods: 在以上的TIP中,你已知道了怎样利用查看事件类modifier变量的办法来检测键盘的修饰键. 检测修饰键的另一中办法是在Event类中建立的controlDown, metaDown, 或shiftDown三种方法. 你可使用这些方法来代替modifiers变量和modifiers常量之间的按位乘操作. 以下的程序altModifierKey.java说明怎样利用内建的Evenr类方法,来检测修饰键: import java.applet.*; import java.awt.*; public classaltModifierKey extends Applet { public void init() { resize(400, 300); } public boolean keyDown(Event evt, int key) { if (evt.controlDown() &&evt.shiftDown()) System.out.println("SHIFT andCTRL pressed"); return(true); } } 419 Detecting Special Keys 419 检测特殊键 You have learned how to detect normal and modifierkeys. For special keys, such as the keyboard arrow and function keys, you mustcheck the key code like you did for normal keys. However, instead of using theASCII codes, you use the special key constants defined in the Event class.Table 419 lists the Event class special key constants . 你已知道了怎样来检测用户按的正常键和修饰键. 对于键盘上的箭头键和功能键之类的特殊键,你必须象检测正常键那样地来查看它们的代码. 但是,你可以不直接使用它们的ASCII码,而改用由Event类定义的特殊键常量. 表419列出了Event类定义的特殊键常量. Special Keys Description F1, F2, F3, F4, F5, F6 Function keys F7, F8, F9, F10, F11, F12 Function keys Left, Right Left and right arrow keys Up, Down Up and down arrow keys Home, End Home and End keys PgUp, PgDown PageUp and PageDown keys Table 419 Event classkey constants. 表419Event类定义的特殊键常量 The following program, testApplet.java,demonstrates how to detect special keys. 以下的程序testApplet.java, 说明了怎样检测特殊键: import java.applet.*; import java.awt.*; public classtestApplet extends Applet { public void init() { resize(400, 300); } public boolean keyDown(Event evt, int key) { switch (key) { case Event.UP: System.out.println("Up arrow"); break; case Event.DOWN: System.out.println("Down arrow"); break; case Event.LEFT: System.out.println("Left arrow"); break; case Event.RIGHT:System.out.println("Right arrow"); break; } return(true); } } 420 Using the handleEvent Method 420 使用handleEvent方法 Each of the Java programs you have examined, thusfar, have handled keyboard and mouse events using the convenience methods. Asyou have learned, the convenience methods separate events by type. Another wayyour programs can handle events is to capture the events using the handleEventmethod. 在此之前你所考查过的每一个Java程序都用了convenience 方法来处理键盘事件和mouse事件. 你已知道了convenience方法是按照类型来区别事件的. 你的程序中可以采用的另一种事件处理方法是利用 handleEvent方法. As it turns out, before Java passes an event to aconvenience method, Java first passes the event to the handleEvent method. Ifyou handle the event (and return true) within the handleEvent method, Java willnot call the convenience method. 当Java将一事件传递给一个convenience方法之前, 首先将事件传递给handleEvent方法.如果你在handleEvent方法中处理事件(并返回True), Java就不再调用convenience方法. In other words, if you handle mouse events withinthe handleEvent method, you do not have to use the mouseDown method. However,using the mouseDown method is a better way to organize your code, because thename clearly identifies the event. 换言之,如果你在handleEvent方法中处理mouse事件, 你就不需要再用mouseDown方法. 但是, 使用mouseDown方法是组织你的程序的一种好的方法, 因为所用的名字能清楚表达事件的功能. On the other hand, to handle events that do nothave convenience methods, you must capture the events within the handleEventmethod. Within the handleEvent method, you check the id variable against theconstants defined in the Event class to distinguish event types. The followingprogram, handleEventApplet.java, captures events and displays their names: 另一方面,如果不用convenience方法来处理事件,你就必须在handleEvent方法中来俘获事件. 在handleEvent方法中,你用检测id变量的办法来区分事件类型,就用不到再检测Event类中定义的常量. 以下的程序,handleEventApplet.java,说明了怎样来俘获事件并显示它们的名字. import java.applet.*; import java.awt.*; public classhandleEventApplet extends Applet { public void init() { resize(400, 300); } public boolean handleEvent(Event evt) { if (evt.id == Event.WINDOW_DESTROY) System.out.println("WINDOW_DESTORY"); else if (evt.id == Event.WINDOW_EXPOSE) System.out.println("WINDOW_EXPOSE"); else if (evt.id ==Event.WINDOW_ICONIFY) System.out.println("WINDOW_ICONIFY"); else if (evt.id ==Event.WINDOW_DEICONIFY) System.out.println("WINDOW_DEICONIFY"); else if (evt.id == Event.WINDOW_MOVED) System.out.println("WINDOW_MOVED"); else if (evt.id == Event.KEY_PRESS) System.out.println("KEY_PRESS"); else if (evt.id == Event.KEY_RELEASE) System.out.println("KEY_RELEASE"); else if (evt.id == Event.MOUSE_DOWN) System.out.println("MOUSE_DOWN"); else if (evt.id == Event.MOUSE_UP) System.out.println("MOUSE_UP"); else if (evt.id == Event.MOUSE_MOVE) System.out.println("MOUSE_MOVE"); else if (evt.id == Event.MOUSE_ENTER) System.out.println("MOUSE_ENTER"); else if (evt.id == Event.MOUSE_EXIT) System.out.println("MOUSE_EXIT"); else if (evt.id == Event.MOUSE_DRAG) System.out.println("MOUSE_DRAG"); else System.out.println(evt); // printother events return(super.handleEvent(evt)); } } 421 How NOT to Handle an Event 421 怎样不处理一个事件 Each of the Event-based examples presented so farhave focused on handling events. After handling an event, each method hasnotified Java that it handled the event by returning true. Sometimes, however,there will be events that your programs do not handle. Either your program willnot know how to handle the event or it may be more appropriate for anothermethod to handle them. To ensure that an alternative method gets a chance tohandle an event, you should use the following return statement: 在此之前你所学过的每一个基于事件的例子都是着眼于事件的处理. 在一个事件处理了之后,每一个方法都用返回True的办法来通指Java它已处理了这个事件. 但,有的时候,你的程序有可能不处理事件. 这或许是因为你的程序不知道如何处理这一事件,或许是因为由其它的程序处理它们会更合适. 为保证别的方法能获得机会来处理一个事件, 你必须使用以下的return语句: return(super.handleEvent(evt)); // evt is the Event object The reason you dont simply return false is thatthe proper path for events to travel is through the inheritance tree. When youdont handle an event in the handleEvent method, you want Java to try one of theconvenience methods to see if it can handle the event. If you return false fromthe handleEvent method, the convenience methods will not be checked. Thefollowing code demonstrates how your programs return from an event they do nothandle: 你不是简单地返回false,理由是:事件所走的固有路径需要通过继承树(inheritance tree). 当你在handleEvent方法中不处理一个事件时, 你希望Java去试一试某一种convenience方法是否能处理该事件. 如果你从handleEvent方法中返回false, 则不再去查convenience方法. 以下的程序说明了你的程序怎样从一个不作处理的事件中返回: import java.applet.*; import java.awt.*; public classbadHandleEvent extends Applet { public boolean mouseDown(Event evt, int x,int y) { /* this method is never called! */ System.out.println("mouseDown:("+ x + ", " + y + ")"); return(true); } public boolean handleEvent(Event evt) { return(false); // never do this! } } Note: If your handleEvent method handles events,do not return the value false because Java will call the correspondingconvenience method. 注意: 如果你的handleEvent方法处理了事件, 则不要返回false, 因为Java将调用对应的convenience方法. 422 Making Sure You Can Quit Your Applications 422 确信你可以退出应用程序 Most operating systems wrap your Java applicationinside a standard window frame. Within these frames, a menu or icon usuallylets the user close a window (ending the program). When you select this item,the operating system generates a WINDOW_DESTROY message. Unless your programhandles the WINDOW_DESTROY message, your application will not quit. In fact, ifyour application is simple, you might not have any way to quit yourapplication. If you are using UNIX, you could kill the process, but that is alittle drastic. Instead, your program should always handle the WINDOW_DESTROY event.Your application can then quit easily and naturally. The following program,quiteApplication.java, shows how to handle a WINDOW_DESTROY event: 大多数操作系统把你的应用程序限制在一标准的窗口帧中.在这些帧中,通常都会设置一项菜单或一个图标使用户能关闭这个闯口(结束程序). 当你选择这一项时,操作系统产生一个 WINDOW_DESTROY(窗口消失)消息. 除非你的程序处理WINDOW_DESTROY消息,你的程序将不会退出. 事实上,如果你的应用程序是简单的, 你可能没有任何办法退出应用程序. 如果你使用UNIX,你可以kill这个进程,但这是有点太激列了. 可取的办法是你的程序永远处理WINDOW_DESTROY使件, 这时你的应用程序就可方便地容易地退出. 以下的程序quiteApplication.java向你说明怎样处理 WINDOW_DESTROY事件: import java.awt.*; class quitApplicationextends Frame { public quitApplication(String label) { setTitle(label); resize(100,100); } public boolean handleEvent(Event evt) { if (evt.id == Event.WINDOW_DESTROY) System.exit(0); // Quit the application return(super.handleEvent(evt)); // Donthandle other events } public static void main(String[] args) { testApplication f = newtestApplication("Window quit test"); f.show(); } } 423 Detecting When a Window Is Iconified 423 检测窗口何时已图标化(Iconified) You have learned how to catch many events. Anotherpair of events that a Java application receives are WINDOW_ICONIFY andWINDOW_DEICONIFY. You should note that icon events are platform dependentbecause not all operating systems iconify applications. You may find it usefulto handle icon events if you wish to disable a graphics intensive program fromupdating while it is iconified. There usually is no reason to update a windowthat is not visible. The following code demonstrates how to disable the paintmethod if an application is iconified: 你已知道了怎样去俘获许多种的事件. Java程序接受的另一对事件是WINDOW_ICONIFY(窗口图标化)和WINDOW_DEICONIFY(窗口去图标化). 你必须注意icon事件是和平台有关的,因为并不是所有的操作系统都把应用程序图标化. 你可发现, 如果你希望禁止一个已图标化的图形密集程序刷新, 利用icon事件是有用的. 通常没有理由要刷新一个不可见窗口. 以下的代码说明了一个应用程序已图标化时怎样禁止paint方法: import java.awt.*; classiconifyApplication extends Frame { boolean icon = false; public iconifyApplication(String label) { setTitle(label); resize(100,100); } public boolean handleEvent(Event evt) { System.out.println("here"); if (evt.id == Event.WINDOW_DESTROY) System.exit(0); // quit application else if (evt.id == Event.WINDOW_ICONIFY) icon = true; else if (evt.id == Event.WINDOW_DEICONIFY) icon = false; return(super.handleEvent(evt)); // Donthandle other events } public void paint(Graphics g) { if (!icon) System.out.println("update"); else System.out.println("don'tupdate"); } public static void main(String[] args) { iconifyApplication f = newiconifyApplication ("iconify"); f.show(); } } 1001 Java Programming Tips Page PAGE 1652 of numpages 15 filename jt074_095.doc TIME \@ "MMMM d, yyyy" September 29, 1996