首页 > 编程语言 >javaSE

javaSE

时间:2024-08-18 13:54:45浏览次数:6  
标签:arr int 数据类型 运算符 数组 javaSE public

JDK的安装与卸载

卸载

首先在控制面版上卸载---》需要在环境变量上删除配置。

安装

直接下载install版的jdk 直接安装即可

配置环境变量(当前电脑在任何位置都能使用jdk中bin目录的命令)

我的电脑--》属性--》高级属性设置--》环境变量--》path 添加jdk安装目录中的bin文件路径

C:\Program Files\Java\jdk-17\bin

环境变量配置

配置JAVA_HOME给其他软件使用java提供一个窗口。

在系统变量中新建一个变量

​ 变量名:JAVA_HOME

​ 变量值::\Program Files\Java\jdk-17

jdk jre jvm

jdk:java开发工具包

jre:java运行时环境

jvm:java虚拟机

jdk包含jre包含jvm

idea自定义快捷模板

File-->Setting-->Editor-->Live Templates

image-20240716115559576

HelloWorld案例常见错误

当cmd命令行窗口的字符编码与.java源文件的字符编码不一致,如何解决?

1.在Notepad++等编辑器中,修改源文件的字符编码:

2.在EditPlus中可以将Java源文件另存为ANSI编码方式(中文操作系统下即为GBK字符集)

3.在使用javac命令式,可以指定源文件的字符编码 --> javac -encoding utf-8 Review01.java

4.一个java文件内有几个类就会生成几个class文件

5.一个java文件内有多个类如果采用动态编译则使用第一个类

6.如果一个类被public修饰则类名必须和它一致

一个java文件中只能有一个类被public修饰

7.java是严格区分大小写

8.java标点符号必须是英文半角

基本语法

  • 大小写敏感:Java 是大小写敏感的,这就意味着标识符 Hello 与 hello 是不同的。
  • 类名:对于所有的类来说,类名的首字母应该大写。如果类名由若干单词组成,那么每个单词的首字母应该大写,例如 MyFirstJavaClass
  • 方法名:所有的方法名都应该以小写字母开头。如果方法名含有若干单词,则后面的每个单词首字母大写。
  • 源文件名:源文件名必须和类名相同。当保存文件的时候,你应该使用类名作为文件名保存(切记 Java 是大小写敏感的),文件名的后缀为 .java。(如果文件名和类名不相同则会导致编译错误)。
  • 主方法入口:所有的 Java 程序由 public static void main(String[] args) 方法开始执行。

注释和打印语句

作用: 对代码进行解释说明
分类: 单行 //
多行 /* * /
文档 /** * /
注意:
1. 多行和文档注释不能嵌套使用
1. 注释只存在于编译时
编译 .java--> .class
反编译 .class --> .java

关键字

被Java语言赋予了特殊含义,用做专门用途的字符串(或单词)

java标识符

标识符:java中对类 方法 变量等命名时采用的字符序列

命名规则:

​ 1.字母 数字 下划线_ 美元符$ 组成

​ 2.数字不能开头

​ 3.不能使用java中的关键字和保留字
​ 保留字:在当前的k版本内没有意义但是以后可能会使用
​ 4.严格区分大小写

命名规范:

​ 对类命名:大驼峰 例: UserTest

​ 对变量 方法命名: 小驼峰 例: userName

​ 对包命名:全部字母小写 例: chs

​ 对常量命名:全部字母大写如果由多个单词组成 中间使用下划线连接 例: PI

两大数据类型

基本数据类型:四类八种

​ 整数类型: byte short int long

​ 浮点: float double
​ 字符: char
​ 布尔: boolean true false

引用数据类型:只要不是基本数据类型那么一定是引用数据类型

整数类型:

image-20240713094623346

计算公式 [2(bit-1)~(2(bit-1))-1]

定义long类型的变量,赋值时需要以"l"或"L"作为后缀。

​ 当赋值的值没有超过int界时,可以不用加 "L"

Java程序中变量通常声明为int型,除非不足以表示较大的数,才使用long。

Java的整型常量默认为 int 型

浮点类型:

image-20240713103639683

  • 浮点型常量有两种表示形式:

    • 十进制数形式。如:5.12 512.0f .512 (必须有小数点)

    • 科学计数法形式。如:5.12e2 512E2 100E-2

      例:5e2==>5*10^2

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

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

  • 定义float类型的变量,赋值时需要以"f"或"F"作为后缀。

  • Java 的浮点型常量默认为double型

如果需要精确数字计算或保留指定位数的精度,需要使用BigDecimal类

字符类型:

char 型数据用来表示通常意义上“字符”(占2字节).

char类型是可以进行运算的。因为它都对应有Unicode码,可以看做是一个数值.

a:97 A:65 0:48

布尔类型:

boolean类型数据只有两个值:true、false,无其它 (一个字节)

计算机存储单位

字节(Byte):是计算机用于计量存储容量基本单位,一个字节等于8 bit。

位(bit):是数据存储的最小单位。二进制数系统中,每个0或1就是一个位,叫做bit(比特),其中8 bit 就称为一个字节(Byte)。

8 bit = 1 Byte

1024 Byte = 1 KB

1024 KB = 1 MB

1024 MB = 1 GB

1024 GB = 1 TB

变量

变量: 在程序执行时值可以发生改变的量
作用: 记录程序运行时产生的信息

注意:
方法内变量是局部变量 它在使用前必须进行初始化赋值就是初始化
在同一个方法内不能声明同名的局部变量

字符串可以与变量名进行拼接中间使用+连接

底层整数存储原理:所有数据在底层都是以2进制形式存储

byte 8bit [-128,127]
二进制最高位是符号位 0正数 1负数

36

源码:0010 0100

反码: 0010 0100

补码: 0010 0100

正整数三码合一

-36:

源码:最高位是1其余位是10进制转为2进制的值 1010 0100

反码: 符号位不变其余位1变00变1 1101 1011

补码: 反码+1 1101 1100

负整数

所有数据在底层是以补码的形式存储

数据类型转换

自动转换 (小转大)

如果有多个数据类型的值做运算结果是最高类型

强制类型转换(大转小)

公式:小的数据类型 变量名=(小的数据类型) 大的数据类型的值;

byte<short==char<int<long<flaot<double;

当强制类型转换大转小超出小的范围时会以2进制形式存储

例:

byte num=(byte)400; ====> num=-112

解:

源码:1 1001 0000 因为byte占8bit,所以只取最后8位

补码:1001 0000

反码:1000 1111

源码:1111 0000

-112

特殊的类型转换

byte short char三个类型的【变量】进行运算结果都是int类型

有时强制类型转换会小转大 (double)100

运算符

按照功能分为:算术运算符、赋值运算符、比较(或关系)运算符、逻辑运算符、位运算符、条件运算符、Lambda运算符

分类 运算符
算术运算符(7个) +、-、*、/、%、++、--
赋值运算符(12个) =、+=、-=、*=、/=、%=、>>=、<<=、>>>=、&=、|=、^=等
比较(或关系)运算符(6个) >、>=、<、<=、==、!=
逻辑运算符(6个) &、|、^、!、&&、||
位运算符(7个) &、|、^、~、<<、>>、>>>
条件运算符(1个) (条件表达式)?结果1:结果2
Lambda运算符(1个) 后面讲解
  • 按照操作数个数分为:一元运算符(单目运算符)、二元运算符(双目运算符)、三元运算符 (三目运算符)
分类 运算符
一元运算符(单目运算符) 正号(+)、负号(-)、++、--、!、~
二元运算符(双目运算符) 除了一元和三元运算符剩下的都是二元运算符
三元运算符 (三目运算符) (条件表达式)?结果1:结果2

算术运算符

image-20240715085043345

“+”号的两种用法
  • 第一种:对于+两边都是数值的话,+就是加法的意思
  • 第二种:对于+两边至少有一边是字符串的话,+就是拼接的意思
符号:=
  • 当“=”两侧数据类型不一致时,可以使用自动类型转换或使用强制类型转换原则进行处理。
  • 支持连续赋值

赋值运算符: +=、 -=、*=、 /=、%= (不会更改数据类型)

赋值运算符 符号解释
+= 将符号左边的值右边的值进行相加操作,最后将结果赋值给左边的变量
-= 将符号左边的值右边的值进行相减操作,最后将结果赋值给左边的变量
*= 将符号左边的值右边的值进行相乘操作,最后将结果赋值给左边的变量
/= 将符号左边的值右边的值进行相除操作,最后将结果赋值给左边的变量
%= 将符号左边的值右边的值进行取余操作,最后将结果赋值给左边的变量

比较(关系)运算符

image-20240715093703313

  • 比较运算符的结果都是boolean型,也就是要么是true,要么是false。

  • > < >= <= :只适用于基本数据类型(除boolean类型之外)

    == != :适用于基本数据类型和引用数据类型

  • 比较运算符“==”不能误写成“=

  • instanceof 检查是否式类的对象 返回结果为true|false

    用法: a instanceof 类型 s

逻辑运算符

image-20240715094053851

  • & 和 &&:表示"且"关系,当符号左右两边布尔值都是true时,结果才能为true。否则,为false。

  • | 和 || :表示"或"关系,当符号两边布尔值有一边为true时,结果为true。当两边都为false时,结果为false

  • ! :表示"非"关系,当变量布尔值为true时,结果为false。当变量布尔值为false时,结果为true。

  • ^ :当符号左右两边布尔值不同时,结果为true。当两边布尔值相同时,结果为false。

  • 区分“&”和“&&”: (&&:如果前面的表达式有一个false,就不再执行后面的表达式了)

    • 相同点:如果符号左边是true,则二者都执行符号右边的操作

    • 不同点:& : 如果符号左边是false,则继续执行符号右边的操作

    ​ && :如果符号左边是false,则不再继续执行符号右边的操作

    • 建议:开发中,推荐使用 &&
  • 区分“|”和“||”:(||:如果前面的表达式有一个ture,就不再执行后面的表达式了)

    • 相同点:如果符号左边是false,则二者都执行符号右边的操作

    • 不同点:| : 如果符号左边是true,则继续执行符号右边的操作

      ​ || :如果符号左边是true,则不再继续执行符号右边的操作

    • 建议:开发中,推荐使用 ||

位运算符

image-20240715102753252

位运算符的运算过程都是基于二进制的补码运算

左移:<<

运算规则:在一定范围内,数据每向左移动一位,相当于原数据*2。(正数、负数都适用)

【注意】当左移的位数n超过该数据类型的总位数时,相当于左移(n-总位数)位

image-20240715104159115

右移:>>

运算规则:在一定范围内,数据每向右移动一位,相当于原数据/2。(正数、负数都适用)

image-20240715104137002

无符号右移:>>>

运算规则:往右移动后,左边空出来的位直接补0。(正数、负数都适用)

image-20240715104125640

条件运算符(可嵌套使用)

条件运算符格式:

(条件表达式)? 表达式1:表达式2

运算符优先级

优先级 运算符说明 Java运算符
1 括号 ()[]{}
2 正负号 +-
3 单元运算符 ++--~
4 乘法、除法、求余 */%
5 加法、减法 +-
6 移位运算符 <<>>>>>
7 关系运算符 <<=>=>instanceof
8 等价运算符 ==!=
9 按位与 &
10 按位异或 ^
11 按位或 `
12 条件与 &&
13 条件或 `
14 三元运算符 ? :
15 赋值运算符 =+=-=*=/=%=
16 位赋值运算符 &=、`

开发建议:

  1. 不要过多的依赖运算的优先级来控制表达式的执行顺序,这样可读性太差,尽量使用()来控制表达式的执行顺序。
  2. 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它分成几步来完成。例如:
    ​ (num1 + num2) * 2 > num3 && num2 > num3 ? num3 : num1 + num2;

分支语句

if-else条件判断结构

单结构分支

if(条件表达式){
  	语句块;
}

双分支条件判断

if(条件表达式) { 
  	语句块1;
}else {
  	语句块2;
}

多分支条件判断:if...else if...else

if (条件表达式1) {
  	语句块1;
} else if (条件表达式2) {
  	语句块2;
}
...
}else if (条件表达式n) {
 	语句块n;
} else {
  	语句块n+1;
}

switch-case选择结构

switch(表达式){
    case 常量值1:
        语句块1;
        //break;
    case 常量值2:
        语句块2;
        //break; 
    // ...
   [default:
        语句块n+1;
        break;
   ]
}

使用注意点:

  • switch(表达式)中表达式的值必须是下述几种类型之一:byte,short,char,int,枚举 (jdk 5.0),String (jdk 7.0)

  • case子句中的值必须是常量,不能是变量名或不确定的表达式值或范围;

  • 同一个switch语句,所有case子句中的常量值互不相同;

  • break语句用来在执行完一个case分支后使程序跳出switch语句块;

    如果没有break,程序会顺序执行到switch结尾;

  • default子句是可选的。同时,位置也是灵活的。当没有匹配的case时,执行default语句。

5.2.2 应用举例

利用case的穿透性

在switch语句中,如果case的后面不写break,将出现穿透现象,也就是一旦匹配成功,不会在判断下一个case的值,直接向后运行,直到遇到break或者整个switch语句结束,执行终止

switch的新写法

在 Java 14 中,新的 switch 表达式主要改变了两个方面:

  • 支持箭头表达式返回;
  • 支持 yied 返回值。
/*
 * 需求:指定一个月份,输出该月份对应的季节。一年有四季:
 * 		3,4,5	春季
 * 		6,7,8	夏季
 * 		9,10,11	秋季
 * 		12,1,2	冬季
 */
  // 改进版
        switch(month) {
            case 1:
            case 2:
            case 12:
                System.out.println("冬季");
                break;
            case 3:
            case 4:
            case 5:
                System.out.println("春季");
                break;
            case 6:
            case 7:
            case 8:
                System.out.println("夏季");
                break;
            case 9:
            case 10:
            case 11:
                System.out.println("秋季");
                break;
            default:
                System.out.println("你输入的月份有误");
                break;
        }

   //改进版2 (一个case后面可以有多个常量值)

     int month =6;
        switch(month){
            case 1,2,12:System.out.println("冬季"); break;
            case 3,4,5:System.out.println("春季"); break;
            case 6,7,8:System.out.println("夏季") ;break;
            case 9,10,11:System.out.println("秋季"); break;
        }

    //改进版3  (switch 可以有返回值)可以省略break;
 		/*
        统计月份对应的季节
          3 4 5 春天
          6 7 8 夏天
          9 10 11 秋天
          12 1 2 冬天
         */
        int month = 3;
        String seasonName =  switch (month) {
           case 3,4,5 ->{
               yield  "春天";   //yield 属性 就是返回的值
           }
           case 6,7,8 -> "夏天";
           case 9,10,11 ->"秋天";
           case 12,1,2->"冬天";
           default -> "您输入的月份有误";
        };
        System.out.println("seasonName = " + seasonName);

总结:switch和if分支

if适用范围判断和等值判断

switch只使用等值判断 但是等值判断的效率比If快很多

如何获取一个随机数

Math.random()

1、Math类的random()的调用,会返回一个[0,1)范围的一个double型值

2、Math.random() * 100 ---> [0,100)
(int)(Math.random() * 100) ---> [0,99]
(int)(Math.random() * 100) + 5 ----> [5,104]

3、如何获取[a,b]范围内的随机整数呢?(int)(Math.random() * (b - a + 1)) + a

class MathRandomTest {
	public static void main(String[] args) {
		double value = Math.random();
		System.out.println(value);

		//[1,6]
		int number = (int)(Math.random() * 6) + 1; //
		System.out.println(number);
	}
}

Random类

借助java.util.Random类来产生一个随机数发生器,也是最常用的一种,构造函数有两个,Random()Random(long seed)

  • 第一个就是以当前时间为默认种子
  • 第二个是以指定的种子值进行。

[n,m] 公式: rand.nextInt(m-n+1)+n;

public static void main(String[] args) {
    Random rand = new Random();
    for (int i = 0; i < 10; i++) {
        System.out.println(rand.nextInt(100) + 1);  //[1,100]
    }
}

循环语句

  • 理解:循环语句具有在某些条件满足的情况下,反复执行特定代码的功能。

  • 循环结构分类:

    • for 循环
    • while 循环
    • do-while 循环
  • 循环结构四要素

    • 初始化部分
    • 循环条件部分
    • 循环体部分
    • 迭代部分

for循环

语法格式

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

执行过程:①-②-③-④-②-③-④-②-③-④-.....-②

说明:

  • for(;;)中的两个;不能多也不能少
  • ①初始化部分可以声明多个变量,但必须是同一个类型,用逗号分隔
  • ②循环条件部分为boolean类型表达式,当值为false时,退出循环
  • ④可以有多个变量更新,用逗号分隔
for(int i=0,j=0,i<=5;i++){
 //循环体
}

while循环

语法格式

①初始化部分
while(②循环条件部分){
    ③循环体部分;
    ④迭代部分;
}

执行过程:①-②-③-④-②-③-④-②-③-④-...-②

说明:

  • while(循环条件)中循环条件必须是boolean类型。
  • 注意不要忘记声明④迭代部分。否则,循环将不能结束,变成死循环。
  • for循环和while循环可以相互转换。二者没有性能上的差别。实际开发中,根据具体结构的情况,选择哪个格式更合适、美观。
  • for循环与while循环的区别:初始化条件部分的作用域不同。
class WhileTest1 {
	public static void main(String[] args) {
		
		int i = 1;
		while(i <= 5){
			System.out.println("Hello World!");
			i++;
		}
	}
}

do-while循环

语法格式

①初始化部分;
do{
	③循环体部分
	④迭代部分
}while(②循环条件部分); 

执行过程:①-③-④-②-③-④-②-③-④-...-②

说明:**

  • 结尾while(循环条件)中循环条件必须是boolean类型
  • do{}while();最后有一个分号
  • do-while结构的循环体语句是至少会执行一次,这个和for和while是不一样的
  • 循环的三个结构for、while、do-while三者是可以相互转换的。
输出1~200能被5整除的数,5个为一行
public class DoWhileExam {
    public static void main(String[] args) {
        int i=1;
        int count=0;
        do{
            if(i%5==0){
                count++;
                System.out.print(i+"\t");
                if(count%5==0){
                    System.out.println();
                }
            }
            i++;

        }while (i<=200);
    }
}

对比三种循环结构

如何选择

  • 遍历有明显的循环次数(范围)的需求,选择for循环
  • 遍历没有明显的循环次数(范围)的需求,选择while循环
  • 如果循环体语句块至少执行一次,可以考虑使用do-while循环
  • 本质上:三种循环之间完全可以互相转换,都能实现循环的功能

"无限"循环

最简单"无限"循环格式:while(true) , for(;;)

关键字break和continue和return的使用

适用范围			在循环结构中使用的作用						相同点

break		switch-case
			循环结构			一旦执行,就结束(或跳出)当前循环结构		    此关键字的后面,不能声明语句

continue	循环结构			一旦执行,就结束(或跳出)当次循环结构		    此关键字的后面,不能声明语句

return      任何地方             一旦执行,结束当前方法					此关键字的后面,不能声明语句

break:如果存在标签,跳出标签所在层的循环

continue:如果存在标签,结束标签所在层的本次循环

image-20240717102424981

买可乐

/*
1. 输出1~100内的数 没有 3的倍数 以及个位是3的

2. 20元买可乐  可乐3元一瓶  瓶子可以换1块钱  最多买几瓶?
  思路一: 一次购买当前钱数的最大瓶数
      总钱数  单价  单次购买的可乐数  剩余钱数
        20    3        6            2
        8     3        2            2
        4     3        1            1
        2
  思路二: 一次购买一瓶
      总钱数  单价  单次购买的可乐数  剩余钱数
        20    3        1           17
        18    3        1           15
        16    3        1           13
        ....
 */
class LoopExer3{
    public static void main(String[] args) {
        int money  =20;
        int price = 3;

        int count = 0;

        while (money>=price){
            //买一瓶可乐
            count++;
            money = money-3+1;

        }
        System.out.println("count = " + count);


    }
}


class LoopExer2{
    public static void main(String[] args) {
        //总钱数
        int money = 20;
        //单价
        int price = 3;
        //todo 定义变量 记录每次购买的瓶子数
        int count = 0;
        //循环购买 总钱数>=单价
        while (money>=price){
            //单次购买的可乐数
            int bottle = money / price;
            //todo 将每次购买的可乐数 加到一起
            count+=bottle;

            //剩余钱数
            int freeMoney = money % price;
            //更改总钱数 = 可乐数 + 剩余钱数
            money = bottle+freeMoney;
        }

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


    }
}
public class Test {
    public static void main(String[] args) {

        for(int i = 1;i<=100;i++){
            if(i%3==0|| i%10==3){
                continue;
            }
            System.out.print(i+"\t");


        }

    }
}

数组

  • 数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
  • ​ 存储相同类型数据的有序集合.
  • 数组中的概念
    • 数组名
    • 下标(或索引)
    • 元素
    • 数组的长度

数组的声明

//推荐
元素的数据类型[] 一维数组的名称;

//不推荐
元素的数据类型  一维数组名[];

数组的声明,需要明确:

(1)数组的维度:在Java中数组的符号是[],[]表示一维,[][]表示二维。

(2)数组的元素类型:即创建的数组容器可以存储什么数据类型的数据。元素的类型可以是任意的Java的数据类型。例如:int、String、Student等。

(3)数组名:就是代表某个数组的标识符,数组名其实也是变量名,按照变量的命名规范来命名。数组名是个引用数据类型的变量,因为它代表一组数据。

数组的初始化

静态初始化

1.
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,...};
或
数据类型[] 数组名;
数组名 = new 数据类型[]{元素1,元素2,元素3,...};

2.
数据类型[] 数组名 = {元素1,元素2,元素3...};//必须在一个语句中完成,不能分成两个语句写
  • 如果数组变量的初始化和数组元素的赋值操作同时进行,那就称为静态初始化。

  • 静态初始化,本质是用静态数据(编译时已知)为数组初始化。此时数组的长度由静态数据的个数决定。

动态初始化

数组存储的元素的数据类型[] 数组名字 = new 数组存储的元素的数据类型[长度];

或

数组存储的数据类型[] 数组名字;
数组名字 = new 数组存储的数据类型[长度];
  • [长度]:数组的长度,表示数组容器中可以最多存储多少个元素。

  • 注意:数组有定长特性,长度一旦指定,不可更改。和水杯道理相同,买了一个2升的水杯,总容量就是2升是固定的。

数组元素的引用

​ 每一个存储到数组的元素,都会自动的拥有一个编号,从0开始,这个自动编号称为数组索引(index)或下标,可以通过数组的索引/下标访问到数组中的元素。

数组名[索引/下标]

数组的下标范围?

Java中数组的下标从[0]开始,下标范围是[0, 数组的长度-1],即[0, 数组名.length-1]

数组元素下标可以是整型常量或整型表达式。如a[3] , b[i] , c[6*i];

数组遍历

​ 1.普通for :通过下标,遍历数组元素展示数据

​ 2.增强for:for(数组元素类型 变量名: 数组名){

​ 变量名(数组内的每个值);}

数组元素的默认值

image-20240717134445183

Java虚拟机的内存划分

为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。

image-20240717152650784

区域名称 作用
虚拟机 用于存储正在执行的每个Java方法的局部变量表等。局部变量表存放了编译期可知长度的各种基本数据类型、对象引用,方法执行完,自动释放。
内存 存储对象(包括数组对象),new来创建的,都存储在堆内存。
方法区(元空间) 存储已被虚拟机加载的类信息、常量、(静态变量)、即时编译器编译后的代码等数据。
本地方法栈 当程序中调用了native的本地方法时,本地方法执行期间的内存区域
程序计数器 程序计数器是CPU中的寄存器,它包含每一个线程下一条要执行的指令的地址

数组的扩容与缩容数组的扩容与缩容

数组的扩容

题目:现有数组 int[] arr = new int[]{1,2,3,4,5}; ,现将数组长度扩容1倍,并将10,20,30三个数据添加到arr数组中,如何操作?

public class ArrTest1 {
    public static void main(String[] args) {

        int[] arr = new int[]{1,2,3,4,5};
        int[] newArr = new int[arr.length << 1];

        for(int i = 0;i < arr.length;i++){
            newArr[i] = arr[i];
        }

        newArr[arr.length] = 10;
        newArr[arr.length + 1] = 20;
        newArr[arr.length + 2] = 30;

        arr = newArr;

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

数组的缩容

题目:现有数组 int[] arr={1,2,3,4,5,6,7}。现需删除数组中索引为4的元素。

public class ArrTest2 {
    public static void main(String[] args) {

        int[] arr = {1, 2, 3, 4, 5, 6, 7};
        //删除数组中索引为4的元素
        int delIndex = 4;
        //方案1:
        /*//创建新数组
        int[] newArr = new int[arr.length - 1];

        for (int i = 0; i < delIndex; i++) {
            newArr[i] = arr[i];
        }
        for (int i = delIndex + 1; i < arr.length; i++) {
            newArr[i - 1] = arr[i];
        }

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

        //方案2:
        for (int i = delIndex; i < arr.length - 1; i++) {
            arr[i] = arr[i + 1];
        }
        arr[arr.length - 1] = 0;

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

数组元素排序

冒泡排序(依次前后两个元素进行比较,根据排序规则确定较大(或较小)的元素向后移动(或向后移动)。最后直到最大(或最小)元素移动到最后一位(或第一位))

  • 时间复杂度:平均 O(n²),最坏 O(n²),最好 O(n)
  • 稳定排序,通常用于教学和简单场景。
//冒泡
public class ArraySort{
    public static void main(String[] args) {
        int[] arr ={3,9,-1,10,-2,6};
        //优化冒泡算法
        boolean flag = false;
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr.length-i-1; j++) {
                if(arr[j]>arr[j+1]){
                    flag=true;
                    int temp  = arr[j+1];
                    arr[j+1]=arr[j];
                    arr[j]=temp;
                }
            }
            System.out.println(Arrays.toString(arr));
            if(!flag){
                break;
            }
        }
    }
}

选择排序(首先选择第“i”个元素下标当作是最小(或是最大)依次去跟后面的元素比较记录下最小(或最大)元素的下标,然后第“i”个元素于记录的下标元素交换位置)

  • 时间复杂度:O(n²)
  • 简单易懂,不稳定,适合小规模数据。
//选择排序
class ArraySort2 {
    public static void main(String[] args) {
        int[] arr = {3, 9, -1, 10, -2, 6};
        for (int i = 0; i < arr.length; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[minIndex] > arr[j]) {
                    //记录最小数字的下标
                    minIndex = j;
                }
            }
            //最小和第一个元素交换位置
            if (minIndex != i) {   //优化  如果最小值的下标没有变化了,就说明已经排好序了
                int temp = arr[minIndex];
                arr[minIndex] = arr[i];
                arr[i] = temp;
            }
            else break;
            System.out.println(Arrays.toString(arr));
        }
    }
}

插入排序(把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表)

  • 时间复杂度:平均 O(n²),最坏 O(n²),最好 O(n)
  • 简单且适合小规模数据,稳定排序。
//插入排序
class ArraySort3 {
    public static void main(String[] args) {
        int[] arr = {3, 9, -1, 10, -2, 6};
        for (int i = 1; i < arr.length; i++) {
            //记录待插入的数
            int insertVal = arr[i];
            //记录待插入的数,插入的前一个有序元素的下标
            int insertIndex = i - 1;
            //防止下标越界和(定位该元素插入有序列表的下标数)
            while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
                arr[insertIndex + 1] = arr[insertIndex];  //将比待插入大的元素都后移一位
                insertIndex--;
            }
            //循环结束后得到了待插入元素插入的位置
            arr[insertIndex+1]=insertVal;
            System.out.println(Arrays.toString(arr));
        }
    }
}

快速排序(通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列)

  • 时间复杂度:平均 O(n log n),最坏 O(n²)
  • 原地排序,适合大多数情况,效率高。
//快速排序
class ArraySort4 {
    public static void main(String[] args) {
        int[] arr = {3, 9, -1, 10, -2, 6};
        //int[] arr = {3, 6, 8, 10, 1, 2, 1};
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }
    public static void quickSort(int[] arr, int low, int high) {
        if (arr == null || arr.length == 0){
            return;
        }

        if (low >= high){
            return;
        }

        int middle = low + (high - low) / 2;   // 这样永远都是一段数组的"最中间值(向下取整)"   例子  low =0    high =3   mid = 0+3/2 =1
        int pivot = arr[middle];
        int l = low, r = high; //记录当前开始下标和当前结束下标
        while (l <= r){
            //从当前开始下标开始查找比中间值   大的值的下标
            while (arr[l] < pivot){
                l++;
            }
            //从当前结束下标开始查找比中间值   小的值的下标
            while (arr[r] > pivot){
                r--;
            }
            //如果找到的下标满足当前开始下标小于等于当前结束下标,就互相交换值 ,并当前开始下标后移1,当前结束下标前移1
            if (l <= r){
                int temp = arr[l];
                arr[l] = arr[r];
                arr[r] = temp;
                l++;
                r--;
            }
        }
        if (low < r){   //如果开始下标小于当前结束下标,向左递归(开始下标不变,结束下标变成,当前结束下标 r)   【1,3,4]   ,2,1】
            quickSort(arr, low, r);
        }
        if (high > l){  //如果结束下标大于当前开始下标,向右递归(结束下标不变,开始下标变成,当前开始下标 l)   【1,3,    [4,2,1】
            quickSort(arr, l, high);
        }
    }
}

归并排序(是利用归并的思想实现的排序方法,该算法采用经典的分治策略(分治法将问题分成一些小的问题然后递归求解,而治的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之))

  • 时间复杂度:O(n log n)
  • 稳定排序,适合处理大数据量,尤其是链表。

二维数组

分类

  • 二维数组:
    • 所谓二维数组其实就是多个一维数组作为元素,存储在一个一维数组中
  • 三维数组
    • 所谓三维数组其实就是多个二维数组作为元素,存储在一个一维数组中
  • 四维数组
    • 所谓三维数组其实就是多个三维数组作为元素,存储在一个一维数组中

声明与初始化

声明

//推荐
元素的数据类型[][] 二维数组的名;

//不推荐
元素的数据类型  二维数组名[][];
//不推荐
元素的数据类型[]  二维数组名[]

静态初始化

int[][] arr = {{1,2,3},{4,5,6},{7,8,9,10}};//声明与初始化必须在一句完成

int[][] arr = new int[][]{{1,2,3},{4,5,6},{7,8,9,10}};

int[][] arr;
arr = new int[][]{{1,2,3},{4,5,6},{7,8,9,10}};

arr = new int[3][3]{{1,2,3},{4,5,6},{7,8,9,10}};//错误,静态初始化右边new 数据类型[][]中不能写数字

动态初始化

/**动态1*/
//(1)确定行数和列数
元素的数据类型[][] 二维数组名 = new 元素的数据类型[m][n];
例:int[][] arr = new int[3][2];
	//其中,m:表示这个二维数组有多少个一维数组。或者说一共二维表有几行
	//其中,n:表示每一个一维数组的元素有多少个。或者说每一行共有一个单元格

//此时创建完数组,行数、列数确定,而且元素也都有默认值

//(2)再为元素赋新值
二维数组名[行下标][列下标] = 值;


/**动态2*/
//(1)先确定总行数
元素的数据类型[][] 二维数组名 = new 元素的数据类型[总行数][];

//此时只是确定了总行数,每一行里面现在是null

//(2)再确定每一行的列数,创建每一行的一维数组
二维数组名[行下标] = new 元素的数据类型[该行的总列数];

//此时已经new完的行的元素就有默认值了,没有new的行还是null

//(3)再为元素赋值
二维数组名[行下标][列下标] = 值;

遍历二维数组(多位也一样)

普通for

for(int i=0; i<二维数组名.length; i++){ //二维数组对象.length
    for(int j=0; j<二维数组名[i].length; j++){//二维数组行对象.length
        System.out.print(二维数组名[i][j]);
    }
    System.out.println();
}

增强for

for(一维数组类型[] 变量名1:二维数组变量){
    for(数据类型 变量名2 : 变量名1){
        变量名(数组内的每个值);
    }
}

空指针异常:

public class TestNullPointerException {
    public static void main(String[] args) {
        //定义数组
        int[][] arr = new int[3][];

        System.out.println(arr[0][0]);//NullPointerException
    }
}

因为此时数组的每一行还未分配具体存储元素的空间,此时arr[0]是null,此时访问arr[0][0]会抛出NullPointerException 空指针异常。

面向对象思想编程

方法(对功能进行封装,实现代码的复用)

  • 方法是类或对象行为特征的抽象,用来完成某个功能操作。在某些语言中也称为函数过程
  • 将功能封装为方法的目的是,可以实现代码重用,减少冗余,简化代码
  • Java里的方法不能独立存在,所有的方法必须定义在类里。
方法必须声明在类中 且不能嵌套使用
    类{
    方法1(){
        
    }
    方法2(){
        
    }
}

定义方法:

    修饰符   返回值类型
public static void 方法名([形参列表]){
   //方法的内容
}

//public static 是方法的修饰符 公共的 静态的
//返回值类型:表示方法运行的结果的数据类型,方法执行后将结果返回到调用者
//方法名:给方法起一个名字,见名知意,能准确代表该方法功能的名字
//形参列表:表示完成方法体功能时需要外部提供的数据列表
//方法体:方法体必须有{}括起来,在{}中编写完成方法功能的代码

方法调用:

public class Method {
    public static void main(String[] args) {
        System.out.println("调用方法");
        eat();
    }
    public static void eat(){
        System.out.println("吃饭了!!!");
    }
}

方法的形参和返回值

形参和实参:

方法的形参:
        1.方法的声明处
        2.规定方法实参的数量和类型
方法的实参:
        方法调用者传递的实际的值
            
例:
public class MethodTest3 {
    //方法的声明
    public static void sum(int a,int b){//形参
        System.out.println(a+b);
    }

    public static void main(String[] args) {
      
        sum(10,30);//实参
    }

}

方法的返回值:

有的时候需要方法执行的结果作为下次执行的条件就需要带返回值的方法
public static 返回值类型 方法名([形参列表]){
        方法体的功能代码
}
返回值类型:  
      void:没有返回值
   数据类型:必须通过 return 关键字 返回一个该类型匹配的值 
   
- return语句的作用是结束方法的执行,并将方法的结果返回去
- 如果返回值类型不是void,方法体中必须保证一定有 return 返回值; 语句,并且要求该返回值结果的类型与声明的返回值类型一致或兼容。
- 如果返回值类型为void时,方法体中可以没有return语句,如果要用return语句提前结束方法的执行,那么return后面不能跟返回值,直接写return ; 就可以。
- return语句后面就不能再写其他代码了,否则会报错:Unreachable code
    
例:    
public class MethodTest4 {
    //方法的声明
    public static int sum(int a,int b){//形参 
        return a+b;
    }

    public static void main(String[] args) {
      
       int result =  sum(10,30);//实参
        System.out.println("result = "+ result);
    }

}

注意:
方法只声明不调用 不会执行"
方法与方法是兄弟关系
class 类{
方法a(){}
方法b(){}
}
方法执行完毕 回到方法调用处

方法的重载(在同一类中使用相同的方法名表示不同细节实现的方法)

新:本类或者父子类中有相同的方法名 不同的形参列表(数量 顺序 类型) 就是重载

要求: 两同一不同

​ 两同:同一类中同一方法实现

​ 不同:参数列表不同: 数量、类型、顺序

//找两个数的最大值
public class MethodsOverload {
    public static void main(String[] args) {
        System.out.println((char)Compare('a','b'));
        System.out.println(Compare(10,2));
        System.out.println(Compare(6.1,5.1));
    }
    public static int Compare(int a, int b){
        return a>b?a:b;
    }
    public static int Compare(double a, double b){
        return (char)(a>b?a:b);
    }
    public static int Compare(char a, char b){
        return a>b?a:b;
    }
}

可变参数

当定义一个方法时,形参的类型可以确定,但是形参的个数不确定,那么可以考虑使用可变参数

声明可变参数:

public 返回值类型 方法名(【非可变参数部分的形参列表,】参数类型... 形参名){  

}

可变参数的特点

(1)一个方法最多只能有一个可变参数(语法规定)

(2)如果一个方法包含可变参数,那么可变参数必须是形参列表的最后一个

(3)在声明它的方法中,可变参数当成数组使用

(4)可变参数中实参的数量[0,n]

public class MethodVariableParams {
    public static void main(String[] args) {
        System.out.println(joins('-',"c","h","s"));
    }
    //字符于字符串拼接
    public static String joins(char c,String ...s){
        String temp="";
        for (int i = 0; i < s.length; i++) {
            if(i==s.length-1) temp+=s[i];
            else  temp+=s[i]+c;
        }
        return temp;
  }

方法的值传递(画图)

基本类型数据的值:传递的是值的副本

数组作为参数:传递的是地址值

标签:arr,int,数据类型,运算符,数组,javaSE,public
From: https://www.cnblogs.com/21CHS/p/18365558

相关文章

  • javaSE面向对象
    面向对象思想编程学习面向对象内容的三条主线Java类及类的成员:(重点)属性、方法、构造器;(熟悉)代码块、内部类面向对象的特征:封装、继承、多态、(抽象)其他关键字的使用:this、super、package、import、static、final、interface、abstract等方法(对功能进行封装,实现代码的复用)方......
  • 【JavaSec】JDK动态代理初探
    JDK动态代理初探文章目录JDK动态代理初探静态代理动态代理静态代理用户接口:publicinterfaceIUser{voidshow();voidcreate();voidupdate();}用户实现类:/***实现类*/publicclassUserImplimplementsIUser{publicUserI......
  • JavaSE基础知识分享(八)
    写在前面前面讲的是java中集合这部分的内容,今天给大家发一个上期题目参考答案!Person类:packagecom.shujia.TiMu_1000.ten2.Ti15;/***@authorcjy*@create2024-08-07-20:47*/publicabstractclassPerson{privateStringname;privateintage;pri......
  • JavaSE基础知识分享(七)
    写在前面前面讲的是面向对象中的常用类部分,下面让我们来看看java中集合这部分的内容!在本文的最后给大家发一个题目,便于复习Java面向对象部分的知识!集合数据结构栈和队列数组和链表树哈希表图本部分知识太多,就不一一列举了。了解更多泛型泛型类格式......
  • JavaSE基础知识分享(六)
    写在前面前面讲的是面向对象中的多态这部分,下面让我们来看看java中常用类这部分的内容!常用类Object概述:是Java中所有类的父类,包括自己定义的类和数组都继承自Object类。成员方法hashCode()获取对象地址值的int类型形式。getClass()获取对象的类的字节码文件对......
  • javase-day06
    aFile_FileDemo01packagecom.se.aFile;/***绝对路径与相对路径的说明:*1.当前工作空间是/home/user/michael/**需求1:访问/home/user/michael/file1.txt*相对路径:file1.txt*绝对路径:/home/user/michael/file1.txt**需求2:访问/home/user/mi......
  • 24-08-08 JavaSE Map集合
    24-08-08javaSEMap集合Map接口的特点Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value(双列元素)Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中3.Map中的key不允许重复,原因和HashSet一样,前面分析过源码.Map......
  • JavaSE基础(5)——抽象类与接口
    目录1、abstract关键字 2、抽象方法3、抽象类4、接口5、接口与抽象类的区别6、JDK8版本接口新特性7、类之间的关系8、UML类图1、abstract关键字 可以修饰类和方法,不可以修饰属性,对应的类和方法就称之为抽象类和抽象方法;2、抽象方法有抽象方法的类一定是抽象类......
  • JavaSE基础知识分享(五)
    写在前面前面讲的是面向对象中的继承思想,下面让我们来看看多态这部分的内容!Java面向对象概念概述多态概述:某一个事物在不同状态下的多种状态。实现多态的三大前提:要有继承关系。要有方法的重写。要有父类的引用指向子类对象。访问成员的特点:成员变量:编译时看左,运行......
  • javase-day01
    aException_Exception01packagecom.se.aException;/***异常,Exception,父类Throwable。与其平级的是Error(Error错误,程序员无法处理,属于JVM级别的错误)*1.程序员可以处理异常。如果不处理,即JVM帮忙处理,简单粗暴,就是终止程序的运行*2.所以,程序员应该处理......