Java基础语法

JAVA--黑马程序员 笔记

一、Java入门

1、JAVA 是一种很火的计算机语言。

2、JAVA 代码编写分三步:

  • 编写程序源码,即编写一个java文件

  • 编译:翻译文件, javac是JDK提供的编译工具,对java文件编译后会产生一个class文件,class文件即交给计算机执行的文件。Eg:javac hello.java

  • 执行:运行程序, java是JDK提供的运行工具。Eg:java hello

3、JAVA--配置环境变量

  • 下载Java安装后,仅帮助配置了`java、javac、javaw、jshell

  • 若变量不够用,需选择手动配置环境变量。标准配置方式:先配置路径不带bin的JAVA_HOME;然后再配置Path。

4、JAVA 代码中的类名一定要与文件名一致。

5、判断JAVA版本命令为:

java --version或者java -version(旧)

6、JAVA 的下载和安装

  • 通过官方网站获取JDK进行下载,http://www.oracle.com

  • 建议:安装路径不要有中文,不要有空格等一些特殊的符号。

7、JDK 的安装目录介绍:

目录名称 说明
bin 该路径下存放了JDK的各种工具命令。javac和java就放在这个目录。
conf 该路径下存放了JDK的相关配置文件。
include 该路径下存放了一些平台特定的头文件。
jmods 该路径下存放了JDK的各种模块。
legal 该路径下存放了JDK各模块的授权文档。
lib 该路径下存放了JDK工具的一些补充JAR包。

8、编译运行时常见问题:

  • 非法字符问题。Java中的符号都是英文格式的。

  • 大小写问题。Java语言对大小写敏感(区分大小写)。

  • 在系统中显示文件的扩展名,避免出现HelloWorld.java.txt文件。

  • 编译命令后的java文件名需要带文件后缀.java

  • 运行命令后的class文件名(类名)不带文件后缀.class

  • ...

9、Java 的三大平台:

JavaSE(基础)、JavaME(小型)、JavaEE(Web网站、服务器)

10、Java 用法:

桌面应用开发、企业级应用开发、移动应用开发、科学计算、大数据开发、游戏开发。

11、Java 的主要特性:

  • 面向对象

  • 安全性

  • 多线程

  • 简单易用

  • 开源

  • 跨平台

12、Java 语言跨平台的原理:

  • Java提供了不同操作系统对应的虚拟机,即JVM(Java Virtual Machine,Java虚拟机)

注:高级语言的编译运行方式——编译型、解释型、混合型(半编译,半解释)

13、JRE和JDK:

  • JRE(Java Runtime Environment),Java运行环境,包含了JVM和Java的核心类库(Java API)。JRE:JVM、核心类库、运行工具。

  • JDK(Java Development Kit)称为Java开发工具,包含了JRE和开发工具。JDK:JVM、核心类库、开发工具。

  • JDK、JRE、JVM三者包含关系:JDK包含了JRE,JRE包含了JVM。

  • 总结:我们只需安装JDK即可,它包含了java的运行环境和虚拟机。

14、Java 开发工具:

  • javac 编译工具

  • java 运行工具

  • jdb 调试工具

  • jhat 内存分析工具

二、Java基础概念

1、注释:是对代码的解释和说明文字。Java中的注释分为三种:

  • 单行注释

// 这是单行注释文字
  • 多行注释

/*
这是多行注释文字
注意:多行注释不能嵌套使用。
*/
  • 文档注释(暂时用不到):

/**
这是多行文档注释文字
这是多行文档注释文字
*/

2、关键字:被Java赋予了特定含义的英文单词,字母全部小写,共有51个+2个保留字=53个关键字。

  • 关键字包括:48个关键字(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)、2个保留字(goto、const)、3个特殊直接量(true、false、null)。

  • 第一个关键字class:用于创建/定义一个类,类是Java项目最基本的组成单元。class后面跟随的就是这个类的名字,简称:类名。在类名后面会有一对大括号,表示这个类的内容/范围。

3、字面量-作用:告诉程序员,数据在程序中的书写格式。

  • 字面量的分类:

字面量类型 说明 程序中的写法
整数 不带小数的数字 666,-88
小数 带小数的数字 13.14,-5.21
字符 必须使用单引号,有且仅能一个字符 ‘A’,‘0’,‘我’
字符串 必须使用双引号,内容可有可无 “HelloWorld”,“黑马程序员”
布尔值 布尔值,表示真假,只有两个值:true,false true 、false
空值 一个特殊的值,空值 值是:null
  • 区分技巧:

  1. 不带小数点的数字都是整数类型的字面量。

  2. 只要带了小数点,那么就是小数类型的字面量。

  3. 只要用双引号引起来的,不管里面的内容是什么,不管里面有没有内容,都是字符串类型的字面量。

  4. 字符类型的字面量必须用单引号引起来,不管内容是什么,但是个数有且只能有一个。

  5. 字符类型的字面量只有两个值,true、false。

  6. 空类型的字面量只有一个值,null。

4、vscode中java错误 :编码GBK的不可映射字符。

  • 使用javac编译的时候编译程序首先会获取当前操作系统默认的编码格式GBK,然后JDK就把Java源文件从GBK编码格式转换为Java内部默认的unicode编码格式放入计算机内存中,再然后javac会把转换格式后的文件进行编译成class文件,最后将unicode编码格式的class文件从内存写入到磁盘当中。

  • 因vscode默认是utf-8编码格式,而编译的时候认为文件是GBK编码格式,所以出现了错误。

  • 解决方法:编译的时候使用带参数的编译指令:javac -encoding utf-8 Test.java; 或者修改vscode上的编码方式为:GBK 。

5、变量: 在程序的执行过程中,其值有可能发生改变的量(数据)。 变量就是在程序中临时存储数据的容器。但是这个容器中只能存一个值。

变量的定义格式:

  • 数据类型 变量名 = 数据值;

变量的注意事项:

  • 只能存一个值

  • 变量名不允许重复

  • 一条语句可以定义多个变量

  • 变量在使用之前必须要赋值

  • 变量的作用域范围

6、计算机的存储规则

  • 计算机中任意数据都是以二进制的形式来存储的。

  • 不同进制在代码中的表现形式:二进制(以0b开头),十进制,八进制(以0开头),十六进制(以0x开头)。

  • 不同的字符编码规则,将数据按照其中某种规则(查询码表)转换成对应的二进制编码进行存储。即text文本中数字(直接转二进制存储)、字母和汉字(皆是查询码表)。

  • 图片数据分为:黑白图、灰度图和彩色图。显示器;分辨率、像素和三原色。计算机采用光学三原色:红绿蓝RGB,范围是0~255。图片数据存储是通过每一个像素点的RGB三原色来存储的。

  • 声音数据存储是对声音的波形图进行采样再对数据二进制存储。

7、JAVA 数据类型分为:基本数据类型(int等)和引用数据类型(类、接口、数组、String等)。

注意基本数据类型和引用数据类型区别:
- 基本数据类型包括整数、浮点数、布尔和字符类型;而引用数据类型是除了基本数据类型外的其它所有类型。
- 基本数据类型在栈内存中存储的是真实的数据;而引用数据类型在栈内存中存储的是地址值,即引用是使用了其它空间中的数据。

基本数据类型有四类八种:

数据类型 关键字 内存占用 取值范围
整数 byte 1 负的2的7次方 ~ 2的7次方-1(-128~127)
  short 2 负的2的15次方 ~ 2的15次方-1(-32768~32767)
  int 4 负的2的31次方 ~ 2的31次方-1
  long 8 负的2的63次方 ~ 2的63次方-1
浮点数 float 4 1.401298e-45 ~ 3.402823e+38
  double 8 4.9000000e-324 ~ 1.797693e+308
字符 char 2 0-65535
布尔 boolean 1 true,false

基本数据类型注意事项:

  • byte类型的取值范围:​ -128 ~ 127

  • int类型的大概取值范围:​ -21亿多 ~ 21亿多

  • 整数类型和小数类型的取值范围大小关系:double > float > long > int > short > byte

  • 如果要定义一个long类型的变量,那么在数据值的后面需要加上L后缀。(大小写都可以,建议大写。)

  • 如果要定义一个float类型的变量,那么在数据值的后面需要加上F后缀。(大小写都可以)

8、标识符:给类、方法、变量等起的名字。

标识符命名规则————硬性要求

  • 必须由数字、字母、下划线_、美元符号$组成。

  • 不能以数字开头。

  • 不能是关键字(关键字都是小写),如Class可以而class不行。

  • 区分大小写的。

标识符命名规则————软性要求

  • 小驼峰命名法(适用于变量名和方法名)

  • 大驼峰命名法(适用于类名)

  • 不管起什么名字,都要做到见名知意。

  • 规范细节:尽量不要用拼音。但是一些国际通用的拼音可视为英文单词。

  • 规范细节:平时在给变量名、方法名、类名起名字的时候,不要使用下划线或美元符号。

9、键盘录入: 关于接收键盘输入的内容,使用JAVA写好的类Scanner。步骤:导包、创建对象、接收数据。

三、运算符

1、运算符和表达式

  • 运算符:就是对常量或者变量进行操作的符号。

  • 表达式:用运算符把常量或者变量连接起来的,符合Java语法的式子就是表达式。

2、运算符分类:算术运算符、自增自减运算符、赋值运算符、关系运算符、逻辑运算符、三元运算符、其它运算符

  • 算术运算符:+ - * / %

    注意:(1)代码中如果有小数直接参与计算,计算结果有可能是不精确的。 (2)整数相除结果只能得到整除,如果结果想要是小数,必须要有小数参数。 (3)取模、取余,做的也是除法运算,只不过获取的是余数。其应用场景有判断整除、奇偶性等。 (4)当连续进行+操作时,从左到右逐个执行的。 (5)字符串的+操作:当+操作中出现字符串时,此时就是字符串的连接符,会将前后的数据进行拼接,并产生一个新的字符串。 (6)字符的+操作:当+操作中出现了字符,会拿着字符到计算机内置的ASCII码表中去查对应的数字,然后再进行计算。 (7)字符串只有+操作,没有其他操作。

  • 自增自减运算符:++(自增运算符)、--(自减运算符)

    注意:(1)用方式:放在变量的前面,我们叫做先++。比如:++a。 放在变量的后面,我们叫做后++。比如:a++。 (2)不管是先++,还是后++。单独写在一行的时候,运算结果是一模一样的。 (3)a++是先用后加;++a是先加后用。

  • 赋值运算符:=、+=、-=、*=、/=、%=(扩展的赋值运算符)

    注意:扩展的赋值运算符中隐层还包含了一个强制转换。 例:a、b为byte,有a += b ;实际上相当于 a = (byte)(a + b);

  • 关系运算符(比较运算符):==、!=、>、>=、<、<=

    注意:(1)关系运算符最终的结果一定是布尔类型的。要么是true,要么是false。 (2)在写==的时候,千万不要写成=。

  • 逻辑运算符:&(逻辑与,而且)、|(逻辑或,或者)、^(逻辑异或)、!(逻辑非,取反)、短路逻辑运算符(短路与&&、短路或||)

    注意:(1)取反最好只用一个。 (2)短路与&&、短路或||,两个短路逻辑运算符具有短路效果,即:当左边的表达式能确定最终的结果,那么右边就不会参与运行了.

  • 三元运算符(又称三元表达式或者问号冒号表达式):关系表达式 ? 表达式1 :表达式2 ;

    注意:(1)三元运算符的最终结果一定要被使用,要么赋值给一个变量,要么直接打印出来。 (2)计算关系表达式的值,如果关系表达式的值为真,那么执行表达式1;否则执行表达式2。

  • 其它运算符:& |(数值中的逻辑与和或)、<<(左移)、>>(右移)、>>>(无符号右移)

3、运算符的优先级:

  • 小括号优先于所有。

4、类型转换:

隐式转换(自动类型提升):就是把一个取值范围小的数据或者变量,赋值给另一个取值范围大的变量。此时不需要我们额外写代码单独实现,是程序自动帮我们完成的。

两种提升规则:

  • 取值范围小的,和取值范围大的进行运算,小的会先提升为大的,再进行运算。

  • byte、short、char三种类型的数据在运算的时候,都会直接先提升为int,然后再进行运算。

强制转换:如果要把一个取值范围大的数据或者变量赋值给另一个取值范围小的变量。是不允许直接操作。如果一定要这么干,就需要加入强制转换。

  • 强制转换的书写格式:目标数据类型 变量名 = (目标数据类型)被强转的数据;

  • 强制转换有可能会导致数据发生错误。(数据的精度丢失)

5、原码、补码、反码

  • 计算机中的存储和计算都是以补码的形式进行的。

  • 因为补码的定义关系,一个字节的范围是-128~+127。

  • 原码:十进制数据的二进制表现形式,最左边是符号位,0为整,1为负。

  • 产生补码和反码的原因是原码计算中的弊端:利用原码进行负数计算时,结果会出错,即实际运算方向跟正确的运算方向是相反的。

  • 反码:正数的反码不变,但负数的反码在原码的基础上,符号位不变,数值取反,0变1,1变0。

  • 反码出现目的是为解决原码中不能计算负数的问题而出现的。反码的弊端是在负数计算时,结果跨0时,跟实际结果会有1的偏差。

  • 补码:正数的补码不变,负数的补码在反码的基础上+1。另外因为+1的原因,补码还能多记录一个特殊的值-128,该数据在1字节范围内,但该数值没有原码和反码。

  • 补码出现目的是为了解决负数计算时跨0的问题而出现的。

  • 强制转换中数值转换出错的原因就是因为强制转换位数,将多位删除到少位,造成错误。

四、判断和循环

1、流程控制语句分类:顺序结构、分支结构(判断和选择结构,if、switch)、循环结构(for, while, do…while)。

  • 分支结构中判断语句——if语句:单条件、双条件以及多条件判断

//其语句格式1:
if (关系表达式) {
   语句体;
}
/* 注意:
1. 如果我们要对一个布尔类型的变量进行判断,不要写==,直接把变量写在小括号中即可。
2. 如果大括号中的语句体只有一条,那么大括号可以省略不写。
  如果大括号省略了,那么if只能控制距离他最近的那一条语句。
  建议自己不要去写,如果别人这么写了,你要能看懂即可。
  注意: int a = 1; 这行代码包含定义变量a和给其赋值两句语句。
3. 大括号的开头可以另起一行书写。
*/

//其语句格式2:
if (关系表达式) {
   语句体1;
} else {
   语句体2;
}

//其语句格式3:
if (关系表达式1) {
   语句体1;
} else if (关系表达式2) {
   语句体2;
}

else {
   语句体n+1;
}
  • 分支结构中选择语句——switch语句:

//switch语句格式:
switch (表达式) {
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
...
default:
语句体n+1;
break;
}
/* 注意:
1. 表达式:(将要匹配的值)取值为byte、short、int、char。JDK5以后可以是枚举,JDK7以后可以是String。
2. case:后面跟的是要和表达式进行比较的值(被匹配的值)。
3. break:表示中断,结束的意思,用来结束switch语句。
4. default: 表示所有情况都不匹配的时候,就执行该处的内容,和if语句的else相似。
5. case后面的值只能是字面量,不能是变量。
6. case给出的值不允许重复。
*/

//switch在JDK12中的新特性:
switch (表达式) {
case 值1 -> { 语句体1; }
case 值2 -> { 语句体2; }
...
default -> { 语句体n+1; }
}

注意switch中有:1)default可以放在任意位置,也可以省略。 2)语句中不写break会引发case穿透现象。使用场景:如果多个case的语句体重复了,考虑利用case穿透来简化代码。 3)如果switch中匹配成功的case生成结果,可以在switch前写上变量=来接收这个结果。

注意:1)switch和if第三种格式各自的使用场景:当我们需要对一个范围进行判断的时候,用if的第三种格式。当我们把有限个数据列举出来,选择其中一个执行的时候,用switch语句。

  • 循环结构——for语句:

//for循环格式:
for (初始化语句;条件判断语句;条件控制语句) {
循环体语句;
}
  • 循环结构——while语句:

//while循环格式:
初始化语句;
while(条件判断语句){
循环体;
条件控制语句;
}

注意:1)循环是重复的做某事,具有明确的开始和停止标记。 2)for 和 while 的区别:for循环中,知道循环次数或者循环的范围。而while循环中,不知道循环的次数和范围,只知道循环的结束条件。

  • 循环结构——do...while循环

//do...while循环格式:
初始化语句;
do{
循环体;
条件控制语句;
}while(条件判断语句);
//do...while循环特点:先执行,再判断。

2、无限循环(死循环):循环一直停不下来。

//for循环
for(;;){
System.out.println("循环执行一直在打印内容");
}
//while循环(最常用)
while(true){
System.out.println("循环执行一直在打印内容");
}
//do...while循环
do{
System.out.println("循环执行一直在打印内容");
}while(true);

//注意:无限循环下面不能再写其他代码了,因为永远执行不到。

3、跳转控制语句

——(条件控制语句):在循环的过程中,跳到其他语句上执行。

  • break:不能单独存在的,可以用在switch和循环中。表示结束,跳出的意思,用来结束整个循环,跳转到循环后的语句上执行。break是指跳出单层循环/内循环。

  • continue:不能单独存在的,只能存在于循环当中。表示跳过本次循环,继续执行下次循环,指跳转到循环的条件控制语句上执行。

五、数组

1、数组:指的是一种容器,可以同来存储同种数据类型的多个值。但是数组容器在存储数据的时候,需要结合隐式转换考虑。

2、数组的定义:

  • 格式一:数据类型 [] 数组名。比如:int [] array。(常用)

  • 格式二:数据类型 数组名 []。比如:int array []。

3、数组的静态初始化:

  • 完整格式:数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,元素4...}; 比如:int[] arr = new int[]{11,22,33};

  • 简化格式:数据类型[] 数组名 = {元素1,元素2,元素3,元素4...}; 比如:int[] array = {1,2,3,4,5};

  • 注意点:等号前后的数据类型必须保持一致。数组一旦创建之后,长度不能发生变化。

4、数组的地址值:表示数组在内存中的位置。

  • 输出的地址值表示含义,以[I@6d03e736为例: [:表示现在打印的是一个数组。 I:表示现在打印的数组是int类型的。 @:仅仅是一个间隔符号而已。 6d03e736:就是数组在内存中真正的地址值。(十六进制的)

5、数组元素访问的格式:数组名[索引];

  • 数组元素访问的作用:获取或修改数组中对应索引上的值。

  • 索引:也叫角标、下标,就是数组容器中每一个小格子对应的编号。索引的特点:索引一定是从0开始的,连续不间断,且逐个+1增长。

  • 获取数组中数据的方式。

6、数组的遍历:就是把数组里面所有的内容一个一个全部取出来。

  • 遍历指的是取出数据的过程。遍历后可以执行打印、求和、判断等操作。

  • 数组的长度:数组名.length;

7、数组的动态初始化:

  • 格式:数据类型[] 数组名 = new 数据类型[数组的长度];

  • 特点:在创建的时候,由我们指定数组的长度,但由虚拟机给出默认的初始化值。

  • 数组的默认初始化值:整数类型是 0;小数类型是 0.0;布尔类型是 false;字符类型是 '\u0000'(即空格);引用类型是 null。

注意:数组两种初始化方式的区别。静态初始化:手动指定数组的元素,系统会根据元素的个数,计算出数组的长度。动态初始化:手动指定数组长度,由系统给出默认初始化值。

8、数组常见问题

当访问了数组中不存在的索引,就会引发索引越界异常

9、如何在数组中添加数据?

  • 可以在已初始化的有未赋值的空间数组中直接对索引元素赋值添加数据。

  • 是否可以对数组空间进行扩容来添加更多的数据?

10、数组的内存图:

  • 变量存储的是真实的数据,而数组存储的是数据存储在内存中的地址值。

  • 两个数组指向同一个空间的内存图。

  • 当两个数组指向同一个小空间时,其中一个数组对小空间中的值进行修改,那么其它数组再次访问的则是已经改变的结果。

注意:Java的内存分配

  • Java的内存分配由JVM管理,JVM内包含 栈、堆、方法区(改进为 元空间)、本地方法栈以及寄存器这个部分。 

  • 栈:方法运行时使用的内存,比如main方法运行,进入方法栈中执行。

  • 堆:存储对象或者数组,new来创建的,都存储在堆内存。

  • 方法区:存储可以运行的class文件。

  • 本地方法栈:JVM在使用操作系统功能的时候使用。

  • 寄存器:给GPU使用。

  • 对于栈,main等方法在开始执行时会进栈,代码等方法执行完毕后会出栈。对于堆,new出来的对象或数组等,在这块内存中会开辟出空间并产生地址。

六、方法

1、方法(method):是程序中最小的执行单元

  • 方法定义:把一些代码打包在一起,该过程称为方法定义。

  • 同一方法中的代码要么一起执行,要么都不执行。

  • 方法的用处:是将一整个(一些)功能代码打包在一起作为方法,方便进行整体调用,使代码编写进行简化。

  • 方法的优点:提高代码的复用性;提高代码的可维护性

  • 实际开发中,什么时候用到方法? 重复的代码、具有独立功能的代码可以抽取到方法中。

注意,方法定义和方法调用的比较: 方法必须先创建才可以使用,该过程成为方法定义。 方法创建后并不是直接可以运行的,需要手动使用后,才执行,该过程成为方法调用。

2、方法的定义格式:

//下面参数为形参
public static 返回值类型 方法名(参数) {
方法体;
return 返回值;
}

方法的定义格式可以分为 最简单的(无参数的)、带参数的 和带返回值 的方法定义。

  • 1)最简单(无参数)的方法定义和调用

    //定义格式:
    public static void 方法名(){
    方法体(就是打包起来的代码);
    }
    //调用格式:
    方法名();

    //注意:方法必须先定义后调用,否则程序将报错。
  • 2)带参数的方法定义和调用

    参数:由数据类型和变量名组成 -- 数据类型 变量名。参数范例:int a。

    //定义格式:
    //下面参数为形参
    //单参数
    public static void 方法名 (参数1) {
    方法体;
    }
    //多参数
    public static void 方法名 (参数1, 参数2, 参数3...) {
    方法体;
    }

    //注意:方法定义时,参数中的数据类型与变量名都不能缺少,缺少任意一个程序将报错。方法定义时,多个参数之间使用逗号( ,)分隔。

    //调用格式:
    //下面参数为实参
    方法名(参数);
    方法名(参数1,参数2);

    //注意:方法调用时,参数的数量与类型必须与方法定义中的设置相匹配(即形参和实参必须一一对应),否则程序将报错。

注意:形参和实参: 形参:方法定义中的参数。等同于变量定义格式,例如:int number 实参:方法调用中的参数。等同于使用变量或常量,例如: 10 number

  • 3)带返回值方法定义和调用

    在调用出处要根据方法的结果,区编写另外一段代码的时候,需要用到有返回值的方法。

    //定义格式:
    //下面参数为形参
    public static 数据类型 方法名 ( 参数 ) {
    方法体 ;
    return 数据 ;
    }

    //注意:方法定义时return后面的返回值与方法定义上的数据类型要匹配,否则程序将报错。

    //调用格式:
    ////下面参数为实参
    方法名 ( 参数 ) ; //直接调用
    数据类型 变量名 = 方法名 ( 参数 ) ; //赋值调用
    System.out.println( 方法名 ( 参数 ) ); //输出调用

    //注意:方法的返回值通常会使用变量接收,否则该返回值将无意义。

3、方法的注意事项:

  • 方法不调用就不执行。

  • 方法与方法之间是平级关系,不能互相嵌套定义。

  • 方法的编写顺序与执行顺序无关。

  • 方法中有返回值,就必须要写return关键字,其表示结束方法和返回结果。

  • 方法中void返回值类型表示无返回值,可以省略return;也可以单独的书写return;,后面不加数据,表示结束方法。

  • return语句下面,不能编写代码,因为其永远执行不到,属于无效的代码。

4、方法的重载:

  • 概念——方法重载指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载:多个方法在同一个类中;多个方法具有相同的方法名;多个方法的参数不相同,即参数的数量、类型或者顺序不同。

  • 形式参数的顺序不同可以构成方法的重载,但是不建议。

  • 重载仅对应方法的定义,与方法的调用无关,调用方式参照标准格式。

  • 重载仅针对同一个类中方法的名称与参数进行识别,与返回值无关,换句话说不能通过返回值来判定两个方法是否相互构成重载。

5、方法的内存:

  • 1.方法调用的基本内存原理

    栈内方法的运行过程:先进后出。

  • 2.方法传递基本数据类型的内存原理

    注意:传递基本数据类型时,传递的是真实的数据,形参的改变,不影响实际参数的值。

  • 3.方法传递引用数据类型的内存原理

    注意:传递引用数据类型时,传递的是地址值,形参的改变,影响实际参数的值。

七、综合练习

1、练习:双色球

代码示例:

package com.itheima.test;

import java.util.Random;
import java.util.Scanner;

public class Test11 {
public static void main(String[] args) {
//1.生成中奖号码
int[] arr = createNumber(); // 123456 7

System.out.println("=======================");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}

System.out.println("=======================");



//2.用户输入彩票号码(红球 + 蓝球)//654321
int[] userInputArr = userInputNumber();

//3.判断用户的中奖情况
//红球 蓝球
int redCount = 0;
int blueCount = 0;

//判断红球
for (int i = 0; i < userInputArr.length - 1; i++) {
int redNumber = userInputArr[i];
for (int j = 0; j < arr.length - 1; j++) {
if(redNumber == arr[j]){
redCount++;
//如果找到了,那么后面的数字就没有必要继续比较了
//跳出内循环,继续判断下一个红球号码是否中奖
break;
}
}
}

//判断蓝球
int blueNumber = userInputArr[userInputArr.length-1];
if(blueNumber == arr[arr.length - 1]){
blueCount++;
}

//根据红球的个数以及蓝球的个数来判断中奖情况
if(redCount == 6 && blueCount == 1){
System.out.println("恭喜你,中奖1000万");
}else if(redCount == 6 && blueCount == 0){
System.out.println("恭喜你,中奖500万");
}else if(redCount == 5 && blueCount == 1){
System.out.println("恭喜你,中奖3000");
}else if((redCount == 5 && blueCount == 0) || (redCount == 4 && blueCount == 1)){
System.out.println("恭喜你,中奖200");
}else if((redCount == 4 && blueCount == 0) || (redCount == 3 && blueCount == 1)){
System.out.println("恭喜你,中奖10");
}else if((redCount == 2 && blueCount == 1) || (redCount == 1 && blueCount == 1)|| (redCount == 0 && blueCount == 1)){
System.out.println("恭喜你,中奖5");
}else{
System.out.println("谢谢参与,谢谢惠顾");
}

}

public static int[] userInputNumber() {
//1.创建数组用于添加用户购买的彩票号码
//6个红球 1个蓝球 数组长度:7
int[] arr = new int[7];

//2.利用键盘录入让用输入
Scanner sc = new Scanner(System.in);
//让用户输入红球号码
for (int i = 0; i < 6; ) {
System.out.println("请输入第" + (i + 1) + "个红球号码");
int redNumber = sc.nextInt();
//redNumber 在1~33 唯一不重复
if (redNumber >= 1 && redNumber <= 33) {
boolean flag = contains(arr, redNumber);
if (!flag) {
//不存在
//有效的,可以添加到数组当中
arr[i] = redNumber;
i++;
} else {
//存在
System.out.println("当前红球号码已经存在,请重新输入");
}
} else {
System.out.println("当前红球号码超出范围");
}
}

//让用户输入篮球号码
System.out.println("请输入篮球号码");
//1~16
while (true) {
int blueNumber = sc.nextInt();
if (blueNumber >= 1 && blueNumber <= 16) {
arr[arr.length - 1] = blueNumber;
break;
} else {
System.out.println("当前篮球号码超出范围");
}
}
return arr;

}


public static int[] createNumber() {
//1.创建数组用于添加中奖号码
//6个红球 1个蓝球 数组长度:7
int[] arr = new int[7];

//2.随机生成号码并添加到数组当中
//红球:不能重复的 1 2 3 4 5 6
//蓝球:可以跟红球号码重复 5

//生成红球号码并添加到数组当中
Random r = new Random();
for (int i = 0; i < 6; ) {
//获取红球号码
int redNumber = r.nextInt(33) + 1;
boolean flag = contains(arr, redNumber);
if (!flag) {
//把红球号码添加到数组当中
arr[i] = redNumber;
i++;
}
}

//生成蓝球号码并添加到数组当中
int blueNumber = r.nextInt(16) + 1;
arr[arr.length - 1] = blueNumber;
return arr;
}

//用于判断数在数组中是否存在
public static boolean contains(int[] arr, int number) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == number) {
return true;
}
}
return false;
}
}

2、二维数组

  • 数组中存数组。当需要对数组进行分组管理时使用二维数组。

  • 二维数组的初始化:静态和动态初始化。

    • 二维数组的静态初始化格式:

    //格式与范例:
    数据类型[][] 数组名 = new 数据类型[][] {{元素1,元素2},{元素1,元素2}};
    int[][] arr = new int[][]{{1,2},{3,4}};
    //简化格式与范例:
    数据类型[][] 数组名 = {{元素1,元素2},{元素1,元素2}};
    int[][] arr = {{1,2},{3,4}}; //选用
    int arr[][] = {{1,2},{3,4}};
    • 二维数组的动态初始化格式:

    //格式与范例:
    数据类型[][] 数组名 = new 数据类型[m][n];
    int[][] arr = new int[2][3];

---

PS:

该笔记学习自:Java入门-01-Java学习介绍_哔哩哔哩_bilibili