1、变量
基本概念
概念
变量本质上就是代表一个可操作的存储空间,空间位置是确定的,但是里面放置什么值不确定。
我们可以通过变量名来访问对应的存储空间,从而操作这个存储空间的值。
变量作为程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。
变量在使用前,必须对其申明,只有在变量声明以后,才能为其分配相应长度的存储空间。
变量的申明
- 格式:
type varName [=value][,varName[=value]...]
数据类型 变量名 [=初始值]
- 例子
double salary;
long earthPopulation;
int age;
不同的数据类型的常量会在内存中分配不同的空间,如下图所示:
注意事项
- 每个变量都有类型,类型可以使基本类型,也可以是引用类型
- 变量名必须是合法的标识符
- 变量声明是一条完整的语句,因此每一个声明都必须以分好结束
- 变量需要声明且必须初始化才能够使用
- 在一行中声明多个变量
int i,j;
- 变量的声明和初始化放在同一行中
int age =19;
分类
局部变量
- 方法或者语句块内部定义的变量。生命周期是从生命位置开始到方法或者语句块执行完毕为止。
- 局部变量必须先声明,初始化,然后使用。
成员变量
- 方法外部,类的内部定义的变量,从属于对象,生命周期始终伴随对象
- 如果不自行初始化,它会自动初始化成该类型的默认初始值。
静态变量
使用static
定义,从属于类,生命周期始终伴随类,从类加载到卸载。
2、常量
常量通常指的是一个固定的值,例如:1,2,3,‘a’,'你好'
在Java语言中,主要是利用关键字final来定义个常量。
常量有点被初始化后不能在更改其值。
格式:
final typle varName = value
3、基本数据类型
Java中定义了4类8种基本数据类型
- 整数型
byte
、short
、int
、long
、
- 浮点型
float
、double
- 字符型
char
- 布尔型
boolean
整数
整型用于表示没有小数部分的数值,它可以是负数。
类型 | 占用存储空间 | 表示的范围 |
---|---|---|
byte | 1个字节 | -128~127 |
short | 2个字节 | -2的15次方 到 2的15次方-1 |
int | 4个字节 | |
long | 8个字节 |
Java语言的整型常数默认都是int
类型,如果声明long
类型,需要价格后缀L
或者l
,例如:long a = 10L
;
浮点型
带小数的数据在Java中称为浮点型。
浮点型可分为float
和double
类型.
类型 | 占用存储空间 | 表示的范围 |
---|---|---|
float | 4个字节 | |
double | 8个字节 |
-
float
类型要被称作单精度类型,尾数可以精确到7位有效数字,在很多情况下,float
类型的精度很难满足要求。 -
double
表示这种类型的数值精度约是float
类型的两倍,又被称作双精度类型,绝大部分应用程序都采用double
类型。 -
浮点型常量默认类型也是
double
。 -
float
类型的数值有一个后缀F
或者f
,没有后缀F
,则默认是double
类型
注意
浮点类型不适合在金融计算领域。如果需要进行不产生误差的精确的计算,可以使用BigDecimal
字符型
字符型在内存中占2个字节,在java中使用单引号来标识字符常量。例如:'A'
是一个字符,和"A"
不同,"A"
标识一个字符的字符串。
char
类型用来表示在Unicode
编码中的字符。
Unicode
编码是被设计用来处理各种语言的文字,它占用2个字节,可以允许65536
个字符。
java语言中还可以使用转义字符'\'
来讲其后面的字符转变为其它的含义。
char c = 'a';
char d ='赵';
布尔型
boolean
类型只有两个值:true
和false
,在内存中占一位(不是一个字节)。
boolean flag = true;
if(flag){
// true 分支
} else {
// false 分支
}
4、运算符
计算机的最基本用途之一就是执行数学运算,作为一门计算机语言,java
同样有一套丰富的运算符来操作变量。
算数运算符
算数运算符中 +
,-
,*
,/
,%
属于二元运算符,二元运算符指的是需要两个操作数才能完成运算的运算符。
其中的%
是取模运算符,就是我们常说的求余数操作。
整数运算
- 如果两个操作数有一个为
long
类型,结果也是long
- 没有
long
时,结果为int
。即使操作数全为short
,byte
,结果也是int
。
浮点运算
- 如果两个操作数有一个为
double
,则结果为double
- 只有两个操作数都是
float
,则结果才为float
取模运算
其操作数可以是浮点数,一般使用整数,结果是余数,余数的符号和左边操作数相同,如:7%3=1,-7%3=-1;
自增,增减
算数运算符中,++
,--
属于一元运算符,该类运算符只需要一个操作数。
int a = 10;
int b = ++a;//a先自增为11然后赋值给b
System.out.println(b);//11
int c = b++;//b先赋值给c,然后b自增
System.out.println(c);//11
System.out.println(b);//12
赋值运算符
运算符 | 用法举例 | 等效的表达式 |
---|---|---|
+= 1 | a+=b | a = (a+b) |
-= | ... | ... |
*= | ... | ... |
/= | ... | ... |
%= | ... | ... |
总体来说,就是简化运算写法。没有太大实际意义。
关系运算符
关系运算是用来进行比较运算的,如下图。关系与寒酸的结果是布尔值:true
者false
运算符 | 含义 |
---|---|
== | 等于 |
| 大于
< | 小于
= |大于等于
<= | 小于等于
!= | 小于等于
注意点
=
是赋值运算,而==
是判断是否相等的==
和!=
适合所有数据类型(基本和引用)>
,<
,>=
,<=
仅仅适合数值型比较以及char类型的
逻辑运算符
逻辑运算的操作数和运算结果都是boolean
的值
-
&&
: 表达式两边结果都是truee结果就是true,前面条件正确时,才执行后面,不正确时,就不执行,就效率而言,这个更好 -
||
: 表达式两边有一个是true结果就是true -
&
:不管前面的条件是否正确,后面都执行。 -
|
:不管前面的条件是否正确,后面都执行。
其中 &&
和 ||
是短路操作,从左到右的计算中,如果只通过运算符左边的操作数就能苟确定该逻辑表达式的值,则不会继续计算运算符右边的操作数,提高效率。
三目运算符
- 语法
x ? y : z;
其中x为布尔类型的值,先计算x的值,若为true,则整个运算符的结果是y,否则是z。
public static void main(String[] args) {
int b = 2 >1?10:12;
System.out.println(b);// 10
}
运算符的优先级
源代码就是一份文档,源代码的可读性比代码运行效率更重要。 因此在这里要提醒大家:
- 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它分成几步来完成。
- 不要过多地依赖运算符的优先级来控制表达式的执行顺序,这样可读性太差,尽量使用()来控制表达式的执行顺序。
5、数据类型转换
自动类型转换
定义
自动类型转换指的是容量小的数据可以自动转换为容量大的数据类型。如下图所示:
- 实线表示无数据丢失的自动类型转换
- 虚线表示在转换时可能会有精度的损失
可以将整形常量直接复制给byte
,short
,char
等类型变量,而不需要进行强制类型转换,只要不超出其表数的范围即可。
byte a = 18; // 合法
short b = 12312312312; // 非法,超出了short的表数范围
强制类型转换
强制类型转换,又称为造型(cast
),用于显示的转换一个数值的类型。
在有可能丢失信息的情况下进行的转换是通过造型阿里完成的,但是可能造成精度的降低或者溢出
double a = 3.14;
int b = (int)a;
System.out.println(b); // 3
6、控制语句
选择结构
if
单选择结构
if语句对布尔表达式进行一次判定,若判定为真,则执行{}中的语句,否则跳过该语句块。
double a = 3.14;
if (a > 0) {
System.out.println("a > 0");
}
if-else
双选择结构
当布尔表达式为真的时候,执行语句块1,否则执行语句块2。
double a = 3.14;
if (a > 0) {
System.out.println("a > 0");
} else {
System.out.println("a<0");
}
if-else if-else
多选择结构
double a = 3.14;
if (a > 0) {
System.out.println("a > 0");
} else if (a > -1) {
System.out.println("a>-1");
} else {
System.out.println("a<=-1");
}
switch
多选择结构
语法结构
int a = 34234;
switch (a) {
case 1:
System.out.println(1);
break;
case 2:
System.out.println(2);
break;
default:
System.out.println(3);
break;
}
switch
语句会根据表达式的值从相匹配的case
标签处开始执行,一直执行到break
语句处或者是switch
语句处的末尾。
如果表达式的值与任何一个case
都不匹配,则进入default
语句(前提是存在default
语句)
根据表达式值的不同可以执行许多不同的操作。switch
语句中case
标签在JDK1.5
之前必须是整数(long
除外)或者是枚举。在JDK1.7
之后可以使用字符串。
循环结构
- while
while(boolean表达式){
循环体;
}
在循环刚开始的时候,会计算一次布尔表达式的值,若条件为真,执行循环体。而对于后来每一次额外的循环,都会在开始前重新计算一次。
语句中应该有使循环结束的语句,否则会出现无限循环。
跳出循环可以使用break
关键字;
- do while
do {
循环体;
}while(布尔表达式);
do-while
循环体结构会先执行循环体,然后在判断布尔表达式的值,若条件为真,执行循环体,当条件为假的时候结束循环。do-while
循环体至少会执行一次。
- for循环
for(初始表达式;boolean表达式;迭代因子){
循环体;
}
示例1:计算 1+2+3+...100
public static void main(String[] args) {
int sum = 0;
for (int i = 1; i < 101; i++) {
sum += i;
}
System.out.println(sum);
}
示例2:无限循环
public static void main(String[] args) {
int sum = 0;
for (;;) {
System.out.println(new Date());
}
}
示例3:多个变量赋值
public static void main(String[] args) {
for (int i = 1, j = i + 1; i < 101; i++,j++) {
System.out.println(i);
System.out.println(j);
}
}
示例4:嵌套循环
如下代码,使用嵌套循环打印九九乘法表
public static void main(String[] args) {
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(j + "" + "*" + i + "=" + j * i);
System.out.print(" ");
}
System.out.println();
}
}
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
break、continue
在任何循环语句中,均可使用break控制循环的流程。
break用于强行退出循环,不执行循环中剩余的语句。
示例:
public static void main(String[] args) {
for (int i = 1; i <= 9; i++) {
if(i ==4) {
break;
}
System.out.println(i);
}
}
结果
1
2
3
Process finished with exit code 0
continue语句用在循环语句,用来终止某次循环过程,即跳出循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。
示例
public static void main(String[] args) {
for (int i = 1; i <= 9; i++) {
if(i ==4) {
continue;
}
System.out.println(i);
}
}
结果
1
2
3
5
6
7
8
9
7、方法
实例方法
方法就是一段用来完成特定功能的代码片段,类似于其他语言的函数。
方法用于定义该类或者该类的实例的行为特征和功能实现。方法是类和对象行为特征的抽象。
方法类似面向过程中的函数。
面向对象中,整个程序的基本单位是类,方法是从属于类和对象的
- 方法格式
[修饰符1 修饰符2 ...] [返回值类型] 方法名称([形式参数列表]){
java代码;
}
- 方法调用
对象名.方法名(实际参数)
- 形式参数:在方法声明时候用于接收外接传入的数据
- 实参:调用方法时,实际传给方法的数据
- 返回值:方法在执行完毕后返回给调用它的环境的数据
- 返回值类型:实现约定的返回值的数据类型,如果没有返回值,必须显示指定为
void
示例:
计算两个数之和
public static void main(String[] args) {
// 实例化对象
Demo01_Type demo = new Demo01_Type();
// 调用方法传入实参
int sum = demo.sum(2, 3);
System.out.println(sum);
}
public int sum(int a, int b) {
return a + b;
}
静态方法
所谓静态方法,就是方法前面加上static
关键字,调用静态方法时一般用类名.方法名
,当然也可以用对象名.方法名
;
示例:
public static void main(String[] args) {
Demo.sum(2, 3);
System.out.println(sum);
}
public static int sum(int a, int b) {
return a + b;
}
注意:
非静态方法既可以访问静态数据成员又可以访问非静态数据成员,而静态方法只能访问静态数据成员;
非静态方法既可以访问静态数据方法又可以访问非静态数据方法,而静态方法只能访问静态数据方法。
原因:
因为静态方法和静态数据成员会随着类的定义而被分配和装载入内存中;
而非静态方法和非静态数据成员只有在类的对象创建时在对象的内存中才有这个方法的代码段。
方法的重载
重载的方法,实际是完全不同的方法,只是名字一样而已。
方法名称相同,但是参数不同(参数类型,参数个数)可以构成重载,返回类型与是否重载无关!
示例:
public int sum(int a, int b) {
return a + b;
}
// 参数个数不同,构成重载
public int sum(int a, int b, int c) {
return a + b + c;
}
// 参数类型不同,构成重载
public double sum(double a, double b) {
return a + b;
}
// 参数类型不同,不构成重载
public double sum(int a, int b) {
return 0.0d;
}
注意点:参数返回类型不同和重载无关
递归
递归是一种常见的解决问题的方法,即把问题逐步简单化。递归的基本思想就是自己调用自己,一个使用递归技术的方法将会直接或者间接的调用自己。
利用递归可以用简单的程序来解决一些复杂的问题。比如:斐波那契额数列的计算,汉罗塔,快排等问题。
递归结构包含两个部分:
- 定义递归头
什么时候不调用自身方法。如果没有头,将陷入死循环,也就是递归的结束条件。
- 递归体
什么时候需要调用自身方法
示例1:计算n!
阶乘
public class Demo01_Type {
public static void main(String[] args) {
int a = a(10);
System.out.println(a);
}
public static int a(int n) {
if (n == 1) {
return 1;
} else {
return n * a(n - 1);
}
}
}