2.1 注释
作用:
- 方便程序的阅读
- 提高程序的可读性
注释不会出现在字节码文件中,即java编译器会跳过注释语句。
在Java中根据注释的功能不同,主要分为单行注释,多行注释,文档注释。
- 单行注释:使用“//”开头,后面的单行内容均为注释。
- 多行注释:/*abc*/ 使用多行注释作为行内注释。
- 多行注释不能嵌套使用。
- 文档注释:/** abc */ 包含一些说明性的文字及一些JavaDoc标签
- 后期写项目时,可以生成项目内的API
2.2 标识符规则
标识符是用来给变量,类,方法以及包进行命名的
标识符需要遵守的规则:
- 必须以字母,下划线,美元符号$开头,数字不能开头
- 其他部分可以是字母,下划线,美元符$,数字的任意组合
- 大小写敏感,且长度无限制
- 不可以是Java的关键字。
标识符的使用规范:
- 表示类名的标识符:每个单词的首字母大写
- 表示方法和变量的标识符:驼峰原则,第一个单词小写,从第二个单词开始首字母大写。
- Java不采用通常语言使用的ASCII字符集,而采用Unicode标准的国际字符集。
- 所以,这里的字母不仅仅是英文,还包括汉字等,但不建议使用汉字。
Java的关键字/保留字
变量
- 变量本质上代表一个“可操作的存储空间”。空间位置确定,但里面放置的值不确定,可通过变量名来访问“对应的存储空间”,从而操纵这个“存储空间”的值。
- 把内存比作一个停车场,变量就是一个一个的车位,车位的位置是确定的,但大小不确定,根据车的大小确定。
- Java是一种强类型语言,每个变量必须声明其数据类型。
- 变量的数据类型决定了变量占存储空间的大小。
- 变量作为程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。
- 变量在使用前必须先声明,才能为其分配相应长度的存储空间。
- 每个变量都有类型,类型可以是基本类型,或引用类型。
- 变量名必须是合法的标识符。
- 变量声明是一条完整的语句,因此每个声明必须以分号结束。
- 在一行中可以声明多个变量,如int i,j;
- 但不建议,逐一声明每个对象可以提高程序的可读性。
- 可以将变量的声明和初始化放在同一行中。
- local变量(局部变量)必须声明并初始化才可以用。
变量分类
- 局部变量(local variable)
方法或语句块内部定义的变量。
生命周期:从生命位置开始到方法或语句块执行完毕为止。
使用前,必须先初始化
2. 成员变量(实例变量 member variable)
方法外部,类的内部定义的变量。
从属于对象,生命周期伴随对象始终。
如果不自行初始化,它会自动初始化成该类型的默认初始值。
3. 静态变量(类变量 static variable)
使用static定义。
从属于类,生命周期伴随类始终,从类加载到卸载。
常量(Constant)
Java中,主要利用关键字final来定义一个常量。
常量一旦被初始化后不能再更改其值。
字面量常量:如1,2,'b',"234"等
符号常量:用final修饰的常量。
基本数据类型(primitive data type)
整型变量/常量
Java语言整型常量的四种表示形式
- 十进制整数
- 八进制整数,以0开头
- 十六进制,以0x或0X开头
- 二进制数,以0b或0B开头
Java语言的整型常数默认为int型,声明long型常量可以在后面加‘l’或‘L’
浮点型变量/常量
float类型:单精度类型,尾数可以精确到7位有效数字。
double类型的数值精度约是float类型的两倍,又称双精度类型。
浮点型常量默认类型是double。
Java浮点型常量的两种表示形式
- 十进制数形式
- 科学计数法形式 ,e表示10
float类型的数值要加后缀F或f。
浮点类型float,double的数据不适合在不容许误差的金融计算领域。
如果需要进行不产生误差的精确数字计算,需要使用BigDecimal类。
不要用浮点数进行比较。
二进制浮点数不能精确的表示0.1,0.01这样的10的负次幂。
并不是所有的小数都可以精确的用二进制浮点数表示。
java.math包下的两个类:BigInteger和BigDecimal,可以处理任意长度的数值。
BigInteger实现了任意精度的整数运算。
BigDecimal实现了任意精度的浮点运算。
字符型变量/常量char
在内存中占2个字节,在Java中使用单引号表示字符常量。
char类型用来表示在Unicode编码中的字符。
Unicode编码被实际用来处理各种语言的文字,它占2个字节,可允许有65536个字符。
Unicode具有从0到65536之间的编码,通常从'\u0000'到'\uFFFF'之间的十六进制值来表示。
转义字符
使用'\'来将其后的字符转换为其它含义。
布尔类型
在内存中占一位(不是一个字节),不可以使用0或非0的整数替代。
boolean类型用来判断逻辑条件,一般用于程序流程控制。
运算符
算术运算符
二元运算符的运算规则:
整数运算:
1. 如果两个操作数有一个为Long,则结果也为Long
2. 没有long时,结果为int,即使操作数全为short,byte,结果也是int
浮点运算:
1. 如果两个操作数有一个为double,则结果为double
2. 只有两个操作数都是float,则结果才为float
取模运算:
1. 其操作数可以为浮点数,一般使用整数,结果是“余数”
2. “余数”符号和左边操作数相同
++,--属于一元运算符,该类运算符只需要一个操作数。
赋值运算符及扩展赋值运算符
int a = 3;
int b = 4;
a *= b+3;//相当于a = a * (b + 3);
System.out.println("a = "+a);
System.out.println("b = "+b);
关系运算符
- == != 是所有(基本和引用)数据类型都可以使用
- > >= < <仅针对数值类型(byte/short/int/long,float/double,以及char)
char b = 'a';
char b2 = 'c';
//将char型强转为int型,2种方法
System.out.println((int)b);
System.out.println(0+b);
逻辑运算符
短路与,第一个操作数的值为false,则不需要计算后面的操作数
位运算符
1. &和|既是逻辑运算符,也是位运算符。
如果两侧操作数都是boolean类型就作为逻辑运算
如果两侧的操作数是整数,就是位运算符
2. 不要把“^”当做数学运算“乘方”,是“位的异或”操作
字符串连接符 “+”
条件运算符 x ? y : z
运算符优先级问题
- 逻辑非 > 逻辑与 > 逻辑或
自动类型转换
容量小的数据类型自动转换为容量大的数据类型。表示范围的大小,不是所占内存的大小。
实线表示无数据丢失的自动类型转换
虚线表示在转换时可能会有精度的损失
可以将整型常量直接赋值给byte,short,char等类型变量,而不需要进行强制转换,只要不超出其表数范围即可。
强制类型的转换
用于显式转换一个数值的类型。
可能丢失信息,造成精度降低或溢出
基本类型常见错误
1. 操作比较大的数时,要留意是否溢出,尤其是整数操作。溢出时返回负数
2. Long类型使用大写L不用用小写。
Math类的使用
- java.lang包中的Math类提供一些用于数学计算的方法。
- Math.random():产生一个0到1区间的double类型的随机数,但不包括1
- int i = (int)(6*Math.random()); //产生[0,5]之间的随机数
for循环
支持迭代的一种通用结构,是最有效,最灵活的循环结构。
编译器将while(true)与for(;;)看作一回事,都是无限循环。
在for语句的初始化部分声明的变量,其作用域为for循环体,不能在循环体外部使用该变量。
用,分隔多个初始化语句和步进迭代(i++)。
for(int i=1,j=i+10;i<5;i++,j=i*2){
System.out.println("i = "+i+"j = "+j);
}
嵌套循环
九九乘法表
break用于强制退出循环,不执行循环中剩余的语句
continue用于终止某次循环过程,跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。
continue用在while,do-while中,跳转到循环首部,越过当前循环的其余部分。
continue用在for循环中,跳到for循环的迭代因子部分
带标签的break和continue,跳出多重嵌套循环
//打印101-105之间的所有质数
public static void main(String[] args){
outer:for(int i = 101;i<150;i++){
for(int j = 2;j<i/2;j++){
if(i%j == 0){
continue outer;
}
}
}
}
语句块
确定了局部变量的作用域。
块中的程序代码,作为一个整体被一起执行。
块可以嵌套,但不能在嵌套的块中声明同名变量。
语句块可以使用外部变量,而外部不能使用语句块中定义的变量。
块,没有名字,无法被反复调用,所以不常用。
方法
完成特定功能的代码片段。
方法是类和对象行为特征的抽象。
面向对象中,整个程序的基本单位是类,方法是从属于类和对象的。
方法声明格式:
[修饰符1 修饰符2...] 返回值类型 方法名(形式参数列表){
java语句
}
方法的调用:
对象名.方法名(实参列表)
- 形式参数:在方法声明时用于接收外界传入的数据
- 实参:调用方法时实际传给方法的数据
- 返回值:方法在执行完毕后返还给调用它的环境的数据
- 返回值类型:事先约定的返回值的数据类型,如无返回值,必须显示指定为void
方法的好处:可以多次反复调用
return的作用
1.结束方法的执行
2. 返回值
注意事项:
- 实参的数目,数据类型和次序必须和所调用的方法声明的形式参数列表匹配。
- return语句终止方法的运行并指定要返回的数据
- Java中进行方法调用传参时,遵循值传递的原则,传递的是数据的副本
- 基本类型传递的是该数据的copy值
- 引用类型传递的是该对象引用的copy值,但指向的是同一个对象。
方法的重载(overload):方法名相同
构成方法重载的条件:
不同的含义:形参类型,形参个数,形参顺序不同。
不构成方法的重载:
只有返回值不同
只有形参的名称不同
递归结构
基本思想:自己调用自己
解决的问题:斐波那契数列的计算,汉诺塔,快排
递归结构包括2个部分:
- 定义递归头:什么时候不调用自身方法。如果没有头,就会陷入死循环。
- 递归体:什么时候调用自身方法。
//求阶乘的方法
public static void main(String[] args){
long d1 = System.currentTimeMillis();
System.out.printf("%d阶乘的结果:%s%n",10,factorial(10));
long d2 = System.currentTimeMillis();
System.out.printf("递归费时:%s%n",d2-d2);
}
static long factorial(int n){
if(n == 1){
return 1; //递归头
}else{ //递归体
return n*factorial(n-1);
}
}
递归的缺陷
递归调用会占用大量的系统堆栈,内存耗用多。
在递归调用层次多时速度要比循环慢很多,所以使用递归时要慎重。
注意事项
任何能用递归解决的问题也能用迭代解决。
在要求高性能的情况下尽量避免使用递归,递归既花时间又耗内存。