3.1 A simple java program
最简单的Hello world程序:
public class FirstSample
{
public static void main(String[] args)
{
System.out.println("We will not use 'Hello, World!'");
}
}
Java对大小写敏感(case sensitive)。public是访问控制描述符(access modifier)。class当然是Java的灵魂。这些东西之后都会再详细地解释。class的命名规则就是字母开头,由字母和数字组成,但是不能和保留名重名。
然后提到了CamelCase的命名规则,这本书认为是大写字母开头的。其实小写开头的貌似也行。
另外程序运行的时候就是运行那个main函数,必须要是public类型的。
3.2 Comments
双斜杠进行单行注释,/* */进行多行注释。还有一种文档式的注释,/** */。
3.3 Data Types
Java是一个strongly typed language,也就是说每一个变量必须有类型,与之形成鲜明对比的是Python。
Java有八种基础数据类型(primitive types),4种是整数类型,2种浮点类型,还有字符类型和布尔类型。
3.3.1 Integer Types
4种整数类型:
int 4 bytes –2,147,483,648 to 2,147,483, 647 (just over 2 billion)
short 2 bytes –32,768 to 32,767
long 8 bytes –9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
byte 1 byte –128 to 127
常规来说,int类型是最常用的,short和byte都是为了特殊的场合准备的,而long适用于数据值非常大的时候。
long型数据必须以L或者l结尾。
十六进制数必须以0x或者0X开头。
八进制必须以0开头。当然书上也说了这个有点容易搞混,因此一般不用。
从Java SE 7 开始,可以写二进制,以0b或者0B开始。可以插入下划线来帮助阅读,不会影响实际的值。例如0b1010_1100.
3.3.2 Floating-Point Types
2种浮点型:
float 4 bytes Approximately ±3.40282347E+38F (6–7 significant decimal digits)
double 8 bytes Approximately ±1.79769313486231570E+308 (15 significant decimal digits)
double的意思就是两倍于float的精度。很多时候float的精度都不够,因此除非必须,否则一般用double。
float类型的数后缀应该是f或者F,假如没有会被认为是double类型的。double可以不加后缀,当然也可加上d或者D作为后缀。
有三种特殊的float类型:正无穷Positive infinity,负无穷Negative infinity还有not a number NaN,比如某个数被0除的时候。
3.3.3 The char Type
这个类型开始是想用来表示单个字符的,但现在并不是这样。如今有些Unicode字符可以用一个char来表示,而有些需要两个。
char字符以单引号来表示单个字符,'A'就是一个char,而"A"则是字符串string,它并不在八大基础数据类型里面。
当然char类型也可以用十六进制来表示,从\u0000到\uffff。这四位其实是Unicode编码值。这种值会在编译的时候首先替换成为其符号,即使在comment里面,因此要小心处理。例如// \u00A0 is a newline这个就会报错,因为\u00A0会变成new line。
3.3.4 Unicode and the char Type
Unicode是用来统一符号界的,从其名字上面其实就可以看出这一点。
Unicode本来是16位,后来发现不够。总之除非确实是在UTF-16的环境里面,否则不要使用char。
3.3.5 The boolean Type
布尔值,false和true。在Java里面并不能和int直接转换。Python可以。
3.4 Variables
定义一个变量:类型在前,变量名在后,然后是值,如果有的话。
变量名必须以字母开头。这里的字母的意思就是Unicode里面的字符。还是不能和保留名重合。
3.4.1 Initializing Variables
在使用变量之前应该要初始化。
3.4.2 Constants
用final来表示常量。一般多用大写字母作为变量名。
3.5 Operators
算术符号+-*/。
3.5.1 Mathematical Functions and Constants
介绍了Math库。还有谈到跨平台保证高精度数据一致的问题。
3.5.2 Conversions between Numeric Types
数据可以自动转换,看下图:
[数据转换图]:http://a1.qpic.cn/psb?/V10nQaA30D4ggF/qFBxMq91S4werHvUKbSCK37SM9M6kYb0xQ223piXw!/m/dMgAAAAAAAAAnull&bo=KAJMAQAAAAABB0c!&rf=photolist&t=5
不知道为什么显示不出来,只能贴个链接。
实线表示没有信息损失,虚线表示有。可以发现,只能从位数较多的整型数据传到位数相等或者较少的浮点数,而且因为小数部分丢失,会有信息损失。
假如两个数直接相加减的话,会有以下规则:
• If either of the operands is of type double, the other one will be converted to a double.
• Otherwise, if either of the operands is of type float, the other one will be converted to a float.
• Otherwise, if either of the operands is of type long, the other one will be converted to a long.
• Otherwise, both operands will be converted to an int.
3.5.3 Casts
Cast即转型,手动进行数据类型的转换。在要转换的变量之前加上“(数据类型)”。例如int x = (int) y,y可以是double。在上面那个图可以看到是没有从double到int的实线的,因为那是自动转换,这里通过手动可以实现。
当然,假如要转换的数超过了目标数据类型的范围,超出的部分就会被截断,因为说到底都是以二进制的形式存在的。
并不能把布尔值cast到int。
3.5.4 Combining Assignment with Operators
提到了+=符合。x=x+y等价于x+=y.
3.5.5 Increment and Decrement Operators
用++和--来代表递增和递减,x++等价于x+=1.放前面放后面还不太一样,放前面的先加了然后参与其他运算,放后面的则是最后再加。一般不建议用在复杂表达式里面,容易造成混淆。
3.5.6 Relational and boolean Operators
关系符号,==判断是否相等,!=判断不等,>,<,>=,<=,还有与或非&&,||,!。
还有一个三元关系符:statement?trueExp:falseExp
3.5.7 Bitwise Operators
位操作符,&|~^,还有<<,>>
3.5.8 Parentheses and Operator Hierarchy
Operators Associativity
[] . () (method call) Left to right
! ~ ++ -- + (unary) - (unary) () (cast) new Right to left
* / % Left to right
+ - Left to right
<< >> >>> Left to right
< <= > >= instanceof Left to right
== != Left to right
& Left to right
^ Left to right
| Left to right
&& Left to right
|| Left to right
?: Right to left
= += -= *= /= %= &= |= ^= <<= >>= >>>= Right to left
大部分都是从左往右,少数几个是从右往左的优先度。建议还是加一些括号。
3.5.9 Enumerated Types
枚举类型。适合某个数据类型只有有限的种类,例如:
enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE };
后面还会详细再讲。
3.6 Strings
从概念上讲,Java里面的字符串就是Unicode符号的序列。String并不是一个数据类型,而是一个类。
3.6.1 Substrings
str.substring(start,end),包含start但不包含end。
3.6.2 Concatenation
可以用+符号来连接两个字符串。用String.join()来连接多个字符串。
3.6.3 Strings Are Immutable
和Python一样,Java里面的String也是不可改变的。所谓不可改变,就是值不可改变,实际操作时,可以通过换一个字符串来实现值的改变。这样做的好处就是,编译器能够安排共享的字符串。也就是说,不同的变量,假如值是相同的字符串,其实都是指向一个字符串。
这个设计在大部分时候是合适的,因为大部分时间字符串都不需要改变。但假如有一个个建立字符串的场景,要使用String Builder,之后会讲到。
3.6.4 Testing Strings for Equality
s1.equals(s2),或者s1.equalsIgnoreCase(s2)忽略大小写。不要用==判断是否相等。
3.6.5 Empty and Null Strings
if (str != null && str.length() != 0)先检查null再检查是不是空。
3.6.6 Code Points and Code Units
The char data type is a code unit for representing Unicode code points in the UTF-16 encoding. The most commonly used Unicode characters can be represented with a single code unit. The supplementary characters require a pair of code units.
这一段不知道怎么翻译,code point和code unit怎么翻译?大概意思就是UTF-16编码的code points需要一个或者两个code unit。
s.length()方法就是返回字符串中code unit的个数,从上面的描述可以知道,有的符号可能有两个code unit,因此还有另外一种方法,s.codePointCount(0,,s.length())使用public int codePointCount(int beginIndex, int endIndex)。
s.charAt(idx)返回idx下的code unit。当某一个字符有两个code unit的时候,就有可能和期望的结果不一样。
总之,处理code point是很麻烦的,有办法,但除非有需要,不然没必要深究。
int[] codePoints = str.codePoints().toArray();//从str到code point array
String str = new String(codePoints, 0, codePoints.length);//从code point array到str
3.6.7 The String API
String包含超过50种方法。太长了就不在这里列出了。很多方法都很有用。
3.6.8 Reading the Online API Documentation
主要介绍怎么查在线文档。
3.6.9 Building Strings
当需要构造一个字符串的时候,假如用+符号,因为字符串不变的特性,相当于每一次都构造一个新的字符串,这样相当浪费,因为需要的只是最后那个字符串。因此用StringBuilder这个类来实现字符串的构造。
- 新建:
StringBuilder builder = new StringBuilder(); - 添加:
builder.append(ch); // appends a single character
builder.append(str); // appends a string - 完成:
String completedString = builder.toString();
此外,StringBuilder很多方法和String很像。
3.7 Input and Output
3.7.1 Reading Input
用Scanner来实现读取:
Scanner in = new Scanner(System.in);
读取一行输入:
String name = in.nextLine();
读取一个词,空格处结束:
String firstName = in.next();
读取一个int:
int age = in.nextInt();
读取一个double:
double v = in.nextDouble();
假如是要输入密码的话,用Console类:
Console cons = System.console();
String username = cons.readLine("User name: ");
char[] passwd = cons.readPassword("Password: ");
3.7.2 Formatting Output
使用printf方法控制输出格式。一般分成两部分,前面用%规定格式,后面提供对应的参数。格式有两部分,一部分是转换符,例如%d表示十进制整数;另一部分是flag也就是标志符,例如0表示在开头填充0.
也可以用String.format()方法只改格式,不输出。
此外日期也还有一套输出控制符。
这部分内容太多,就不贴在这里了。
3.7.3 File Input and Output
从一个文件里面读取:
Scanner in = new Scanner(Paths.get("myfile.txt"), "UTF-8");\假如有路径存在,要使用双斜杠。
写文件:PrintWriter out = new PrintWriter("myfile.txt", "UTF-8");
然后可以使用print系列方法输出。假如没有该文件,会新建一个文件。
3.8 Control Flow
3.8.1 Block Scope
用{}来规定一个block。block里面的local变量只在该block有效。
3.8.2 Conditional Statements
就是讲if else语句。
3.8.3 Loops
循环,while语句,do...while...语句。
3.8.4 Determinate Loops
for循环。
3.8.5 Multiple Selections—The switch Statement
switch语句。
3.8.6 Statements That Break Control Flow
break和continue语句。
3.9 Big Numbers
BigInteger和BigDecimal是java.math包里面两个用来对付大数的类。
BigInteger a = BigInteger.valueOf(100);
但是不能再用常规的+-*/符号了:
BigInteger c = a.add(b); // c = a + b
BigInteger d = c.multiply(b.add(BigInteger.valueOf(2))); // d = c * (b + 2)
其他操作包括subtract,divide,mod。
3.10 Arrays
数组是一种存储同类型的数据的集合的数据结构。
定义一个数组:int[] a;
定义加规定大小:int[] a = new int[100];
3.10.1 The “for each” Loop
for (*variable *: collection) statement
类似于Python里面的for x in y语句。
3.10.2 Array Initializers and Anonymous Arrays
定义加赋值:int[] smallPrimes = { 2, 3, 5, 7, 11, 13 };
匿名数组:new int[] { 17, 19, 23, 29, 31, 37 }
3.10.3 Array Copying
int[] copiedLuckyNumbers = Arrays.copyOf(luckyNumbers, luckyNumbers.length);
常用来扩容:
luckyNumbers = Arrays.copyOf(luckyNumbers, 2 * luckyNumbers.length);
默认填充0或者false,看具体的数据类型。
3.10.4 Command-Line Parameters
之前我们看到main函数接受String[] args变量,因此可以在命令行里面给出变量:
java Message -g cruel world
这里Message是一个class,main函数接受后面三个String变量。
3.10.5 Array Sorting
Arrays.sort(a),使用的是Quick Sort。
另外还有binarySearch(a, v)方法,和fill(a, v)方法。
3.10.6 Multidimensional Arrays
二维:double[][] balances;
balances = new double[NYEARS][NRATES];
int[][] magicSquare ={{16, 3, 2, 13},{5, 10, 11, 8},{9, 6, 7, 12},{4, 15, 14, 1}};
3.10.7 Ragged Arrays
Java其实并没有多维数组,上面的多维数组其实是用一维数组造出来的!
网友评论