一、JAVA背景知识
0、学习视频
老师讲的很详细,很有趣,推荐学习。
java零基础自学首选黑马程序员Java入门教程(含Java项目和Java真题)
1、java入门知识
1.java背景知识
- Java是美sun公司,1995年推出的计算机高级编程语言
- 2009,被Oracle甲骨文收购
2.java能做?
| 应用类型 | 示例 |
|---|---|
| 桌面应用开发 | 各种税务管理软件、idea |
| 企业级应用开发 | 微服务、大型互联网应用 |
| 移动应用开发 | android、医疗设备 |
| 服务器系统 | 应用后台 |
| 大数据开发 | hadoop |
| 游戏开发 | 我的世界 |
3.Java技术体系
| 技术体系 | 说明 |
|---|---|
| Java SE (Java Standard Edition):标准版 | Java技术的核心和基础 |
| Java EE (Java Enterprise Edition):企业版 | 企业级应用开发的一套解决方案 |
| Java ME(Java Micro Edition ):小型版 | 针对移动设备应用的解决方案 |
2、Java快速入门
1.JDK相关
-
JDK(Java Development Kit)java开发者工具包
-
JDK(8.0、LTS):Long-term support 长期支持版
CMD中:
| 命令 | 作用 |
|---|---|
| java javac | 查看是否安装成功 |
| java -version | 查看版本 |
| java.exe | 执行工具 |
| javac.exe | 编译工具 |
| Java程序是高级语言,计算机底层不识别 | |
| 先用javac翻译工具翻译,java.exe执行工具执行,驱动机器 |
2.命令行窗口常用命令
| 命令 | 作用 |
|---|---|
| 盘符: | 切换盘 F: |
| dir | 查看当前路径下文件信息 |
| cd | 进入单极目录 cd in 进入多级目录 cd F:\my\Javase 回到上级目录 cd .. 退回到盘符目录 cd \ |
| cls | 清屏 |
3.入门程序
java开发三步骤:编写代码--->编译代码-->运行代码
写好HelloWorld.java,打开cmd,进入文件存放位置,javac XX.java;可以使用TAB键补全文件名;
javac HelloWorld.java
java HelloWorld
3、Java执行原理,bug设计
编程语言发展历程
- 机器语言
- 汇编语言
- 高级语言:接近人类语言,好学
1.java执行原理
不管是什么高级语言,最终都是翻译成计算机底层可识别的机器语言
2.机器语言组成:01
4、JDK组成,跨平台原理
1.JDK组成
| JVM(Java Virtual Machine) | java虚拟机,真正运行java程序的地方 |
|---|---|
| 核心类库 | java准备好的程序,随时调用 |
| JRE(Java Runtime Environment) | java运行环境,由上面二者组成 |
| JDK | java开发工具包,包括上面所有,和开发工具 |
2.JAVA执行顺序
开发工具编译javac--》Hello.java生成--》Hello.class-->工具java执行--》放入JVM运行--》调用核心类库的方法
3.跨平台原理
拥有对应不同平台系统的JVM虚拟机,实现一次编译,到处运行
5、JDK安装后Path和JAVA_HOME配置
1.Path环境变量
用于记住程序路径,方便命令行窗口任意目录启动程序
C:\Program Files\Java\jdk1.8.0_211\bin;
C:\Program Files\Java\jdk1.8.0_211\jre\bin;
2.JAVA_HOME
C:\Program Files\Java\jdk1.8.0_211;
6、IDEA开发工具
1.下载(不要安装在有空格或中文路径下)
2.IDEA项目结构介绍
由上到下包含:
| project | 项目、工程 |
|---|---|
| module | 模块 |
| package | 包 |
| class | 类 |
建立工程、模块、包的方法
| 建一个空工程流程 | new Project | Empty Project |
|---|---|---|
| 建一个新模块 | new module | 选择java模块 |
| 建包 | 包名是网站网址倒写 | com.yanf.www |
3.调整主题
Settings --》Appearance--》Theme
4.调整字体
Settings --》Font
5.IDEA快捷键
6.IDEA其他操作
6.1修改模块名称
要磁盘和文件中一起改module and directory
6.2导入模块
file --》new--》module from existing Source --》选中模块内带黑点的文件
以上存在问题,导入模块位置改变,可能丢失;
建议创建新模块,将com下文件直接复制过来;
6.3删除模块
-
找到文件删除
-
选中,上方删除(删不干净,进入模块xml中删除配置,重启IDEA)
RecordDate:2021/08/06
二、Java基础语法
1.注释
java文件通过javac编译生成class文件中并不会存在注释内容
工程下的out文件中可以找到编译后的class文件,可以拖到idea中反编译显示;
//普通注释
/*
多行注释
*/
/**
*
*文档注释:内容可以自动提取到程序说明书
*/
| 快捷注释 | 效果 |
|---|---|
| Ctrl + / | 单行注释 |
| Ctrl + Shift + / | 对选中代码多行注释 |
2.字面量
3.变量
3.1什么是变量?
- 变量是用来存储一个数据的内存区域,里面存储数据可变
- 变量定义格式:
- 数据类型 变量名称 = 初始值;
3.2变量使用注意
- //1.变量声明后再用
- //2.变量声明后不能存储其他类型数据
- //3.变量有效范围从定义开始到”}“截止;
- 同一范围不能有同名变量
- //4.变量定义时可以没有初始化值,使用时必须赋值
4.变量在计算机中底层原理
4.1二进制
逢二进一
十进制转二进制计算方法:除二取余,从下往上倒取值;
4.2计算机中数据最小单位
- 计算机最小组成单元
- 使用8个二进制位为一组,存数据,为一个字节(byte,简称B)
- 每个二进制位为一位(bit,简称b)
- 1byte=8bit,1B=8b
4.3字符在计算机中如何存储
ASCII编码表:美国信息交换标准码
//a=97
char a = 'a';
//a+1=98
System.out.println(a+1);
字符做运算,会用编码参加,返回数字
5.进制转换
5.1二进制和十进制互相转换
5.2八进制和十六进制
-
八进制每一位扩展成三位二进制
- 93 135(八进制) 001-011-101(二进制)
-
十六进制,0-9 ABCDEF
- 97 61(十六进制) 0110-0001(二进制)
- 93 5D(十六) 0101-1101(二)
-
程序中支持书写二、八、十六进制数据
-
分别需要以0B或者0b、0、0X或者0x开头
-
int z = 0b01011101; System.out.println(z); int x = 0135; System.out.println(x); int c = 0x5D; System.out.println(c); ============= 93
-
5.3数据大小单位换算
| 大单位 | 小单位 |
|---|---|
| 1B | 8B |
| 1KB | 1024B |
| 1MB | 1024KB |
| 1GB | 1024MB |
| 1TB | 1024GB |
6.数据类型
6.1数据类型分类
-
引用数据类型(除基本形外)
-
基本数据类型:四大类8种
-
Double采用特殊计数法,范围更大
-
随便写一个大整数需要在后面用L或l标识为Long,因为整数默认是int型
int p= 154646546; //Long p1 = 46546545456465; Long p2 = 136458416315635631L; -
小数默认是双精度Double型,用单精度Float时,需要数字后标记F或者f
-
double q = 45.96; //float f = 45.8; float ff = 45.8F;
-
-
6.2理解float和double、单精度和双精度
1.内存占用
| 占用字节 | 总位数 | 备注 | |
|---|---|---|---|
| float | 4个字节 | 32位 | 1位4个0000 |
| double | 8个字节 | 64位 | 因此,能用float尽量不用double。 |
2.范围
| 范围 | |
|---|---|
| float | -2^128 ~ 2^127 |
| double | -2^1024 ~ 2^1023 |
3.为什么浮点数会有精确度问题? 浮点数是用二进制数据的科学计数法表示的,因此不能精确的表示。就像十进制1/3 0.3333…一样
4.float 32位,double64位是怎么组成的?
| float | 1位符号位 | 8位指数位 | 23位尾数 |
|---|---|---|---|
| double | 1位符号位 | 8位指数位 | 52位尾数 |
5.有效位数
| 有效位数 | 备注 | |
|---|---|---|
| float | 6位 | 小数点后6位都是准确的,而第7位就不一定 |
| double | 15位 |
6.关于单精度和双精度的命名? 为什么叫单精度,为什么叫双精度 1)是因为精确度位数的区别而命名的吗?
–不是,至少没有资料表明,它是以这个来命名的。 2)是因为二进制科学计数法存储的尾数(float尾数23,double尾数52)的单双来命名吗?–好像也不是。 所以,只要记住单精度是float,双精度是double就好了。
7.关键字和标识符
7.1关键字
不能用来作为类名或者变量名称
7.2标识符
给类,方法,变量起名的规矩
- 标识符要求
- 基本要求:由数字,字母,下划线,$组成
- 强制要求:不能以数字开头,不能是关键字,区分大小写
- 命名规范
- 驼峰式:
- 变量首字母小写
- 类名称,首字母大写
- 驼峰式:
RecordDate:2021/08/06
三、类型转换
1.自动类型转换
概念:类型范围小的变量,直接赋值给类型范围大的变量
自动类型转换底层原理:
a存八位;b占32位,把a直接放在后面,前方补0;
/**
* 自动类型转换
*/
public class TypeDemo {
public static void main(String[] args) {
byte a = 20;
int b =a;
}
}
自动类型转换由小到大的顺序:
byte-->short(char)-->int-->long-->float-->double
char ch ='a';
int chq = ch;//97
System.out.println(ch+"and"+chq);//aand97
2.表达式的自动类型转换
表达式中,小范围类型会自动转换成当前较大范围类型再运算
byte、short、char-->int-->long-->float-->double
注意:
- 结果由最高类型决定
- 表达式中,byte、short、char直接转换为int参与运算
//面试题:计算中,byte直接当int,预防结果值过大
byte op=10;
byte opp=20;
// byte ropp = op+opp;
byte ropp = (byte) (op+opp);
int ropp2 = op+opp;
3.强制类型转换
大范围变量强行赋给小范围变量,有丢失精度风险;
/**
* 强制类型转换
*/
public class TypeDemo3 {
public static void main(String[] args) {
int a=5;
byte b = (byte) a;
int c = 1500;
byte d = (byte) c;
System.out.println(c+"and"+d);//1500 and -36
double c1 = 1500.2699;
int d1 = (int) c1;
System.out.println(c1+"and"+d1);//1500.2699 and 1500
}
}
强制类型转换底层原理:
| 整数: | 把后面的位数强行转给小范围变量; |
|---|---|
| 小数: | 直接截断小数后位数,转成整数; |
四、运算符
1.基本运算符
/**
* 基本加减乘除
*/
public class OperatorDemo1 {
public static void main(String[] args) {
int a=9;
int b=5;
System.out.println(a + b);
System.out.println(a - b);
System.out.println(a * b);
System.out.println(a / b);//1
System.out.println(a*1.0 / b);//1.8
System.out.println(3 / 2);//1
System.out.println(3*1.0 / 2);//1.5;该方法用来取小数
System.out.println(3 / 2*1.0);//1.0;
System.out.println(a % b);//余数:4
}
}
2.数值拆分
/**
* 基本数据拆分
*/
public class OperatorDemo2 {
public static void main(String[] args) {
int a=987;
int b,c,d;
b=a % 10;
c=a / 10 % 10 ;
d=a/100;
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
}
3.连接符
/**
* 连接符
* ''字符在一定条件下参与运算
* “ ”字符串不参与运算
*/
public class OperatorDemo3 {
public static void main(String[] args) {
int a =5;
char b ='爱';
String china ="中国";
System.out.println(a+b+china);//29238中国
System.out.println(a+""+b+""+china);//5爱中国
System.out.println(5+a);//10
System.out.println("abc"+a);//abc5
System.out.println("afasdf"+'a'+a);//afasdfa5
System.out.println("afasdf"+('a'+a));//afasdf102
System.out.println('a'+a);//5+97=102
System.out.println('a'+""+a);//a5
System.out.println(a+""+'a');//5a
}
}
4.自增自减运算符
- 注意:
- ++和--,可以放在变量的前方和后方
- 只能操作变量,不能操作字面量
- 不是单独使用,前后意义不同
- 变量前,先+1,再运算
- 变量后,先运算,再+1
/**
* 自增自减
*/
public class OperatorDemo4 {
public static void main(String[] args) {
int a =5;
int rs = a++;//5
System.out.println(a+"and"+rs);//6and5
int b =5;
int rs2 =++b;//6
System.out.println(b+"and"+rs2);
}
}
4.1.自增自减扩展(面试)
System.out.println("===========扩展(面试)============");
int k=5;//6 7 6
int p=5;//4 3 4
// kp = 5 + 7 - 4 + 4 - 7 + 4 + 2
int kp = k++ + ++k - --p + p-- - k-- + ++p + 2;
System.out.println(k);//6
System.out.println(p);//4
System.out.println(kp);//11
5、赋值运算符
/**
* 赋值运算符
*/
int a=10;
int b=100;
a=a+b;
a+=b;
byte c=10;
byte d=20;
c= (byte) (c+d);
c+=d;//byte
6.关系运算符
7.逻辑运算符
/**
* 逻辑运算符
*/
int a=10;
int b=100;
System.out.println(a>20&b>100);//false
System.out.println(a<10&b<100);//false
System.out.println(a<=10|b<100);//true
System.out.println(!true);//false
System.out.println(false^true);//true
System.out.println(false^false);//false
/**
* 短路逻辑运算符
*/
System.out.println(a<10 && ++b>100);//false
System.out.println(a==10 && ++b>100);//true b101
System.out.println(a==10 || ++b>100);//true b101 前方正确,后方不执行
System.out.println(a<10 || ++b>100);//true b102
8.三元运算符
格式:条件表达式?值1:值2;
执行流程:计算表达式结果;true,返回值1;否则值2.
/**
* 三元运算符
*/
double score = 95.5;
String rs = score >=60 ? "通过":"挂科";
System.out.println(rs);
//输出较大的值
int a=5;
int b=15;
int c = a>b ? a:b;
System.out.println("较大值:"+c);
//三个值取最大
int q=5;
int w=15;
int e=88;
int tempMax = q>w ? q:w;
int Max = tempMax>e ? tempMax:e;
System.out.println("Max:"+Max);
//简化上式
Max = q>w ? q>e ? q:e :w>e ? w:e;
// Max = q>w ? (q>e ? q:e) :(w>e ? w:e);
System.out.println("Max:"+Max);
9.运算符:优先级
/**
* 运算符:优先级
*/
System.out.println(10>3 || 10>3 && 10<3 );//true.先执行&&,false || true
System.out.println((10>3 || 10>3) && 10<3 );//false.先执行(),true && false
10.API:键盘录入
- API(Application Programming Interface)应用程序编程接口:
- Java功能代码;
- API文档(技术使用说明书);
- API文档下载
/**
* 键盘输入API:Scanner
*/
Scanner scanner = new Scanner(System.in);
System.out.println("请输入您的姓名:");
//scanner.next();等待用户输入完成
String name = scanner.next();
System.out.println("请输入您的年龄:");
int age = scanner.nextInt();
System.out.println("身份录入成功姓名:"+name+" 年龄:"+age);
RecordDate:2021/08/06
五、程序流程控制
1.流程控制语句
控制程序的执行流程;
| 顺序结构 | 分支结构 | 循环结构 |
|---|---|---|
| 默认 | if | for |
| switch | while | |
| do while |
2.分支结构
2.1 if分支(适合区间匹配)
三种格式:
public class IfDemo {
public static void main(String[] args) {
/**
* If判断
*/
//心跳60-100正常,否则要检查
int heartBeat=30;
if (heartBeat<60 || heartBeat>100){
System.out.println("心跳数据是:"+heartBeat+"需要检查");
}
//转账
double money=100;
if (money<=100){
System.out.println("转账成功");
}else {
System.out.println("余额不足");
}
//打分 >90 A+;>=80 A;>=70 B;>=60 C;<60 D
int score = 98;
if (score>90){
System.out.println("成绩为:A+");
}else if (score>=80){
System.out.println("成绩为:A");
}else if (score>=70){
System.out.println("成绩为:B");
}else if (score>=60){
System.out.println("成绩为:C");
}else {
System.out.println("成绩为:D");
}
}
}
2.2 switch分支(适合值匹配)
-
switch注意事项:
-
表达式类型只能是byte、short、int、char,
-
JDK5开始支持枚举,
-
JDK7开始支持String;
-
不支持double、float、long;
-
case值不能重复,只能是字面量,不能是变量;
-
不能忘记写break,会出现穿透现象
-
穿透现象:没有遇到break,执行下一case,直到遇到break;
-
可以解决代码冗余,多个条件有相同结果可以共用
-
switch(weekDay){ case "周一": case "周二": case "周三": System.out.println("打牌"); break; default: System.out.println("沉迷打牌,不可自拔(^_^)"); }
-
-
2.3执行流程:
- 执行表达式,结果与case匹配
- 匹配成功哪条就执行,遇到break跳出
- case值都不匹配,执行default
public class SwitchDemo {
public static void main(String[] args) {
/**
* Switc
*/
//胡适之日记展示
String weekDay = "周四";
switch(weekDay){
case "周一":
System.out.println("读书");
break;
case "周二":
System.out.println("打牌");
break;
case "周三":
System.out.println("打牌");
break;
case "周四":
System.out.println("胡适之啊,胡适之,你怎么如此堕落,要努力读书啊!");
break;
case "周五":
System.out.println("打牌");
break;
default:
System.out.println("沉迷打牌,不可自拔(^_^)");
}
}
}
3.循环结构
3.1 for循环
/**
* 求1-10的奇数和
*/
int sum = 0;
for (int i = 0; i < 10; i++) {
if (i%2 ==1 ){
sum+=i;
}
}
for (int i = 0; i < 10; i+=2) {
sum+=i;
}
/**
* 水仙花数:三位数 and 个十百的数字立方和等于原数
*/
for (int i = 100; i <999 ; i++) {
int a = i/100;
int b = i/10%10;
int c = i%10;
int count = 0;
if ((a*a*a + b*b*b + c*c*c) == i){
count++;
System.out.println(i+"\t");
}
System.out.println("水仙花个数:"+count);
}
}
3.2 while循环
while和for功能上一样;
使用:直到循环多少次,用for;不知道多少次,while
/**
* 纸张折叠多少次可以超过珠穆朗玛峰
*/
double peakHeight=8848868;
double paperThickness=0.1;
int count=0;
//while内条件成立才可以执行,完成后跳出
while (paperThickness < peakHeight){
paperThickness *= 2;
count++;
}
System.out.println(count+"次,可以超过珠峰");
//for代替
//for (;paperThickness < peakHeight;){
3.3 do while循环
特点:一定会先执行一次循环体
/**
* 抢票:
* 先抢一次,再判断
*/
int i=0;
do {
System.out.println("没抢到票,继续");
i++;
}while (i<3);
System.out.println("抢票成功");
3.4总结
- 三种循环区别:
- for和while,先判断,后执行
- do while 先执行一次,再判断
- for和while区别:
- 执行流程一样
- 已知循环次数,用for;不知,while
- for中,变量只能在循环内用;while结束后可以继续用;
4.死循环、循环嵌套
4.1死循环
/**
* 死循环
*
*/
/* for (;;){
System.out.println("死循环");
}*/
//经典死循环
while(true){
System.out.println("死循环");
}
/* do {
System.out.println("死循环");
}while (true){
System.out.println("死循环");
}*/
/**
* 死循环:
* 用户不断输入密码,直到正确
*/
int PassWord = 520;
Scanner scanner = new Scanner(System.in);
while (true){
System.out.println("请输入正确密码:");
int pass = scanner.nextInt();
if (pass == PassWord){
System.out.println("登录成功");
break;
}else {
System.out.println("密码错误");
}
}
4.2循环嵌套
- 循环嵌套
- 循环包循环
- 特点
- 外部循环一次,内部循环全部
/**
* 嵌套循环
* 五天,每天吃三顿饭
*/
for (int i = 1; i <=5; i++) {
System.out.println("第"+i+"天,开始");
for (int j = 1; j <=3; j++) {
System.out.println("吃第"+j+"顿饭");
}
System.out.println("=============第"+i+"天,结束==================");
}
5.跳转控制语句
- break:跳出并结束当前所在循环
- continue:跳出当前循环的当次执行,进入下一次循环
- 只能在循环中使用
/**
* 准备写5天日记,第三天后不写了,
*/
for (int i = 1; i < 6; i++) {
System.out.println(i+"天日记");
if (i==3){
break;
}
}
System.out.println("========================");
/**
* 准备写5天日记,第三天忘了,之后继续
*/
for (int i = 1; i < 6; i++) {
if (i==3){
continue;
}
System.out.println("第"+i+"天日记");
}
6.随机数Random类
- Random生成随机数特点:
- random.nextInt(n);生成一个0到n-1的随机数
- Random生成区间随机数技巧:
- 减加法:random.nextInt(10)+1;生成1-10
/**
* 猜字游戏
*/
public class RandomDemo1 {
public static void main(String[] args) {
Random random = new Random();
Scanner scanner = new Scanner(System.in);
//random.nextInt(n);生成一个0到n-1的随机数
int i = random.nextInt(100)+1;
System.out.println(i);
while (true){
System.out.println("请输入1-100间的数字:");
int s = scanner.nextInt();
if (s<0||s>100){
System.out.println("请输入1-100范围的数字");
}else if (s==i){
System.out.println("恭喜你猜中了");
break;
}else if (s<i){
System.out.println("猜的数略小");
}else if (s>i){
System.out.println("猜的数略大");
}else {
System.out.println("请输入正确的数字");
}
}
}
}
RecordDate:2021/08/07
六、数组
1.数组概述
1.1数组是什么?
数组是用来存储一批同种类型数据的内存区域(容器)
1.2示例
int[] arr={21,58,698,88};
String[] names={"张三","lisi","王wu"};
1.3关键点
- 定义数组存储数据;
- 操作数组元素;
- 解决问题;
- 数组内存原理
- 数组使用注意点
2.数组定义方式
2.1静态初始化数组
定义数组时直接赋值:
数据类型[] 数组名 = new 数组数据类型[]{元素1,元素2}
int[] ages = new int[]{15,24,28};
//简化格式
数据类型[] 数组名 ={元素1,元素2}
int[] ages = {15,24,28};
/**
* 静态初始化数组
*/
double[] money = new double[]{15.6,65.3,99.9};
double[] money2 ={15.6,65.3,99.9};
int[] ages = new int[]{5,6,5,6};
int[] ages2 = {5,6,5,6};
String[] names = new String[]{"张三","lisi","王wu"};
String[] names2 = {"张三","lisi","王wu"};
2.2 数组基本原理
- 内存中开辟数组变量区域ages;
- new出来对象存储信息,是一片连续区域,地址给变量名;
- 引用类型里面存地址;基本类型里面存数据
| [I@4c873330 | [ | I | @4c873330 |
|---|---|---|---|
| 示例解释 | 代表数组 | 代表int型 | 表示地址,后接十六进制首地址 |
2.3 数组访问
- 数组访问
- 数组名[索引]
- 数组长度属性:length
- 数组最大索引:length-1;元素最少有一个,索引位0
- 注意事项
- 数据类型[] 数组名 也可以是 数据类型 数组名[]
- 数组存放数据类型固定
- 数组一旦定义,程序执行过程中,长度、类型固定
2.4 动态初始化数组
-
定义数组时,只确定元素类型和长度,之后存值
-
格式:
int[] sums= new int[9];
-
原理:
- 类似静态初始化,变量名存入首地址,长度确定,每个地址存入默认值,如:int型默认存0;引用类型null
-
静动两者使用场景区别:
- 静态,知道具体值;
- 动态,知道数据量,不知道具体值
-
静动分开使用
3.数组遍历
3.1求和 求最大值
int[] arr={21,58,698,88};
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
//求和
int sum=0;
for (int i = 0; i < arr.length; i++) {
sum+=arr[i];
}
System.out.println(sum);
//求最大值
//建议用第一个元素作为参照
int Max=arr[0];
for (int i = 1; i < arr.length; i++) {
if (Max<arr[i]){
Max = arr[i];
}
}
System.out.println("最大值:"+Max);
3.2猜字游戏
public class ArrayDemo2 {
public static void main(String[] args) {
/**
* 猜字游戏:
* 随机生成1-20间5个数(不论是否重复)
* 猜字:输出第一次出现该树的位置,全部输出结束
*/
Random random = new Random();
int[] Numbers = new int[5];
int count = 0;
for (int i = 0; i < 5; i++) {
Numbers[i] = random.nextInt(20)+1;
}
// System.out.println(Arrays.toString(Numbers));
Scanner scanner = new Scanner(System.in);
OUT:
while (count<5){
boolean a = false;
System.out.println("请输入1-20的数字");
int test = scanner.nextInt();
if (test<0 || test>20){
System.out.println("数字范围输入错误");
continue ;
}
for (int i = 0; i < 5; i++) {
if (Numbers[i] == test){
System.out.println("运气不错,猜中了,数字"+Numbers[i]+"第一次出现在"+i+"位置");
Numbers[i]=99;
count++;
System.out.println("还差"+(5-count)+"个,就都猜中了!");
a=true;
//break OUT;//结束了整个循环,游戏结束
}
}
if (!a){
System.out.println("没猜中,再来一次吧");
}
}
System.out.println("恭喜,猜中全部数字,本局结束。");
}
}
3.3 随机排名
/**
* 随机排位:
* 录入五个人,给他们随机排序
*/
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要给几个人排序");
int length=scanner.nextInt();
int[] users = new int[length];
int count = 0;
for (int i = 0; i < users.length; i++) {
System.out.println("请输入第"+i+"个人的ID");
users[i]=scanner.nextInt();
}
Random random = new Random();
for (int i = 0; i < users.length; i++) {
int temp=random.nextInt(users.length);
int tempUser = users[0];
users[0]=users[temp];
users[temp]=tempUser;
}
System.out.println(Arrays.toString(users));
4.数组排序
- 数组排序
- 对数组中元素,按从小到大或从大到小排序
- 排序技术
- 冒泡排序
- 选择排序
- 快速
- 插入
- 数组搜索相关技术
- 二分搜素
- 分块查找
- 哈希表查找
4.1 冒泡排序:
- 思想:
- 从头开始,两两排序,大小互换
- 每轮把当前数组最大元素,存到数组末尾
- 实现步骤:
- 外部循环轮次(数组长度-1)
- 内部循环轮次,每轮次依次往后比较几个位置(数组长度-i-1)
- 前大于后,二者交换
/**
* 冒泡排序
*/
int[] arr={6,8,7,3};
//定义控制循环比较轮次
for (int i = 0; i < arr.length-1; i++) {
//0轮,比较3次,j=0 1 2
//1轮,比较2次,j=0 1
//2轮,比较1次,j=0
for (int j = 0; j < arr.length-i-1 ; j++) {
if (arr[j]>arr[j+1]){
int temp = arr[j+1];
arr[j+1]=arr[j];
arr[j]=temp;
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
System.out.println(Arrays.toString(arr));
5.数组的内存图
5.1 Java内存分配
- 栈(数据方法短暂地运行区域)
- 栈内存:方法运行时进入的内存;变量也在这里
- 堆(数据停留较长时间的区域)
- new出来东西,在此内存开辟空间并产生地址
- 空间大,将new出大量数据存入
- 方法区
- 字节码文件加载时进入的内存
- 本地方法栈
- 寄存器
5.2 Java内存分配流程:
- 编译后运行,到main方法,放入方法区;
- 方法,开辟栈内存空间,基本数据类型存入值,引用类型存入变量名;
- new在栈内存中开辟空间,生成地址,存入数值,;
- 根据从右向左运行的原理,将new生成的地址赋给变量;
- 根据地址和空间内索引,赋值;
5.3两个变量指向同一数组
原理同上;将arr的地址赋给arr2;
/**
* 两个变量指向同一数组
*/
int[] arr={6,8,7,3};
int[] arr2=arr;
System.out.println(arr);//[I@1b6d3586
System.out.println(arr2);//[I@1b6d3586
arr2[0]=1;
System.out.println(arr[0]);//1
6.数组使用常见问题
| 问题 | 释义 | 原因 |
|---|---|---|
| ArrayIndexOutOfBoundsException | 数组索引越界异常 | 访问元素位置超过最大索引 |
| NullPointerException | 空指针异常 | 数组变量中没存地址,null,访问 |
RecordDate:2021/08/07
七、方法
1.方法概述
| 方法 | 一种语法结构,把一段代码封装成一个功能,方便重复使用; |
|---|---|
| 好处: | 提高代码复用性; 让程序逻辑更清晰; |
2.方法定义格式
完整格式:
修饰符 返回值类型 方法名(形参列表){
方法体代码(需要执行的功能代码)
return 返回值;
}
2.1 方法常见问题
- 编写顺序无所谓;
- 方法间是平级,不能嵌套定义;
- void,无需return;其他设置类型需return相应类型;
- 方法不调用,不执行,严格匹配参数情况;
- 有返回值的方法,调用可以选择定义变量接收结果;
2.2 求和
/**
* 计算1-n的和
* @param n
* @return
*/
public static int sum(int n){
int sum = 0;
for (int i = 0; i < n; i++) {
sum+=i;
}
return sum;
}
2.3 判断奇数偶数
/**
* 判断是奇数还是偶数
* @param n
* @return
*/
public static int X(int n){
int x;
if (n%2==0){
x=2;
System.out.println(n+"是偶数");
}else {
x=1;
System.out.println(n+"是偶数");
}
return x;
}
2.4 求最值
/**
* 求数组最大值
* @param array
* @return
*/
public static int MaxArray(int[] array){
int max = array[0];
for (int i = 1; i <array.length ; i++) {
if (max<array[i]){
max = array[i];
}
}
return max;
}
3.方法的内存原理
3.1 方法的调用流程,内存图解
- 方法,没有被调用的时候,在方法区的字节码文件中存放;
- 方法,被调用时候,需要进入到栈内存中运行;
- 方法不调用时,存放在方法区;
- 方法main运行时,在栈内存开辟空间;
- 再调用add方法,再开辟空间,将传入值存在开辟的空间;
- 方法使用结束,从栈内存退栈;
4.方法的参数传递机制
4.1基本类型传递机制
- Java参数传递机制:值传递(不同方法内,只是数值相同);
- 注意:
| 实参: | 方法内部定义变量 |
|---|---|
| 形参: | 定义方法时,()中所声明的参数 |
/**
* 基本类型,值传递
*/
public static void main(String[] args) {
int a=10;
chang(a);
System.out.println(a);//10
}
public static int chang(int a){
System.out.println(a);//10
a=50;
System.out.println(a);//50
return a;
}
4.2 引用类型传递
引用类型:传递地址,修改地址空间内的数据;
/**
* 引用类型,地址传递
*/
public static void main(String[] args) {
int[] a={10,2,6};
chang(a);
System.out.println(a[0]);//50
}
public static void chang(int[] a){
System.out.println(a[0]);//10
a[0]=50;
System.out.println(a[0]);//50
}
4.3 打印整形数组内容
/**
* 引用类型,地址传递
*/
public static void main(String[] args) {
int[] a={10,2,6};
print(a);
}
public static void print(int[] a){
if (a!=null && a.length>0){
System.out.println("该数组内容为:"+ Arrays.toString(a));
}
}
4.4 数组中查询指定元素的索引
/**
* 数组中查询指定元素的索引
*/
public static void main(String[] args) {
int[] a={10,2,6};
int b = 10;
System.out.println(select(a, b));
}
public static int select(int[] a,int b){
if (a!=null && a.length>0){
for (int i = 0; i < a.length; i++) {
if (a[i] == b){
return i;
}
}
}
return -1;
}
4.5 比较任意两个数组是否一样
/**
* 比较任意两个数组是否一样
*/
public static void main(String[] args) {
int[] a={10,2,6};
int[] b={10,2,6};
if (compare(a,b)){
System.out.println("两个数组相等");
}else {
System.out.println("两个数组不等");
}
}
public static boolean compare(int[] a,int[] b){
if (a.length != b.length){
return false;
}
for (int i = 0; i < a.length; i++) {
if (a[i] != b[i]){
return false;
}
}
return true;
}
5.方法重载
-
方法重载:
- 同一个类中,多个名称相同,但形参列表不同,形参类型不同,这些方法就是方法重载;
-
重载识别技巧:
-
同一个类,方法名称相同,形参列表不同,就是重载(无关修饰符,返回值类型)
-
形参列表不同:形参个数,类型、顺序不同,不关心形参名称
/** * 方法重载 * @param args */ public static void main(String[] args) { fire(); fire("老A"); fire("老A",666); Integer a = 666; System.out.println("嗨嗨"+fire("老A",a)); } public static void fire(){ fire("老E"); } public static void fire(String location){ fire(location,1); } public static void fire(String location,int number){ System.out.println("给"+location+"的老铁送"+number+"个大火箭!"); } //无法以返回值类型区分,可以以形参类型区分 public static int fire(String location,Integer number){ System.out.println("给"+location+"的老铁送"+number+"个大火箭!"); return 666; }
-
6.单独使用return关键字
| 关键字 | 作用 |
|---|---|
| return: | 可以立即跳出并结束当前方法的执行 |
| break: | 跳出并结束当前所在的循环 |
| continue: | 跳过当次循环,进入下一次; |
RecordDate:2021/08/08
八、面向对象
1.面向对象概述
- 更加符合现实生活;
- 面对问题,寻找合适的工具,调用合理的方法,解决问题;
- 复杂问题,梳理流程,组合工具和使用方法,灵活应对复杂局面,更具拓展性和维护性;
- 没有合适的工具,就自己设计,自己用;
- 自己设计的工具,足够范用,足够安全稳定,可以开源给别人用;
2.设计对象及注意事项
| 描述 | |
|---|---|
| 类(设计图): | 对象共同特征的描述; |
| 对象: | 真实存在的具体实例; |
| 结论: | java中,必须先设计类,才能创建对象并使用 |
2.1类注意事项:
首字母大写,满足驼峰式;
一个java文件可以定义多个class,只可以有一个public修饰,且必须是用来修饰文件名;
3.内存机制
3.1两个对象内存图
- 运行
Test.class,main方法存入方法区,在栈内存开辟main方法空间; - 执行第一行,创建变量
Car c1存入栈内存; - 执行
new Car(),在堆内存中开辟对象空间,对象属性值为默认,最后存入成员方法引用地址(指向方法区方法); - 将空间地址赋给变量
c1; - 根据
c1地址和属性索引给c1赋值(原理同数组赋值类似); c1.start()是c1通过地址找到对象,再找到成员方法引用地址,找到start方法,start()方法提取到栈内存运行;- 由于
start()方法是通过c1路径调用,内部属性值访问c1;
3.2 两个对象指向同一个内存图
- 基本原理与上方相同;
- 将s1地址赋给s2,s2修改了堆内存中数据,s1和s2输出值都变化;
Student s = new Student();
s.name="英语龙";
Student s1 = s;
s1.name = "三角箭";
3.3 垃圾回收装置
当堆内存中对象,没有被任何变量引用(指向)时,就会被判定为内存中垃圾;
Java存在自动垃圾回收器,会定期清理;
4.构造器
4.1 构造器作用
- 定义在类中,可以用于初始化一个类的对象,并返回对象地址;
new Car();中的Car()便是构造器
4.2 构造器格式
修饰符 类名(){
//无参构造器
}
修饰符 类名(形参列表){
//有参构造器
}
public Car(String name, double price) {
this.name = name;
this.price = price;
System.out.println("有参构造器被调用");
}
public Car() {
System.out.println("无参构造器被调用");
}
4.3调用构造器得到对象格式
类 变量名 = new 构造器;
Car c = new Car();
Car car1 = new Car("胜利冲锋", 19.9);
4.4 构造器的分类和作用
| 构造器 | 表现 | 注意 |
|---|---|---|
| 无参构造器(默认存在): | 初始化对象时,成员变量数据均采用默认值; | 一旦有参构造器创建;再用无参构造器需要自行创建 |
| 有参构造器: | 初始化对象时,同时可以接收参数为对象赋值; |
4.5 this关键词,代表当前对象地址
可以出现在构造器中,方法中;
4.6 this关键字作用
可以用于指定访问当前对象的成员变量、方法;
public Car(String name, double price) {
this.name = name;
this.price = price;
System.out.println("有参构造器被调用");
}
public void goWith(String name) {
System.out.println(this.name+"和"+name+"比赛!");
}
Car car = new Car();
car.name = "旋风冲锋";
car.goWith("飓风音速");
//旋风冲锋和飓风音速比赛!
5.封装
- 面向对象三大特征:封装、继承、多态;
- 封装:如何正确设计对象的属性和方法;解决属性和方法属于哪个对象问题;
- **封装原则:**对象代表什么,就得封装对应数据,并提供数据对应的行为;
- 基本思想:决定属性和行为的归属问题,行为是用来处理对应属性的;人吃饭睡觉;门开关;票地址价格买票
5.1 进行更好的封装
- 对成员变量使用private(私有隐藏)关键字修饰
- private修饰成员只能在当前类中访问;
- 为每个成员提供配套的public修饰的getter和setter方法,
- 方便取值和赋值
public class Student {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
if (age>0 && age<200){
this.age = age;
}else {
System.out.println("不符合符合规范");
}
}
}
Student s = new Student();
s.setAge(-99);
System.out.println(s.getAge());
s.setAge(99);
System.out.println(s.getAge());
不符合符合规范
0
99
5.2 特征的含义
所谓特征,指java的基本特点,即使毫无意义,通常也要满足这样的设计要求来编写;
6.标准 JavaBean
JavaBean:实体类,其对象用于在程序中封装数据;
6.1成员变量和局部变量区别
| 区别 | 成员变量 | 局部变量 |
|---|---|---|
| 类中位置 | 类中,方法外 | 常见方法内 |
| 初始化值 | 有默认值,无需初始化 | 需初始化 |
| 内存位置 | 堆 | 栈 |
| 生命周期 | 随对象创建存在,随对象消失 | 随方法存在 |
| 作用域 | 所归属的大括号内 |
RecordDate:2021/08/09
九、API
- API(ApplicationProgrammingInterface,应用程序编程接口)
- java写好的功能代码,可直接调用
- 有相应的技术文档
十、String类型
定义的变量用于存储字符串,同时提供了很多操作字符串的功能;
1 String类特点
- String常被称为不可变字符串类型,对象创建后不可更改;
- String每次修改都是产生并指向新的字符串对象;
- 通过“+”连接几个字符串,原来字符串没有改变,只是可以通过拼接控制输出效果
2 创建字符串对象
/**
* 创建String的常用方法
*/
public class StringDemo {
public static void main(String[] args) {
String name = "wind";
System.out.println(name);
String s1 = new String();
System.out.println(s1);//空白
String s2 = new String("岩峰");
System.out.println(s2);
char[] c = {'a','v','i'};
String s3 = new String(c);
System.out.println(s3);//avi
byte[] b ={97,98,99};
String s4 = new String(b);
System.out.println(s4);//abc
}
}
3 方法间区别
以“ ”方式给出字符串对象,在字符串常量池中存储,相同内容只存一份;
new对象,产生新对象,放在堆内存中;
String name = "wind";
String name2 = "wind";
System.out.println(name==name2);//true
char[] c = {'a','v','i'};
String s3 = new String(c);
String s33 = new String(c);
System.out.println(s3==s33);//false
3.1 String常量原理
- 在堆内存的字符串常量池创建,将地址赋给变量名;
- 相同内容不会在常量池中创建新的;
3.2 new String对象原理
每次new都会在堆内存中创建新的对象,赋予常量的地址不同;
4 常见面试题
String s2 = new String("wind");//创建两个对象;一个常量,一个new;指向堆内存
String s22 = "wind";//创建0个对象,原因是常量池中有wind了,上方创建,指向常量池
System.out.println(s2==s22);//false
String s1 = "abc";//常量池
String s2 = "ab";
String s3 = s2 + "c";//运算,指向堆内存
System.out.println(s1==s3);//false
String s1 = "abc";//常量池
String s2 = "a"+"b"+"c";//java存在编译优化机制,直接转成"abc";字面量是确定的会优化
//变量编译阶段不知道值,字面量可以
System.out.println(s1==s2);//true
5 String类型常用API
//自定义一个字符串
//注意这里字符串最后是空,下面会用到
String str = new String("13,2df+fk,05s,kd, ");
//这里我们假设使用","作为分隔符
String[] newStr = str.split(",");
//[13, 2df+fk, 05s, kd, ]
System.out.println(Arrays.toString(newStr));
//两个分隔符的情况 ","和"+"作为分隔符
//同样还是返回字符串数组类型的数据
//这里我实验之后发现给"+"加上"[]"之后才可以通过编译,得到正确的结果
String[] newStr2 = str.split(",|[+]");
//[13, 2df, fk, 05s, kd, ]
System.out.println(Arrays.toString(newStr2));
————————————————
String name = "wind";
String passWord = "qq123456";
Scanner scanner = new Scanner(System.in);
System.out.println("输入姓名:");
String name1 = scanner.next();
System.out.println("输入密码:");
String pass = scanner.next();
/**
* equals 比较字符串是否一致
*/
if (name.equals(name1) && passWord.equals(pass)){
System.out.println("正确!");
}else {
System.out.println("错误!");
}
String nameTwo = "WinD";
String passTwo= "Qq123456";
/**
* equalsIgnoreCase 忽略大小写,比较字符串是否一致
*/
if (name.equalsIgnoreCase(nameTwo) && passWord.equalsIgnoreCase(passTwo)){
System.out.println("正确");
}
5.1 验证码
/**
* 验证码:
*/
public class StringTest1 {
public static void main(String[] args) {
String datas = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890";
int dataLength = datas.length();
Random random = new Random();
String code = "";
for (int i = 0; i < 5; i++) {
int index = random.nextInt(dataLength);
char c = datas.charAt(index);
code += c;
}
System.out.println("输出字符串:"+code);
}
}
5.2 屏蔽手机号
/**
* 屏蔽部分手机号码
*/
public class StringTest2 {
public static void main(String[] args) {
String phone = "132xxxx9xxx";
//截取前三位
String before = phone.substring(0,3);
//截取后四位
String after = phone.substring(7);
String phone2 = before+"****"+after;
System.out.println(phone2);
}
}
十一、ArrayList
- 代表集合类,集合是一种容器,与数组类似,不同的是集合大小不固定;
- 非常适合元素个数不确定,进行增删业务场景
- 功能丰富
- 通过创建ArrayList对象得到一个集合容器;
- ArrayList是集合一种,支持索引
ArrayList list = new ArrayList();
list.add(1);
list.add("张燕");
list.add("凛冬");
list.add(188);
list.add(1999);
//[1, 张燕, 凛冬, 188, 1999]
System.out.println(list);
//指定位置插入,后面后移
list.add(2,"小火火");
//[1, 张燕, 小火火, 凛冬, 188, 1999]
System.out.println(list);
1. 泛型概述
| ArrayList | 泛型类,编译阶段约束集合对象只能操作某种数据类型; |
|---|---|
| ArrayList | 只能操作字符串类型; |
| ArrayList | 只能操作整数类型; |
| 注意: | 集合中只能存储引用类型,不支持基本数据类型 |
2.集合案例
2.1 遍历并删除元素值
删除两种方案:
1.应对补位,i--;
2.倒序删除;
/**
* 遍历并删除元素值:
* 低于80的值删除;
*/
public class ArrayListDemo1 {
public static void main(String[] args) {
Integer[] list = {98,77,66, 89,79,50,88,100};
ArrayList<Integer> scores = new ArrayList<>();
//同<泛型>添加
Collections.addAll(scores, list);
//方案一:i--补位
/* for (int i = 0; i < scores.size(); i++) {
if (scores.get(i) < 80){
scores.remove(i);
i--;//删除成功后,后退一步,再次判断,应对补位
}
}*/
//方案二:倒排,删除后补位不影响
for (int i = scores.size()-1; i >0 ; i--) {
if (scores.get(i) < 80){
scores.remove(i);
}
}
System.out.println(scores.toString());
}
}
2.2 存储自定义型对象:
集合中存储的是对象的地址!
/**
* 存储自定义型对象:
* 存入三部电影信息,并输出
*/
public class ArrayListDemo2 {
public static void main(String[] args) {
Movie m1 = new Movie("斗破苍穹",6.6,"消炎");
Movie m2 = new Movie("武动乾坤",6.6,"林东");
Movie m3 = new Movie("大主宰",7.6,"木木");
ArrayList<Movie> movies = new ArrayList<>();
//存了三个地址
movies.add(m1);
movies.add(m2);
movies.add(m3);
for (int i = 0; i < movies.size(); i++) {
Movie movie = movies.get(i);
System.out.println(movie.getName()+movie.getScore()+movie.getActor());
System.out.println("----------------------------");
}
}
}
2.3 元素搜索
/**
* 元素搜索:
*/
public class ArrayListDemo3 {
public static void main(String[] args) {
ArrayList<Student> students = new ArrayList<>();
students.add(new Student("1","赵日天",18,"炸天一班"));
students.add(new Student("2","叶良辰",38,"炸天一班"));
students.add(new Student("3","荀彧",88,"炸天二班"));
students.add(new Student("4","李白",28,"炸天二班"));
System.out.println("全部学生信息");
System.out.println("-------------------------");
for (int i = 0; i < students.size(); i++) {
Student s = students.get(i);
System.out.println(s.getStudyNumber()+"\t"+s.getName()+"\t"+s.getAge()+"\t"+s.getClassName());
System.out.println("-------------------------");
}
Scanner scanner = new Scanner(System.in);
while (true){
System.out.println("输入要搜索学生信息的Id:");
String id = scanner.next();
//根据学号搜索信息
Student ss = getStudentById(students, id);
if (ss==null || ss.equals("")){
System.out.println("查无此人");
System.out.println("-------------------------");
}else {
System.out.println("-------查询到的信息如下--------");
System.out.println(ss.getStudyNumber()+"\t"+ss.getName()+"\t"+ss.getAge()+"\t"+ss.getClassName());
System.out.println("-------------------------");
}
}
}
/**
* 根据学号查询信息:
* @param students 全体学生信息集合
* @param id
*/
private static Student getStudentById(ArrayList<Student> students,String id) {
for (int i = 0; i < students.size(); i++) {
Student student = students.get(i);
if (student.getStudyNumber().equals(id)){
return student;
}
}
return null;
}
}
RecordDate:2021/08/10