第一章:Java程序设计概述
面试题:Java和C的不同点
a. C语言不可以跨平台,Java可以跨平台
b. 指针管理
C语言中的指针可以让用户几乎可以访问计算机的所有内存资源和其他部分资源,但同时指针也使C语言很难掌握和调试,给系统的安全性和稳定性也带来了和大的困难。
Java中没有指针的概念,机关有数组和对象的引用概念,但全部交给系统管理,限制了用户的资源访问,也给Java系统带来了安全性和稳定性。
c. 封装
在Java中引入了package的概念,使面向对象和组件开发更加方便。Java面向对象,而C面向过程。
d. 数据类型和类
Java是完全面向对象的语言,所有的函数和变量必须是类的一部分,除了基本数据类型之外,其余的都作为类对象,包括数组。对象将数据和方法结合起来,把它们封装在类中,这样每个对象都可实现自己的特点和行为。而c语言允许将函数和变量定义为全局的。
e. 自动内存管理
Java程序中所有的对象都是用new操作符建立在内存堆栈上, Java自动进行无需内存回收操作,不需要程序员进行删除。而c语言中必须由程序员释放内存资源,增加了程序设计者的负担。Java中当一个对象不被再用到时,无用内存回收器将给它加上标签以示删除。Java里无用内存回收程序是以线程方式在后台运行的,利用空闲时间工作。
f. 字符串
C语言不支持字符串变量,在c语言程序中使用null终止符代表字符串的结束,在Java中字符串是用类对象(string和stringBuffer)来实现的。
g. 函数&方法
Java没有函数,作为一个比c语言更纯的面向对象的语言,Java强迫开发人员把所有例行程序包括在类中,事实上,用方法实现例行程序可激励开发人员更好地组织编码。
多线程的好处:可以带来更好的交互响应和实时行为。
第二章: Java程序设计环境
编译Java程序的过程:javac程序是一个Java编译器,将.java文件编译成.class文件。java程序启动Java虚拟机,虚拟机执行编译器放在class文件中的字节码。
Java明确区分大小写。(在Linux系统下,文件名以大写字母开头)
第三章:Java的基本程序设计结构
Java应用程序中的全部内容必须放置在类中。
Java类命名规则:名字必须以字母开头,后面可以跟字母和数字的任意组合。长度没有限制,但不能使用Java关键字。
标准命名规则:以大写字母开头的名词,如果多个单词,每个单词的首字母均大写。
源代码的文件名必须和公共类名字相同,并用.java作为扩展名。
运行已编译的程序时,JVM将从指定类的main方法开始执行,因此类的源文件中必须包含一个main方法。根据Java语言规范,main方法必须声明为public,而且必须是静态的。
Java注释:
//每行注释
/*和*/将一段比较长的注释括起来,但不能嵌套
/**和*/可以用来自动生成文档
Java是一种强类型语言。必须为没一个变量声明一种类型。共有8种基本数据类型,4种整型,2种浮点型,1种用于表示Unicode编码字符单元的字符类型char和一种用于表示真值的boolean类型。
整型:int(4字节,-2^31~2^31-1),short(2字节,-2^7~2^7-1),long(8字节,-2^63~2^63-1,数值后面加L或l),byte(1字节)(十六进制数值有前缀0x或0X,八进制有前缀0,二进制可以加前缀0b或0B)
Java没有任何无符号形式的int, long, short或byte类型。
浮点类型:float(4字节,加后缀F或f),double(8字节,可以不加后缀,也可以加D或d)。
需要注意的小细节:
1/0 报错,1/0.0
INF,1.0/0 INF,0/0 报错,0/0.0 NAN,0.0/0 NAN,sqrt(-1) NAN
包装类的无穷表示:Double.POSITIVE_INFINITY,Double.NEGATIVE_INFINITY,Double.NaN
判断语句中:
if(Double.isNaN(x))
char类型:\u 转义字符,\b 退格,\t 制表,\n 换行,\" 双引号, \' 单引号,\\ 反斜杠
码点:与一个编码表中的某个字符对应的代码值。Unicode的码点可以分为17个代码级别。
代码单元:UTF-16编码采用不同长度的编码标识所有Unicode码点。在基本的多语言级别中,每个字符用16位表示,被称为代码单元。
变量:
判断Unicode字符属于Java中“字母”:Character.isJavaIdentifierStart和Character
.isJavaIdentifierPart方法
声明一个变量后,
必须用赋值语句对变量进行显式初始化,不可以使用未初始化的变量。
常量:
Java中利用关键字final指示常量。
关键字final代表这个变量只能被赋值一次,一旦被复制后,不可以被更改。习惯上,常量名全用大写。
类常量:使某个常量可以再一个类中的多个方法中使用。用static final设置。类常量的定义位于main外部。如果设置为public,则其他类也可以使用。
运算符:
如果将一个类标记为strictfp,这个类中的所有方法都要使用严格的浮点计算。
余数问题:n%2,如果n为负数,则表达式值为-1。
数值类型之间的合法转换:
强制类型转换:
double→int:通过截断小数部分将浮点值转换为整型。
对浮点数进行舍入运算:Math.round() [round方法返回long类型]
例题:
int x;
x += 5.5;
正确,等价于x = (int)(x + 5.5)
&&和||运算符按照“短路”方式来求值。
位运算符:
&(与) |(或) ^(异或) ~(非)
&和|不能采用短路方式求值。
>>和<<运算符将位模式左移或右移。
>>>运算符用符号位填充高位(没有<<<运算符)。
m<<n,要对n完成模32的运算(1<<35价于1<<3),若m是long类型,则对n完成模64的运算。
字符串:
Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类,叫做String。
子串:
String s = "Hello";
String s1 = s.substring(0,3); //得到Hel(从0到3,不包括3)。
substring方法优点:容易计算子串长度,3-0=3.
拼接:
Java语言允许使用+号拼接两个字符串。
如果需要把多个字符串放在一起,并用定界符分隔,可以用静态join方法:
String all = String.join("/","S","M","L","XL") //all is the string "S/M/L/XL"
String类没有提供用于修改字符串的方法。
字符串相等:
可以使用equals方法检测两个字符串是否相等。s.equals(t)
检测两个字符串是否相等,不区分大小写:"Hello".equalsIgnoreCase("hello")
不能使用==运算符检测两个字符串是否相等,它只能确定两个字符串是否放置在同一个位置上。
空串与null串:
检测是否为空串的方法:
if(str.length() == 0) 或 if(str.equals(""))
检测是否为null串的方法:
if(str == null)
同时检查一个字符串既不是null也不是空串:
if(str != null && str.length()!=0)
码点与代码单元:
代码单元数量:length()方法
码点数量:codePointCount(0,str.length())方法
返回位置n的代码单元:str.charAt(n)
String API:
int compareTo(String other):按照字典顺序,如果字符串位于other之前,返回一个负数;之后,返回一个正数;相等,返回0.
boolean equals(Object other):如果字符串与other相等,返回true.
boolean equalsIgnoreCase(String other):
如果字符串与other相等(忽略大小写),返回true.
String replace(CharSequence oldString,CharSequence newString):返回一个新字符串。这个字符串用newString代替原始字符串中的所有oldString。可以用String或StringBuilder对象作为CharSequence参数。
String substring(int beginIndex)或String substring(int beginIndex,int endIndex):返回一个新字符串,这个字符串包含从beginIndex到endIndex-1的所有代码单元。
String toLowerCase()/String toUpperCase():返回一个新字符串,这个字符串将原始字符串中大(小)写字母改成小(大)写字母。
String trim():返回一个新字符串。这个字符串将删除原始字符串头部和尾部的空格。
构建字符串:
有时需要由较短的字符串构建字符串,采用字符串连接的方式达到此目的效率比较低,每次连接字符串,都会构建一个新的String对象,既耗时又浪费空间。使用StringBuilder类可以避免此种问题的发生。
StringBuilder builder = new StringBuilder();
builder.append(str);
String completeString = builder.toString();
输入输出:
通过控制台输入:Scanner in = new Scanner(System.in);
输入行可能包含空格:String name = in.nextLine();
读取一个单词(以空白符作为分隔符):String firstName = in.next();
读取一个整数:int age = in.nextInt();
读取一个浮点数:int age = in.nextDouble();
读取一个密码:
Console cons = System.console();
String username = cons.readLine("User name: ");
char[] passwd = cons.readPassword("Password: ");
检测输入中是否还有其他单词:boolean hasNext();
检测输入中是否还有其他数字:boolean hasNextInt();/boolean hasNextDouble();
格式化输出:
x = 3333.33333333333333
System.out.printf("%8.2f",x):用8个字符宽度(包括小数点和小数部分)和小数点后2个字符的精度打印x。3333.33
System.out.printf("%,.2f",x):逗号标志增加了分组的分隔符。 3,333.33
可以使用静态的String.format方法创建一个格式化的字符串,而不打印输出:
String message = String.format("Hello,%s. Next year, you will be %d",name,age);
文件输入输出:
要想对文件进行读取,需要一个用File对象构造一个Scanner对象:
Scanner in = new Scanner(Paths.get("myfile.txt"),"UTF-8");
要想写入文件,需要构造一个PrintWriter对象。
PrintWriter out = new PrintWriter("myfile.txt","UTF-8");
已经知道有可能出现“输入/输出”异常,需要在main方法中用throws字句标记
public static void main(String[] args) throws IOException
{
Scanner in = new Scanner
(Paths.get("myfile.txt"),"UTF-8");
......
}
流程控制:
switch语句中case的标签类型可以是:char, byte, short或int的常量表达式,枚举常量,字符串字面量。
中断控制流程语句:
不带标签的break:用于退出循环语句
带标签的break:用于跳出多重嵌套的循环语句。标签必须放在希望跳出的最外层循环之前,并且必须紧跟一个冒号。
continue语句:将控制转移到最内层循环的首部。
带标签的continue语句:跳到与标签匹配的循环首部。
大数值:
BigDecimal和BigInteger:处理包含任意长度数字序列的数值,BigInteger类实现了任意精度的整数运算,BigDecimal类实现了任意精度的浮点运算。
使用静态的valueOf方法可以将普通的是指转换为大数值:BigInteger a = BigInteger.valueOf(100);
处理大数值不能用算术运算符:用add, subtract, multiply, divide, mod, compareTo
BigInteger c = a.add(b);
BigInteger d = c.multiply(b.add(BigInteger.valueOf(2)));
数组:
数组是一种数据结构,用来存储同一类型值的集合。
创建一个数字数组时,所有元素都初始化为0;boolean数组的元素都初始化为false;对象数组元素初始化为null。
用a.length获取数组长度。
一旦创建了数组,就不能改变大小。如果想在运行过程中扩展数组大小,应该用数组列表(array list)。
foreach循环:用来依次处理数组中的每个元素
for(int i :collection) {......}
collection可以使一个数组或者是一个实现了Iterable接口的类对象 (e.g. ArrayList)。
打印数组中所有值的方法:a. foreach语句 b. Arrays类的toString方法
匿名数组:
可以初始化匿名数组:new int[] {2,3,4,5,6}
Java中允许数组长度为0,数组长度0与null不同。
数组拷贝:
将一个数组的所有值拷贝到一个新的数组中去:Arrays.copyOf(arr1,arr1.length)
如果第二个参数大于arr1.length,则多余数值元素被赋值为0,多余boolean元素被赋值为false。
如果小于,则只复制前面元素。
命令行参数:
public static void main(String[] args): args表明main方法将接受一个字符串数组,也就是命令行参数。
数组排序:
对数值型数组进行排序,可以使用Arrays.sort()方法。利用了优化的快速排序算法(待完善原理)。
java.util.Arrays:
static String toString(type[] a):返回包含a中数据元素的字符串,这些元素被放在括号内,并用逗号分隔。
(type: int, long, char, byte, boolean, float, double)
static int binarySearch(type[] a, type v) / static int binarySearch(type[] a, int start, int end, type v):采用二分搜索算法查找值v,如果查找成功,返回相应下标值,否则,返回负数值r。-r-1是保持有序v应该插入的位置。
static void fill(type[] a, type v):将数组的所有元素值都设置为v。
多维数组:
for each语句不能自动处理二维数组中的每一个元素,要用嵌套。
for(double[] row : a)
for(double value : row)
do something
快速打印一个二维数组的数组元素列表:
System.out.println(Arrays.deepToString(a));
不规则数组:
数组每一行都有不同的长度。