目录
5.javaSE,javaEE,javaME分别可以做什么?
一、Java基础知识
1.java是什么?
(1)java是java面向对象程序设计语言和java平台的总称。
2.java的开发平台
(1)javaSE:标准版
(2)javaEE:企业版
(3)javaME:嵌入式
3.JRE和JDK
(1)JRE:jre是java运行时环境,包含JVM和运行时所需要的核心类库;
(2)JDK:jdk时java程序开发工具包,包含jre和开发人员使用的工具;
(3)JDK中的开发工具:编译工具(javac.exe)和运行工具(java.exe);
(4)如果我们只是想运行一个java程序,那么我们只需要安装JRE就可以了,但是如果我们想要开发java程序,我们就必须安装JDK。
4.java的运行过程
(1)java源文件 -> java字节码文件 ->操作系统可以识别的代码(运行出来)。
5.javaSE,javaEE,javaME分别可以做什么?
(1)javaSE:控制台app 和 桌面app;
(2)javaEE:Web app;
(3)javaME:嵌入式app;
(4)java除了上面的三个平台以外,还有一个移动开发,用来做andorid和鸿蒙;
6.IDEA中的快捷键
(1)改文件名:shift + f6;
(2)自动生成main方法:psvm 或 main;
(3)自动生成输出语句:sout;
(4)显示自动补全:alt + ctrl + 空格;
(5)查找:ctrl + f;
(6)替换:ctrl + r;
二、Java基础语法
1.注释
(1)注释分为单行注释(ctrl + /),多行注释(ctrl + shift + /),文档注释:
//单行注释
/*
多行注释
多行注释
多行注释
*/
/**
* 文档注释
* 文档注释
* 文档注释
*/
2.java关键字
(1)关键字就是被java语言赋予了特定含义的单词;
(2)关键字全是小写;
(3)在代码编辑器中,关键字会带有自己特有的颜色;
(4)可以在官网中查看具体有哪些关键字:https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html
3.常量
(1)在程序运行过程中,不会改变的量;
(2)常量使用 final 修饰;
4.数据类型
(1)java存储数据的最小单位是字节(byte);
(2)基本数据类型:
// 整数
byte,short,int,long
// 浮点数
float,double
// 字符
char
// 布尔值
boolean
(3)引用数据类型:
// 类
class
// 接口
interface
// 数组
[]
5.变量
(1)在程序运行过程中,其值可以发生改变的量;
(2)从本质生讲,变量是内存中的一小块区域,不仅仅是变量,我们所有程序的运行都会加载到内存中;
(3)使用变量:
//定义变量
int num = 10;
//输出变量
System.out.println(num);
//修改变量
num = 100;
(4)变量的注意事项
- 名字不能重复;
- 变量未赋值,不能使用;
- long类型的变量定义的时候,为了防止整数过大,后面要加L;
- float类型的变量定义的时候,为了防止类型不兼容,后面要加F;
6.标识符
(1)给类,方法,变量等起名字的符号;
(2)标识符中只包含字母、数字、下划线(_)、美元符号($);
(3)标识符的注意事项:
- 不能以数字开头;
- 不能是关键字;
- 区分大小写;
(4)标识符的命名方法:
- 小驼峰命名法:第一个单词的首字母小写,其余单词的首字母大写。如:有两个单词student和name,小驼峰就是:studentName。方法名,变量名,参数名都是遵循小驼峰命名法的;
- 大驼峰命名法:每个单词的首字母大写。如:有两个单词student和name,大驼峰就是:StudentName。类名是遵循大驼峰命名法的;
- 包名全小写,不遵循驼峰命名法;
- 常量名全大写,不遵循驼峰命名法,如果是两个单词则使用下划线隔开。如:MAX_VALUE;
7.类型转换
(1)注意:boolean 是非数值类型,不参与转换;
(2)字符类型会转换为ascii码值;
- '0'~'9': 48~57;
- 'A'~'Z': 65~90;
- 'a'~'z': 97 ~122;
(3)自动类型转换(目标类型 >= 源类型);
- 自动类型转换是正常转换,不会丢失数据;
-
// 定义一个字符 char c = 'a'; System.out.println(c); // 'a' // 获取字符的ascii码 // 这里就用到了自动类型转换,将char转换为int int num = c; System.out.println(num); // 97 : 'a' // int类型转换为long类型 long num2 = num; System.out.println(num2); // 97 // int类型转换为float类型 float f = num; System.out.println(f); // 97.0
(4)强制类型转换(目标类型 < 源类型);
- 强制类型转换是非正常转换,可能会丢失数据;
- 格式:目标类型 变量名 = (目标类型) 值或者变量;
- 如:int num = (int)9.9,因为9.9是小数,所以在转换为整数时会丢失小数部分;
-
int num3 = 20; // int类型转换为short类型 // 因为int类型要大于short类型,所以需要强制转换,把源类型(int)变为目标类型(short),然后在赋值 short s = (short) num3; System.out.println(s); // long类型转换为short类型 越级 long l = 179; short s2 = (short) l; System.out.println(s2); // int的4字节(B)和float的4字节(B)不一样,因为float是小数,就像1和1.32虽然都是1,但是1 < 1.32 也就是 int < float // 因为float精度高,有小数 float f2 = 123; // 自动类型转换 int num4 = (int) f2; // 强制类型转换
三、Java运算符
1.算术运算符
(1)乘法运算符:*
(2)除法运算符:/
- 整数操作只能得到整数,要想得到小数,必须有浮点数参与运算;
(3)取模运算符:%,就是取余数
(4)除法和取模的特殊情况:
// 特殊情况:/ %
System.out.println(5 / 2); // 结果为:2 得到商 整数相除得到的都是整数,想要得到小数,就需要参与运算的值中至少有一个是小数
System.out.println(5 % 2); // 结果为:1 得到余数
System.out.println(5f / 2); // 2.5
System.out.println(5f / 2f); // 2.5
System.out.println(5 / 2f); // 2.5
// System.out.println(5.0/2); // 5.0/2的结果为double类型,太大了,不需要
(5)加法运算符:+
- 字符的+:将字符的ascii码值加上数字;
-
// 字符的+:将字符的ascii码值 + 数字 char c = '0'; // '0'~'9': 48~57 'A'~'Z': 65~90 'a'~'z': 97~122 int result = c + 10; System.out.println(result); // 58 // 将一个小写字母转换为大写字母:'a':97 - 32 --> 'A':65
- 字符串的+:当 "+"操作中出现字符串时, 这个“+”是字符串连接符,而不是算术运算;
-
// 字符串的+ System.out.println("张三" + 666); // "张三666" System.out.println(100 + "年张三" + 666); // "100年张三666" System.out.println(1 + 99 + "年张三"); // "100年张三" 先进行算术运算然后拼接字符串,因为1和99都是数值所以要先进行算术运算 System.out.println("张三" + 666 + 888); // "张三666888" // "张三" + 666 ==> "张三666" + 888 ==> "张三666888"
- 当 "+"操作中,如果出现了字符串,就是连接运算符,否则就是算术运算。当连续进行"+"操作时,从左到右逐个执行;
(6)减法运算符:-
(7)例题:
// 1.声明两个变量
int a = 10;
int b = 2;
// 2.对这两个变量进行算术运算
System.out.println(a + b); // 10 + 2 = 12
System.out.println(a - b); // 10 - 2 = 8
System.out.println(a * b); // 10 * 2 = 20
System.out.println(a / b); // 10 / 2 = 5
System.out.println(a % b); // 10 % 2 = 0
(8)自增运算符:++
- 将变量加1;
-
// 1.声明一个变量 int a = 10; a++; // 相当于a = a + 1,但是++ 要比 a = a + 1好,因为++带有一个强制类型转换的效果,不会因为类型转换而报错,--同理 System.out.println(a) // 11
(9) 自减运算符:--
- 将变量减1;
-
// 1.声明一个变量 int a = 10; a--; // 相当于a = a - 1 System.out.println(a) // 9
2.赋值运算符
(1)=,+=,-=,*=,/=,%=
(2)赋值运算符“=”:就是将=右边的值保存在左边的变量中;
(3)赋值运算符“+=”:就是数值的累加;
// 1.声明一个变量
int a = 10;
a += 25; // 相当于 a = a + 25;但是+= 要比 a = a + 25好,因为+=是带有一个强制类型转换的效果,不会因为类型转换而报错
System.out.println(a) // 35
(4)-=,*=,/=,%=:这些运算符和运算符+=是差不多的,可以参照+=,唯一不同的就是前面的+,-,*,/,%
3.关系运算符
(1)比较两个数值的大小,返回一个boolean类型;
(2)关系运算符有:
- 大于:>
- 小于:<
- 大于等于:>=
- 小于等于:<=
- 等于:==
- 不等于:!=
int age = 18;
System.out.println(age > 20); // 18 > 20:false
System.out.println(age >= 18); // 18 >= 18:true
System.out.println(age >= 0); // 18 >= 0 :true
System.out.println(age <= 150); // 18 <= 150 :true
System.out.println("--------------------------------");
// 判断数字是否为偶数
System.out.println(age % 2 == 0);
// 判断数字是否为奇数
System.out.println(age % 2 == 1);
System.out.println(age % 2 != 0);
(3)关系运算符中,>,<,>=,<=比较的是数值类型;而==和!=可以是任意类型,但是==不推荐用于String类型,因为==在比较String类型时比的是地址,而不是地址中的值,String类型推荐使用equals方法,如:字符串1.equals(字符串2);
String name = "admin"; // 用户名
//String name = new String("admin"); // 一旦我的地址更改了,虽然内容是一样的,都是admin,但是使用==比较的话就会认为这两个字符串不一样
// 判断用户名是否为admin
System.out.println(name == "admin"); // true 虽然这里是true,但是这个比较大概率是false,因为==用在String类型中比较的是地址,一旦地址不同,结果就会为false
System.out.println(name.equals("admin")); // true
4.逻辑运算符
(1)逻辑运算符左右两边的都是boolean类型;
(2)逻辑运算符有:
- 逻辑非:!(not) 逻辑非只有一个操作符,作用是取反,假为真,真为假;
- 逻辑与:&&(and) 左右两边都为真(true),则结果为真(true),其他为假(false);
- 逻辑或:||(or) 左右两边都为假,则结果为假,其他为真;
- 逻辑异或:^(xor) 左右两边,一个为真,一个为假,则结果为真,其他为假。如:true ^ false => true false ^ true => true;
-
// 逻辑非 boolean flag = true; System.out.println(!flag); // false 原来是真的,取反之后变成了假的 // 逻辑与 char sex = '女'; int age = 18; System.out.println(sex == '女' && age >= 20); // false sex == '女' => true age >= 20 => false true && false => false sex = '男'; age = 23; System.out.println(sex == '男' && age >= 22); // true sex == ''男'' => true age >= 22 => true true && true => true // 逻辑或 char sex = '女'; int age = 18; System.out.println(sex == '女' || age >= 20); // true sex == '女' => true age >= 20 => false true || false => true
5.条件运算符
(1)?:
- 格式:boolean类型的表达式 ?值1 : 值2
- 解释:判断表达式,如果表达式为true则返回值1否则返回值2
- 条件运算符相当于if...else
四、选择
1.程序的执行顺序
(1)顺序结构
- 序结构就是从上到下每一条语句都会执行,中间没有任何判断和跳转;
(2)分支结构
- 分支结构就是用于程序中有不同的选择,不同的选择有不同的结果;
- 分支结构包括:if,if...else,if...else if...else,switch
(3)循环结构
- 循环结构就是将一段代码重复执行,直到满足条件才会停止循环,去执行循环后面的语句;
- 循环结构包括:while,do...while,for
2.if结构
(1)语法:if(boolean类型的表达式){要执行的语句}
(2)boolean类型的表达式:结果只有true或者false的表达式;
(3)解释:判断括号中的表达式,如果为true,就执行if下面大括号中的语句,如果为false,则不会执行大括号中的语句;
(4)案例:
// 1.1提示用户输入
System.out.println("请输入年份(1900~2200):");
year = sc.nextInt();
// 1.2判断数据的有效性
// 1.2.1验证年
if(!(year >= 1900 && year <= 2200)){
System.out.println("输入的年份不满足要求,程序结束");
return;
}
3.if...else结构
(1)语法:if(boolean类型的表达式){要执行的语句}else{语句}
(2)解释:判断括号中的表达式,如果为true,就执行if下面大括号中的语句,如果为false,就会执行else后面的语句;
(3)案例:
// 1.赋值
int num = 10;
// 2.业务判断
boolean isEven = num % 2 == 0; // true
// System.out.println(isEven); // 是:true 否:false
// 因为true或者false普通用户很难明白是什么意思,所以我们需要一个更简单的方法让用户看明白,将true/false转为文字
if(isEven == true){ // true == true : true
// 如果结果是true,则执行这里面的语句
System.out.println(num + "是偶数");
}else {
// 如果结果是false,则执行这里面的语句
System.out.println(num + "不是偶数");
}
4.if...else if...else结构
(1)语法:if(boolean类型的表达式){要执行的语句}else if(boolean类型的表达式){要执行的语句}else{语句}
(2)解释:判断括号中的表达式,如果为true,就执行if下面大括号中的语句,如果为false,则会去判断else if后面的括号中的表达式是否为true,如果为true,就会执行else if后面的大括号中的语句,如果为false,就会继续判断,直到所以的else if语句都判断完成,如果都不满足,就会执行else后面大括号中的语句;
(3)注意:if...else if...else结构中,if和else之间可以有多个else if语句,如果其中某一个if或者else if的判断为true了,就不会再去执行下面的else if的判断了;
(4)案例:
// 1.声明一个变量保存月份(1~12)
int month = 8;
// 2.判断月份是属于大月、小月、二月
if(month == 2){
// 3.打印对应的天数
// 2月
System.out.println(month + "月:28天");
}else if(month == 4 || month == 6 || month == 9 || month == 11){
// 3.打印对应的天数
// 小月
System.out.println(month + "月:30天");
}else {
// 3.打印对应的天数
// 大月
System.out.println(month + "月:31天");
}
5.总结:if或者else if的括号中可以存放什么?
(1)有关系运算符的表达式(>,>=,<,<=,==,!=);
(2)有逻辑运算符的表达式(! && ||);
(3)boolean变量或者boolean常量;
6.switch结构
(1)语法:switch(变量){case 值1://语句 break;case 值2: //语句 break;case 值3://语句 break;...;default://语句}
- switch后面的括号中可以放:byte,short,int,char,String类型的表达式;
-
// 1.确定星期几(1~7) int weekday = 1; // 2.判断日期展示不同的食物 switch (weekday){ case 1: System.out.println("红烧肉"); break; // 用于结束switch结构 case 2: System.out.println("臭豆腐"); break; case 3: System.out.println("辣椒炒肉"); break; case 4: System.out.println("鱼香肉丝"); break; case 5: System.out.println("烤牛肉"); break; case 6: System.out.println("不想吃饭"); break; default: System.out.println("剁椒鱼头"); }
(2)解释:
- switch结构是用括号中的变量去和case后面的值去比较,和哪个值相同就会去执行case后面的语句;
- break是用来结束switch分支的,防止代码穿透。当碰到break语句的时候,switch结构结束,执行switch结构后面的语句;
- 注意:case语句可以有多个,没有数量限制,但是case后面要跟一个值和一个冒号,而且值的类型必须和括号中变量的类型相同;
- 值的类型只能是常量或者字面常量;
- switch 语句可以包含一个 default 分支,该分支一般是 switch 语句的最后一个分支(可以在任何位置,但建议在最后一个)。default 在没有 case 语句的值和变量值相等的时候执行。default 分支不需要 break 语句;
(3)switch结构括号中变量和case的值是相等的关系,所以switch只适合用于条件是相等的多重判断;
(4)在java中,switch是可以没有break的,如果没有break,switch的代码就会有一个穿透的效果,就是当你的switch括号中的变量和case后面的值相等时,会执行当前case中的语句,如果有break,在执行完case中的语句后,switch就会结束,不在执行后面的case语句,如果没有break,在执行完case中的语句后,switch就会去执行后面的case语句,直到碰到break,如果没有碰到,就会一直执行到switch结构完成;
// 1.确定星期几(1~7)
int weekday = 1;
// 2.判断日期展示不同的食物
switch (weekday){
case 1:
System.out.println("红烧肉");
case 2:
System.out.println("臭豆腐");
case 3:
System.out.println("辣椒炒肉");
case 4:
System.out.println("鱼香肉丝");
case 5:
System.out.println("烤牛肉");
case 6:
System.out.println("不想吃饭");
default:
System.out.println("剁椒鱼头");
}
/*
如果weekday==1,那么这个程序就会输出case值为1的语句以及后面的全部语句,如如果weekday==5,那么这个程序就会输出case值为5的语句以及后面的全部语句
*/
(5)注意:尽量避免嵌套,多一层嵌套,代码的复杂度和维护成本将会成指数被增长;
(6)控制语句:
- break:跳出switch或者跳出循环;
- return:跳出方法;
(7)输入方法:
- 如果程序想要接收用户输入的语句,需要使用util包下Scanner类;
- util包是:java的工具包,提供了很多工具类;
- Scanner类是:扫描器类型,可以帮助程序获取用户在控制台输入的信息(需要构建对象和导包);
- 输入整数:输入整数是使用对象名.nextInt(),如果需要输入其他类型,需要使用不同的方法,如果字符串对象名.next(),小数对象名.nextFloat()等等;
-
// 1.构建扫描器对象(导包) Scanner sc = new Scanner(System.in); // 2.用对应方法扫描用户输入的类型 // 2.1提示用户输入数据 System.out.println("请输入年份:"); // 2.2接收数据:什么类型的数据就得用什么类型的方法 int year = sc.nextInt(); // 2.3打印用户输入的数据 System.out.println(year); // 输入月份 System.out.println("请输入月份:"); int month = sc.nextInt(); System.out.println(month);
五、循环
1.循环的组成
(1)初始化语句:用于表示选好开启时的起始状态,也就是循环从什么时候开始
- 可以是一条或者多条语句。这些语句可以完成初始化操作;
-
for(int i = 1...){ ... }
(2)条件判断语句:用于表示循环反复执行的条件,也就是循环从什么时候停止
- 可以使用一个值为boolean类型的表达式,这个表达式决定是否执行循环体;
-
for(int i = 1;i <= 10;...){ ... }
(3)循环体语句:
- 可以是任意语句,这些语句会重复执行;
-
for(int i = 1;i <= 10;...){ //循环体语句 }
(4)条件控制语句:
- 使用一条语句来说改变条件判断中变量的值,达到循环可以在我们完成想要的功能后停止(类似i++ 或 i--);
-
for(int i = 1;i <= 10;i++){ //循环体语句 }
2.循环的语法结构
// for循环
for(初始化语句;条件判断语句;条件控制语句){
循环体语句
}
// while循环
初始化语句
while(条件判断语句){
循环体语句
条件控制语句;
}
// do...while循环
初始化语句
do{
循环体语句
条件控制语句;
}while(条件判断语句);
3.用好
(1)了解每种循环的长处:
- for:用于明确的循环次数;
- while:用于不明确的循环次数;
- do...while:用于询问式的系统;
4.循环控制语句
(1)continue:结束本次循环,开始下次循环:循环还在继续;
(2)break:终止循环;
(3)switch+break:break用于结束switch结构;
5.嵌套
(1)嵌套分为条件嵌套和循环嵌套;
(2)条件嵌套:
- if,if...else,switch可以相互嵌套,例如:
-
if(){ if(){ } } switch(){ if(){ } } if(){ switch(){ } } if(){ if(){ }else{ } }
(3)循环嵌套:
- 循环嵌套和条件嵌套差不多,也是for,while,do...while可以相互嵌套,例如:
-
for(){ for(){ } } for(){ while(){ } } for(){ do{ }while(); } while(){ for(){ } do{ }while(); }
- 一般情况下,两个for循环嵌套,外面的for循环是外层循环,里面的for循环是内层循环;
- 外层循环控制行,内层循环控制列;
6.块
(1)形式:{}
(2)块是由一组大括号组成的,它规定了代码的执行范围和变量的使用范围,对代码进行了整合;
(3)例如:main,if,for都有块,如下:
main(){}
if(){}
for(){}
六、方法
1.方法的概述
(1)方法是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集;
(2)注意:
- 方法必须先创建才可以使用,该过程称为定义方法;
- 方法在创建后并不是直接运行的,需要手动使用后才会执行,该过程称为调用;
2.方法的定义
(1)格式:
public static void 方法名(){
// 方法体
}
3.方法的调用
(1)格式:方法名();
public class Demo1{
public static void main(String[] args){
// 调用方法
getMax();
}
// 定义方法,获取最大值
public static void getMax(){
int a = 10;
int b = 20;
int max = a > b ? a : b;
System.out.println("max:" + max);
}
}
(2)注意:方法必须先定义再调用,否则程序会报错;
4.方法的参数
(1)形参:
- 形参是在定义方法的时候在括号中定义的;
- 形参必须有参数类型和参数名;
- 格式:下面的a和b就是形参;
-
public static void getMax(int a,int b){ // 方法体 }
(2)实参:
- 实参是在方法调用的时候,写在括号中传递给形参的值;
- 实参可以是一个具体的数值,也可以是变量或者是引用类型;
- 格式:下面调用方法时,括号中就是实参;
-
public static void main(String[] args){ // 调用方法1 getMax(10,20); // 调用方法2 int a = 10; int b = 20; getMax(a,b) } public static void getMax(int a,int b){ // 方法体 }
5.方法的重载
(1)方法想要重载的话,需要满足两个条件,一个是方法名相同,一个是参数列表不同;
(2)参数列表不同可以分为:
- 个数不同
-
public static void getMax(int a){ // 方法体 } public static void getMax(int a,int b){ // 方法体 }
- 类型不同
-
public static void getMax(int a){ // 方法体 } public static void getMax(String a){ // 方法体 }
- 顺序不同
-
public static void getMax(int a,String b){ // 方法体 } public static void getMax(String a,int b){ // 方法体 }
6.方法的返回值
(1)格式:注意返回的数据类型和定义方法时定义的数据类型是一致的,如果不一致,程序会报错;
public static 数据类型 方法名(参数){
return 数据;
}
- 范例:
-
public static boolean isEvenNumber(int num){ return true; } public static int getMax(int num){ return 100; }
(2)通常带返回值的方法在调用的时候需要用变量来接收这个方法的返回值,否则返回值将无意义;
- 例如:
-
boolean flag = isEvenNumber(1); int num = getMax(20);
7.方法中值类型的参数传递和引用类型的参数传递的区别
(1)值类型:传值
- 一个值类型变量,在调用一个方法的时候,将这个值类型变量的值传递到了方法中,无论这个值在传递到方法中之后做了什么改变,都不会影响到在调用方法时将值传递到方法中的那个值类型变量;
- 例如:
-
public static void main(String[] args) { int num = 10; add(num); System.out.println(num); // 10 } public static void add(int a){ a++; }
(2)引用类型:传地址
- 一个引用类型,在调用方法的时候,这个引用类型传递到方法中的是一个地址,所以这个时候就会有两个引用类型指向了同一个地址,一旦其中一个引用类型更改了这个地址中的值,那么就会影响到另一个引用类型;
- 例如:
-
public static void main(String[] args) { int[] ages={12,9,60}; add2(ages); System.out.println(Arrays.toString(ages)); // 13,10,61 } public static void add2(int[] nums){ for(int i=0;i<nums.length;i++){ nums[i]++; } }
七、数组
1.数组的概念
(1)一种用于存储多个相同数据的存储结构;
2.数组的声明
// 方法一
int[] nums; // 推荐
// 方法二
int nums[];
3.数组的初始化
(1)静态初始化
int[] nums = {1,2,3};
(2)动态初始化
int[] nums = new int[3];
4.数组的遍历
// 方法一
for(int i = 0;i < nums.length;i++){
System.out.println(nums[i]);
}
// 方法二
for(int i : nums){
System.out.println(i)
}
5.foreach循环的优点和缺点
(1)代码:
for(int i : nums){
System.out.println(i)
}
(2)优点:速度快
(3)缺点:同时只能完成一个数组的遍历,而且只能查不能改
6.API
(1)含义:Java为我们写好的,我们只是用而已
(2)遍历数组可以使用Arrays帮助类中的toString()方法
System.out.println(Arrays.toString(nums))
7.随机数
(1)随机数加个种子可以生成一组固定的随机数
Random random = new Random(10) // 10就是种子,可以是任意数字
8.内存
(1)栈
- 空间小,但是块
(2)堆
- 空间大,但是慢
9.null的作用
(1)给引用类型赋初值,如:String str = null;
(2)自动垃圾回收(如果将引用类型赋值为null,可以更快的将此类型确定为垃圾)
- 确定谁是垃圾;
- 确定这些垃圾没有被其他的代码引用;
- 回收;
10.值类型和引用类型的区别
(1)值类型:存值;
(2)引用类型:存地址;
11.引用类型赋值和复制的区别
(1)值类型的赋值和复制是没有什么区别的,值类型改变的是值,并不会影响到其他变量的值;
(2)引用类型赋值:
- 给引用类型赋值就是赋地址;
- 给多个引用类型赋同一个值,就会让多个引用类型指向同一个地址,那么,一旦其中一个引用类型改变了这个地址中保存的数据,就会影响到其他的引用类型;
- 例题:
-
int[] ages = {10,20,30}; // 赋值 int[] temps = ages; System.out.println(Arrays.toString(ages)); // [10,20,30] System.out.println(Arrays.toString(temps)); // [10,20,30] // 修改 ages[0] = 100; // 输出结果 System.out.println(Arrays.toString(ages)); // [100,20,30] System.out.println(Arrays.toString(temps)); // [100,20,30]
(3)引用类型复制:
- 给引用类型复制的话,是会生成一个新地址来保存复制的数据的,所以给多个引用类型复制是不会指向同一个地址的;
- 因为给多个引用类型复制不会指向同一个地址,所以其中一个引用类型发生改变的话,它只是改变自己所指向地址中的数据,是不会影响到其他引用类型所指向地址中的数据的;
- 例题:
-
int[] ages = {10,20,30}; // 1.new一个新的数组 int[] temps = new int[ages.length]; System.out.println(Arrays.toString(temps)); // [0,0,0] // 2.一个一个赋值 for(int i = 0;i < ages.length;i++){ temps[i] = ages[i]; } System.out.println(Arrays.toString(ages)); // [10,20,30] System.out.println(Arrays.toString(temps)); // [10,20,30] // 3.测试变化 ages[0] = 100; System.out.println(Arrays.toString(ages)); // [100,20,30] System.out.println(Arrays.toString(temps)); // [10,20,30]
(4)给引用类型赋null值:
- 如果多个引用类型指向了同一个地址,那么,给其中一个引用类型赋值为null,是不会影响到其它指向相同地址的引用类型的;
12.API的复制方法
(1)可以使用Arrays帮助类中的copyOf方法,如下:
int[] ages = {10,20,30};
int[] ages2 = Arrays.copyOf(ages,ages.length);
13.判断两个数组是否相同
(1)原生代码:
- 处理引用类型为null的情况;
- 比较数组的地址;
- 比较数组的长度;
- 比较数组中的数据;
(2)API方法:
- 使用Arrays帮助类中的equals方法;
- 例如:
-
int[] arr = {1,2,3}; int[] arr2 = {4,5,6}; System.out.println(Arrays.equals(arr,arr2)); // false
14.数组中的常见异常
(1)空指针异常:java.lang.NullPointerException
(2)数组下标越界:java.lang.ArrayIndexOutOfBoundsException: -1
15.数组排序
(1)数组排序分为升序排序和降序排序:
- 升序:从小到大;
- 降序:从大到小;
(2)数组的冒泡排序算法:
- 冒泡:难度最小;
- 实现:冒泡排序-升序;
- 1.外层循环是用来控制比较次数的,4个元素就比较3次,length - 1;
- 2.内层循环是用来控制相邻元素比较的,这里需要特别注意一下下标越界的问题;
- 3.判断,如果位置在前,并且数据是大的,还有交换,就是升序;如果位置在前,并且数据是小,还有交换,即使降序;
- 4.换位:注意要首尾相接;