What & How & Why

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录前一修订版
cs:programming:java:courses:gtx_cs1311x:foundations_n_syntaxs [2024/01/15 13:08] – 移除 - 外部编辑 (未知日期) 127.0.0.1cs:programming:java:courses:gtx_cs1311x:foundations_n_syntaxs [2024/01/15 13:08] (当前版本) – ↷ 页面名由cs:programming:java:courses:gtx_cs1311x:module_1改为cs:programming:java:courses:gtx_cs1311x:foundations_n_syntaxs codinghare
行 1: 行 1:
 +======Foundations and Syntax Basics======
 +//Course I notes//
 +----
 +====Module 1====
 +===Introduction to Java===
 +==Histroy==
 +{{ cs:programming:java:courses:gtx_cs1311x:history.jpg?600 |}}
 +
 +==Java 的基本运行条件==
 +  * 至少有一个 Method
 +  * 至少有一个被称之为 ''main'' 的 method
 +  * mehod 需要被包含在 class 里
 +  * 程序至少要一个类
 +<code js>
 +//class
 +public class project {
 +    //method
 +    public static void main(String[] args) {
 +        //statements
 +        String x = "Hello world";
 +        //print line
 +        System.out.println(x);
 +    }
 +}
 +</code>
 +==java 的文件名==
 +  * **文件的名字**必须与**文件中的类名匹配**
 +  * 后缀为 ''.java''
 +===Executing Java Programs===
 +==两种类型的程序转换==
 +  * 编译器(//Compiler//):将整个程序一次性转换为机器码(二进制),然后再执行
 +    * 速度快:只用编译一次即可反复使用
 +    * 不同的机器支持的指令集不同(需要的中间文件也不一样),因此编译器是基于机器来设计的。因此,在一台机器上编译好的程序很可能不能在另外一台机器上跑。如果需要跨平台,那么针对每个平台都要编译一次。
 +  * 解释器(//Interpreter//):会立即转化(不会有 pre-processing),没有中间文件,逐行执行
 +  * 速度慢,每次运行都要执行
 +  * 没有中间文件的生成,因此可以在任何电脑上执行。
 +==Java's Hybrid Approach==
 +  * Java 不会直接编译基于机器码的中间文件,而是编译程序为 ''bytecode'' 类型的文件,存储在 ''.class'' 文件中。''bytecode'' 文件不基于指令集,但足够接近底层。
 +  * 当编译了 ''bytecode'' 文件后,Java 会以解释器的方式,将 ''bytecode'' 文件转换为特定的机器语言。
 +<WRAP center round box 100%>
 +  * Java 的解释器被称为 Java Virtual Machine(//JVM//)
 +  * 这种混合的方式被称为 //Just-In-Time compilation//
 +</WRAP>
 +==Java 程序的编译与执行==
 +<code bash>
 +# complie java
 +javac + file_name.java
 +
 +# a file_name.class file will generated 
 +# initiate interpreter, where JVM comes in
 +# no extension needed!
 +java + file_name
 +</code>
 +==The Java Development Kit==
 +//Java Development Kit(JDK)// 是 java 用于编译和执行文件的工具集合。与之前概念一些区别:
 +  * //Java Development Kit(JDK)// : 包含了写 java 的工具,以及编译 java 需要的环境(//JRE//)。**非**跨平台
 +  * //Java Runtime Environment(JRE)//:包含对**执行** java 程序的支持。**非**跨平台
 +  * //Java Virtual Machine(JVM)//:将编译器生成的 ''bytecode'' 文件转化为对应机器的机器码文件。跨平台
 +三者从上到下是依次包含的关系。
 +===Why OOP===
 +==Identifier==
 +java 的类名,函数名,变量名等一切由用户自定义的 name 被称为 identifier:
 +  * identifier 可以包括:字母(letters),数字(digits),下划线 ''_'',和美元符号 ''$''
 +  * 数字**不能**作为 name 的开头
 +  * identifier 不能为关键字(均为小写)
 +  * indentier 区分大小写
 +  * Java 使用骆驼写法(头字母小写)来对 identifier
 +==Java 的数据类型==
 +^ Type    ^ Size     ^ Range     ^
 +| <color #900>byte</color>    | 8 bits    | $[-2^7, 2^7)$|
 +| <color #900>short  </color> | 16 bits  | $[- 2^{16}, 2^{16})$|
 +| <color #900>int</color>     | 32 bits    |$[- 2^{32},  2^{32})$|
 +| <color #900>long   </color> | 64 bits    |$[- 2^{64}, 2^{64})$|
 +==变量的声明与赋值==
 +<code js>
 +#类型必须匹配
 +int a = 78;
 +double d = a * 5;
 +</code>
 +<WRAP center round box 100%>
 +跟 C++ 类似,Java 的运算中存在隐式转换。赋值的时候需要注意。
 +</WRAP>
 +==Objects==
 +//Objects// 的两种属性:
 +  * //attribute// 表示状态,比如车的颜色,大小,品牌
 +  * //actions// 代表行为,比如点火,熄火,踩刹车
 +====Module 2====
 +===Basics===
 +==whitespace==
 +  * blanks, tabs, newline
 +  * 编译器将其视作分界线
 +  * 增强代码的可读性
 +===Errors===
 +  * Error types: Complier, Runtime, Logical
 +  * Smantics vs systax : meaning of the code vs coding rule
 +==Compile and Runtime Errors==
 +  * Complie error: 指程序在编译过程中出现的错误,具体指systax error
 +  * Runtime error : 指程序在执行中出现的错误(比如除零)
 +==Logical Errors==
 +  * Logial error 指 semetics error
 +<WRAP center round box 100%>
 +  * 推荐写完每一个 method 之后测试一次
 +  * 添加 comments
 +</WRAP>
 +==Comments==
 +<code js>
 +// this is inline comment
 +
 +/* this is
 +   block comment
 +*/
 +
 +/** javadoc comments
 +    this scan your source code for certain comments
 +    and automatically creates html files to describe your code,
 +    starts with forward slash and to asterisks
 +    end with an astrisk and forward slash
 +*/
 +</code>
 +===Variables and Constants===
 +  * variable 拥有自己的 scope
 +  * 其区域通常以 method 为单位
 +==constant 的定义==
 +  * 使用 ''final'' 关键字:
 +<code js>
 +final double PI = 3.1415926
 +</code>
 +==Primitive Types==
 +^ Type    ^ Size      Range     ^
 +| <color #900>byte</color>    | 8 bits    | $[-2^7, 2^7)$ |
 +| <color #900>short  </color> | 16 bits  | $[- 2^{16}, 2^{16})$ |
 +| <color #900>int</color>     | 32 bits    | $[- 2^{32},  2^{32})$ |
 +| <color #900>long   </color> | 64 bits    | $[- 2^{64}, 2^{64})$ |
 +|<color #7092be>float</color>| 32 bits|$[3.40282347 x 10^{38}, 1.40239846 x 10^{-45}]$ |
 +|<color #7092be>double</color>|64 bits| $[1.7976931348623157 x 10^{308}, 4.9406564584124654 x 10^{-324}]$ |
 +==default type==
 +  * 整型的 default type 是 ''int''
 +  * 浮点型的 default type 是 ''double''
 +因此,如下的语句会错误:
 +<code js>
 +long bigNum = 99999999999999
 +</code>
 +因为此处将 ''99999999999999'' 视作是 ''int'' 类型数据,但该数据已经超过了 ''int'' 类型所能表示的上限。因此我们需要指定其为 ''long'' 类型:
 +<code js>
 +//adding L to the end of the number
 +long bigNum = 99999999999999L
 +</code>
 +同理,如果要使用 ''float'' 表示浮点数,也需要再后面加 ''F'' 或者 ''f''
 +<code js>
 +float PI = 3.14159F
 +float PI = 3.14159f
 +</code>
 +我们也可以使用类似后缀强制将默认为 ''int'' 的数据转化为浮点型:
 +<code js>
 +double num1 = 2D;
 +double num1 = 2d;
 +</code>
 +<WRAP center round box 100%>
 +低精度的数据有助于减少内存的使用。
 +</WRAP>
 +==char==
 +  * char 的排序取决于 character set
 +  * Java 使用 unicode 作为 character set,该 set 是 ASCII 的超集
 +定义 char 使用单引号(single qoute):
 +<code js>
 +char yes = 'Y'
 +</code>
 +<WRAP center round box 100%>
 +double quote 代表 string,不能用于 char
 +</WRAP>
 +==boolean==
 +''boolean'' 类型的定义:
 +<code js>
 +boolean parked = true;
 +</code>
 +==escape sequences==
 +使用 back slash 作为 escape sequence 的开始,表示特殊字符:
 +<code js>
 +// single quote
 +\'
 +// double quote
 +\"
 +// back slash
 +\\
 +// tab
 +\t
 +// new line
 +\n
 +// carriage return
 +\r
 +</code>
 +===Arithmetic Expressions===
 +  * 包括 operand 和 operator
 +==Integer Division==
 +Java 的整数除法会完全忽略小数部分,比如 ''9/2 = 4''。如果希望得到浮点数结果:
 +  * 将任意一个 operand 改为浮点数
 +  * 强制转化 operand 为浮点数类型:
 +<code js>
 +9.0 / 2 = 4.5
 +9 / 2.0 = 4.5
 +9.0 / 2.0 = 4.5
 +9D / 2 = 4.5
 +9 / 2D = 4.5
 +9D / 2D = 4.5
 +</code>
 +==String Arithmetic==
 +String 的加法代表链接两个 string:
 +<code js>
 +//result is "1331"
 +"13" + "31"
 +</code>
 +==order of precedence==
 +  * 遵从基本的算数优先级
 +  * 使用括号改变优先级
 +==Mixed Type Expressions==
 +在有不同类型参与的表达式计算中,Java 会对某些不合要求的 operand 进行 “promotion”,以此达到完成运算的目的。具体的类说:
 +  * 整型和浮点型:整型会被提升为浮点型
 +  * 任何类型与 string 进行算术相加,都会被提升为 string,再进行连接。
 +===Conversion===
 +分为两种:
 +  * Assignment Convenrsion
 +  * Casting
 +==Assignment Conversion==
 +  * Coversion 是否合法取决于数据类型的范围是否能表示数据。比如:
 +<code js>
 +double average = 4.0;
 +int gpa = average;
 +</code>
 +就是非法的,因为 ''int'' 不能表示 ''double''。因此,导致丢失精度的 assignment 是非法的。
 +\\ \\ 
 +{{ cs:programming:java:courses:gtx_cs1311x:type_range.png?400 |}}
 +==Casting==
 +Casting 是手动的强制转换。写法为:
 +<code js>
 +(type)expression
 +</code>
 +比如下面的表达式:
 +<code js>
 +//casting 5 from int to double
 +//then do the 5.0 / 9
 +(double)5/9
 +</code>
 +注意,casting 的优先级高于所有的运算,除了括号。因此在括号参与的运算中,要先运算括号中的内容:
 +<code js>
 +//result is 0.0
 +(double)(5/9)
 +</code>
 +<WRAP center round box 100%>
 +casting 不单用于算术类型。
 +</WRAP>
 +===Using Predefined Classes===
 +==Declaring Variables==
 +  * Objects 变量被称为 reference 变量。其本身值是引用。
 +  * Java 中的对象存储在 heap 中,通过引用找到地址进行访问。
 +==Instantiation==
 +Java 中 Object 的实例化被称为 //Instantiation//。写法如下:
 +<code js>
 +new ClassName(parameters)
 +</code>
 +实例化通过构造函数(constructor)建立。以 ''String'' 类为例,其构造函数为 ''String''
 +<code js>
 +String major = new String("computer scinece);
 +</code>
 +==Invoking Methods==
 +Methods 通过 instance 的 identfier,也就是某个类的 reference 进行调用。比如打印:
 +<code js>
 +System.out.println("Hello");
 +//no newline version
 +System.out.print("Hello");
 +</code>
 +''out'' 是指向 ''PrintStream'' 类对象的引用。''System'' 是 JAVA STL 的一部分。
 +
 +<WRAP center round box 100%>
 +实例化的只有对象的数据。methods 属于 class,是唯一的。
 +</WRAP>
 +==Java 中的拷贝==
 +  * primtive 类型的拷贝是直接复制
 +  * 对象名存储的是引用,因此拷贝对象等于**拷贝引用**,也就是复制地址。两者指向同一个实例。这种情况下,两者被称为 //alias//
 +<WRAP center round tip 100%>
 +跟 C++ 不同的是,如果在 Java 中更改了指向某个地址的引用,但忘记了释放指向的资源,Java 会在随后的恰当时间内**自动**回收这部分资源。这个功能被称为 Java 的 //Garbage Collection//
 +</WRAP>
 +===String methods===
 +  * //Signiture Type//:描述 method 的方式,包括了 method name, parameter 的数量及其位置。
 +  * //String literal// (比如 ''"Hello"'') 也是 String 实例,也可以直接调用 String method。
 +  * //String// is **IMMUTABLE**!
 +<WRAP center round box 100%>
 +Docs: [[https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html|check here]]
 +</WRAP>
 +
 +<code js>
 +major = "CS"
 +interest = "system"
 +//compute the length of the string, return int
 +//ret_num has val 2
 +int ret_num  = major.length()
 +
 +//return a new string will switching all uppercases to lowercases. 
 +//dosen't modifiy the original string
 +//"newString" has value "cs"
 +String newString = major.toLowerCase();
 +
 +//concatnate a string with another string
 +//return a new string 
 +//"concated" has value "CSsystem"
 +String concated = major.concat(interest)
 +
 +//return a new string
 +//replace oldchar with newchar
 +//"replaced" has value "PS"
 +String replaced = major.replace('C', 'P')
 +
 +//return new string 
 +//copying a range of characters from the string
 +//range is LEFT include.
 +//"subStr" has value "sys": 0,1,2
 +String subStr = interest.substring(0,3);
 +
 +// returns the index of the first occurrence of the sequence, or return - 1 if no match
 +// support int, char, string
 +// char will be converted to Unicode int
 +indexOf(String str)
 +indexOf(int char)
 +indexOf(String str, int fromIndex)
 +indexOf(int char, int fromIndex)
 +</code>
 +==formal & actual parameter==
 +  * method 使用的 paramter 被称为// actual parameter//(实参,argument),method 定义中的 paramter 被称为// formal parameter//(形参, parameter)
 +  * 直接传递 actual paramter 给 formal paramter 时,actual parameter 会拷贝后再传递给 formal parameter。这个过程被称为 //pass by value//
 +==substring index==
 +  * Java 的 index 也是从 $0$ 开始。
 +  * Index error 属于 runtime error。编译器不会检查
 +===Input & MutiInput===
 +==Scanner==
 +<WRAP center round box 100%>
 +Docs: [[https://docs.oracle.com/javase/10/docs/api/java/util/Scanner.html#method.summary|check here]]
 +</WRAP>
 +
 +''Scanner'' 类是 Java 提供的,用于接受输入信息的类。实例化一个 ''Scanner'' 对象需要提供一个 //input// 对象:
 +<code js>
 +import java.util.Scanner; 
 +public class FahrenheitToCelsius {
 +    public static void main(String[] args) {
 +        Scanner input = new Scanner(System.in); //read keyboard input
 +    }
 +}
 +</code>
 +这里的 ''System.in'' 就是一个输入对象。''Scanner'' 实例可以通过该对象按顺序读取从键盘输入的信息。比如下面的信息:
 +<code bash>
 +78 long
 +walks
 +</code>
 +会以:
 +<code bash>
 +78 long\n\walks\n
 +</code>
 +这种 “流(stream)” 的形式被接收。流中的各个部分被称为 //Token//,每种类型的 //Token// 可以被指定的 ''Sanner'' method 进行筛选。比如 ''nextInt()'' 就可以在流中读取下一个可见的 ''int'' 数据。
 +\\ \\ 
 +''Scanner'' 通过特殊的,被称为 //delimiter// 的边界来分割 //Token//。默认情况下,//delimiter// 是 whitespace(''\t'', ''\n'', space)。
 +\\ \\ 
 +整个输入环节的顺序:
 +  - 实例化 Scanner 对象
 +  - 使用 Scanner 对象调用对应的 Method (比如我要一个 ''int'' 就用 ''nextInt()'')
 +  - 再创建一个变量接受 Scanner 对象调用 Method 的结果。
 +
 +<code js>
 +import java.util.Scanner; 
 +public class FahrenheitToCelsius {
 +    public static void main(String[] args) {
 +        Scanner input = new Scanner(System.in); //read keyboard input
 +        System.out.print("Please enter the temperture(F): ");
 +        int fah = input.nextInt();
 +        System.err.print("The current temperture in F is: " + fah);
 +    }
 +}
 +</code>
 +<WRAP center round box 100%>
 +  * Scanner 需要被导入才能使用:''import java.util.Scanner; ''
 +  * //next// 系列 method (除开 ''nextLIne()'') 会自动忽略 Token 前后的所有 whitespace
 +  * 输入类型不匹配的数据会导致抛出异常
 +  * //hasNext// 系列可以检查 Token 的数据类型。
 +</WRAP>
 +==hasNext 的用法==
 +//hasNext// 系列函数会返回一个 bool 值。为 true 时输入有效,反之无效。以 ''int'' 数据为例:
 +<code js>
 +int num;
 +if (input.hasNextInt()) {
 +    num = input.nextInt();
 +}
 +else {
 +    System.out.println("invalid input.")
 +}
 +</code>
 +==多个输入==
 +多个输入可以通过顺序性的调用 ''next'' 系列的 method 来完成:
 +<code js>
 +int fah = input.nextInt();
 +System.out.print("Enter a day of the week: ");
 +String day = input.next();
 +</code>
 +但有一点需要注意的是,''nextLIne()'' method 不会忽略 ''\n''。这会带来什么样的后果呢?
 +\\ \\ 
 +首先要明确的是存在多个输入的情况时,我们的输入流程:
 +  - 输入数据
 +  - 回车输入下一个数据
 +这里的回车(//Enter//)实际上产生的效果是添加 ''\n'' 到流的末尾。假设我们输入一个数 ''78'',那么回车以后,''78'' 存储到本地变量,流就会变为 ''\n''。之前提到过,其他 ''next'' 系列的 Methods 都会忽略 Token 之前的 ''\n'',除了 ''nextLine()''; 因此,其他的 ''next'' method 都会在此处等待用户的下一次输出,但 ''nextLine()'' 会在这里读取到的首个 Token ''\n'',这将导致当前的输入立即结束。
 +<WRAP center round box 100%>
 +输入数据 + 回车 + 输入数据只是一种流程,原理上是使用了 ''\n'' 作为 delimiter。但我们也可以通过 space 来做 delimiter,比如本节开头的,使用 ''next()'' 例子中,如果使用 ''78 monday'' 只输入一行,也可以达到效果。此时流通过 space 将 Token 分为了 ''78'' 和 ''monday'',''fah'' 接受了 ''78'', ''day'' 接受了 ''monday'',因此只需要输入一行也能达到效果。
 +</WRAP>
 +
 +==nextLine 的应用场景==
 +使用 ''nextLIne()'' 可以一次性的获取单个 String(可以包含各种 whitespace,除了 ''\n'')。但在使用之前,需要将之前的 ''\n'' 信息全部清空。我们可以**额外的**调用一次 ''nextLine()'' 来实现这个目的:
 +<code js>
 +int fah = input.nextInt();
 +//clean up the newline info
 +input.nexLine();
 +//read the input
 +System.out.print("Enter a day of the week: ");
 +String day = input.nextLine();
 +</code>
 +Java 也提供了 method ''trim()'' 来实现这个功能:
 +<code js>
 +String day = input.nextLine().trim();
 +</code>
 +===Packages & import===
 +<WRAP center round box 100%>
 +Docs:[[https://docs.oracle.com/javase/7/docs/api/java/lang/package-summary.html|check here]]
 +</WRAP>
 +
 +Class 可以按照其提供的函数进行打包。 这些包通常被称为 packages,比如 System, String 等等。Java 中存在一个 package Long list,使用属于该 list 中的 package 时无需做额外的准备。任何不属于该 list 的 package,都需要 //import//,格式如下:
 +<code js>
 +import packageName.memberName;
 +</code>
 +需要注意的是,package 之间存在着继承关系。在导入的时候,需要按层级将所有的 package 写出来。比如 ''Scanner'' 就继承自 ''util'' Package,而 ''util'' 继承自 ''java'',因此导入时就需要写成:
 +<code js>
 +import java.util.Scanner;
 +</code>
 +<WRAP center round info 100%>
 +Import 的 overhead cost 处于编译期,不影响运行期的 performance。
 +</WRAP>
 +
 +==using wildcard in import==
 +如果需要导入当前 package 的所有内容,可以使用通配符(//wildcard//) ''*''(//asterisk//):
 +<code js>
 +import java.util.*;
 +</code>
 +==confilct in import==
 +假设有如下的两个 package:
 +<code js>
 +long.walks.Beach
 +swim.surf.Beach
 +</code>
 +这两个 package 都被称为 ''Beach'',但来自于不同的 package,其实现也不一样。如果我们同时导入这个两个 package,再进行调用的话:
 +<code js>
 +import long.walks.*;
 +import swim.surf.Beach;
 +//using the package
 +Beach tybee;
 +</code>
 +那么此时编译器会报错包冲突。比较好的解决方法是,导入其中一个,使用另外一个的时候直接使用其 //Full-qualified name//,即:
 +<code js>
 +import long.walks.*;
 +//using full-qualified name to make the declaration
 +swim.surf.Beach tybee;
 +</code>
 +===Output & Formating===
 +==printf()==
 +Java 使用 ''printf()'' 来控制输出格式:
 +  * ''printf()'' 由成对的 //placeholder// 与变量组成,可以存在多组
 +  * //placeholder// 以 ''%'' 开头,按位置对应变量
 +下面例子中,''%s'' 代表的是 ''String'' 类型的 placeholder, 对应 ''day'';''%f'' 代表 ''double'' / ''float'' 类型的 placeholder, 对应 ''celsius''
 +<code js>
 +System.out.printf("%s Celsius: %f\n", day, celsius);
 +</code>
 +<WRAP center round box 100%>
 +  * ''printf()'' 也不会自动换行,因此需要再 ''%f'' 后加上一个 ''\n''
 +  * 如果希望打印 ''%'',需要输入 ''%%''
 +</WRAP>
 +
 +==placeholder==
 +placeholder 的结构如下:
 +<code js>
 +%[flag][width][.precision]type
 +</code>
 +中间方括号的内容是可选的部分,type 是指之前例子中的 ''s'' 等。具体的来说:
 +  * ''d'' 代表整型
 +  * ''f'' 代表 ''double'' 或是 ''float''
 +  * ''s'' 代表 ''String''
 +再来看看可选部分:
 +  * 如果想要控制小数的位数,使用 ''.percision ''。比如 ''25.6666666'',如果希望只打印一位小数的话,使用 ''.1%f''
 +<code js>
 +double fahd = 25.6666666
 +System.out.printf("The current temperture in F is: %.1f\n" ,fahd);
 +</code>
 +打印结果为 ''25.7'',最后一位进行了四舍五入。
 +  * 如果想要控制宽度,使用 ''width''。控制宽度的具体意思是,无论被打印的内容有多长,显示的内容长度都会占 ''witdh'' 指定的数据。如果给定的数据没有这么长,则使用空格填充。这个参数对自动对齐非常有用,比如:
 +<code js>
 +System.out.printf("The temperture is: %4.1f\n" ,fahd);
 +System.out.printf("Next day is: %10s", day);
 +</code>
 +这里设置 ''fahd'' 占用 4 个长度,''day'' 占用 10 个长度,打印的结果正好上下对齐。因此,不管 ''fahd'' 和 ''day'' 的长度是多少,这两行都会对其在文本末尾:
 +<code bash>
 +The temperture is:  3.1
 +Next day is:     Monday
 +
 +The temperture is: 82.1
 +Next day is:    Tuesday
 +</code>
 +默认情况下长度是按照右对齐的。如果希望**左对齐**,将 ''witdh'' 的值改为**负数**:
 +<code js>
 +System.out.printf("The temperture is: %-4.1f\n" ,fahd);
 +System.out.printf("Next day is: %-10s", day);
 +</code>
 +<code bash>
 +Please enter the day: Monday
 +The temperture is: 3.1
 +Next day is: Monday
 +
 +The temperture is: 82.1
 +Next day is: Tuesday
 +</code>
 +==String.format==
 +''String'' 提供了一个 method ''format'',与 ''printf()'' 功能一致。唯一不同的是,它会将格式化的 ''String'' 对象返回,因此需要一个变量来存储返回值:
 +<code js>
 +String celsiusOutput = String.format("%s %-11s %,.1f \n", day, cText, celsius);
 +</code>
 +==NumberFormat==
 +Java 提供了一个 package: ''NumberFormat'',专门用于自动将数字打印为对应的货币格式。其导入方式为:
 +<code js>
 +import java.text.NumberFormat;
 +</code>
 +在打印的时候需要建立一个 ''NumberFormat'' 对象,使用该对象调用 ''getCurrencyInstance()'' method 得到对应的货币字符串,再使用 ''format'' method 对其进行输出:
 +<code js>
 +import java.text.NumberFormat;
 +
 +double total = 25.666666;
 +NumberFormat currencyFmt = NumberFormat.getCurrencyInstance();
 +System.out.println("Total is: " + currencyFmt.format(total));
 +</code>
 +打印结果为:
 +<code js>
 +Total is: ?25.67
 +</code>
 +可以看到货币符号为 ''?'',输出结果格式化为小数点后两位。如果希望打印指定国家的货币符号,需要配合 ''util'' 下的 ''Locale'' package 一起使用:
 +<code js>
 +import java.text.NumberFormat;
 +import java.util.Locale;
 +
 +double total = 25.666666;
 +NumberFormat currencyFmt = NumberFormat.getCurrencyInstance(Locale.CANADA);
 +System.out.println("Total is: " + currencyFmt.format(total));
 +</code>
 +打印结果为:
 +<code js>
 +Total is: $25.67
 +</code>
 +==DecimalFormat==
 +<WRAP center round box 100%>
 +Docs: [[https://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html|check here]]
 +</WRAP>
 +
 +''DecimalFormat'' 是 Java 提供的,按照 parrtern 输出的数字的 package。同 ''NumberFormat'' 类似,''DecimalFormat'' 需要建立对象,然后通过该对象调用 ''format()'' method 来实现目的。几种常用的用法有:
 +  * 数字 ''0'':''0'' 用于占位使用,代表当前位至少会有数字显示。该用法区分几种情况:
 +如果 ''0'' 的位数**大余**实际数字的位数:那么多出来的位数会被 ''0'' 填充:
 +<code js>
 +double num = 13.1;
 +DecimalFormat outNum = new DecimalFormat("000.00");
 +// print 013.10
 +System.out.println(outNum.format(num));
 +</code>
 +如果 ''0'' 的位数**等于**实际数字的位数:那么打印当前数字:
 +<code js>
 + double num = 13.1;
 +DecimalFormat outNum = new DecimalFormat("00.0");
 +// print 13.1
 +System.out.println(outNum.format(num));
 +</code>
 +如果 ''0'' 的位数**小于**实际数字的位数:整数部分打印数字的**实际位数**,小数部分按照 ''0'' 的位数进行四舍五入:
 +<code js>
 +double num = 1313.11933334;
 +DecimalFormat outNum = new DecimalFormat("000.00");
 +// print 1313.12
 +System.out.println(outNum.format(num));
 +</code>
 +  * 字符 ''%'':如果 pattern 的末尾带有带有 ''%'',那么数字会以百分比的形式输出,比如:
 +<code js>
 +double num = 0.119333334;
 +DecimalFormat outNum = new DecimalFormat("00.00%");
 +// print 11.93%
 +System.out.println(outNum.format(num));
 +</code>
 +注意这里小数部分,也就是 ''.00'' 的占位,会直接应用到百分比上;也就是原来小数部分的第四位。
 +  * 字符 ''#'':用法与 ''0'' 基本相同,唯一的差别是不会显示 ''0''
 +<code js>
 +double num = 0.119333334;
 +DecimalFormat outNum = new DecimalFormat("#.00");
 +// print .12
 +System.out.println(outNum.format(num));
 +</code>
 +====Module 3====
 +==if & else statment==
 +用法 与 C++ 相同,格式:
 +<code js>
 +if (condition) {
 +    statement;
 +    //...
 +}
 +else if (condition) {
 +    statement;
 +    //...
 +}
 +else {
 +    statement;
 +    //...
 +}
 +</code>
 +<WRAP center round box 100%>
 +if / else 配对是找最近的彼此,与 C++ 相同。
 +</WRAP>
 +==The switch Statement==
 +同 C++。 格式:
 +<code js>
 +switch (expression) {
 +    case value1:
 +            statement(s)
 +            break;
 +    case value2:
 +            statement(s)
 +            break;
 +    default:
 +            statement(s)
 +        }
 +</code>
 +  * ''expression'' 可以是任意的 primtive type, 以及结果是 primtive type、emum、Character、Byte、Short、Interger(注意大小写,这些是和 primtive 不一样的类型)
 +  * 不要忘记 ''break''。忘记 ''break'' 会导致会导致 switch 继续执行接下来的语句。
 +===Comparing Non-numeric Data===
 +  * 字符的大小比较通过 ASCII 码来比较
 +==equals method==
 +Java 中比较两个 String 的时候,通常会出现两种方式:''=='' 和 ''x.equals(y)''。这两种方式比较的内容不同:
 +  * ''=='' 比较的是两个 String 的 reference 是否指向同一个地址,也就是两个 String 是否是同一个 instance
 +  * ''equals()'' 只是再单纯的比较两个 String 的内容是否相同。
 +以上的区别解释了 Java 为什么会存在两种初始化 String 的方式:
 +<code js>
 +//method 1
 +String xOne = "park";
 +//method 2
 +String yOne = new String("park");
 +</code>
 +如果是第一种方式,那么 ''park'' 只会在**第一次创建**时在堆上申请空间。Java 在堆上有一个专门的空间被称作 //string constant pool// 用于存储这类 string literial。当之后再使用 assignement 创建相同内容的 string literial 时,创建的对象会直接引用到第一次 创建时的地址。也就是说,所有非 new 方式的 String 对象创建均指向第一次创建该对象时的地址。
 +\\ \\
 +第二种方式会在堆上强制申请新的空间,因此其内容与第一种方式相同,但代表的 instance,在内存中的地址是不一样的。
 +因此:
 +<code js>
 +String xOne = "park";
 +String xTwo = "park";
 +String yOne = new String("park");
 +
 +//True, same address
 +if (xOne == xTwo) { //......}
 +//True, same content
 +if xOne.equals(xTwo) {//... }
 +
 +//False, different address
 +if (xOne == yOne ) { //...}
 +//True, same content
 +if xOne.equals(yOne) {//... }
 +</code>
 +==compareTo method==
 +  * String 不能用关系运算符比较**大小**
 +  * 需要使用 ''compareTo'' method 来比较
 +''compareTo()'' method 会将 String 中的每一位字符转换为 ASCII 值,并按位进行比较。''compareTo()'' 的逻辑(以 ''a.compareTo(b)'' 为例):
 +  - 返回值为 ''int'',为正代表 ''a > b'',为负代表 ''a < b''
 +  - 按位比较,找出第一位不同的字符。返回的 ''int'' 的是两个字符之间的 **ASCII 码**值之差
 +  - 如果 ''a'',''b'' 之间,有一个 String 是另外一个 的 subString,则返回的 ''int'' 是两者**长度**之差 
 +一些实例:
 +<code py>
 +String a = "pppp";
 +String b = "pppq";
 +String c = "ppppbbb";
 +
 +// return -1
 +System.out.println(a.compareTo(b));
 +// return -3
 +System.out.println(a.compareTo(c));
 +// return 1
 +System.out.println(b.compareTo(c));
 +</code>
 +===Operators===
 +==Logical Operators==
 +  * 与 C++ 相同。
 +  * 优先级:
 +    * 括号最优先(推荐使用)
 +    * ''!'' > ''&&'' > ''||''
 +==Short-circuit Evaluation==
 +Java 在逻辑表达式评估中会首先评估 left operand:
 +  * 对于  ''&&'',如果值为 false 则不会再对 right operand 进行评估。
 +  * 对于 ''||'',如果值为 true 则不会再对 right operand 进行评估。
 +这种评估方式被称为 //Short circuit evaluation//
 +
 +  * //**如何利用 short circuit evaluation?**//
 +尽量将运算复杂的条件作为 right operand,比如 function call 之类的。
 +==Ternary Conditional Operator==
 +与 C++ 一致。
 +<code js>
 +condition ? expression1 : expression2
 +</code>
 +===Iteration===
 +==while==
 +  * 写法与 C++ 相同
 +  * 循环的条件一般写称**左闭右开**,也就是初始次数包含在条件里,而终止条件是小于循环次数。
 +使用输入作为条件的循环:
 +<code js>
 +int condition = myInput.nextInt();
 +while(condition != 100)
 +{
 +    // ...do sth
 +    condition = myInput.nextInt();
 +}
 +</code>
 +==Do-while==
 +  * 写法与 C++ 相同
 +  * 循环次数是额外的,不包括初始运行的那一次,可以写成 ''< = looptimes''
 +==For==
 +  * 同 C++
 +  * 循环变量是局部变量
 +  * 变量改变部分是运算表达式
 +==break & continue==
 +  * 同 C++
 +====Module 4====
 +===Arrays===
 +  * Java 的 Array 性质与 C++ 类似:长度和类型都是被定义的。
 +  * Array 是指向内存序列的首地址。
 +  * 每个 Array 都会附带一个 final variable(常量)用于存储数组的长度。
 +  * Java 的 Array 可以存储 Objects;准确的说,是存储指向 Objects 的 references
 +==Array 的定义==
 +声明的方式:
 +<code js>
 +//both are fine
 +//first is recommonded
 +elementType[] identifier;
 +elementType identifier[];
 +</code>
 +定义的方式:
 +<code js>
 +//default value of elements is 0.0
 +double[] weekHighs = new double[7];
 +</code>
 +==Default Values==
 +  * Primtive numeric type 的初始值是 ''0'' / ''0.0''
 +  * boolean 的初始值是 ''false''
 +  * char 的初始值为空(不打印)
 +  * String 的初始值为 ''nulll''(java 关键字,表示对象没有 address)
 +==Specifying Values==
 +<code js>
 +//direct init
 +double[] weekHighs = {80, 70, 75, 69, 72, 74, 90};
 +
 +//assignment init
 +double[] weekHighs; //declaration
 +weekHighs = {80, 70, 75, 69, 72, 74, 90}; //initialization
 +
 +//accessing by index(starts from 0, end at len - 1)
 +weekHighs[0];
 +//modifiying
 +weekHighs[0] = 80;
 +//modifiying with the value from input
 +weekHighs[0] = input.nextDouble();
 +</code>
 +==Using Arrays==
 +<code js>
 +//accessing the length
 +weekHighs.length;
 +
 +//looping array
 +for (int i = 0; i < weekHighs.length; ++i) {
 +    System.out.println(weekHighs[i]);
 +}
 +</code>
 +==The for-each Statement==
 +  * 类似 C++ 的 Range based loop
 +  * 优势是不用担心 index 越界
 +定义如下:
 +<code js>
 +for (arrayType element : array) {...}
 +//example
 +for (int element : weekHighs) {
 +    System.out.println(element);
 +}
 +</code>
 +==Sparse Arrays and Null Checking==
 +如果遍历的数组是对象数组(比如 String array):
 +  * Java 默认该数组为 non-sparse array,即任意元素值都不为 ''null''
 +  * 如果有值为 ''null'' 的元素,该 array 被称为 //sparse array//
 +//For-each// 在遍历 //sparse array// 时,如果遇到值为 ''null'' 的元素并且需要与其**比较**的话,会抛出 //NullPointerException//。解决的方法是做一个 null check:
 +<code js>
 +String concepts[] = new String[5];
 +        for (int i = 0; i < 4; ++i) {
 +            concepts[i] = "item";
 +        }
 +
 +        String result = "not found.";
 +
 +        for (String element : concepts) {
 +            if ((element != null) && element.equals("items")) {
 +                result = "found";
 +                break;
 +            }           
 +        }
 +        System.out.println(result);
 +</code>
 +<WRAP center round box 100%>
 +注意这里的 null check 必须要优先检查,也就是至于 ''&&'' 之前。如果比较之于检查之前发生,那么依然会抛出异常。
 +</WRAP>
 +==Command-line Arguments==
 +Java 的 ''main()'' 函数自带一个 String array,这个 array 会接受来自于命令行的内容,元素以空格区分。我们可以从命令行对该数组进行初始化:
 +<code js>
 +//calculating average in args[]
 +double total = 0;
 +    for (String num : args) {
 +        total += Double.parseDouble(num);
 +    }
 +    System.out.println(total / args.length);
 +</code>
 +编译之后,只需要从命令行输入数据就可以得到结果了:
 +<code bash>
 +java Array 10 10 10 10 20
 +12.0
 +</code>
 +需要注意的是,程序中自带了:
 +<code js>
 +total += Double.parseDouble(num);
 +</code>
 +''Double'' 是 Java 提供的一个 package, ''parseDouble()'' 是其中的一个 method,用于将 String 转化为 double。
 +==2-D Arrays==
 +  * 实质上是存储了一系列 array 首地址 的 array
 +  * 可以想象为 ''array[row][col]'',''row'' 的元素是 array 的首地址,''col'' 是每个 array 中元素的 index, 元素内容是 array 中的元素或(地址)
 +<code js>
 +//declaration
 +elementType[][] indentifier;
 +indentifier elementType[][];
 +
 +//direct init
 +double[][] array2d = {{80,70,75}, {69, 72, 74}};
 +
 +//init with diaensions, with default value
 +//2 arrays, each has 3 double elements
 +double[][] array2d = new double[2][3]
 +
 +//assignments
 +array2d[0][0] = 80;
 +
 +//traversing 2d-array
 +//array2d.length is how many arrays that array2d has
 +//array2d[0].length is how many elements that each array has
 +for (int row = 0; row < array2d.length; ++row) {
 +    for (int col = 0; col < array2d[0].length; ++ col) {
 +        System.out.println(array2d[row][col]);
 +    }
 +}
 +</code>
 +<WRAP center round important 100%>
 +必须记得使用 //.length()// method。2d array 中很可能存在 array 长度不一的情况。
 +</WRAP>
 +===Methods===
 +==method 的定义==
 +Java 的 method 定义分为四大块:
 +  * modifier:处于定义的最开始,一般是 ''public static''
 +    * ''public'' 代表的是该 method 的 visibility,也就是说该 method 可见,并且可以被其他类型的对象调用。
 +    *  ''static'' 表示该 method 不基于 obejct(也就是没有 this,不是成员函数),使用时无需创建对象
 +  * return value type:如果没有返回类型,则使用 ''void''
 +  * parameter list:method 需要的参数列表,必须指定类型。
 +  * method body: 如果 method 有返回类型,必须返回一个类型为返回类型的值,使用 return 语句。
 +简单的示例:
 +<code js>
 +public static String serachKeywords(String keyword, String[] array) {
 +    
 +    String result = "not found.";
 +    for (String element : array) {
 +        if (element != null && element.equals(keyword)) {
 +            result = "found";
 +            break;
 +        }
 +    }
 +    return result;
 +}
 +
 +// calling
 +public static void main(String[] args) {
 +    String[] myDict = {"love", "me"};
 +    String result = serachKeywords("love", myDict);
 +    System.out.println(result);
 +}
 +</code>
 +==外部调用 method==
 +假设 ''serachKeywords()'' 被定义于 ''Methods.java''。假设我们希望在另一个文件 ''External.java'' 中调用 ''serachKeywords()''
 +  * 将 ''Methods.java'' 与  ''External.java'' 置于同一目录
 +  * 使用 ''Methods.serachKeywords()'' 进行调用
 +<code js>
 +public class External {
 +    public static void main(String[] args) {
 +        String[] newArray = {"123", "456", "789"};
 +        System.out.println(Methods.serachKeywords("123", newArray));
 +    }
 +}
 +</code>
 +==method overloading==
 +  * 与 C++ 类似,相似功能但是 method 的 singature 不同,也就是**至少**满足下面一项:
 +    * parameter 的**类型**不同
 +    * parameter 的**顺序**不同
 +    * parameter 的**数量**不同
 +  * return type 不是 signature 的一部分,因此只有 return type 不同不是 overloading
 +<code js>
 +// overloading 
 +public static boolean searchArray(String target, String[] array)
 +public static boolean searchArray(int target, int[] array)
 +
 +// not a overloading
 +public static int searchArray(int target, int[] array)
 +public static boolean searchArray(int target, int[] array)
 +</code>
 +  * 编译器会根据 parameter 的类型来进行函数匹配。如果没有匹配的函数会报错。
 +  * 参考 C++ 的[[cs:programming:cpp:cpp_primer:6_function#重载函数匹配的机制|函数匹配]](针对 overloading 的二义性)