返回

Java基础-1

java概述

cmd命令

指定位置快捷打开cmd:在文件夹下的路径上直接输入cmd回车打开

环境变量:就是把文件/软件所在的路径记录下来,从而在任何地方都能够打开。(一般是添加到系统环境变量中的path,直接把软件的完整路径复制就行,而不是添加到用户环境变量)

1
过程:当在任何一个位置打开文件时,系统会从上往下依次扫描所记录的全部环境变量,一个一个查      看这个路径下是否有所要打开的文      件,直到找到

java安装和运行

(建议把所有开发相关的软件放在同一文件夹下)

1、下载和安装JDK

image-20250420163654961

2、下载IDEA

java最好用的集成开发环境(编译、调试等),下载时下载收费版的exe文件(zip文件会包含一些说明文档,这些我们不需要),然后傻瓜式安装即可

  • 输入psvmmain会自动生成main语句
  • 输入so会自动生成输出语句

(javac、java工具都在jdk文件下的bin目录下,安装时自动配置了环境变量,所以在命令行任何地方都能使用)运行java程序包含三个步骤:

  1. 编写代码
  2. 编译文件(即翻译成机器认识的语言)
    1. javac是jdk提供的一个编译工具,编译后生成.class文件
  3. 运行程序
    1. java也是jdk提供的一个工具,用来运行程序(运行时不加后缀)

Idea UI的一些使用步骤:

  • 项目是整体的大文件(微信);项目中模块是相互独立的(聊天、好友、朋友圈、我);模块中有多个组成,即文件夹;在包里面有一个或多个用来写java代码
  • 注意:包的命令是有规范的,一般用公司域名的反写+包的作用命名,如com.itheima.demo1
  • 配置:设置字体(consolas)、字号(18)、自动导包、不区分大小写、背景图片

项目模块相关操作:

  • 类的操作:新建类、删除类、修改类
    • 修改类需要在类的文件右键重命名进行修改,而不能直接在代码里直接修改类名(要和文件名保持一致)
  • 模块的操作:新建、删除、修改、导入
  • 项目的操作:新建、打开、关闭、修改
image-20250420165055831
image-20250420165113681
image-20250420165136484
image-20250420165233917
image-20250420165306459

配置环境变量

为java相关的软件单独配置一个路径:JAVA_HOME

image-20250420165644574

这样配置其实也就等价于直接置环境变量E:\develop\jdk\bin了(只不过path里面有很多环境变量,可能会操作到其他变量,如果不小心修改就完了)

java历史和分类

java历史

JDK(Java Development Kit)是Java开发工具包的缩写,主要组成部分有:

  • java运行环境 –JRE
  • java虚拟机 –JVM
  • java工具 –如javac、java、javap等
  • java基础类库 –如rt.jar

长期支持版本:

  • JDK 8 发布于2014年
  • JDK 11 发布于2018年
  • JDK 17 发布于2021年
  • JDK 21 发布于2023年
image-20250420170013636

一文彻底搞懂令人疑惑的Java和JDK的版本命名!

Java Platform, 版本更新说明

Java版本历史图 - 大佬总结

java分类

  • Java SE:java语言标准版,是其他两个版本的基础,用于桌面应用的开发
  • Java ME:java语言的小型版,用于嵌入式设备开发(可忽略)
  • Java EE:java语言的企业版,在SE基础上添加了一些企业级开发的规范和框架(最火爆)

java跨平台原理

java语言的跨平台是通过虚拟机实现的

java语言不是直接运行在操作系统里面的,而是运行在虚拟机中的

针对不同的操作系统(平台),安装不同的虚拟机就可以了

jdk和jre

java历史中已经简单介绍了,现在详细介绍一下:

  • JDK:java开发工具包,用于开发和运行java程序代码
    • JVM虚拟机:java程序运行的地方
    • 核心类库:各种类
    • 开发工具:javac、java、jdb、jhat
  • JRE:java运行环境,用来运行java代码,相当于从JDK取了一部分出来
    • JVM
    • 核心类库
    • 部分运行工具

关系:JDK包含JRE,JRE包含JVM

JRE 与 JDK的区别 | 菜鸟教程

IDEA快捷键

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Ctrl + alt + L                   自动格式化代码(排版)
main                             打印主函数语句
so/sout                          打印输出语句
5.fori / arr.fori                打印for循环语句,循环5次 / 数组遍历
arr.forr                         倒着遍历
ctrl+alt+v                       自动补全代码
ctrl+alt+t                       选择用if还是while等包裹一段代码
ctrl+p                           查看(自定义方法)形参、参数等
ctrl+alt+M                       自动抽取方法(选中代码,按快捷键自动抽取)
alt + insert                     构造方法、set/get生成
ctrl + b                         查看(类方法-API)源码
alt + enter                      打开红色报错

常用库

Scanner

1
2
3
import java.util.Scanner;    //导包
Scanner sc = new Scanner(System.in);   //创建对象
int i = sc.nextInt();       //接收数据

Random

1
2
3
4
5
6
7
import java.util.Random;     //导包(自动)
Random r = new Random();     //创建对象
int number = r.nextInt(终止范围);    //生成随机数,左闭右开,一定是从0开始

//实现任意数到任意数的范围,如7-15(对应0-8)
Random r = new Random();
int number = r.nextInt(9) + 7;

Java 基础语法 | 菜鸟教程

java语法基础

常量、变量、数据类型

(1)注释和关键字

  • 注释分为单行注释、多行注释和文档注释
  • 关键字:程序根据关键字知道要做什么事情

(2)第一个关键字-class

class关键字表示定义一个类,后面跟随类名。那如何理解类呢?可以把类当成人体的细胞,一个java程序由超级多的类组成,编写代码的时候看需要那个细胞就编写那个细胞,从而组成一个完整的人

注:类名要和文件名保持一致

(3)常量/字面量

  • 字面量分类:整数、小数、字符串、字符、布尔、空(null)
  • 一些特殊的字面量:制表符\t、空类型null
1
2
3
4
5
6
null不能直接打印,只能用字符串的形式打印,如System.out.println("null");
直接输出会导致编译错误:System.out.println(null);

制表符的作用是把前面的字符串长度补齐到8,或者8的倍数,从而想表格一样整齐,如
            System.out.println("name"+"\t"+"tom");   补4个空格
            System.out.println("age"+"\t"+"23");     补5个空格

(4)变量

  • 变量可以重复使用,但不能重复定义,即不能写两次int a = xxx;
  • 变量使用之前一定要进行赋值
  • 变量的作用域范围:只在当前所属的大括号内有效
  • 一条语句中可以定义多个变量,如int d=100,e=200,f=300;

(5)数据类型-1

  • java中的数据类型分为:基本数据类型(四类八种)和引用数据类型【string是典型的引用数据类型
  • 【四类八种外加引,1+1+2+4】
1
2
3
4
注意事项:
定义long类型变量:需在数值后面加入L作为后缀(大小写均可)  long a = 99999L;
定义float类型变量:需在数值后面加入F作为后缀(大小写均可) float a = 23.3F;
如果不加后缀的话使用的是默认的数据类型(int和double)
image-20250420175257654

(6)计算机中的数据存储

  • 二进制:0b开头; 十进制; 八进制:0开头; 十六进制:0x开头
  • 之所以使用二进制是因为:二进制很好区分,以前是有孔和没孔,现在是高压和低压
  • 我们知道,计算机中任何数据都是二进制存储。可以把计算机中所有数据归为:文本、图片、声音三类数据,那这三类数据是如何存储的呢?

文本:又包括数字、字母、汉字三类,字母和汉字都是通过码表先转换为十进制数字,然后用二进制存储在计算机中,如Unicode编码表包含了世界各国语言对应的数字

图片:图片就是一个一个的像素(分辨率)组成,一个像素对应一个数字(对于灰度图,数字范围是0-255表示不同灰度等级)存储在计算机;而如果是彩色图片,无非就是每一个像素搭配了不同的三原色RGB实现存储(RGB红绿蓝,一个像素点对应三个数字)

声音:也是类似,对声音的波形图进行采样再进行存储,即将声音的波形图划分,图上每一个点对应一个数字(类似码表的一一映射)。日常生活中的声音无损和有损就是采样点的多少,采样的多就和真实没啥区别。图片的有损和无损也是同样道理。

(7)标识符-2

标识符/变量名命令建议(阿里规范)

image-20250420175545181

(8)键盘录入-3

Java有一个类叫Scanner,这个类就可以接受键盘输入的数字。(变量i记录键盘所敲的数字)

image-20250420175614616

类–>对象–>多个实例

(9)输出语句

1
2
3
System.out.println(arr[i]);         //打印后换行
System.out.print(arr[i] + " ");     //打印不换行
System.out.println();               //只进行换行,不输出内容

运算符🌙

(9)数值拆分

使用运算符进行数值拆分

1
2
3
4
5
1234
个位:数值 % 10
十位:数值 / 10 % 10
百位:数值 / 100 % 10
千位:数值 / 1000 % 10

自增自减运算符:a++先用后加,a的值发生改变;++a先加后用,a的值发生改变

1
2
3
4
int x = 10;
int y = x++;
int z = ++x;
最终x=12,y=10,z=12

扩展赋值运算符:+=、-=、*=、/=、%=底层都隐藏了一个强制类型转换

1
2
3
short s = 1;
s += 1;     //先进行s+1,为int类型,然后强转后赋值
等同于s = (short)(s + 1);

逻辑运算符:

image-20250420175956129

短路逻辑运算符:

因为逻辑运算符效率比较低(无论左边能不能确定结果,右边都要判断),所以之后常用的是短路逻辑运算符来提高效率。

举个例子:登陆时需要输入用户名和密码,使用逻辑运算符&时无论用户名输入是否正确,密码都需要判断;而使用短路逻辑运算符&&时,如果用户名输入错误,那无论密码正确与否都不重要的,即不用判断密码了,代码只判断用户名错误就结束了

image-20250420180241815

三元运算符:关系表达式 ? 表达式1 : 表达式2;

先执行关系表达式,结果如果为真,则输出表达式1,结果如果为假,则输出表达式2

(10)运算符优先级

所有数学运算基本都是从左往右进行的;只有单目运算符、赋值运算符和三目运算符例外(从右往左)

Tip:注意最后一行的扩展赋值运算符是从右往左执行的;记死小括号最高,扩展赋值最低
在大部分编程语言中,都是这样的:有些远算符是从左到右,有些是从右到左(如赋值)

image-20250420180441451

(11)类型转换

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

  • 数字相加
  • 字符串相加:当执行“+”操作时,只要出现字符串,就不是运算操作,而是拼接操作了
  • 字符相加:先把字符通过ascii转为数字在相加
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
byte b1 = 10;
byte b2 = 20;
byte result = (byte)(b1+b2);
b1+b2在计算前都会先转成int,相加后也是int类型,而最终要赋给byte类型,因此要用强转

byte b1 += 10;    //这个不用强转也不报错,原因见上面

1+99+"xxcjw"+1    //输出结果是"100xxcjw1"
true+"xxcjw"      //输出结果是"truexxcjw"
连续+操作时,从左到右依次执行;当+前后有字符串时,就是拼接操作

字符相加

1
System.out.printIn('0'+0);    //

字符在运算时都会先转换成数字在运算(查码表),所以这里有个操作就是如果想知道某个数字字符对应的数字,可以通过+0实现,因为0不会改变运算的结果

原码、反码、补码

  • 正数的原码、反码、补码就是其本身,不变
  • 原码:数据的二进制表现形式,最左边是符号位
    • 弊端:如果是负数计算,运算方向和实际相反,导致结果错误
  • 反码:(负数反码为)符号位不变,其余数值取反
    • 出现目的:为了解决原码不能计算负数的问题出现
    • 弊端:0有两种表示,如果负数运算时跨0,与实际结果会有1的偏差
  • 补码:负数的补码在反码的基础上+1
    • 为了解决负数反码计算时跨0的问题而出现
    • 计算机中的存储和计算都是以补码形式进行的(核心!)
1
2
3
4
5
看个例子:
int a = 300;          //0000 0000 0000 0000 0000 0000 1100 1000
byte b = (byte)a;     //1100 1000
所以b就是1100 1000,注意啦,这个数值在计算机是以补码存储的,正数无所谓,
但此时这个是负数,将补码转为原码最终就是-56,所以b=-56

计算总结:

image-20250420181244190

从位的角度理解逻辑运算符(以原码反码补码解释)

image-20250420181316947

流程控制语句

分支结构

(1)if语句

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
if( xxxx ) {             # 第一种结构
xxxxx;
}

if( xxxx ) {             # 第二种结构
xxxxx;
} else {
xxxx;
}

if( xxxx ) {              # 第三种结构
xxxxx;
} else if {
xxxxx;
} else {
xxxxx;
}

(2)switch语句

注意一点:case后面的值只能是常量而不能是变量;switch后面的表达式通常是变量,来表示各种情况

  • default可以写在任意位置,但习惯写在最后来表示异常情况

  • case穿透:就是去掉了break语句导致的

    • 拿表达式的值和下面每一个case的值匹配,如果匹配上,则执行相应语句,如果有break,则结束
    • 如果没有发现break,那么程序会继续执行下一下case的语句体,一直遇到break为止
  • switch新特性,即优化了写法(JDK12及以后)

    • 在 Java 12 及以后的版本中,switch 语句引入了新的语法形式,即使用 -> 箭头语法,这种语法下不会发生 case 穿透。
  • if第三种结构适用于范围判断;switch适用于枚举,把有限的数据一一列举出来

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
switch(表达式){
    case 值1:
        语句1;
        break;
    case 值2:
        语句2;
        break;
    ...
    default:
        语句n+1;
        break;
}

示例如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
case穿透实例输入日期如果是1-5则是工作日如果是6-7则是休息日
//比如输入2,和case 1不匹配;和case 2匹配,则执行case 2的语句体,发现没有break,则会继续往下执行case的语句体(就不用匹配了),直到遇见break,即执行完case 5的语句体结束

//1、键盘录入
Scanner sc = new Scanner(System.in);
System.out.println("请录入一个整数表示星期");
int week = sc.nextInt();
//2、利用switch语句选择
switch (week){
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        System.out.println("工作日");
        break;
    case 6:
    case 7:
        System.out.println("休息日");
        break;
    default:
        System.out.println("没有这个星期");
        break;
}

//简化代码
switch (week){
    case 1,2,3,4,5:
        System.out.println("工作日");
        break;
    case 6,7:
        System.out.println("休息日");
        break;
    default:
        System.out.println("没有这个星期");
        break;
}

switch新特性:(不会触发case穿透)

  • 不用写break(把break简化了,不用手动写l);也不会触发case穿透
1
2
3
4
5
6
7
8
int number = 1;
switch (number){
    case 1 -> {System.out.println("一");}
    case 2 -> {System.out.println("二");}
    case 3 -> {System.out.println("三");}
    default -> {System.out.println("没有这个选项");}
}
// 输出为“一”

循环结构

(1)for循环

1
2
3
4
5
6
7
for(初始化语句;条件判断语句;条件控制语句){
    循环体语句
}

for(int i = 0;i <= 10;i++){
    System.out.println("xxcjw");
}
  • 变量的作用范围只在变量所属的大括号中有效
    • 之后如果要写累加求和的变量,可以把变量定义在循环的外面。当把变量定义在循环里时,当前变量只在本次循环中有效,当本次循环结束时,变量会消失;当下次循环开始时,又会重新定义一个该变量
  • for循环中的累加思想:定义一个变量在循环外,循环内+=
  • for循环中的统计思想:统计个数用自增运算符,循环外定义一个变量,循环内自增

(2)while循环

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
初始化语句;
while(条件判断语句){
    循环体语句;
    条件控制语句;
}

int i =1;
while(i <= 100){
    System.out.println(i);
    i++;
}

(3)for和while区别

  • 初始化语句中变量的作用域区别(不绝对)
image-20250421103411538
  • 开发中根据情况使用
image-20250421103447127

跳转控制语句⭐

  • continue:跳出本次循环,继续下次循环
  • break:跳出整个循环

⭐在for循环或while循环中,适当使用跳转控制语句可以大大提高效率,要把循环语句和跳转控制语句绑在一起,提起一方就想到另一方。比如循环100次,但在第10次就得到结果了(求平方根),那使用break后面就不用在执行了,提高效率。

⭐比如经常碰见的场景:(猜数字)不知道循环多少次,那就写死循环,直到相等时break退出就行

⭐注意:这两个语句都和判断语句if无关

一些思想😊

倒序输出思想、标记思想、统计思想

练习两道力扣题:(1)回文数(2)判断质数(3)猜数字

1、回文数(注意与数值切分的区别,倒序输出思想)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
//回文数:正着读和反着读都一样,如121,1221
//思路:把数字倒过来跟原来的数字进行比较(容易想到的是数值切分和拼接,但有很多细节)

int x =12345;
int temp = x;    //临时变量记录原来输入的值,用于最后比较,因为x会变化
int num = 0;     //记录倒过来之后的值
while(){         //一开始不知道循环结束条件可以先不写
    int ge = x % 10;     //从右往左获取每一位数字
    x = x / 10;
    num = num * 10 + ge;   //拼接
}
System.out.println(num == temp);   //比较

2、判断是否为质数(用到了标记思想)

标记思想通常用于数据筛选与过滤中,比如筛选特定数据、路径搜索与图算法中的节点状态deng

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//判断一个属是否为质数(只能被1和它本身整除)

//1、键盘录入一个整数
Scanner sc = new Scanner(System.in);
System.out,println("请输入一个正整数");
int number = sc.nextInt();

//表示最初就认为是一个质数,标记思想
boolean flag = true;

//2、for循环判断
for (int i = 2;i < number;i++){        //number.fori快捷键
    if(number % i == 0){
        flag = false;
        System.out.println(number + "不是一个质数");
        break;
    }
}
if(flag){
    System.out.println(number + "是一个质数");
}else{
    System.out.println(number + "是一个质数");
}

进一步优化:

1
2
3
//上述代码,如果输入的数很大,则需要循环很多次,下面进行优化
//思路:如果一个数不是质数,则它的因子中必定有一个是小于其平方根的,如81,只需要循环到9
//     for(int i = 2;i <= number的平方根;i++)

3、猜数字游戏【注:统计思想和求和思想见for循环】

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//1、生成1-100之间的随机数字
Random r = new Random();
int number = r.nextInt(100) + 1;
//2、键盘录入
Scanner sc = new Scanner(System.in);
int count = 0;
while(true){      //死循环,和break配合
    System.out.println("输入你猜的数字:");
    int guessNumber = sc.nextInt();
    
    //3、判断,给出提示
    if(guessNumber > number){
        System.out.println("大了");
    } else if(guessNumber < number) {
        System.out.println("小了");
    } else {
        System.out.println("猜中了");
        break;
    }
    
    //4、保底机制
    count++;
    if(count == 3){
        System.out.println("猜中了");
        break;
    }
}

数组

定义和初始化

1、定义

数组就是一种容器,可以用来存储多个同种类型数据

2、静态初始化

1
2
3
4
5
6
7
8
9
//完整格式(了解)
数据类型[] 数组名 = new 数据类型[]{num1,num2...}
int[] array = new int[]{11,22,33};

//简化格式(掌握)
数据类型[] 数组名 = {num1,num2...}
int[] array = {11,22,33};
double[] array = {11.1,22.2,33.3};
string[] array = {"张三","李四","王五"};

3、数组元素访问

数组的长度属性:数组名.length arr.length

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
//直接打印数组名输出的是数组的地址值
int[] array = {11,22,33};
System.out.println(array);    //输出  [D@776ec8df
//[-表示是一个数组;D-表示数组里面元素是double类型;@-间隔符号,固定格式;776ec8df-地址值
                              
//用索引数组实现元素访问
System.out.println(array[0]);    //打印第一个元素
array[0] = 100;                  //修改数组元素

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

小技巧:一个循环尽量只干一件事情;比如一个循环修改数组元素值,用另一个循环打印输出

4、动态初始化

定义:初始化时只指定数组长度,系统为该数组分配初始值

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
//动态初始化
String[] arr = new String[50];
//添加数据
arr[0] = "张三";
arr[1] = "里斯";

/* 引用数据类型 默认初始化为null
   整数数据类型 默认初始化为0
   浮点数数据类型 默认初始化为0.0
   char数据类型 默认初始化为空格
 */

5、区别

image-20250421110557602

数组常见操作

(1)求最值

思路:定义一个变量存储最值(参照物),拿数组中的元素比较

1
2
3
4
5
6
int max = arr[0];
for(int i = 1;i < arr.length;i++){
    if(arr[i] > max){
        max = arr[i];
    }
}

(2)随机生成+求和

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
int[] arr = new int[10];   //动态初始化
Random r = new Random();

//生成10个随机数
for(int i = 0;i < arr.length;i++){
    int number = r.nextInt(100) + 1;
    arr[i] = number;
}

//求和,一个循环干一件事
int sum = 0;
for(int i = 0;i < arr.length;i++){
    sum += arr[i];
}

(3)交换数据

思路:定义两个变量分别从前往后和从后往前记录索引

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
//输入12345,输出54321
int[] arr = {1,2,3,4,5};

//先进行两个数据的交换,然后无非就是多次循环
for(int i = 0,j = arr.length - 1;i < j;i++,j--){
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

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

(4)打乱数据

关键问题:获取随机索引;对每个元素进行随机交换数据

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

for(int i = 0;i < arr.length;i++){
    //定义随机索引
    int randomIndex = r.nextInt(arr.length); 
    //交换数据
    int temp = arr[i];
    arr[i] = arr[randomIndex];
    arr[randomIndex] = temp;
}

(5)打印数组+逗号

1
2
3
4
5
6
7
8
9
//将数组打印至一行,并以逗号相隔

for(int i = 0;i < arr.length;i++){
    if(i == arr.length - 1){
        System.out.print(arr[i]);
    } else {
        System.out.print(arr[i] + ",");
    }
}

6、copy数组

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
//将数组arr从索引from开始,到索引to结束(不包含)的元素复制到新数组中

int[] arr = {1,2,3,4,5,6,8,7};
int[] copyArr = copyOfRange(arr,3,7);

//定义方法来做这件事
public static int[] copyOfRange(int[] arr,int from,int to){
    int[] newArr = new int[to - from];
    
    int index = 0;    //伪造索引的思想
    for(int i = from;i < to;i++){
        newArr[index] = arr[i];    //这里需要注意,新数组的下标不是从0开始
        index++;
    }
    return newArr;
}

数组内存图

(1)java(虚拟机)内存分配

image-20250421112632125

一看见new就知道是存储在中的,堆中的每一个对象/数组都对应一个地址值(即只要是new出来的一定在堆里面开辟了一个小空间)

方法以及方法内的变量都存储在栈中

(2)例子:数组内存图

image-20250421112907608
image-20250421112947714
最后更新于 2025-04-27 21:48
光终究会洒在你的身上,你也会灿烂一场!
本博客已稳定运行