[Java核心技术]学习笔记--第三章

来源:互联网 发布:济南软件外包服务 编辑:程序博客网 时间:2024/06/01 18:12

第三章

Java的基本语法(数据类型、分支以及循环)。


3.1一个简单的Java应用程序

经典的HelloWorld:

public class FirstSample {static public void main(String[] args){System.out.println("We will not use 'Hello world!");}}

编写Java程序的注意事项:

  • Java语言对大小写敏感。
  • 类名:以大写字母开头的名词。如果类名由多个单词组成,每个单词的第一个字母都应该大写(骆驼命名法:CamelCase)。
  • 源代码文件名必须与公共类的名字相同,并用.java作为扩展名。
  • 如果源文件没有错误,编译后会生成一个与源文件同名的以.class为扩展名的文件。
  • 使用Java ClassName的方式运行。
  • 运行时,Java虚拟机将从指定类中的main方法开始执行。

3.2注释

与大多数程序设计语言一样,Java中的注释也不会出现在可执行程序中。因此可以在源代码中添加任意多的注释,不用担心代码膨胀。


Java的三种注释:

  • 单行注释"// ", 其注释内容是从//开始到本行结尾。
  • 多行注释"/×", "×/"。
  • 可用来自动生成文档的注释。以"/××"开始,以"×/"结束。

※需要注意的是,Java中/**/注释不能嵌套。如果代码本身包含了一个×/,就不能用/××/将注释括起来。

3.3数据类型

Java整型类型存储需求取值范围int4字节-2 147 483 648 ~ 2 147 483 647short2字节-32 768 ~ 32 767long8字节-9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807byte1字节-128 ~ 127









浮点类型类型存储需求取值范围float4字节大约 ±3.402 823 47E+38F(有效位数为6~7位)double8字节大约 ±1.797 693 134 862 315 70E+308(有效位数为15位)







char类型

用于表示单个字符。通常用来表示字符常量。

boolean类型

有两个值:false和true,用来判断逻辑条件。整型值和布尔值之间不能进行相互转换。

3.4变量

变量名:以字母开头的由字母和数字构成的序列。字母包括'A'~'Z', 'a'~'z', '_', '$'或在某种语言中代表字母的任何Unicode字符。同样,数字包括‘0’~‘9’和在某种语言中代表数字的任何Unicode字符。但是其他符号和空格不能出现在变量名中。

※尽管$是一个合法的Java字符,单不要在你自己的代码中使用这个字符。它只用于Java编译器或其他工具生成的名字中。

3.4.1变量初始化

变量声明后,必须用赋值语句对变量进行显式初始化。

3.4.2常量

在Java中,利用关键字final指示常量。

关键字final表示这个变量只能被赋值一次。一旦被赋值之后,就不能够再更改了。习惯上,常量名使用全大写。

在Java中,经常希望某个常量可以在一个类中的多个方法使用,通常将这些常量成为类常量。

※const是Java保留的关键字,但目前并没有使用。在Java中,必须使用final定义常量。

3.5运算符

位运算:

对以为运算符右侧的参数需要进行模32(求余运算)的运算(除非左边的操作数时long类型,在这种情况下需对右侧操作数模64)。例如,1<<35与1<<3是相同的。


数学函数与常量

在Math类中,包含了各种各样的数学函数。

计算平方根:

double x = 4;double y = Math.sqrt(x);System.out.println(y);

计算x的a次幂:

double y = Math.pow(x, a);

常用的三角函数:

Math.sin

Math.cos

Math.tan

Math.atan

Math.atan2

指数函数及它们的反函数

Math.exp

Math.log

Math.log10

π和e常量的近似值:

Math.PI

Math.E

运算符优先级运算符结合性[] . ()(方法调用)L → R! ~ ++ -- +(一元运算)  ()(强制类型转换) newR → L* / %L → R+ -L → R<< >> >>>L → R< <= > >= instanceofL → R== !=L → R&L → R^L → R|L → R&&L → R||L → R?:R → L= += -= *= /= %= &= |= ^= <<= >>= >>>=R → L















3.6字符串

Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类String。每个用双引号括起来的字符串都是String类的一个实例。

3.6.1子串

String类的substring方法可以从一个较大的字符串提取出一个子串。

String greeting = "Hello";String s = greeting.substring(0, 3);

上述语句创建了一个由字符“Hel”组成的字符串。

substring的第二个参数时不想复制的第一个位置。substring的工作方式有一个优点:容易计算子串的长度。字符串s.substring(a, b)的长度为b-a。

3.6.2拼接

与绝大多数程序设计语言hi杨,Java允许使用+号连接(拼接)两个字符串。

String expletive = "Expletive";String PG13 = "deleted";String message = expletive + PG13;
上述代码讲“Expletivedeleted”赋给变量message。

当将一个字符串与一个非字符串的值进行拼接时,后者被转换成字符串。


3.6.3不可变字符串

String类没有提供用于修改字符串的方法。如果想要修改字符串,首先提取需要的字符,然后在拼接上替换的字符串:

greeting = greeting.subsring(0, 3) + "p!";
由于不能修改Java字符串中的字符,因此在Java文档中讲String类对象成为不可变字符串。

可变字符串的优点:编译器可以让字符串共享。

字符串共享的工作方式:可以想象将各种字符串存放在公共的存储池中。字符串变量指向存储池中相应的位置。如果复制一个字符串变量,原始字符串与复制的字符串共享相同的字符。

※Java字符串不是字符型数组,它更像C/C++中的char×指针。

3.6.4检测字符串是否相等

使用equals方法检测字符串相等。

对于s.equals(t),如果s与t相等,则返回true;否则,返回false。

※s和t都可以是字符串变量或字符串常量。例如,下列表达式是合法的:

"Hello".equals(greeting);
如果不区分大小写,可以使用equalsIgnoreCase方法。

"Hello".equalsIgnoreCase(greeting);
一定不能使用==运算符检测两个字符串是否相等!这个运算符只能够确定两个字符串是否放在同一个位置上。

3.6.5空串与Null串

空串""是长度为0的字符串。可以用如下方式检测字符串是否为空:

if (str.length() == 0)

if (str.equals(""))
空串是一个Java对象,有自己的长度(0)和内容(空)。


String变量还可以存放一个特殊的值,名为Null,着表示目前没有任何对象与该变量关联。检车字符串是否为Null,可以使用如下方法:

if (str == NULL)

有时要检查一个字符串既不是Null又不是空,可是使用以下方法:

if (str != NULL && str.length() != 0)

3.6.6代码点与代码单元

Java字符串由char序列组成。char数据类型是一个采用UTF-16编码表示Unicode代码点的代码单元。大多数的常用Unicode字符使用一个代码单元就可以表示,而辅助字符需要一对代码单元表示。

length方法将返回采用UTF-16编码表示的给定字符串所需要的代码单元数量。

String greeting = "Hello";int n = greeting.length(); // is 5
想要得到实际的长度,即代码点数量,可以调用:

int cpCount = greeting.codePointCount(0, greeting.length());
调用s.charAt(n)将返回位置n的代码单元,n介于0~s.lenght() - 1之间。

char first = greeting.charAt(0); // first is 'H'\char last = greeting.charAt(4); // las is 'o'

想要得到第i个代码点,应该使用下列语句

int index = greeting.offsetByCodePoint(0, i);int cp = greeting.codePointAt(index);

3.6.7字符串API

String类包含了50多个方法,都很有用。


String类的常用方法API描述char charAt( int index )返回给定位置的代码单元。除非对底层的代码单元感兴趣,否则不需要调用这个方法。int codePointAt( int index )返回给定位置开始或接续的代码点。int offsetByCodePoints( int startIndex, int cpCount )返回从startIndex代码点开始,位移cpCount后的代码点索引。int compareTo( String other)按照字典顺序,如果字符串位于other之前,返回负数;如果位于other之后,返回正数;如果相等,返回0。boolean endsWith( String suffix)如果字符串以suffix结尾,返回ture。boolean equals( Object other )如果字符串与other相等,返回true。boolean equalsIgnoreCase( String other )如果字符串与other相等(忽略大小写),返回true。int indexOf( String str )
int indexOf( String str, int fromIndex ) 
int indexOf( int cp )
int indexOf( int cp, int from Index)返回与字符串str或代码点cp匹配的第一个子串的开始位置。这个位置从索引0或fromIndex开始计算。如果在原始串中不存在str, 返回-1。int lastIndexOf( String str )
int lastIndexOf( String str, int fromIndex )
int lastIndexOf( int cp )
int lastIndexOf( int cp, int from Index)返回与字符串str或代码点cp匹配的最后一个子串的开始位置。这个位置从索引0或fromIndex开始计算。如果在原始串中不存在str, 返回-1。int length()返回字符串的长度。int codePointCount( int startIndex, int endIndex )返回startIndex和endIndex-1之间的代码点数量。没有匹配成对的代用字符将计入代码点。String replace(CharSequence oldString, CharSequence newString)返回一个新字符串。这个字符串用newString代替原始字符串中所有的oldString。可以使用String或StringBuilder对象作为CharSequence参数。boolean startsWith(String prefix)如果字符串以prefix开始,返回true。String substring( int beginIndex )
String substring( int beginIndex, int endIndex )返回一个新字符串。这个字符串包含原始字符串中从beginIndex到串尾或endIndex-1的所有代码单元。String toLowerCase()返回一个新字符串。这个字符串将原始字符串中的所有大写字母改成了小写字母。String toUpperCase()返回一个新字符串。这个字符串将原始字符串中的所有小写字母改成了大写字母。String trim()返回一个新字符串。这个字符串将删除了原始字符串头部和尾部的空格。


3.6.8阅读联机API文档

3.6.9构建字符串

有时候需要使用较短的字符串构建字符串,例如按键或来自文件中的单词。采用字符串连接的方式达到次目的的效率比较低。每次连接字符串,都会构建一个新的String对象,既耗时,又浪费空间。使用StringBuilder类就可以避免此问题发生。


步骤:

首先构建一个空的字符串构建器:

StringBuilder builder = new StringBuilder();
当需要添加内容时,调用append方法。

builder.append(ch); // appends a single character<pre name="code" class="java">builder.append(str); // appends a string

在需要构建字符串时就调用toString方法。

String completedString = builder.toString();

3.7输入输出

3.7.1读取输入

输出到“标准输出流”(即控制台窗口),调用System.out.println。

读取“标准输入流”,首先构造Scanner对象,并与“标准输入流”System.in关联。

Scanner in = new Scanner(System.in);
之后使用Scanner类的各种方法实现输入操作。

读入一行:

System.out.print("What is your name?");String name = in.nextLine();
读取一个单词(以空白符分割):

String firstname = in.next();
读取一个整数:

System.out.print("How old are you?");String name = in.nextInt();
读取一个浮点数调用in.nextDouble方法。

※Scanner类定义在java.util包中。当使用的类不是定义在java.lang包中时,一定要使用import指示字讲相应的包加载进来。


输入输出练习(InputTest.java):

import java.util.*;/* * This program demonstrates console input. * @version 1.0 * @author XXX * */public class InputTest {public static void main(String[] args){Scanner in = new Scanner(System.in);// get first inputSystem.out.print("What is your name?");String name = in.nextLine();// get second inputSystem.out.print("How old are you?");i age = in.nextInt();// display output on consoleSystem.out.println("Hello, " + name + ".Next year, you'll be " + (age + 1));}}

Scanner类不适用于从控制台读取代码。应使用Console类读取密码:

Console cons = System.console();String usrname = cons.readLine("User name: ");char[] passwd = cons.readPassword("Password: ");

※需要注意的一点,上述三行代码只能在控制台下运行,在Eclipse IDE下运行会出错。原因如下:

java.io.Console 这个类是 JDK 6 中新增的类库,用于操作系统的控制台,系统的控制台只能在操作系统原生的控制台中使用,不能在 IDE 的控制台中使用,因为 IDE 中的控制台是经过重定向的。

3.7.2格式化输出

System.out.printf()方法,用法与C的printf方法相同。


例如:

System.out.printf("Hello, %s, Next year, you'll be %d", name, age);

用于printf的转换符转换符类型举例转换符类型举例d十进制整数159s字符串Hellox十六进制整数9fc字符Ho八进制整数237b布尔truef定点浮点数15.9h散列码42628b2e指数浮点数1.59e+01tx日期时间见表【日期和时间的转换符】g通用浮点数-%百分号%a十六进制浮点数0x1.fccdp3n与平台有关的行分隔符-

※可以使用s转换符格式化任意的对象。对于任意实现了Formattable借口的对象都将调用formatTo方法;否则将调用toString方法,它可以将对象转换为字符串。

另外,还可以给出控制格式化输出的各种标志。

System.out.printf("%,.2f", 10000.0 / 3.0);

上述代码打印:3333.33

可以使用多个表示,例如,“%,(.2f”使用分组的分隔符并将负数括在括号内。

用于printf的标志标志目的举例+打印正数和负数的符号+3333.33空格在正数之前添加空格| 3333.33|0数字前面补0003333.33-左对齐|3333.33 |(将负数括在括号内(3333.33),添加分组分隔符3,333.33#(对于f格式)包含小数点3,333.#(对于x或0格式)添加前缀0x或00xcafe$给定被格式化的参数索引。例如,%1$d, %1$x将以十进制和十六进制格式打印第一个参数159 9F<格式化前面说明的数值。例如,%d%<x以十进制和十六进制打印同一个数值159 9F


printf方法还可以按照一定格式打印日期和时间。

例如:

System.out.printf("%tc", new Date());

上述语句将会按照下面格式打印当前日期和时间:

Sat Nov 22 17:31:25 CST 2014


日期和时间的转换符转换符类型举例c完成的日期和时间Sat Nov 22 17:31:25 CST 2014FISO 8601日期2014-11-22D美国格式的日期(月/日/年)11/22/14T24小时时间17:35:45r12小时时间05:36:14 PMR24小时时间没有秒17:36Y4位数字的年(前面补0)2014y年的后两位数字(前面补0)14C年的前两位数字(前面补0)20B月的完整拼写Novemberb或h月的缩写Novm两位数字的月(前面补0)11d两位数字的日(前面补0)22e两位数字的日(前面不补0)11A星期几的完整拼写Saturdaya星期几的缩写Satj三位数的年中的日子(前面补0),范围在001到366之间326H两位数字的小时(前面补0),在00到23之间17k两位数字的小时(前面补不0),在0到23之间17I两位数字的小时(前面补0),在00到12之间05l两位数字的小时(前面不补0),在00到12之间5M两位数字的分钟(前面补0)45S两位数字的秒(前面补0)35L三位数字的毫秒(前面补0)790N九位数字的毫微秒(前面补0)050000000P上午或下午的大写标志PMp上午或下午的小写标志pmz从GMT起,RFC822数字位移+0800Z时区CSTs从格林威治时间1970-01-01 00:00:00起的秒数1416649762


从上表中可以看到,某些格式只给除了指定日期的部分信息。例如,只有日期或月份。如果想对日期的多个部分进行格式化的话,可以使用一个格式化的字符串来指出要被格式化的参数索引。索引必须紧跟在%后,并以$终止。

例如:

System.out.printf("%1$s %2$tB %2$te, %2$tY", "Due date:", new Date());

输出:

Due date: November 22, 2014

※参数索引从1开始,而不是从0开始。


3.7.3文件输入与输出

读取文件:

java.util.Scanner

java.nio.file.Paths

Scanner in = new Scanner(Paths.get("testFIleIO"));
※如果文件名中包含反斜杠,就要在每个反斜杠之前再加一个额外的反斜杠“c::\\mydirectory\\myfile.txt”。


写入文件:

java.io.PrintWriter

PrintWriter out = new PrintWriter("testFileIO");

如果文件不存在,就创建该文件。


3.8控制流程

Java没有goto语句,但break语句可以带标签,可以利用它实现从内层循环跳出的目的。

3.8.1块作用域

块可以嵌套,但是不能在嵌套的两个块中声明同名的变量。

例如,下面代码不能够通过编译。

public static void main(String[] args){     int n;     ...     {         int k;         int n; // ERROR--can't redefine n in inner block     }}

※在C++中可以在嵌套的块中重定义一个变量,但是在Java中不行。


3.8.2条件语句

同C/C++,略。

3.8.3循环

同C/C++,略。

3.8.4确定循环

同C/C++,略。

3.8.5多重选择:switch语句

从Java SE7开始,case标签还可以是字符串字面量。

例如,

String input = ...;switch (input.toLowerCase()){case "yes": // OK since Java SE 7    ...    break;...}

3.8.6中断控制流程语句

Java提供一条带标签的break语句,用来支持类似于goto语句的功能,跳出多重嵌套的循环语句。

※标签必须放在希望跳出的最外层的循环之前,并且必须紧跟一个冒号。

Scanner in = new Scanner(System.in);int n;read_data:while (...)// this loop statement is tagged with the label{...for (...)// this inner loop is not labeled{System.out.print("Enter a number >= 0:");n = in.nextInt();if (n < 0)// should never happend-can't go onbreak read_data;// break out of read_data loop...}}// this statement is executed immediately after the labeled breakif (n < 0)// check for bad situation{// deal with bad situation}else{// carry out normal processing}

如果输入有误,通过执行带标签的break跳转到带标签的语句块末尾。对于任何使用break语句的代码都需要检测循环时正常结束还是由break跳出。

标签可以应用到任何语句中,用于跳出语句块。不能用于跳入语句快。


continue语句将控制转移到最内层循环的首部。

3.9大数值

java.math包中提供了两个处理大数值的类:BigInteger和BigDecimal。BigInteger类实现了任意精度的整数运算,BigDecimal实现了任意精度的浮点数运算。


使用静态的valueOf方法可以将普通的数值转换为大数值:

BigInteger a = BigInteger.valueOf(100);

在大数值的运算时,不能使用熟悉的算数运算符(如: +, - ,×, / )处理大数值。必须使用大数值类中提供的add和multiply方法。

※Java语言没有像C++一样提供运算符重载的功能。


大数值计算的例子:

import java.math.*;import java.util.*;/* * This program uses big numbers to compute the odds of winning the grand prize in lottery. * @version 1.0 * @author XXX * */public class BigIntegerTest {public static void main(String[] args){Scanner in = new Scanner(System.in);System.out.print("How many numbers do you need to draw ?");int k = in.nextInt();System.out.print("What is the highest number you can draw ?");int n = in.nextInt();/* * compute binomial coefficient n * (n - 1) * (n - 2) * ... * (n - k + 1) / (1 * 2 * 3 * ... * k) * */BigInteger lotteryOdds = BigInteger.valueOf(1);for (int i = 1; i <= k; i++){lotteryOdds = lotteryOdds.multiply(BigInteger.valueOf(n - i + 1)).divide(BigInteger.valueOf(i));}System.out.print("Your odds are 1 in " + lotteryOdds + ". Good luck!");}}


3.10数组

数组的声明,

int[] a;

int a[];

大多数Java程序员喜欢第一种风格,因为可以将数组int[]与变量int区分开。

初始化: int[] a = new int[100];

※数组大小不要求是常量。

3.10.1 for each循环

格式:for ( variable : collection ) statement;

定义一个变量用于暂存集合中的每一个元素,并执行相应的语句(或语句块)。collection这一集合表达式必须是一个数组或一个实现了Iterable接口的类对象。

for each语法比之前的for语法更加简介,不容易出错(无需关心数组下标是否有效)。

3.10.2数组初始化及匿名数组

■创建同时赋初值:

int[] smallPrimes = {2, 3, 5, 7, 11, 13};

此时不需要使用new。


■初始化匿名数组

new int[] {2, 3, 5, 7, 11, 13};
使用此方法可以在不创建新变量的情况下重新初始化一个数组。

例如,

smallPrimes = new int[] {2, 3, 5, 7, 11, 13};

3.10.3数组拷贝

Java允许将一个数组变量拷贝给另一个数组变量。此时,两个变量将引用同一数组:

int[] luckNumbers = smallPrimes;luckNumbers[5] = 12; // now smallPrimes[5] is also 12

如果希望将一个数组的所有值拷贝到一个新的数组中。要使用Arrays类的copyOf方法。

int[] copiedLuckyNumbers = Arrays.copyOf(luckNumbers, luckNumbers.length);

第二个参数时新数组的长度,这个方法通常用来增加数组的大小。如果数组元素是数值型,那么多余的元素被赋值为0.如果是布尔型,则是false。

※Java的数组类似于C++的数组指针。

3.10.4命令行参数

略。

3.10.5数组排序

可以使用Arrays.sort方法,这个方法使用了优化的快速排序算法。


排序程序:

import java.util.*;/* * This program demonstrates array manipulation. * @version 1.0 * @author XXX * */public class LotteryDrawing {public static void main(String[] args){Scanner in = new Scanner(System.in);System.out.print("How many numbers do you need to draw?");int k = in.nextInt();System.out.print("What is the highest number you can draw?");int n = in.nextInt();// fill an array with numbers 1 2 3 ...nint[] numbers = new int[n];for (int i = 0; i < numbers.length; i++){numbers[i] = i + 1;}// draw k numbers and put them into a second arrayint[] result = new int[k];for (int i = 0; i < result.length; i++){// make a random index between and n - 1int r = (int)(Math.random() * n);// pick the element at the random locationresult[i] = numbers[r];// make the last element into the random locationnumbers[r] = numbers[n - 1];n--;}// print the sorted arrayArrays.sort(result);System.out.println("Bet the following combination. It'll make you rick!");for (int r : result)System.out.println(r);}}

3.10.6多维数组

注意:

for each循环语句不能自动处理二维数组的每一个元素。它是按照行,也就是一维数组处理的。要想访问二维数组的每一个元素,需要使用两个for each循环嵌套。

例如,

for (double [] row : a)    for (double value : row)        do something withw value

要想快速打印一个二维数组的数据元素列表,可以使用:

System.out.println(Array.deepToString(a));

3.10.7不规则数组

Java中实际上没有多维数组,只有一维数组。多维数组被解释为“数组的数组”。

因此Java可以存在不规则数组,即多维数组的每一位指向的数组的大小可以不同。


第三章完毕!吐舌头

0 0
原创粉丝点击