01_基础语法
数据类型
分类
数据类型 | 关键字 | 取值范围 | 内存占用(字节) |
---|---|---|---|
整数 | byte | -128~127 | 1 |
short | -32768~32767 | 2 | |
int(默认) | -2147483648~2147483647 (10位数) | 4 | |
long | -9223372036854775808~9223372036854775807 (19位数) | 8 | |
浮点数 | float | 1.401298e-45~3.402823e+38 | 4 |
double(默认) | 4.9000000e-324~1.797693e+308 | 8 | |
字符 | char | 0~65535 | 2 |
布尔 | boolean | true/false | 1 |
小数默认为double,加上F/f为float
转换
-
自动类型转换
表达式的最终结果类型由表达式中的最高类型决定
在表达式中,byte、short、char 是直接转换成int类型参与运算的- char -> int
- byte -> short -> int
- int -> long -> float -> double
-
强制转换
强行将类型范围大的变量、数据赋值给类型范围小的变量:
数据类型 变量2 = (数据类型)变量1/数据,例:
int a = 20; byte b = (byte)a;
强制类型转换可能造成数据(丢失)溢出;
浮点型强转成整型,直接丢掉小数部分,保留整数部分返回
运算符
对字面量或者变量进行操作的符号
算数运算符
符号 | 作用 | 说明 |
---|---|---|
+ | 加 | 参考小学一年级 |
- | 减 | 参考小学一年级 |
* | 乘 | 参考小学二年级,与“×”相同 |
/ | 除 | 与“÷”相同,注意:在Java中两个整数相除结果还是整数。 |
% | 取余 | 获取的是两个数据做除法的余数 |
+ 连接符
能算则算,不能算就直接拼在一起
int i = 4;
System.out.println(i + 2); //6
System.out.println("x" + 5 + i + 5); //x545
System.out.println('a' + i); // 类型自动向上转换为int:101
System.out.println((char) ('a' + i)); // 强转回char:e
System.out.println('a' + i + "-strive"); //101-strive
System.out.println("strive-" + i + 'a'); //strive-4a
自增自减运算符
符号 | 作用 | 说明 |
---|---|---|
++ | 自增 | 变量自身的值加1 |
-- | 自减 | 变量自身的值减1 |
++ 和 -- 既可以放在变量的后边,也可以放在变量的前边。
++ 、-- 只能操作变量,不能操作字面量的
int i = 3;
System.out.println(i++);//3
System.out.println(++i);//5
int c = 10;
int d = 5;
int rs3 = c++ + ++c - --d - ++d + 1 + c--;//10 + 12 - 4 - 5 + 1 + 12 = 26
System.out.println(rs3); // 26
System.out.println(c); // 11
System.out.println(d); // 5
赋值运算符
基本运算符:=
扩展运算符:
符号 | 作用 | 说明 |
---|---|---|
+= | 加后赋值 | a+=b 等价于 a = (a的数据类型)(a+b); 将a + b的值给a |
-= | 减后赋值 | a-=b 等价于 a = (a的数据类型)(a-b); 将a - b的值给a |
*= | 乘后赋值 | a*=b 等价于 a = (a的数据类型)(axb); 将a * b的值给a |
/= | 除后赋值 | a/=b 等价于 a = (a的数据类型)(a/b); 将a / b的商给a |
%= | 取余后赋值 | a%=b 等价于 a = (a的数据类型)(a%b); 将a % b的商给a |
扩展的赋值运算符隐含了强制类型转换
关系运算符
是对数据进行条件判断的符号,最终会返回一个比较的布尔结果(false,true)
符号 | 说明 |
---|---|
== | a==b,判断a和b的值是否相等,成立为true,不成立为false |
!= | a!=b,判断a和b的值是否不相等,成立为true,不成立为false |
> | a>b, 判断a是否大于b,成立为true,不成立为false |
>= | a>=b,判断a是否大于等于b,成立为true,不成立为false |
< | a<b, 判断a是否小于b,成立为true,不成立为false |
<= | a<=b,判断a是否小于等于b,成立为true,不成立为false |
在做相等判断时,千万不要把==误写成=
逻辑运算符
可以把多个条件的布尔结果放在一起运算,最终返回一个布尔结果
符号 | 介绍 | 说明 |
---|---|---|
& | 逻辑与 | 必须都是true,结果才是true; 只要有一个是false,结果一定是false。 |
| | 逻辑或 | 只要有一个为true、结果就是true |
! | 逻辑非 | 你真我假、你假我真。 !true=false 、 !false= true |
^ | 逻辑异或 | 如果两个条件都是false或者都是true则结果是false。两个条件不同结果是true。 |
短逻辑运算符
符号 | 介绍 | 说明 |
---|---|---|
&& | 短路与 | 判断结果与“&”一样。过程是左边为false,右边则不执行 |
|| | 短路或 | 判断结果与“|”一样。过程是左边为true, 右边则不执行 |
三元运算符
条件表达式 ? 值1 : 值2
首先计算条件表达式的值,如果值为true,返回值1,如果为false,返回值2,例:
// 取2个数值中较大的
result = num1 > num2 ? num1 : num2
优先级
流程控制
顺序结构
程序默认执行流程
public class Test {
public static void main(String[] args) {
System.out.println("A");
System.out.println("B");
System.out.println("C");
}
}
分支结构
判断条件来选择某段程序执行
if
格式1:
if (条件表达式) {
语句体;
}
格式2:
if (条件表达式) {
语句体1;
} else {
语句体2;
}
格式3:
格式3:
if (条件表达式1) {
语句体1;
} else if (条件表达式2) {
语句体2;
. . .
else {
语句体n+1;
}
if 语句中,如果大括号控制的只有一行代码,则大括号可以省略不写
switch
匹配条件去执行分支, 适合做值匹配的分支选择,结构清晰,格式良好:
switch (表达式) {
case 值1:
执行代码...;
break;
case 值2:
执行代码...;
break;
…
case 值n - 1:
执行代码...;
break;
default:
执行代码n;
}
switch注意事项:
表达式类型只能是byte、short、int、char,JDK5开始支持枚举,JDK7开始支持String、不支持double、float、long。
case给出的值不允许重复,且只能是字面量,不能是变量。
不要忘记写break,否则会出现穿透现象:如果代码执行到没有写break的case块,执行完后将直接进入下一个case块执行代码(而且不会进行任何匹配),直到遇到break才跳出分支。
可以利用穿透现象归集相同的分支处理,如获取某月天数:
int month = 8;
switch (month){
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
System.out.println("31 days");
break;
case 4:
case 6:
case 9:
case 11:
System.out.println("30 days");
break;
case 2:
System.out.println("28 or 29 days");
break;
default:
System.out.println("Invalid month!");
}
小结
if与switch:
- if适合做区间匹配。
- switch适合做值匹配的分支选择,代码优雅
循环结构
判断条件来选择某段程序执行
for循环
for (初始化语句; 循环条件; 迭代语句) {
循环体语句(重复执行的代码);
}
// 示例:输出3次HelloWorld
for (int i = 0; i < 3; i++) {
System.out.println("Hello World");
}
while循序
初始化语句;
while (循环条件) {
循环体语句(被重复执行的代码);
迭代语句;
}
// 示例:输出3次HelloWorld
int i = 0;
while (i < 3) {
System.out.println("Hello World");
i++;
}
do-while循环
do {
循环体语句;
迭代语句;
} while (循环条件);
// 示例:输出3次HelloWorld
int i = 0;
do {
System.out.println(“Hello World!");
i++;
} while( i < 3);
do-while循环的特点:一定会先执行一次循环体
跳转关键字
- break : 跳出并结束当前所在循环的执行。
- continue: 用于跳出当前循环的当次执行,进入下一次循环。
小结
- for循环 和 while循环(先判断后执行)
- do...while (第一次先执行后判断)
- for循环和while循环的执行流程是一模一样的。
- 如果已知循环次数建议使用for循环,如果不清楚要循环多少次建议使用while循环。
- for循环中定义的控制循环的变量只在循环中可以使用;While循环中,控制循环的变量在循环后还可以继续使用
数组
用来存储一批同种类型数据的容器。
定义
-
静态初始化
定义数组的时候直接给数组赋值
// 完整格式 数据类型[] 数组名 = new 数据类型[]{元素1,元素2 ,元素3… }; double[] scores = new double[]{89.9, 99.5, 59.5, 88.0}; // 简化格式 数据类型[] 数组名 = { 元素1,元素2 ,元素3,… }; int[] ages = {12, 24, 36};
数组变量名中存储的是数组在内存中的地址,数组是引用类型
-
动态初始化
只确定元素的类型和数组的长度,之后再存入具体数据
数据类型[] 数组名 = new 数据类型[长度]; int[] arr = new int[3]; arr[0] = 10; // 后赋值
元素默认值:
数据类型 明细 默认值 基本类型 byte、short、char、int、long 0 基本类型 float、double 0.0 基本类型 boolean false 引用类型 类、接口、数组、String null -
注意事项
-
"数据类型[] 数组名"也可以写成 "数据类型 数组名[]"
int[] ages =...; int ages[] =...; double[] scores = ...; double scores[] = ...;
-
什么类型的数组存放什么类型的数据,否则报错
-
数组一旦定义出来,程序执行的过程中,长度、类型就固定了
-
使用
-
访问:数组名称[索引],如arr[0]
-
长度:数组名称.length
-
最大索引:数组名称.length - 1
-
遍历:
int[] ages = {20, 30, 40, 50}; for (int i = 0; i < ages.length; i++) { System.out.println(ages[i]); }
内存分配
常见问题
- 如果访问的元素位置超过最大索引,执行时会出现ArrayIndexOutOfBoundsException
- 如果数组变量中没有存储数组的地址,而是null, 在访问数组信息时会出现NullPointerException
方法
方法是一种语法结构,它可以把一段代码封装成一个功能,以方便重复调用。
使用方法的好处是:
- 提高代码的复用性
- 让程序的逻辑更清晰
定义
修饰符 返回值类型 方法名( 形参列表 ){
方法体代码(需要执行的功能代码)
return 返回值;
}
例:使用方法对2个整数求和并返回
注意:
- 方法申明了具体的返回值类型,内部必须使用return返回对应类型的数据
- 形参列表可以有多个,甚至可以没有; 如果有多个形参,多个形参必须用“,”隔开,且不能给初始化值
- 方法的编写顺序无所谓
- 方法与方法之间是平级关系,不能嵌套定义
- 方法的返回值类型为void(无返回值),方法内则不能使用return返回数据,如果方法的返回值类型写了具体类型,方法内部则必须使用return返回对应类型的数据
- return语句下面,不能编写代码,因为永远执行不到,属于无效的代码
- 方法不调用就不执行, 调用时必须严格匹配方法的参数情况
- 有返回值的方法调用时可以选择定义变量接收结果,或者直接输出调用,甚至直接调用;无返回值方法的调用只能直接调用
内存分配
参数传递
-
基本类型传参:传输存储的数据值
-
引用类型传参:传输存储的地址值
重载
同一个类中,出现多个方法名称相同,但是形参列表是不同的,那么这些方法就是重载方法。
形参列表不同指的是:形参的个数、类型、顺序不同,不关心形参的名称
作用:可读性好,方法名称相同提示是同一类型的功能,通过形参不同实现功能差异化的选择,这是一种专业的代码设计。
return:可以立即跳出并结束当前方法的执行
面向对象
-
面向:找、拿。
-
对象:东西。
-
面向对象编程:找或拿东西过来编程
面向对象学习什么?学习自己设计对象并使用->面向对象的语法
设计对象并使用
-
类(设计图) :是对象共同特征的描述;
-
对象:是真实存在的具体实例。
在Java中,必须先设计类,才能创建对象并使用。
- 定义类:
public class 类名 {
1、成员变量(代表属性,一般是名词)
2、成员方法(代表行为,一般是动词)
3、构造器 (后几节再说)
4、代码块 (后面再学)
5、内部类 (后面再学)
}
如:
public class Car {
// 属性 (成员变量)
String name;
double price;
// 行为(方法)
public void start(){
}
public void run(){
}
}
-
得到类的对象:
类名 对象名 = new 类名(); Car c = new Car();
-
使用对象:
访问属性: 对象名.成员变量
访问行为: 对象名.方法名(…)
类名首字母建议大写,且有意义,满足“驼峰模式”
一个Java文件中可以定义多个class类,但只能一个类是public修饰,而且public修饰的类名必须成为代码文件名。
实际开发中建议还是一个文件定义一个class类
成员变量的完整定义格式是:修饰符 数据类型 变量名称 = 初始化值; 一般无需指定初始化值,存在默认值,与数组动态声明的默认值一致。
内存分配
构造器
定义在类中的,可以用于初始化一个类的对象,并返回对象的地址
- 定义格式:
修饰符 类名(形参列表){
...
}
如:
public class Car {
...
// 无参数构造器
public Car(){
...
}
// 有参数构造器
public Car(String n, double p){
...
}
}
- 调用格式:
类 变量名称 = new 构造器;
如:
Car c = new Car();
Car c1 = new Car(“奔驰”, 39.8);
-
分类及作用:
无参数构造器(默认存在的):初始化对象时,成员变量的数据均采用默认值。
有参数构造器:在初始化对象的时候,同时可以接收参数为对象进行赋值。
任何类定义出来,默认就自带了无参数构造器,写不写都有;
一旦定义了有参数构造器,那么无参数构造器就没有了,如果还想用无参数构造器,此时就需要自己手写一个无参数构造器了。
this关键字
代表当前对象的地址,可以出现在构造器、方法中。
作用:用于指定访问当前对象的成员变量、成员方法
封装
面向对象的三大特征:封装,继承,多态
封装:告诉我们,如何正确设计对象的属性和方法;
封装的原则:对象代表什么,就得封装对应的数据,并提供数据对应的行为
封装的好处:
- 让编程变得很简单,有什么事,找对象,调方法就行
- 降低我们的学习成本,可以少学、少记,或者说压根不用学,不用记对象的那么多方法,有需要时去找就行
标准JavaBean
也可以称为实体类,其对象可以用于在程序中封装数据。
须满足如下书写要求:
- 成员变量使用 private 修饰
- 提供成员变量对应的 setXxx() /getXxx()方法
- 必须提供一个无参构造器,有参数构造器是可写可不写的
成员变量/局部变量
区别 | 成员变量 | 局部变量 |
---|---|---|
类中位置不同 | 类中,方法外 | 常见于方法中 |
初始化值不同 | 有默认值,无需初始化 | 没有默认值,使用之前需要完成赋值 |
内存位置不同 | 堆内存 | 栈内存 |
生命周期不同 | 随着对象的创建而存在,随着对象的消失而消失 | 随着方法的调用而存在,随着方法的运行结束而消失 |
作用域 | 在所归属的大括号中 |