2.1 Java基础

当当!更新笔记啦!

关键字和保留字

 

  • 保留字(reserved word)

    • java保留字:现有Java版本尚未使用,但以后版本可能会作为关键字使用。自己命名标识符时要避免使用这些保留字。

    • goto const

标识符

  

注:如果不遵守标识符的命名规则,编译不通过!需严格遵守。

如果不遵守标识符的命名规范,编译通过!建议大家遵守。

变量

  • 概念:

    • 内存中的一个存储区域

    • 该区域的数据可以在同一类型范围内不断变化

    • 变量是程序中最基本的存储单元,包含变量类型、变量名和存储的值

  • 定义变量的格式:

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

  • 注意:

    • Java中每个变量必须先声明,后使用

    • 使用变量名来访问这块区域的数据

    • 变量的作用域:其定义所在的一对{}内

    • 变量只有在其作用域内才有效

    • 同一个作用域内,不能定义重名的变量

  • 分类:

    • 按数据类型:

      • 基本数据类型:

      • 整型:byte(1字节) \ short(2字节) \ int(4字节) \ long(8字节)
        • 注:

          • byte 范围:-128 ~127

          • 声明long型变量,必须以“l”或“L”结尾

          • 通常,定义整型变量时,使用int型。

        • 浮点型:float \ double

          • 浮点型常量的表示类型:十进制数形式(如5.12)和科学计数法形式(如5.12e2)

          • 说明:

            • float:单精度,尾数可以精确到7位有效数字,很多情况下,精度很难满足需求。

            • double:双精度,精度是float的两倍。通常采用此类型。

        • 字符型:char

          • 定义char型变量,通常使用一对‘ ’,内部只能写一个字符

          • 表示方法:

            • 声明一个字符

            • 转义字符

            • 直接使用Unicode值来表示字符型常量(少用)

        • 布尔型:boolean

          • 只能取两个值之一: true \ false

          • 常常在条件判断、循环结构中使用 

  • 引用数据类型:

    • 类(class)

    • 接口(interface)

    • 数组(array)

  • 按在类中声明的位置:

    • 成员变量

    • 局部变量

    • 成员变量与局部变量的区别

                         

  • 基本数据类型之间的运算规则

    • 前提:这里讨论的只是7种基本数据类型变量间的运算,不包含boolean类型的。

    • 自动类型提升:

      • 结论:当容量小的数据类型的变量与容量大的数据类型的变量做运算时,结果自动提升为容量大的数据类型。

      • byte、char、short --> int --> long --> float --> double

      • 特别地,当byte、char、short三种类型的变量做运算时,结果为int型

    • 强制类型转换(自动类型提升的逆运算):

      • 需要使用强转符:()

      • 注意点:强制类型转换,可能导致精度损失(截断操作)

    • 说明:此时的容量大小指的是,表示数的范围的大和小。比如,float容量要大于long的容量

    • 特殊情况:

      • 整型常量,默认类型为int型

      • 浮点型常量,默认类型为double型

    • String类型变量的使用

      • String属于引用数据类型

      • 声明String类型变量时,使用一对“ ”

      • String可以和8种基本数据类型变量做运算,且运算只能是连接运算:+(连接符号)

      • 注:根据+号左右两边的数据的数据类型来决定+号是连接符号还是运算符号。

      • 运算的结果仍然是String类型

      • 作用:

        • 用于在内存中保存数据

运算符

  2.1.4 运算符(一种特殊的符号,用以表示数据的运算,赋值和比较等)

    算术运算符

  • 注:

  • %(取余运算):结果的符号与被模数的符号相同;开发中,经常使用%来判断能否被除尽的情况。

  • 自增1不会改变本身变量的数据类型

    赋值运算符

  • 符号:=

    • 当“=”两侧数据类型不一致时,可以使用自动类型转换或使用强制类型转换原则进行处理。

    • 支持连续赋值。

  • 扩展赋值运算符:+=,-=,*=,/=,%=

 

Int num1 = 10; num1=num1+2;//num1+=2;两种写法相同。 Short num2 = 10; num2=num2+2;//编译不通过 //num2+=2;//不会改变变量本身的数据类型 //此时两者不相同。 //注意:不能(num++)++;也不能num++++;

    比较运算符(关系运算符)

 

    逻辑运算符

  • 说明:

    • 逻辑运算符操作的都是boolean类型的变量

    • 区分 & 与 &&

      • 相同点1:& 与 && 的运算结果相同

      • 相同点2:当符号左边是true时,二者都会执行符号右边的运算

      • 不同点:当符号左边是false时,&继续执行符号右边的运算;&&不再执行符号右边的运算。

      • 开发中,推荐使用&&

    • 区分 | 与 ||

      • 相同点1:| 与 || 的运算结果相同

      • 相同点2:当符号左边是false时,二者都会执行符号右边的运算

      • 不同点:当符号左边是true时,|继续执行符号右边的运算,而||不再执行符号右边的运算

      • 开发中,推荐使用||

    位运算符(少用)

 

  • 结论:

    • 位运算符操作的都是整型的数据

    • <<:在一定范围内,每向左移1位,相当于 * 2

    • >>:在一定范围内,每向右移1位,相当于 / 2

    三元(目)运算符

  • 格式:(条件表达式)?表达式1:表达式2;

  • 说明:

             如果表达式为true,则执行表达式1,

             如果表达式为false,则执行表达式2.

    • 条件表达式的结果为boolean类型

    • 根据条件表达式真或假,决定执行表达式1,还是表达式2.

    • 表达式1与表达式2要求是一致的。

    • 三元运算符可以嵌套使用。

  • 凡是可以使用三元运算符的地方,都可以改写为if-else。反之,不成立。

  • 如果程序既可以使用三元运算符,又可以使用if-else结构,那么优先选择三元运算符。原因:简洁、执行效率高。

    运算符的优先级

  • 程序流程控制

    • ​​流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块。

    • 其流程控制方式采用结构化程序设计中规定的三种基本流程结构,即:

            顺序结构

            分支结构

              if-else结构(条件判断结构):

       

              switch-case结构

    •       循环结构

              for循环的结构

      for(初始化部分;循环条件;迭代部分){ 循环体 }

              while循环的使用:

       

      ① while(②){ ③; ④;(写while循环千万小心不要丢了迭代条件。一旦丢了,就可能导致死循环!) }

              do-while循环的使用

       

      ① do{ ③; ④; }while(②);

                方式1:循环条件部分返回false

                方式2:在循环体中,执行break

              嵌套循环的使用

              特殊关键字break和continue的使用

              带标签的break和continue的使用

        • 程序从上到下逐行地执行,中间没有任何判断和跳转。

        • 根据条件,选择性地执行某行代码。

        • 有if...else和switch-case两种分支语句。

        • 说明:

          • else结构是可选的。

          • 针对于条件表达式:

            • 如果多个条件表达式之间是“互斥”关系(或没有交集的关系),哪个判断和执行语句声明在上面还是下面,无所谓。

            • 如果多个条件表达式之间有交集的关系,需要根据实际情况,考虑清楚应该将哪个结构声明在上面。举例如下:

            • 如果多个条件表达式之间有包含的关系,通常情况下,需要将范围小的声明在范围大的上面,否则,范围小的就没机会执行了。

            • if-else结构是可以相互嵌套的。

            • 如果if-else结构中的执行语句只有一行时,对应的{}可以省略。但是,不建议大家省略。

        • 说明:

          • 根据switch表达式中的值,依次匹配各个case中的常量,一旦匹配成功,则进入相应的case结构中,直到遇到break关键字或此switch-case结构末尾结束为止。

          • break,可以使用在switch-case结构中,表示一旦执行到此关键字,就跳出switch-case结构

          • switch结构中的表达式,只能是如下的6种数据类型之一:byte 、short 、char 、int 、枚举类型(JDK5.0新增)、String类型(JDK7.0新增)

          • case之后只能声明常量,不能声明范围。

          • break关键字是可选的

          • default:相当于if-else结构中的else,是可选的,而且位置是灵活的。

        • if-else与switch-case

          • 凡是可以使用switch-case的结构,都可以转换为if-else,反之,不成立。

          • 写分支结构时,当发现既可以使用switch-case,(同时,switch中表达式的取值情况不太多),又可以使用if-else时,我们优先选择使用switch-case。原因:switch-case执行效率稍高。

        • 根据循环条件,重复性地执行某段代码。

        • 有while、do...while、for三种循环语句。

        • 循环结构的4个要素:

          • 初始化部分

          • 循环条件 -->是boolean类型

          • 循环体

          • 迭代部分

        • 执行过程:① ~ ② ~ ③ ~ ④ ~ ② ~ ③ ~ ④ ~ ... ~②

        • 注意break关键字的使用:一遇到break就跳出循环。

        • 执行过程:① ~ ② ~ ③ ~ ④ ~ ② ~ ③ ~ ④ ~ ... ~②

        • 注:

          • 我们写程序时,要避免出现死循环。

          • for循环和while循环是可以相互转换的!

          • 区别:for循环和while循环的初始化条件部分的作用范围不同。

        • 执行过程:① ~③ ~ ④ ~ ② ~ ③ ~ ④ ~ ② ~ ③ ~ ④ ~ ... ~②

        • 说明:

          • do-while循环至少会执行一次循环体!

          • 开发中,使用for和while更多一些,较少使用do-while

        • 不在循环条件部分限制次数的结构:for(;;)或while(true)

        • 结束循环有几种方式?

        • 嵌套循环:将一个循环结构A声明在另一个循环结构B的循环体中,就构成了嵌套循环。

        • 外层循环:循环结构B

        • 内层循环:循环结构A

        • 说明:

          • 内层循环结构遍历一遍,只相当于外层循环循环体执行了一次

          • 假设外层循环需要执行m次,内层循环需要执行n次,此时内层循环的循环体一共执行了m*n次

        • 技巧:外层循环控制行数,内层循环控制列数

        • 使用范围:

          • break:switch-case;循环结构中(结束当前循环)(默认跳出包裹此关键字最近的一层循环)

          • continue:循环结构中(结束当次循环)(结束当前包裹此关键字最近的一层循环)

    • 注:JDK1.5提供了foreach循环,方便的遍历集合、数组元素。

数组

  数组(可以用来存储同种数据类型的多个值):

    数组的静态初始化

  • 初始化:就是在内存中,为数组容器开辟空间,并将数据存入容器中的过程。

  • 数组定义格式:

    • 格式1:数据类型[ ] 数组名

    • 范例:int[ ] array;

    • 格式2:数据类型 数组名[ ]

    • 范例:int array[ ];

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

    • 完整格式:数据类型[ ] 数组名 = new 数据类型[ ]{元素1,元素2,元素3...};

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

  • 打印数组名:[I@1b6d3586

            @ :分隔符

            [ :当前空间,是数组类型的

            I:当前数组类型,是int类型

            1b6d3586:数组的十六进制内存地址

    数组元素访问

  • 格式:数组名[索引](索引:是数组容器中空间的编号,编号从0开始,逐个+1增长)

    数组遍历操作

  • 数组遍历:将数组中所有的内容取出来,取出来之后可以(打印,求和,判断..)

  • 数组的属性之一:数组名.length:动态获取到数组的长度(元素的个数)

 

for(int i = 0;i < arr.lengthl;i++){ System.out.println(arr[i]); }//快捷键 :数组名.fori

  • 数组遍历的场景:如果要完成的需求,是需要操作到数组中的【每一个】元素,就需要对数组进行遍历操作

    数组动态初始化

  • 动态初始化:初始化时只指定数组的长度,由系统为数组分配初始值(默认值)。

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

  • 范例:int[ ] arr = new int[3];

  • 默认值的分类:


    • 整数:0

    • 小数:0.0

    • 布尔:false

    • 字符:'\u0000' ---> Unicode字符 ---> 常见的体现是空白字符

    • 引用数据类型(String属于类):null

    两种初始化的对比和使用选择:

  • 区别:

    • 动态初始化:手动指定数组长度,由系统给出默认初始化值。

    • 静态初始化:手动指定数组元素,系统会根据元素个数,计算出数组的长度。

  • 两种初始化的使用选择:

    • 静态初始化:如果要操作的数据,需求中已经明确给出了,直接静态初始化。

    • 动态初始化:只明确元素个数,不明确具体数值

    数组内存图

  • Java内存分配介绍:

    • Java虚拟机的内存可以分为三个区域:

      • 栈stack

                      2. JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)

                      3. 栈属于线程私有,不能实现线程间的共享!

                      4. 栈的存储特性是“先进后出,后进先出”

                      5. 栈是由系统自动分配,速度快!栈是一个连续的内存空间!

        • 特点:

                         1.栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)

      • 堆heap

                      2. JVM只有一个堆,被所有线程共享

                      3. 堆是一个不连续的内存空间,分配灵活,速度慢!

        • 特点:

                         1.堆用于存储创建好的对象和数组(数组也是对象)

      • 方法区method area(又叫静态区)

        • 特点:

                         1.JVM只有一个方法区,被所有线程共享!

                          2. 方法区实际也是堆,只是用于存储类、常量相关的信息!

                          3. 用来存放程序中永远是不变或唯一的内容。(类信息【Class对象】、静态变量、字符串常量等)

  • 两个数组指向相同内存图

    数组拷贝

  • System类里也包含了一个static void arraycopy(object src,int srcpos,object dest, int destpos,int length)方法,

  • 该方法可以将src数组里的元素值赋给dest数组的元素,其中srcpos指定从src数组的第几个元素开始赋值,length参数指定将src数组的多少个元素赋给dest数组的元素。

    java.util.Arrays类

  • 说明:JDK提供的java.util.Arrays类,包含了常用的数组操作

  • 包含:

    • 排序

      • 数组元素是基本数据类型:Arrays.sort(数组名)

      • 数组元素是引用数据类型(Comparable接口的应用):

        import java.util.Arrays; public class Test { public static void main(String[] args) { Man[] msMans = { new Man(3, "a"), new Man(60, "b"), new Man(2, "c") }; Arrays.sort(msMans); System.out.println(Arrays.toString(msMans)); } } class Man implements Comparable { int age; int id; String name; public Man(int age, String name) { super(); this.age = age; this.name = name; } public String toString() { return this.name; } public int compareTo(Object o) { Man man = (Man) o; if (this.age < man.age) { return -1; } if (this.age > man.age) { return 1; } return 0; } }

    • 查找(二分法查找)

      import java.util.Arrays; public class Test { public static void main(String[] args) { int[] a = {1,2,323,23,543,12,59}; System.out.println(Arrays.toString(a)); Arrays.sort(a); //使用二分法查找,必须先对数组进行排序; System.out.println(Arrays.toString(a)); //返回排序后新的索引位置,若未找到返回负数。 System.out.println("该元素的索引:"+Arrays.binarySearch(a, 12)); } }

    • 填充

      import java.util.Arrays; public class Test { public static void main(String[] args) { int[] a= {1,2,323,23,543,12,59}; System.out.println(Arrays.toString(a)); Arrays.fill(a, 2, 4, 100); //将2到4索引(即索引为2和3)的元素替换为100; System.out.println(Arrays.toString(a)); } }

    • 打印内容(Arrays.toString(数组名))(注意:此处的Arrays.toString()方法是Arrays类的静态方法,不是前面讲的Object的toString()方法)

    • 等常见的操作

    数组常见问题

  • 索引越界异常:ArrayIndexOutOfBoundsException

    • 原因:访问了不存在的索引

  • 空指针异常:NullPointerExceptionf

    • 当引用数据类型变量被赋值为null之后,地址的指向被切断,还继续访问堆内存数据,就会引发空指针异常。

  2.1.7 二维数组

    二维数组介绍

  • 二维数组是一种容器,该容器用于存储一维数组

  • 使用思路:今后若要操作的多组数据,属于同一组数据,就可以考虑使用二维数组进行维护

    二维数组静态初始化

  • 完整格式:数据类型[ ][ ] 数组名 = new 数据类型[ ][ ] {{元素1,元素2},{元素1,元素2}};

  • 范例:int[ ][ ] arr = new int[ ][ ]{{11,22},{33,44}};

  • 简化格式:数据类型[ ][ ] 数组名 = {{元素1,元素2},{元素1,元素2}};

  • 范例:int[ ][ ] arr = {{11,22},{33,44}};

  • 打印数组名:

    • 打印二维数组名:为二维数组的地址

    • 打印 二维数组名[i] :为其存储的一维数组的地址

  • 二维数组在存储一维数组的时候,具体存储的是一维数组的地址值

  • 二维数组的元素访问格式:

    • 数组名[m索引][n索引];

    • m索引:指定访问哪一个一维数组

    • n索引:访问一维数组中的哪一个元素

    二维数组遍历

  • 先遍历二维数组,获取到每一个一维数组;

  • 继续遍历一维数组,获取具体的元素。 

public static void printArray(int[][] arr){ //1、遍历二维数组,获取到每一个一维数组 for(int i = 0;i < arr.length;i++){ //arr[i]:每一个一维数组 //2、继续遍历一维数组,获取具体的元素 for(int j = 0;j < arr[i].length;j++){ System.out.println(arr[i][j]); } } }

    二维数组动态初始化

  • 格式:数据类型[ ][ ] 数组名 = new 数据类型[m][n];

      m表示这个二维数组,可以存放多少个一维数组

      n表示每一个一维数组,可以存放多少个元素

  • 范例:int[ ][ ] arr = new int[2][3];

    二维数组内存图

  2.1.8 递归:

  • 即:自己调用自己

  • 递归结构包括两个部分:

    • 定义递归头(即:什么时候不调用自身方法,也就是递归的结束条件。)

    • 递归体(即:什么时候需要调用自身方法。)

  • 举例如下:

  • 递归的缺陷:

    • 会占用大量的系统堆栈,内存耗用多,在递归调用层次多时速度要比循环慢的多(所以在使用递归时要慎重)。

  • 注意事项:

    • 任何能用递归解决的问题也能使用迭代解决。当递归方法可以更加自然地反映问题并且易于理解和调试并且不强调效率问题时,可以采用递归;

    • 要求高性能的情况下尽量避免使用递归,递归调用既花时间又耗内存。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值