1.简单的Java程序
类名 驼峰命名 Java语言规范中main必须声明为public,main方法必须要有一个外壳类,main方法必须是静态的。若main方法退出正常,Java应用程序的退出代码为0,如果希望在终止程序时返回其他代码,需要调用System.exit方法。
2.注释
/** */ 可以自动生成文档
3.数据类型
Java是强类型语言,必须为每一个变量声明一种类型。 Java有一个能精确表示任意精度的算数包,通常称为大数值(big number)是一个Java对象。
3.1.整形
类型 长度 范围 long 8 (-2^ 64)–(2^64-1) int 4 (-2^ 32)–(2^32-1) short 2 (-2^ 16)–(2^16-1) byte 1 (-2^ 8)–(2^8-1)
java中数据长度是固定的,不需要担心移植问题;但是c和c++中,数据类型的大小和平台有关。 Java没有任何无符号的int、long、byte、short类型。 无符号的数据类型,即最高位不是符号位,正数用源码储存,负数用补码储存。 长整型数有后缀L
或l
十六进制有前缀0x
或0X
;八进制有前缀0
,八进制数容易混淆,建议不用;加前缀0b
或0B
表示二进制。 可以在数字字面量间加_
,只为易读,编译器会去除这些下划线。
3.2.浮点类型
类型 长度 float 4字节,取值有效位数6-7 double 8字节。有效位数15位
double精度是float的两倍,大部分应用程序使用double类型 float有后缀F
或f
,无后缀的默认double类型,当然也可以加后缀D
或者d
表示double。 表示溢出和错误的三个特殊浮点数:正无穷大(Double.POSITIVE_INFINITY)、负无穷大(Double.NEGATIVE_INFINITY)、NaN(不是一个数,0/0或者负数的平方根的结果就是NaN)(Double.NaN)
x==Double.NaN
是错的Double.isNaN(x)
可以判断x是不是一个数值。 数值计算不允许有误差的时候使用BIgDecimal类,浮点数用二进制表示,二进制无法准确表示1/10,十进制无法准确表示1/3.
3.3.Char
char原本表示单个字符,但目前有些Unicode需要用两个char值。 char 是字符数据类型 ,是无符号型的,占2字节(Unicode码 );大小范围 是0—65535 ;char是一个16位二进制(16进制范围\u0000-\Uffff)的Unicode字符,JAVA用char来表示一个字符 。 \u 转义序列后接4位16进制数,将十六进制数转换位相应的字符。Unicode转义序列会在解析代码前(编码前)得到处理。\u转义序列可以在引号之外使用,其他转义序列只能在引号的字符面量或者字符串中。其他转义序列
表示 含义 \n 换行符 \t 横向制表符 \\ 反斜线 \’ 单引号 \" 双引号 \r 回车符 \b 退格符 \a 报警(响铃)符 \v 纵向制表符 \? 问号 \f 进纸符
3.4.Unicode和Char
码点(code point):一个编码表中的某个字符对应的代码值。
Unicode中码点用十六进制书写,并加前缀U+,码点分17个代码级别(code plane) 第一个代码级别称为基本的多语言级别(basic multilingual plane) ,码点从U+0000-UFFFF,其中包括经典的Unicode代码;其余16个代码级别码点从U+10000-U+10FFFF,包括一些辅助字符(supplementary character) UTF-6 编码采用不同长度的编码表示所有的Unicode码点。
在基本的多语言级别中,每个字符用十六位表示,通常被称为代码单元(code unit) 辅助字符采用一对连续的代码单元进行编码,这样的编码值落入基本的多语言级别中空闲的2048字节内,通常被称为替代区域(surrogate area),第一单元在U+D800-U+DBFF的1024个中,第二单元在其后的1024个中. Java中的Char类型描述了UTF-16编码中的一个代码单元。 强烈建议不要在程序中使用char类型,除非使用处理UTF-16代码单元。
3.5.Boolean类型
if ( x = 0 )
4.变量
Java中每个变量都有类型。 又字母开头,字母和数字构成的序列(这里的字母和数字包括某种语言中表示字母和数字的任何Unicode字符)(可以有_
,不推荐$
) 不推荐在一行中声明多个变量,逐一声明提高代码的可读性。许多程序员将变量名命名为类型名,也喜欢在类型名前加前缀a作为变量名。
4.1.初始化变量
声明变量后必须显示地用赋值语句初始化 在类中定义的成员变量如果你没有初始化java会自动帮你初始化,如果是数字会自动初始化成0
,字符会初始化成'o'
,对象引用会初始化成null
. 变量的声明尽可能地靠近第一次使用的地方,是一种良好的编程风格。 Java不区分定义与声明,C和C++区分
4.2.常量
用关键词final
指示常量,表示这个变量只能被赋值一次,一旦赋值后便不能再改。 习惯常量名都大写 可以用static final
设置一个类常量。 const是Java的保留关键字
5.运算符
参与/
运算的两个数都是整数时,表示整数除法,否则表示浮点数除法。 整数除法会截断小数部分。整数除法余符号和被除数保持一致;关于商,表达式a/b的商会向0取整,即负数向上取整,正数向下取整,类似于正负数的四舍五入。 运算的精度和浮点溢出、以及strictfp关键字参考核心技术1运算符部分。
5.1.数学函数与常量
Math类中包含了各种数学函数。 静态方法处理的不是对象,非静态方法处理的是引用他的对象 导入Math包(静态导入?还未学习到(2020.06.22))之后就不用再用Math.
调用math中的函数了。 提供了PI和e的近似值:Math.PI 和Math.E。 自由发布的Math库(fdlibm) ?
5.2.数值之间的转换
合法转换(实箭头表示无信息丢失、虚箭头表示可能有精度损失)
byte
short
int
char
long
double
float
在进行二元操作时,要先将两个操作数转换为同一种操作,然后再进行计算。 有double转double,否则有下面哪个转哪个float>long>int
5.3.强制类型转换(cast)
强制类型转换会截断小数部分将浮点转换为整数 可以用Math.round()
四舍五入对浮点数转换,但是round函数返回的是long型。 当转换后超出目标类型的表示范围后,结果会截断成一个完全不同的值。
5.4.结合赋值和运算符
二元运算符一般把运算符放在赋值符号左面x += 4
运算符的结果会强制的转换为赋值号左侧变量相同的类型
5.5.自增自减运算符
前缀形式的自增自减--i
++i
先完成加1;后缀形式的先使用后完成加1. 建议不要在表达式中使用++
5.6.关系和Boolean运算符
==
检测相等,!=
检查不相等$$
||
按照短路逻辑求值,第一操作数能确定值后就不再计算第二操作数。三元操作符f? x:y
f表示的结果ture时返回:
前面的,否则后面的。
5.7.位运算符
&
and |
or ^
xor ~
not
&与|用在布尔值上时也会得到一个布尔值,但是不会再采用短路方式来求解。 位运算可以掩掉其它位,而只只保留其中一位。 <<
与>>
移位运算符不做细述。
5.8.括号与运算符级别
Java中不使用逗号运算符,但是在for语句的第一和第三部分中使用逗号分隔表达式列表。
5.9.枚举类型
enum K { a, b, c, d} ;
K ak = K. a;
枚举类型的变量之只能储存这个类型声明中的某个枚举值 或者null
6.字符串
Java字符串就是UNicode字符序列,Java没有内置的字符串类型,在标准Java库中提供了一个预定义类,叫String,每个由双引号括起来的字符串都是String类的一个实例。 String 继承于CharSequence。 CharSequence是一个接口,它只包括length(), charAt(int index), subSequence(int start, int end)这几个API接口。除了String实现了CharSequence之外,StringBuffer和StringBuilder也实现了CharSequence接口。 需要说明的是,CharSequence就是字符序列,String, StringBuilder和StringBuffer本质上都是通过字符数组实现的!
6.1子串
substring(a,b) 方法的第二个参数是不想复制
的第一个位置 substring 方法的优点是方便计算子串长b-a
String a = "abcdefg" ;
String b = a. substring ( 0 , 3 ) ;
b= "abc"
6.2拼接
+
号拼接字符串与非字符串拼接时,后者被转成字符串 Java对象都可以被转成字符串 如果需要把多个字符串放在一起,用一个定界符分割
使用静态方法join:String all = String. join ( "-/-" , "a" , "b" , "c" , "d" ) ;
all = "a-/-b-/-c-/-d"
6.3不可变字符串
6.4检测字符串是否相
s. equals ( t) ;
s. equalsIgnoreCase ( t) ;
if (s == "hello" ) ;
但是储存池中可能有完全一样的字符串,且只有字符串常量是共享的,+
和substring
操作产生的结果并不共享,所以不确定字符串==
的结果,一定不要使用
。
6.5空串和Null串
6.6码点与代码单元
代码单元(一个char值为一个代码单元) length()
方法返回采用UTF-16编码表示的给定字符串所需要的代码单元数量。charAt(k)
方法返回位置k的代码单元,k~(0,str.length()-1)之间。码点 codePointCount(a,b)
方法返回长度为(b-a)的代码单元中的码点数。没有配成对的代用字符计入代码点。codePointAt(int index)
返回从给定位置开始的码点。int offsetByCodePints(int startIndex, int cpIndex)
返回从头代码点开始位移cp个代码点后 的码点索引
尽量避免使用char,太底层了。 int [] codePoints().toArray();
会生成一个int值的流,每个int对应一个码点,,可以将他转换为数组(toArray())。反过来可以将码点数组转换成字符串,String str = new String(codePints,0,codepoints.length());
其他API
int compareTo ( String other) ;
new String ( int [ ] codepints, int offset, int count) ;
boolean equals ( Object other) ; 字符串相等返回ture。
boolean startsWith ( String prefix) ;
boolean endsWith ( String prefix) ;
String a = "ffaehffffffffehffffffffffffffffffcdehhffff" ;
String bString = "eh" ;
int b = a. indexOf ( bString) ;
int c = a. indexOf ( bString, 4 ) ;
int d = a. indexOf ( 102 ) ;
int e = a. indexOf ( 102 , 4 ) ;
int f = a. lastIndexOf ( bString) ;
int g = a. lastIndexOf ( bString, 1 ) ;
int h = a. lastIndexOf ( 102 ) ;
int j = a. lastIndexOf ( 102 , 1 ) ;
String replace ( CharSequence oldString, CharSequence newString) ;
String toLowerCase ( ) ;
String toUpperCase ( ) ;
String tirm ( ) ;
6.9构建字符串
由较短的字符串频繁连接成的字符串,例如键盘输入字母,每次连接都会产生新的字符串,浪费时间浪费空间,所以使用StringBuilder类。 StringBuffer效率稍低,但是允许多线程的方式执行删除或添加字符的操作。如果所有字符在单线程中操作,应用StringBuilder。 APIStringBuilder aBuilder = new StringBuilder ( ) ;
int N = aBuilder. length ( ) ;
aBuilder. append ( "abc" ) ;
aBuilder. append ( 'A' ) ;
aBuilder. appendCodePoint ( 102 ) ;
aBuilder. setCharAt ( 2 , 'z' ) ;
aBuilder. insert ( 2 , "kkkkkkkk" ) ;
aBuilder. insert ( 2 , 'x' ) ;
aBuilder. delete ( 3 , 4 ) ;
String aString = aBuilder. toString ( ) ;
abc
abcA
abcAf
abzAf
abkkkkkkkkzAf
abxkkkkkkkkzAf
abxkkkkkkkzAf
7.输入输出
7.1.读取输入
Java.util.ScannerString nextLine ( ) ;
boolean hasNext ( ) ;
boolean hasNextInt ( ) ;
Java.lang.Systemstatic Console console ( ) ;
Java.io.Console
因为输入可见,所以Scanner类不适用于读取密码。 Java SE6特别引入Console类, static char [ ] readPassword ( String promit, Object . . . args) ;
static String readLine ( sstring promit, Object . . . args) ;
Console cons = System. console ( ) ;
String username = cons. readLine ( "enter name:" ) ;
Char [ ] password = cons. readPassword ( "enter password:" ) ;
为安全起见,返回的密码放在char数组中,而不是字符串,对密码处理后,应该马上用一个填充值覆盖数组元素。 console对象处理不如scanner方便。每次只能读一行。 如果Java程序要与windows下的cmd或者Linux下的Terminal交互,就可以使用这个Java Console类代劳。Java要与Console进行交互,不总是能得到可用的Java Console类的。一个JVM是否有可用的Console,依赖于底层平台和JVM如何被调用。如果JVM是在交互式命令行(比如Windows的cmd)中启动的,并且输入输出没有重定向到另外的地方,那么就可以得到一个可用的Console实例。 但当使用Eclipse等IDE运行以上代码时Console中将会为null。 表示Java程序无法获得Console实例,是因为JVM不是在命令行中被调用的,或者输入输出被重定向了。在Eclipse诸如类似的IDE工具中运行Console类。如果没有对Console实例判空操作,结果使用了该实例会抛出java.lang.NullPointerException异常。
7.2.格式化输出
print(x); //将以x对应的数据类型所允许的最大非零数字位数打印输出x; printf(); //打印格式化数值。 静态方法String.format(格式化字符串)
创建一个格式化的字符串,而不打印输出。 可以用s转换符格式化任意的对象,对于任意实现了Formattable接口的对象,都将调用formatTo方法,否则调用toString方法,将任意对象转换成字符串。 每个%字符开始的格式说明符都用相应的参数替换。 格式化输出时间与日期,使用java.time包的方法,以t开始,以其他时间转换符结束。 格式说明符的语法图: 索引值从1开始。
7.3.文件输入与输出
对文件读取,用File对象构造一个Scanner对象。文件地址是java虚拟机的相对位置,可以用file = System.getProperty("file.txt");
找到路径位置。(没有例子不是很懂)
Scanner in = new Scanner ( Path. get ( "gile.txt" ) , "UTF-8" ) ;
Scanner in = new Scanner ( File file, "UTF-8" ) ;
Scanner in = new Scanner ( "file.txt" ) ; 会将参数作为包含字符的数据。
如果文件名包含反斜杠,再反斜杠前再加一个反斜杠。 如果省略后面的字符编码参数,Java会使用运行这个Java程序的默认编码,在不同机器上可能有不同的结果。 对文件写入,需要构建一个Print Writer对象,如果文件不存在,会新建文件。 可以像输入到System.out一样使用print、printf等命令。
PrintWriter out = new PrintWriter ( "file.txt" , "UTF-8" ) ;
用一个不存在的文件构造Scanner或者用一个不能被创建的文件名构造PrintWriter会发成异常,应改告诉编译器,在main方法中使用throws IOException
语句标记 用命令行启动程序时,可以利用Shell重定向语法将任意文件关联到System.in和System.out;
public static void main ( String[ ] args) throws IOException {
Scanner in = new Scanner ( Paths. get ( "D:\\JAVAeclipse\\eclipse-workspace\\SelfStudy\\src\\edu\\note\\learnbycode\\test5out.txt" ) , "UTF-8" ) ;
Scanner inScanner = new Scanner ( new File ( "D:\\JAVAeclipse\\eclipse-workspace\\SelfStudy\\src\\edu\\note\\learnbycode\\test5out.txt" ) ) ;
String aString = in. nextLine ( ) ;
System. out. println ( aString) ;
PrintWriter outPrintWriter = new PrintWriter ( "D:\\JAVAeclipse\\eclipse-workspace\\SelfStudy\\src\\edu\\note\\learnbycode\\test5out.txt" ) ;
outPrintWriter. println ( a) ;
outPrintWriter. close ( ) ;
}
8.控制流程
java没有go to语句,但是可以用break语句跳出内层循环 Java不允许在嵌套的块中重定义一个变量 else与最近的if组成一组。 while循环先检查条件。 do y while(x);先执行一边代码。 在循环中检测两个浮点数相等时要小心,有些浮点数(0.1)不能精确地用二进制表示,由于舍入的误差,最后得不到精确值而无法结束循环。
8.1.多重选择:switch语句
switch语句会从与选项值匹配的case处开始一直执行到遇到break语句或直到switch语句结束 如果没有匹配的case,就执行default子句。 case标签可以是char\byte\short\int 的常量表达式、可以是枚举常量,也可以是字符串字面量。 case语句结尾没有break会接着判断其他case,可能会有两个相同的case,这种经常引发错误,不推荐使用switch。
8.2.中断控制流程语句
Java支持带标签的break语句。标签必须放在想要跳出的最外层循环之前,并且紧跟一个冒号:
当希望使用goto语句的时候,就可以使用带标签的break语句,但不提倡。 continue语句会中断正常的控制流程,将控制转移到最内层循环的首部。
9.大数值
如果基本的整数和浮点数不能满足需求,可以使用java.math中的两个类:BigInteger和BigDecimal,可以处理任意长度数字序列的数值。 BIgInteger类实现了任意精度的整数运算。 BigDecimal类实现了任意精度的浮点数运算。 静态方法valueOf可以将普通数值转换成大数值。 不能使用熟悉的算术运算符处理大数值,需要用add和multiply方法。
BigIngeter a = BigIngeter. valueOf ( 100 ) ;
a= a. add ( a) ;
a = a. subtract ( a) ;
a = a. multiply ( a) ;
a = a. divide ( a) ;
BigDecimal divide ( other RoundingMOde mode)
a = a. mod ( a) ;
int b = a. compareTo ( a) ;
10.数组
数组是一种数据结构。 创建一个数组时,数字数组初始化为0,Boolean初始化为false,对象数组初始化为null。 数组一旦创建,就不能改变大小,如果需要经常扩展数组大小,应该使用另外一种数据结构-数组列表(array list)。 array.length
获取数组的长度,当访问长度之外的元素,会发生array index out of bounds
的异常而终止。
10.1.for each循环
依次处理数组中每个元素而不必为下标分心 for(variable : collection) statement
;variable:定义一个变量暂时储存集合中的每一个元素, collection: 必须是一个数组或者实现了Iterable接口的类对象(例如array list) Arrays类的toString方法返回一个包含数组元素的字符串。这些元素被放在括号内,并用逗号隔离。
int [ ] ff = new int [ 5 ] ;
for ( int i : ff) {
System. out. println ( i) ;
}
String fff = Arrays. toString ( ff) ;
10.2.数组初始化及匿名数组
可以不用new就创建新数组并初始化 数组长度允许为0。
int [ ] a = { 1 , 2 , 3 , 4 , 5 } ;
也可以初始化一个匿名数组
,使用这种语法形式可以在不创建新变量
的情况下重新初始化一个数组。
int [ ] b = new int [ 4 ] ;
b = { 1 , 2 , 3 , 4 } ;
int [ ] b = new int [ 4 ] { 1 , 2 , 3 , 4 } ;
int [ ] c = { 1 , 2 , 3 , 4 } ;
b = c ;
System. out. println ( Arrays. toString ( b) ) ;
System. out. println ( Arrays. toString ( c) ) ;
new int [ ] { 2 , 3 , 4 , 5 } ;
d = new int [ ] { 2 , 3 , 4 , 5 } ;
b = new int [ ] { 2 , 3 , 4 , 5 } ;
System. out. println ( Arrays. toString ( b) ) ;
10.3.数组拷贝
10.4.命令行参数
每个java程序都有一个含有参数String arg[]的main方法,表明main方法接受一个字符串数组,也就是命令行参数。 命令行命令java test a b c
中,test是程序名,不在arg[]中。
10.5.数组排序
对数值型数组排序,可以使用Arrays类中的 sort方法Arrays.sort(a)
,这个排序方法使用的是优化过的快速排序算法。 java.util.Arraysstatic string toString ( type[ ] a) ;
static type copyOf ( typr [ ] a, int length) ;
static type copyOfRange ( typr [ ] a, int start, int end) ;
static void sort ( type a[ ] ) ;
static int binarySearch ( typr[ ] a, type v) ;
static int binarySearch ( typr[ ] a, int start, int end, type v) ;
static void fill ( type[ ] a, type v) ;
static boolean equals ( type[ ] a, type[ ] b) ; a与b大小相等,且对应位置分别相等。
10.6.多维数组
for each 循环不能自动处理二维数组的每一个元素,访问二维数组的每一个,可以嵌套两个for each。 Arrays的deepToString(a)
方法可以返回一个含有所有元素的字符串,格式为[[1,2,3],[2,3,4],[3,4,5]]
10.7.不规则数组
Java实际上不存在多维数组,多维数组实际上是先分配一个行数长度的一维数组,每个元素又引向一个一维数组。 要创建一个不规则数组,要先分配一个具有所含行数的数组
int [ ] [ ] a = new int [ 10 ] [ ] ;
a[ 3 ] = new int [ 18 ] ;
a[ 4 ] = new int [ 19 ] ;