Java进阶历程
初级Java后端开发程序员
- 基础知识:掌握Java语言基础,包括语法、数据结构、算法等。
- 框架理解:了解并能使用常见的Java后端框架(如Spring Boot)进行简单的CRUD操作。
- 工具使用:熟悉常用的开发工具(如IDE、Git)和调试技巧。
- 问题解决:在指导下能够解决简单的编码和配置问题。
- 经验:通常具有0-2年的相关工作经验,或是刚从学校毕业的新手。
- 团队合作:能够在团队中完成分配的任务,但可能需要较多指导。
中级Java后端开发程序员
- 深入框架:对所使用的Java后端框架有深入理解,能够独立完成模块的开发和调试。
- 数据库设计:熟悉数据库设计原则,能够设计合理的数据库表结构和索引。
- 性能优化:了解基本的性能优化手段,如SQL优化、缓存策略等。
- 问题解决:能够独立解决中等难度的技术问题,具备一定的故障排查能力。
- 代码质量:注重代码的可读性、可维护性和可扩展性,遵循良好的编程规范。
- 项目管理:可能参与项目管理,如任务分配、进度跟踪等。
- 经验:具有2-5年的相关工作经验。
高级Java后端开发程序员
- 系统架构:能够设计并构建复杂、高性能的分布式系统架构。
- 深入技术:对Java及其生态系统有深入理解,包括JVM、并发编程、网络通信等。
- 技术选型:能够根据业务需求和技术趋势进行技术选型,评估并引入新技术。
- 性能调优:具备高级的性能调优能力,能够解决复杂的性能瓶颈问题。
- 领导力:能够指导初级和中级开发人员,参与团队的技术决策和规划。
- 问题解决:能够迅速定位并解决复杂的技术难题,具备创新思维。
- 经验:具有5年以上的相关工作经验,可能有多年的大型项目开发经验。
需要注意的是,这些标准并不是绝对的,不同公司和项目对开发人员的要求可能有所不同。此外,随着技术的不断发展和个人经验的积累,开发人员的技能水平也会不断提升。因此,持续学习和实践是成为一名优秀Java后端开发程序员的关键。
环境配置
●Java的安装及环境变量的配置
●idea的安装及破解
一、Java基础
1、 Java背景知识
1.1 Java语言的历史
Java是哪家公司的产品?
Java是美国Sun(Stanford University Network,斯坦福大学网络公司)公司在1995年推出的一门计算机高级编程语言。但是在2009年是Sun公司被Oracle(甲骨文)公司给收购了,所以目前Java语言是Oracle公司所有产品。
Java名称的来历?
早期这门语言的名字其实不叫Java,当时称为Oak(橡树的意思),为什么叫橡树呢?原因是因为Sun公司的门口种了很多橡树,但是后来由于商标注册时,Oak商标已经其他公司注册了,所以后面改名为Java了。那么有人好奇为什么叫Java呢?Java是印度的一个岛屿,上面盛产咖啡,可能是因为他们公司的程序员喜欢喝咖啡,所以就改名为Java了。
Java的创始人是谁?
行业普遍认可的Java的创始人 是詹姆斯●高斯林,被称为Java之父
1.2 Java能做什么
Java能做的事情非常多,它可以做桌面应用的开发、企业互联网应用开发、移动应用开发、服务器系统开发、大数据开发、游戏开发等等。目前Java的主流开发方向是使用Java开发企业级互联网应用程序(很多公司的OA系统,客户关系管理系统,包括传智播客使用教学实施管理系统都是用Java语言开发的)
1.3 Java的技术体系
技术体系,就是Java为了满足不同的应用场景提供了不同的技术版本,主要有三个版本。
-
Java SE(Java Standard Edition):叫做标准版,它是后面两个版本的基础,也就是学习后面两个版本必须先学习JavaSE。我们基础班现阶段学习的就是这个版本中的技术。
-
Java EE(Java Enterprise Edition): 叫做企业版,它是为企业级应用开发提供的一套解决方案。在后面就业班课程中主要学习这个版本中的技术。
-
Java ME(Java Micro Edition):叫做小型版,它为开发移动设备的应用提供了一套解决方案。目前已经不被市场认可(淘汰),取而代之的是基于Android系统的应用开发。
小结
1.Java是什么?
答:Java是一门高级编程语言
2.Java是哪家公司的产品?
答:Java以前是Sun公司的产品,现在Java是属于Oracle公司的产品
3.Java之父是谁?
答:詹姆斯●高斯林
4.Java主流的开发方向是什么?
答:企业级互联网应用开发
5.Java技术平台有哪些?
答:JavaSE(标准版)、JavaEE(企业版)、JavaME(小型版)
2、 Java快速入门
2.1 JDK下载和安装
-
JDK的下载
这是JDK下载的官方网址 Java Downloads | Oracle
-
JDK的安装
双击安装包,点击下一步即可安装。
安装验证
1.第一步:在JDK的bin目录,地址栏输入cmd,回车
输入完cmd回车后,会出现一个黑窗口,专业说法叫命令行窗口
2.第二步:在命令行窗口中输入 javac -version
回车,然后输入java -version
回车
如果出现下面红色框框的提示正确版本号,和我们安装的JDK版本号一致,就说明JDK安装成功
2.2 cmd常见命令
javac -version
java -version
D: 切换指定盘符
cls 清理命令行窗口
dir 查看该路径下的目录
cd.. 回退至上一级
cd [指定路径]
2.3 Java程序运行的三个流程
- 编写代码:任何一个文本编辑器都可以些代码,如Windows系统自带的记事本
- 编译代码:将人能看懂的源代码(.java文件)转换为Java虚拟机能够执行的字节码文件(.class文件)
- 运行代码:将字节码文件交给Java虚拟机执行
编写第一个Java入门程序
按照下面提供的步骤,一步一步的完成第一个Java入门程序的编写、编译和执行。
第一步:新建一个后缀为.java的文本文件HelloWorld.java
,用记事本编写代码如下。
public class HelloWorld { public static void main(String[] args) { System.out.println(" HelloWorld "); } }
第二步:进入HelloWorld.java
文件所在目录,在地址栏输入cmd回车,即可在此处打开命令行窗口。
编译:在命令行窗口输入编译命令javac HelloWorld
完成编译,编译后会生成一个HelloWorld.class
文件。
第三步:再接着输入java HelloWorld
就可以运行了。
tips:Java文件的名称必须和代码的类名称一致
2.4 jdk的组成
首先,写好的Java程序会通过javac工具编译成class类型的字节码文件,之后java工具会将字节码文件放到虚拟机中运行,而虚拟机在运行程序的时候会调用类库中的写好的一些程序。
2.5 Java的跨平台
含义:一次编译,处处可用
实现:sun公司根据不同的操作系统都提供了相应运行Java程序的虚拟机,想在什么平台上跑安装对应的虚拟机就可以实现程序的运行。
2.6 环境变量的配置
path 环境变量用来记录程序的路径,以便在任意目录下启动该程序
JAVA_HOME 便于程序后续版本的维护
2.7 菜鸟教程
2.8 Java全栈知识体系
3、IntelliJ IDEA
3.1 debug工具的使用
4、基础语法
4.1 注释
单行注释
多行注释
文档注释
4.2 字面量
●整数
●小数
●字符 不能是空也不能包含两个以上的字符
特殊字符
●\t 一个tab位
●\n 换行
●字符串 可以是任意形式的字符
●布尔
4.3 变量
变量的定义
变量是一个内存中的空间,用来存储数据的容器
变量的优点
编写代码更灵活,管理代码更方便(鞭活,管方)
变量的特点
代码中的数据可以被替换
变量的注意事项
●变量必须先声明而后才能被使用
●变量的生效范围从定义开始到反大括号结束“}”,且同一范围同一个变量名只能使用一次
●定义变量的时候可以不赋值,但在使用时,必须赋值
●什么类型的变量就只能存储什么类型的数据
4.4 关键字
Java自己用的词,有特殊含义;
特点:全部小写
- 普通关键字:abstract、assert、boolean、break、byte、case、catch、char、class、continue、default、do、double、else、enum、extends、final、finally、float、for、if、implements、import、int、interface、instanceof、long、native、new、package、private、protected、public、return、short、static、strictfp、super、switch、synchronized、this、throw、throws、transient、try、void、volatile、while。
- 特殊直接量:true、false、null。
- 保留字:goto、const。
4.5 标识符
定义:变量或者函数(方法)的名字
特点:标识符由字母、数字、下划线、$、组成
不能以数字、特殊符号开头;不能是关键字、
非标识符例子:#itcorporate、main
标识符例子:中国
5、数据的存储规则
5.1 计算机的存储规则
●数据在计算机底层都是以二进制形式存储;
●十进制转二进制 除二取余
●二进制转十进制 从右至左 值乘以二的次方减一
●计算机存储数据的最小单位是字节byte(简:B),一个字节等于八个二进制位bit(简:b)
5.2 ASCII码表
ASCII码 - 基本ASCII码和扩展ASCII码,中文最全ASCII码对照表0~255 (asciim.cn)
'A'对应的 ASCII码值为 65
'a'对应的 ASCII码值为 97
'0'对应的 ASCII码值为 48
5.3 进制转换
二进制转八进制
01100001=》001 100 001 =》141;
三位的二进制数取值范围0-7;
二进制转十六进制
01100001=》0110 0001 = 》61;
11111010 =》1111 1010 = 》FA;
四位的二进制数取值范围0-15;0-9,A,B,C,D,E,F;
6、数据类型
6.1 数据类型
数据类型基本分为两大类:基本数据类型和引用数据类型
基本数据类型又分为4类8种
随意写一个整数字面量默认数据类型为int,如果想让其为long类型在字面量最后添加L/l;
随意写一个小数字面量默认数据类型为double,如果想让其为float类型在字面量最后添加F/f
6.2 引用数据类型
String代表字符串类型的变量,可以存储字符串类型的字面量
7、类型转换(Type Conversion)
7.1 原因
●存在某种类型的变量需转换成另一种类型的变量
●不同类型的变量进行算数运算
7.2 自动类型转换
7.2.1 定义
类型范围小的变量可以直接赋值给类型范围大的变量
7.2.2 执行原理
byte a = 12; 0000 1100
int b = a; 0000 0000 0000 1100
7.2.3 表达式的自动类型转换
●在表达式中,小范围类型的变量,会自动转换成表达式中较大范围的类型,再进行运算。 byte、short、char --> int --> long -->double
float -->double
注意事项:
●表达式的最终结果类型由表达式中的最高类型决定
●在表达式中,byte、short、char是直接转换成int类型参与运算的
●
float
和long
之间没有直接的隐式转换(自动类型转换)
float f = 1.0f;
long l = 2L;
double result = (double)f + (double)l; // 正确
7.3 强制类型转换(Casting)
7.3.1 原因
类型范围大的变量直接赋值给类型范围小的变量会报错
数据类型 变量2 = (数据类型)变量1 数据 快捷键:ALT+ENTER
7.3.2 底层原理
int i = 1500; 00000000 00000000 00000101 11011100
byte j = (byte)i; //-36 11011100
注意事项:
强制类型转换可能造成数据的丢失
浮点型强转成整型,直接丢掉小数部分,保留整数部分返回
8、运算符(operate)
8.1 运算符包括
+、-、*、/、%
8.2 除法的注意事项
如果两个整数做除法,结果一定是整数,因为最高类型为整数
8.3 +的特殊使用
当表达式中有字符串的时候,加号运算符起到连接符的作用
技巧:能算则算,不能算则连在一起
8.4 自增自减运算符
作用:
对当前变量值进行+1、-1操作
注意:
自增自减运算符只能操作变量不能操作字面量
先自增与后自增:
单独使用
先自增与后自增没有区别
非单独使用
自增在前,先对变量进行自增,再使用变量;
自增在后,先使用变量,再对变量进行自增;
8.5 扩展得赋值运算符
●扩展的赋值运算符隐含了强制类型转换
8.6 逻辑运算符
或、且、非、异或(exclusive or)、短路与、短路或
异或:前后结果不相同的时候返回true,前后结果相同返回false
8.7 三元运算符
格式:
表达式 ?值1:值2;
执行流程:
表达式会输出一个结果(true/false),当结果为true时,结果会输出值1;当结果是false时,结果会输出值2;
8.8 运算符的优先级
1 | () |
2 | !、-、++、-- 【一元减号】 |
3 | *、/、% |
4 | +、- 【二元减号】 |
5 | << 、>> 、>>> |
6 | < 、<= 、> 、>= 、instanceof |
7 | == 、!= |
8 | & |
9 | ^ |
10 | | |
11 | && |
12 | || |
13 | ? : |
14 | = 、+=、 *=、 /= 、%= 、&= |
15 |
9、API(Application Programming Interface:应用程序编程接口)
9.1 Scanner
Scanner
是Java中的一个类,用于从各种输入源(如文件、字符串或输入流)读取数据。
System.in
是 Java 中的一个标准输入流,它通常代表从键盘读取的数据。
System
是Java的一个内置类内置类:又称核心类、系统类,是Java编程语言的核心部分,不需要额外的库或者依赖来协助程序的运行,如:String、Math、Thread、ArrayList
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户的年龄");
int age = sc.nextInt();
System.out.println("请输入用户的姓名");
String name = sc.next();
System.out.println("欢迎您!!");
}
}
9.2 Random
生成随机数
import java.util.Random;
public static void main(String[] args) {
//目标:掌握生成随机数的使用
//生成36-51的随机数
Random r = new Random();
/**
* 50-36+1=16,
*/
for (int i = 0;i<10;i++) {
int random = r.nextInt(16)+36;
System.out.println(random);
}
}
运行结果:
45 37 42 49 50 40 51 49 45 42
猜数字
import java.util.Random;
import java.util.Scanner;
public static void main(String[] args) {
//目标:猜数字
//生成1-100的随机数
Random r = new Random();
int luckyNumber = r.nextInt(100)+1;
//进行猜数环节
Scanner sc = new Scanner(System.in);
while(true){
System.out.println("请猜一个数:");
int guessNumber = sc.nextInt();
if(guessNumber>luckyNumber){
System.out.println("您猜的数字过大!");
}else if (guessNumber<luckyNumber){
System.out.println("您猜的数字过小!");
}else {
System.out.println("恭喜您,猜中的幸运数字!");
break;
}
}
}
10、程序流程控制
10.1 三种经典执行顺序
程序中最经典的三种执行顺序
●顺序结构
●循环结构 控制某段代码重复执行
●分支结构 根据条件,选择对应的代码进行执行
10.2 分支结构之if分支
if分支根据条件(真或假)来决定执行某段代码
if分支的三种形式:
if(条件表达式){
代码;
};
if(条件表达式){
代码1;
}else{
代码2;
}
if(条件表达式1){
代码1;
}else if(条件表达式2){
代码2;
}else if(条件表达式3){
代码3;
}
...
else{
代码n;
}
10.3 分支结构之switch分支
switch分支是通过比较值来决定执行那条分支
switch(表达式){
case 1:
执行代码1;
break;
case 2:
执行代码2;
break;
...
case n-1:
执行代码n-1;
break;
default:
执行代码n;
}
switch使用的注意事项
●表达式值的类型只能是byte、short、int、char,jdk5之后支持枚举,jdk7之后支持String,不能是long、float、double
int已经足够大了,因此不需要long;
double和float会引起古典型精度运算的缺失
●case中的值不能重复且只能是字面量不能是变量
重复的case值会使程序不知道走哪条分支
case值如果是变量也有可能造成程序不知道往哪条分支上走
●不需要穿透时,跳转关键字break不能忘
QUESTION:古典型如何实现精度计算---BigDecimal
分支小结
●if的功能比switch强大
●if适合做空间匹配,switch适合做值匹配
10.4 循环结构之for循环
for循环的作用:减少代码的重复编写,灵活控制程序的执行
package com.corporation.loop;
public class forLoop {
public static void main(String[] args) {
//目标:掌握for循环的书写格式,以及执行流程
//打印多个HelloWorld
/**
* 执行流程:
* 当程序识别到for之后,会先执行循环的初始语句int i = 0;
* 在对循环条件进行判断,判断0<5,
* 满足条件后,执行代码块中的语句
* 代码块中的语句执行完后,执行循环结束语
* 进入下一次循环条件的判断
*/
for(int i = 0;i<5;i++){
System.out.println("HelloWorld!");
}
}
}
执行结果:
HelloWorld!
HelloWorld!
HelloWorld!
HelloWorld!
HelloWorld!
10.5 循环结构之while循环
初始化语句;
while(循环条件){
循环体语句{被重复的代码};
迭代语句;
}
package com.corporation.loop;
public class whileLoop {
public static void main(String[] args) {
//目标:掌握while循环的书写格式,以及执行流程
//打印多个HelloWorld
int i = 0;
while (i<5){
System.out.println("HelloWorld!");
i++;
}
}
}
while循环案例--珠峰高度
public static void main(String[] args) {
//目标:计算珠穆朗玛峰的高度
//已知珠穆朗玛峰的高度为8848.86米,8848860mm;
//一张纸的厚度为0.1mm
int count = 0;
double thickNess = 0.1;
while (thickNess<8848860){
thickNess *= 2;
count++;
}
thickNess /=1000;
System.out.println("共折叠"+count+"次!");
System.out.println("纸张的厚度最终为"+thickNess+"米");
}
运行结果:
共折叠27次!
纸张的厚度最终为13421.7728米
10.6 循环结构之do-while循环
初始化语句;
do{
循环体语句;
迭代语句;
}while(循环条件);
public class whileLoop {
public static void main(String[] args) {
//目标:掌握do-while循环的使用
int i = 0;
do {
System.out.println("HelloWorld!");
i++;
}while (i<5);
}
}
运行结果:
HelloWorld!
HelloWorld!
HelloWorld!
HelloWorld!
HelloWorld!
循环小结
1.for循环与while循环功能上没有本质的区别,for循环能做的,while循环也能做。
2.行业规范:知道循环几次的用for;不知道循环几次的用while。
3.do-while循环适用于先执行后判断的需求
10.7 死循环的三种形式
形式一:
for(;;){
System.out.println("Hello World");
}
形式二:
while(true){
System.out.println("Hello World");
}
形式三:
do {
System.out.println("Hello World");
}while (true);
10.8 循环嵌套(nestedLoop)
循环嵌套的特点:外部循环每执行一次,内部循环就会执行完一轮
//目标:掌握循环嵌套的使用
for (int i = 1;i<=2;i++){
for (int j = 1;j<=3;j++){
System.out.println("第"+i+"天的第"+j+"次问候!");
}
System.out.println("----------------");
}
运行结果:
第1天的第1次问候!
第1天的第2次问候!
第1天的第3次问候!
----------------
第2天的第1次问候!
第2天的第2次问候!
第2天的第3次问候!
----------------
10.9 跳转关键字
break:跳出当前执行的循环/分支;
continue:跳出当前当次执行的循环;
attention:
●break只能用于结束当前所在循环或者分支
●continue只能用在循环里
11、数组
数组的定义:
数组就是一个容器,用来存储一批同种类型的数据
分类:
静态初始化数组
动态初始化数组
11.1 静态初始化数组
静态初始化数组就是在定义数组的时候直接给数组赋值
数组定义的格式
完整定义格式:
数据类型【】 数组名 = new 数据类型【】{元素1,元素2,元素3....};
简化格式:
数据类型【】 数组名 = {元素1,元素2,元素3....};
●数组名和【】可以互换
数组在计算机中的基本原理 ![](https://img-blog.csdnimg.cn/direct/f6f23eda19214192a6280e0a62c543d2.png)
11.2 数组的访问
数组名【索引】
获取数组的长度(元素个数):数组名.length
数组的最大索引:数组名.length-1(数组中有数据)
11.3 数组的遍历
对数组进行逐个访问
public static void main(String[] args) {
int[] arr = {11,22,33};
for(int i = 0;i< arr.length;i++){
System.out.println(arr[i]);
}
//对数组进行遍历的快捷方式
// 数组名.fori
}
案例-营业额求和
public static void main(String[] args) {
//5名员工的销售额为16、26、36、6、100,求该门店的总销售额
int[] turnOver = {16,26,36,6,100};
int sumTurnOver = 0;
for (int i = 0; i < turnOver.length; i++) {
sumTurnOver += turnOver[i];
}
System.out.println(sumTurnOver);
}
11.4 动态初始化数组
数组定义的时候只声明数组的大小,不对数组进行具体的赋值
动态初始化数组的定义格式:
数据类型【】 数组名 = new 数据类型 【数组大小】;
int [] age = new int [3];
动态初始化数组定义好后,索引处元素的值为默认值。
动态初始化数组元素的默认值:
●byte、int、short、char、long的默认值都为0
●double、float的默认值为0.0
●String的默认值为null
●Boolean的默认值为false
各自的应用场景
静态初始化数组:已知元素的个数和具体的值 (星期)
动态初始化数组:已知元素个数但不知道具体的值 (评委打分)
案例- 评委打分
public static void main(String[] args) {
//歌唱比赛,六个评委,评委依次打分,最后求出评委的最终得分
//评委一开始的得分并不知道,采用动态初始化数组对评委的得分进行存储
Double [] scorings = new Double[6];
Scanner sc = new Scanner(System.in);
for (int i = 0; i < scorings.length; i++) {
System.out.println("请输入第"+(i+1)+"位评委的打分:");
scorings[i] = sc.nextDouble();
}
Double sumScore = 0.0;
for (int i = 0; i < scorings.length; i++) {
sumScore +=scorings[i];
}
Double averageScore = sumScore/scorings.length;
System.out.println("六位评委的平均分为:"+averageScore);
//对结果进行格式化
DecimalFormat formatAverageScore = new DecimalFormat("#.##");
System.out.println("六位评委的平均分为:"+formatAverageScore.format(averageScore)+"(保留两位小数10)");
}
运行结果:
请输入第1位评委的打分:
9
请输入第2位评委的打分:
8
请输入第3位评委的打分:
7
请输入第4位评委的打分:
6
请输入第5位评委的打分:
6
请输入第6位评委的打分:
5
六位评委的平均分为:6.833333333333333
六位评委的平均分为:6.83(保留两位小数10)
11.5 Java程序在计算机底层的执行原理
首先,Java程序会将字节码文件送到jvm虚拟机中运行,程序便于运行文件,将虚拟机分成了五个部分(方法区、栈、堆、本地方法栈、寄存器)
方法区:字节码文件首先会加载到方法区中,main方法也会先加载到方法区中,
栈内存:方法运行时所进入的区域,变量也在这里
堆内存:new出来的东西会在这块内存中开辟空间并产生地址
attention:
当数组变量没有指向具体的数组的时候,打印的时候会打印出null,并且不能对该数组变量进行访问,会报NullPointerException(空指针异常)。
案例1-数据反转
public static void main(String[] args) {
//数据反转
//1.首先定义一个需要反转的数组
int[] arr = {11,22,33,44,55};
int temp = 0;//用来反转数据的临时变量
//2.定义两个变量用来作为数组的前后索引
int i = 0;
int j = arr.length-1;
int k = 0;//while 循环的循环变量
while (i!=j){
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
System.out.println("----1----");
for (int l = 0; l < arr.length; l++) {
if(l< (arr.length-1)){
System.out.print(arr[l]+",");
}else {
System.out.println(arr[l]);
}
}
System.out.println("----2-----");
}
运行结果:
----1----
55,44,33,22,11
----2-----
数据反转的教学写法
for (int i = 0, j = arr.length-1;i<j;i++,j--) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
案例2- 随机排序
public static void main(String[] args) {
//随机排序
//1、录入一组数据来记录每个员工的编号
int[] staffNumber = {11,22,33,44,55};
Random r = new Random();
int temp = 0;
for (int i = 0; i < staffNumber.length; i++) {
//生成一个该数组索引内的数来指定当前遍历到的数将要与那个索引位置的数进行交换
int rNumber = r.nextInt(staffNumber.length);
//将遍历到的数放到临时变量中
temp = staffNumber[i];
//将要进行交换的的数放到之前遍历到的数中
staffNumber[i] = staffNumber[rNumber];
//将临时变量中的数放大需要交换的数中
staffNumber[rNumber] = temp;
}
for (int i = 0; i < staffNumber.length; i++) {
System.out.println(staffNumber[i]+",");
}
}
12、方法
12.1 方法的定义
方法是一种语法结构,它是把一段代码封装成一个功能,以便重复调用
修饰符 返回值类型 方法名(形参列表) {
方法体代码(需要执行的功能代码)
return 返回值;
}
形参
●方法的形参不能赋值
●形参之间用逗号隔开
方法的优点
●提高代码的复用性,提高开发效率,使程序逻辑更清晰
12.2 方法的形参
●方法在类中的位置通常不影响其功能或执行,但方法不能相互嵌套。
●方法的返回类型必须与返回值相匹配
●方法中,程序执行到return后停止,其后的代码为无效代码。
●方法不调用不执行,调用方法时,传入的参数必须与形参列表中参数的类型相匹配
●调用有返回值的方法,①可以用变量接收②直接输出调用方法的值③直接调用
●调用无返回值的方法,①只能直接调用
案例-奇偶判断
public static void main(String[] args) {
//奇偶判断
Scanner sc = new Scanner(System.in);
System.out.println("请输入您要判断的整数:");
Boolean end = isOdd(sc.nextInt());
if(end){
System.out.println("该数为奇数!");
}else {
System.out.println("该数为偶数!");
}
}
public static Boolean isOdd (int number){
return number %2 !=0;
}
运行结果:
请输入您要判断的整数:
34
该数为偶数!
12.3 方法的执行原理
●方法在调用的时候,是进入到栈内存中运行。栈的特点:先进后出
12.4Java的参数传递机制
12.4.1 基本类型的参数传递
Java的参数传递机制都是:值传递
●所谓的值传递:指的是在传输实参给方法的形参的时候,传输的是实参变量中存储的值的副本。
●实参:在方法内部定义的变量
●形参:方法定义时(小括号)“()”中声明的参数
public static void main(String[] args) {
//参数传递
int a = 10; //实参
change(a);
}
public static void change(int a){
}
public static void main(String[] args) {
//参数传递
int a = 10;
change(10); //将实参中的10传递给change方法形参中的a
}
public static void change(int a){
}
案例-值传递
public static void main(String[] args) {
//值传递
int a = 10;
change(a);
System.out.println("main:"+a);
}
public static void change(int a){
System.out.println("change1:"+a);
a = 20; //将形参a中的值修改成20
System.out.println("change2:"+a);
}
运行结果:
change1:10
change2:20
main:10
12.4.2 引用类型的参数传递
引用类型的参数传递也遵循值传递的这一特点,但是引用类型的参数传输存储的地址值。
public class Test {
public static void main(String[] args) {
//引用类型的参数传递
int arr[] = {11,22,33};
change(arr);
System.out.println("main:"+arr[0]);
}
public static void change(int[] arr){
System.out.println("change1:"+arr[0]);
arr[0] = 20;
System.out.println("change2:"+arr[0]);
}
}
运行结果:
change1:11
change2:20
main:20
案例-数组的传递
public static void main(String[] args) {
//数组的打印
int arr1[] = {11, 22, 33};
printArray(arr1);
int arr2[] = null;
printArray(arr2);
int arr3[] = {}; //空数组也是可以打印的,因为形参中传递的是一个数组地址
printArray(arr3);
}
public static void printArray(int[] arr) {
//防止空指针异常
if (arr==null){
System.out.println(arr);
return;
}
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
/* if (i != (arr.length-1)) {
System.out.print(arr[i] + ",");
} else {
System.out.print(arr[i] );
}*/
System.out.print(i== arr.length-1?arr[i]:arr[i]+",");
}
System.out.println("]");
}
运行结果:
[11,22,33]
null
[]
案例-数组的比较
public static void main(String[] args) {
//两个数组比较是否相同
int arr1[] = {11, 22, 33};
int arr2[] = {11, 22, 33};
Boolean isIndentical = compareArray(arr1, arr2);
System.out.println(isIndentical);
}
public static Boolean compareArray(int[] arr1, int[] arr2) {
//判断两个数组是不是都为空
if (arr1 == null && arr2 == null) {
return true;
}
//判断两个数组中的是不是有一个为空
if (arr1 == null || arr2 == null) {
return false;
}
//判断两个数组的长度是否相等
if (arr1.length != arr2.length) {
return false;
}
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
运行结果:
true
Process finished with exit code 0
12.5 方法的重载(overload)
一个类中,出现多个方法名称相同,形参列表不同,这些方法就被称为方法重载。
attention:
●修饰符、返回值类型对方法是否重载没有影响
●形参列表不同:形参的个数、类型、顺序不同,不关心形参的名称
12.6 return在方法中的单独使用
●return;用在无返回值的方法中,立即跳出并结束当前方法的执行。
public static void main(String[] args) {
//return 关键字的使用
System.out.println("Program starting...");
division(10, 0);
System.out.println("Program ending...");
}
public static void division(int a, int b) {
if (b == 0) {
System.out.println("除数为零!");
return;
}
int c = a / b;
System.out.println(c);
}
运行结果:
除数为零!
基础案例
案例一:机票订购
public class OrderTicket {
enum CabinType{
First_CLASS,
ECONOMY_CLASS
}
public static void main(String[] args) {
/*
创建一个方法,
这个方法需要接受三个参数:原始票价、淡旺季、客舱类型
5-10为旺季 旺季头等舱9折;经济舱8折
11-4为淡季 淡季头等舱7折;经济舱6折
*/
priceCount(100, 12, "头等舱");
}
public static void priceCount(double ticketFare, int season, String type) {
if (season >= 5 && season <= 10) {
switch (type) {
case "头等舱":
ticketFare *= 0.9;
break;
case "经济舱":
ticketFare *= 0.8;
}
} else {
switch (type) {
case "头等舱":
ticketFare *= 0.7;
break;
case "经济舱":
ticketFare *= 0.6;
}
}
System.out.println(ticketFare);
}
}
案例二:生成验证码
public static void main(String[] args) {
//生成验证码
String captcha = generateCaptcha(20);
System.out.println(captcha);
}
public static String generateCaptcha(int n) {
Random r = new Random();
//3、定义一个字符串来接受生成的数
String captcha = "";
int type;//接着写
//1、定义一个for循环来确定需要生成的验证码位数
for (int i = 1; i <= n; i++) {
//2、为每个位置生成一个字面量
//思路:0代表生成数字;1代表生成大写字母;2代表生成小写字母
switch (r.nextInt(3)) {
case 0:
captcha += r.nextInt(10);
break;
case 1:
char cr1 = (char) (r.nextInt(26) + 65);
captcha += cr1;
break;
case 2:
char cr2 = (char) (r.nextInt(26) + 97);
captcha += cr2;
break;
}
}
return captcha;
}
案例三:评委打分
public static void main(String[] args) {
//评委打分
Double averageScore = score(7);
System.out.println(averageScore);
}
public static double score(int n) {
Scanner sc = new Scanner(System.in);
double judgeScore[]= new double[n];
double sum = 0;
//n 指将会产生的评委数
for (int i = 0; i <= judgeScore.length-1; i++) {
System.out.println("请第"+(i+1)+"位裁判进行评分!");
judgeScore[i] = sc.nextDouble();
sum +=judgeScore[i];
}
double max = judgeScore[0];
double min = judgeScore[0];
double averageScore = 1.0*(sum-max-min)/(n-2);
return averageScore;
}
案例四:密码加密
public static void main(String[] args) {
//密码加密
System.out.println("---------Program starting---------");
// 1997
passWordEncryption(1987);
System.out.println("\n");
System.out.println("=========Program ending===========");
}
public static void passWordEncryption(int secret) {
if (secret == 0) {
System.out.println("密码为空!");
return;
}
//1、首先对密码进行拆分,拆分后放到一个数组中
int numbers[] = split(secret);
//numbers[] ={1,9,8,7};
//2、 对数组中的每个数进行加密操作,+5 %10 反转
for (int i = 0; i < numbers.length; i++) {
//i = 0 1 2 3
numbers[i] = (numbers[i] + 5) % 10;
}
//numbers[] = {6,4,3,2}
//3、用一个方法来实现反转
reverse(numbers);
for (int i = 0; i < numbers.length; i++) {
System.out.print(numbers[i]);
}
}
//数字反转
public static void reverse(int[] numbers) {
//[6,4,3,2]
int temp = 0;
for (int i = 0, j = numbers.length-1; i <j ; i++,j--) {
temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
}
}
//数字拆分
public static int[] split(int secret) {
//1987
int numbers[] =new int[4];
numbers[0] = secret/1000;
numbers[1] = (secret/100)%10;
numbers[2] = (secret/10)%10;
numbers[3] = secret%10;
return numbers;
}
案例五:数据拷贝
public static void main(String[] args) {
//数组拷贝
System.out.println("---------Program starting---------");
int arr1[] = {11, 22, 33};
int arr2[] = copyArray(arr1);
printArray(arr2);
System.out.println("\n");
System.out.println("=========Program ending===========");
}
//数组的拷贝
public static int[] copyArray(int[] arr1) {
//1、创建一个动态数组用于接收需要拷贝的数组
int[] arr2 = new int[arr1.length];
//2、将数组中每个索引所对应的数拷贝到新数组中
for (int i = 0; i < arr1.length; i++) {
arr2[i] = arr1[i];
}
return arr2;
}
//打印数组
public static void printArray(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length ; i++) {
System.out.print(i== arr.length-1?arr[i]:arr[i]+",");
}
System.out.println("]");
}
tips:
int[] arr2 = arr;
这只是把原数组的地址拷贝到新的数组变量中,并没有生成新的数组
案例六:抢红包
public static void main(String[] args) {
//抢红包
System.out.println("---------Program starting---------");
//1、定义一个数组用来存放红包,红包的金额为66,88,99,520,9999
int[] redEnvelop = {66, 88, 99, 520, 9999};
drawAResEnvelop(redEnvelop);
System.out.println("=========Program ending===========");
}
public static void drawAResEnvelop(int[] redEnvelop) {
//调用Scanner来触发抢红包
Scanner sc = new Scanner(System.in);
Random r = new Random();
for (int i = 0; i < redEnvelop.length; i++) {
System.out.println("请输入任意数字来触发抢红包:");
sc.next();
while(true) {
//红包是随机的,用Random来表示抢到的任意索引处的红包
int index = r.nextInt(redEnvelop.length);
if (redEnvelop[index] != 0) {
System.out.println("您抢到的红包是" + redEnvelop[index]);
redEnvelop[index] = 0;
break;
}
}
}
}
案例七:找素数
//找素数
System.out.println("---------Program starting---------");
// 找到101-200中间的素数
//首先创建一个数组,用来记录素数
int prime[] = new int[25];
int index = 0;
//创建一个for循环,来产生101-200的数
for (int i = 101; i <= 200; i++) {
Boolean isPrime = true;
for (int j = 2; j * j <= i; j++) {
if (i % j == 0) {
isPrime = false;
break;
}
}
if (isPrime) {/*代码中不要出现isPrime == true这种现象,将其改为isprime*/
prime[index++] = i;
}
}
printArray(prime);
System.out.println("=========Program ending===========");
}
案例八:双色球
public class Test {
public static void main(String[] args) {
//双色球
/*
双色球一共七个号码前六个为红色号码,最后一个为蓝色号码
6+1 1000万 6+0 500万
5+1 3000 5+0 200
4+1 200 4+0 10
3+1 10 2+1 5
1+1 5 0+1 5
红色球不能重复
*/
int[] userNumbers = userSelectNumber();
printArray(userNumbers);
int[] luckyNumbers = luckyNumber();
printArray(luckyNumbers);
ifWinePrize(userNumbers,luckyNumbers);
}
//打印数组
public static void printArray(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length ; i++) {
System.out.print(i== arr.length-1?arr[i]:arr[i]+",");
}
System.out.println("]");
}
//1、用户挑选号码
public static int[] userSelectNumber() {
//2、定义一个长度为7的动态数组用来存储将要存放的用户号码
int[] numbers = new int[7];
//扫描器用来接受用户的号码
Scanner sc = new Scanner(System.in);
//3、遍历数组的前六位来对用户的红色号码进行录入
for (int i = 0; i < numbers.length-1; i++) {
//i = 0 1 2 3 4 5
while (true) {
//4、让用户输入选定的号码
System.out.println("请您输入第" + (i + 1) + "个号码!");
int number = sc.nextInt();
//对这个号码进行判断,判断是不是属于红球号码;判断是不是与元素组中的数重复
if (number < 1 || number > 33) {
System.out.println("您输入的这个号码有误!");
} else {
if (isRepeat(number, numbers)) {
System.out.println("您输入的号码已重复!");
} else {
numbers[i] = number;
break;
}
}
}
}
while (true) {
System.out.println("请输入最后一个蓝色号码:");
int number = sc.nextInt();
if(number<1||number>16){
System.out.println("您输入的号码有误!");
}else {
numbers[6] = number;
break;
}
}
return numbers;
}
//判断某个数在不在某个数组中
public static Boolean isRepeat(int number, int[] numbers) {
//numbers = [23,44,14,0,0,0]
//number = 14;
for (int i = 0; i < numbers.length; i++) {
//0 1 2 3 4 5
if(numbers[i]==0){
break;
}
if(numbers[i]==number){
return true;
}
}
return false;
}
//2、随机生成一组中奖号码
public static int[] luckyNumber(){
//1.定义一个数组用来存放幸运号码
int[] luckyNumbers = new int[7];
//创建一个生成随机数的对象
Random r = new Random();
//2.遍历数组中的前六个位置放入红色号码
for (int i = 0; i < luckyNumbers.length - 1; i++) {
while (true) {
int number = r.nextInt(33)+1;
if(!isRepeat(number,luckyNumbers)){
luckyNumbers[i] = number;
break;
}
}
}
luckyNumbers[6] = r.nextInt(16) +1;
return luckyNumbers;
}
//3、判断中奖情况
public static void ifWinePrize(int[] userNumbers,int[] luckyNumbers){
// 11,22,12,13,14,15,8
// 11,3,12,23,31,24,7
int sameRedNumber = 0;
int blueNumber = 0;
for (int i = 0; i < userNumbers.length - 1; i++) {
for (int j = 0; j < luckyNumbers.length-1; j++) {
if (userNumbers[i]==luckyNumbers[j]){
sameRedNumber++;
break;
}
}
}
blueNumber = userNumbers[6]==luckyNumbers[6]?1:0;
if(sameRedNumber==6&&blueNumber==1){
System.out.println("恭喜您中了1000万!");
}else if (sameRedNumber==6&&blueNumber==0){
System.out.println("恭喜您中了500万!");
} else if (sameRedNumber == 5 && blueNumber == 1) {
System.out.println("恭喜您中了3000元");
} else if (sameRedNumber == 5 && blueNumber == 0 || sameRedNumber == 4 && blueNumber == 1) {
System.out.println("恭喜您中了200元");
} else if (sameRedNumber == 4 && blueNumber == 0 || sameRedNumber == 3 && blueNumber == 1 || sameRedNumber == 2 && blueNumber == 1) {
System.out.println("恭喜您中了10元");
} else if (sameRedNumber == 1 && blueNumber == 1 || sameRedNumber == 0 && blueNumber == 1) {
System.out.println("恭喜您中了5元");
}else {
System.out.println("感谢您的参与!");
}
}
}
二、面向对象
1、面向对象和面向过程
public class Test {
//面向过程编程
//通过在主程序中调用每个开发的方法来处理数据
public static void main(String[] args) {
totalScore("小明",98,102);
averageScore("小明",98,102);
totalScore("小丽",102,98);
averageScore("小丽",102,98);
}
public static void totalScore(String name,double chinese,double math){
System.out.println(name+"的总分为:"+(chinese+math));
}
public static void averageScore(String name,double chinese,double math){
System.out.println(name+"的平均分为:"+(chinese+math)/2);
}
}
public class Student {
String name;
double math;
double chinese;
public void totalScore(){
System.out.println(name+"的总分为:"+(chinese+math));
}
public void averageScore(){
System.out.println(name+"的平均分为:"+(chinese+math)/2.0);
}
//tips:除以2.0方便保留小数位
}
public class Test {
//面向对象
//通过调用每个对象中自己的方法来实现对数据的处理
public static void main(String[] args) {
Student s1 = new Student();
s1.name = "小明";
s1.chinese = 50;
s1.math = 100;
s1.averageScore();
s1.totalScore();
}
}
小明的平均分为:75.0
小明的总分为:150.0
Process finished with exit code 0
2、面向对象的深入理解
2.1 面向对象的