Java基础知识点整理_java的基础知识,零基础入门到精通,收藏这篇就够了
步骤一:定义类名public class 类名(每个单词首字母大写,例如Student) {...步骤二:编写类的属性...步骤三:编写类的方法...//方法体//方法体通过对象的共性可以实现分类,分好的类就是Java的类型定义(名词),通过代码的"class"来进行定义。之后通过查找该类型的特性形成属性(名词),再通过该类型的行为动作(动词),生成方法。
目录
一.Java的诞生
1. C & C++
2. Java预想
3. Java初生
4. Java 特性和优势
5. Java三大版本
6. JDK、JRE、JVM
二.控制台程序开发
1.开发java程序步骤
2.程序运行机制
3.程序开发环境及结构
4.控制台I/O
5.程序注释
6.程序调试
三.变量与运算符
1.变量
2.成员变量与局部变量的区别
3.命名规范
4.常量
[final修饰符](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0final%E4%BF%AE%E9%A5%B0%E7%AC%A6)
5.运算符
6.位运算
四.数据类型与数组
1.Java引用数据类型
2.Java基本数据类型
3.类型转换
4.数组概述
5.数组声明创建及初始化
6.数组赋值
7.数组的默认值
8.数组长度
9.数组应用
求数组元素最大(小)值
数组元素排序
向数组中插入元素
10.二维数组
五.流程控制语句
1.分支结构
if结构
switch结构(多重分支并且条件判断是等值判断的情况)
2.循环结构
While循环(当型循环)
Do-while循环(直到型循环)
For循环(计数器循环)
Foreach循环
二重循环,以for循环为例
3. 跳转结构
break
continue
return
六.Java常见异常
七.类和对象
1.对象
2.如何创建和使用对象
3.面向对象(OO)的优点
4.封装
5.类
6.类的定义
类的定义步骤
类的方法编写步骤
方法返回值
7.方法的调用
8.带参方法
形参与实参
参数传递注意事项
9.引用数据类型传参
10.构造方法
[基本概念](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5%C2%A0%C2%A0)
[构造方法的类型](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%E7%9A%84%E7%B1%BB%E5%9E%8B%C2%A0%C2%A0)
[构造方法的重载](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%E7%9A%84%E9%87%8D%E8%BD%BD%C2%A0)
[构造方法的调用](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%E7%9A%84%E8%B0%83%E7%94%A8%C2%A0)
[this关键字](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0this%E5%85%B3%E9%94%AE%E5%AD%97%C2%A0)
[父类构造方法的调用](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%E7%88%B6%E7%B1%BB%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%E7%9A%84%E8%B0%83%E7%94%A8%C2%A0)
[构造方法的特点](about:blank#%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%E7%9A%84%E7%89%B9%E7%82%B9%C2%A0)
八.包
1.包的声明
2.包的引入
九.String字符串
1.Stirng的声明
3.字符串的length()
4.字符串的equals()
[equals() 方法的代码逻辑](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0equals%28%29%20%E6%96%B9%E6%B3%95%E7%9A%84%E4%BB%A3%E7%A0%81%E9%80%BB%E8%BE%91)
[equals()的规范](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0equals%28%29%E7%9A%84%E8%A7%84%E8%8C%83)
5.==比较
6.常用其他API方法
concat
substring
indexOf
lastIndexOf
trim
isEmpty
isBlank
split
replace和replaceAll
matches
7.StringBuffer与StringBuilder
StringBuffer与StringBuilder的区别
常用方法
十.继承
1.类的定义
[类图](about:blank#%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%E7%B1%BB%E5%9B%BE)
2.方法重载(Overload)
重载的特点
3.static关键字
[静态方法](about:blank#%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95)
[static代码块](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0static%E4%BB%A3%E7%A0%81%E5%9D%97)
[static的特点及应用场景](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0static%E7%9A%84%E7%89%B9%E7%82%B9%E5%8F%8A%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF)
4. 静态代码块,实例代码块,构造方法的执行顺序
[静态代码块](about:blank#%C2%A0%C2%A0%20%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%E9%9D%99%E6%80%81%E4%BB%A3%E7%A0%81%E5%9D%97)
[实例代码块](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%E5%AE%9E%E4%BE%8B%E4%BB%A3%E7%A0%81%E5%9D%97)
[构造方法](about:blank#%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95)
执行顺序示例
5.封装
[封装的优点](about:blank#%C2%A0%20%C2%A0%20%C2%A0%20%C2%A0%20%E5%B0%81%E8%A3%85%E7%9A%84%E4%BC%98%E7%82%B9)
[封装的步骤](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%E5%B0%81%E8%A3%85%E7%9A%84%E6%AD%A5%E9%AA%A4)
6.继承
[继承的语法](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%E7%BB%A7%E6%89%BF%E7%9A%84%E8%AF%AD%E6%B3%95)
[构造函数](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0)
[重写 (Override)](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%E9%87%8D%E5%86%99%20%EF%BC%88Override%EF%BC%89)
[super关键字](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0super%E5%85%B3%E9%94%AE%E5%AD%97%C2%A0)
[Object类](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0Object%E7%B1%BB%C2%A0)
[抽象类 与抽象方法](about:blank#%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%C2%A0%E6%8A%BD%E8%B1%A1%E7%B1%BB%20%E4%B8%8E%E6%8A%BD%E8%B1%A1%E6%96%B9%E6%B3%95)
思维导图
一.Java的诞生
1. C & C++
① 1972年,C语言诞生,它是一种接近硬件、运行速度快、效率高的语言,被广泛应用于操作系统、编译器、数据库和网络系统等领域。
② 1982年,C++语言诞生,它在C语言的基础上增加了面向对象的特性,并且兼容C语言,常用于图形领域和游戏开发。
2. Java预想
设计者们希望创建一种新的编程语言,它具有类似C语言的语法,但是没有指针和内存管理,具备真正的可移植性(编写一次,到处运行),并且是面向对象的、类型安全的,并提供高质量的类库。
3. Java初生
① 1995年,当时的网页内容简单,缺乏互动性。Java的出现允许开发者创建具有图形界面的Applet,这些Applet可以在网页上运行。
②Bill Gates曾称赞Java是迄今为止设计的最好的语言。
③ Java分为三个版本:Java 2 标准版(J2SE)、Java 2 移动版(J2ME)和Java 2 企业版(J2EE),分别适用于PC、手机和服务器开发。
4. Java 特性和优势
①简单性:Java设计得易于学习和使用。
②面向对象:Java是一种面向对象的编程语言,支持封装、继承和多态等特性。
③可移植性:Java程序可以在任何支持Java的平台上运行。
④高性能:Java提供了高效的运行时环境。
⑤分布式:Java支持网络通信和分布式计算。
⑥动态性:Java可以动态地扩展和更新类库。
⑦多线程:Java支持多线程编程,允许同时执行多个任务。
⑧安全性:Java提供了沙箱安全模型,防止恶意代码破坏系统。
⑨健壮性:Java的异常处理机制使得程序更加健壮。
5. Java三大版本
①JavaSE(Java Standard Edition):适用于开发桌面程序和控制台应用程序的标准版。
②JavaME(Java Micro Edition):适用于嵌入式系统,如手机和小家电的微型版。
③ JavaEE(Java Enterprise Edition):适用于企业级应用,如web端和服务器开发的扩展版。
6. JDK、JRE、JVM
① JDK(Java Development Kit):Java开发工具包,包括编译器、调试器和运行时环境,用于开发和测试Java应用程序。
② JRE(Java Runtime Environment):Java运行时环境,包括JVM和核心类库,用于运行Java应用程序。
③JVM(Java Virtual Machine):Java虚拟机,是Java运行时环境的核心,负责执行Java字节码。
二.控制台程序开发
1.开发java程序步骤
(1)①编写源程序
②编译源程序,JDK 中的 javac.exe(java compiler,Java 编译器), 编译后会产生一个 .class 文件(ByteCode,字节码文件)
③运行java

(2)使用IDE开发java程序的步骤
①首先需要创建一个Project
②在“src”文件目录中创建package(包)
包名一般将域名进行倒置,例如:www.chinasofti.com,包 名 :com.chinasofti.xxxx
③在包中创建类,类的声明要求首字母必须大写,如果有多个单词,则要采用Pasical命名法。例如"HelloWorld"。
④编写代码后,直接在编译器使用run来执行编译和运行
2.程序运行机制
编译型语言
编译型语言写的程序执行之前,需要一个专门的编译过程,一次性的编译成平台相关的机器语言文件,运行时脱离开发环境,运行效率高
与特定平台相关,一般无法移植到其他平台
一次编译,多次执行
编译型语言:C、C++、Delphi、Pascal
解释型语言
使用专门的解释器对源程序逐行解释成特定平台的机器码并立即执行
是代码在执行时才被解释器一行行动态翻译和执行,而不是在执行之前就完成翻译,效率较低
只要平台提供相应的解释器,就可以运行源代码,程序可移植性好;
解释型语言:Java、python,javascript、Basic
3.程序开发环境及结构
Java开发环境
记事本、Eclipse、MyEclipse、IntelliJ、NetBeans
Java程序结构
-
类名与文件名完全一样
-
main()方法是java程序的入口点
-
main()方法的四要素```
public static void main(String[] args) -
“{”和“}”一一对应,缺一不可
public class 类名 {
public static void main(String[] args) {
//代码段
}
}
4.控制台I/O
①使用Scanner从控制台输入信息
②使用System.out.println()、System.out.print()及\\n、\\t等向控制台输出信息
5.程序注释
单行注释
只能注释一行内容,用在注释信息内容少的地方
//注释内容
多行注释、块注释
能注释多行内容,用在注释信息内多的地方
/*
注释内容
注释内容
注释内容
*/
文档注释
包含在“/\*\*”和“\*/”之间,也能注释多行内容,一般用在类、方法和变量上面,用来描述其作用。注释后,鼠标放在类和变量上面会自动显示出我们注释的内容。
6.程序调试
Debug的基本方法
**断点(breakpoint)**
打上断点以后,程序运行到断点处就会暂停,可以一步一步观察运行情况。
**跟踪(trace)**
跟着流程一步一步走,看看程序代码的执行流程。
跟着流程一步一步走,看看变量动态的变化情况。
**监视(watch)**
即时监视:鼠标指向变量。
快速监视:点右键,Inspector。
添加监视:点右键,Watch。
三.变量与运算符
1.变量
****在程序运行过程中允许改变其值的量****。变量是存储在内存中的一个内容,由于内存地址不便记忆,所以使用变量名替代内存地址,存储在内存地址中的值被称为变量值,变量所开辟的空间大小由数据类型决定。
Java语言支持的变量类型
- 类变量:独立于方法之外的变量,用static修饰
- 实例变量:独立于方法之外的变量,不过没有static修饰
- 全局变量:全局变量通常定义在类下,具备初始化值。全局变量又被称为成员变量或字段,在当前类中全局可见。
- 局部变量:类的方法中的变量,作为局部变量在声明后必须赋初始化值,否则就会抛出异常。```
public class Variable{
//类变量 static
static int allClicks=0; // 类变量
//实例变量:从属于对象,如果不自行初始化 数值默认值为0 0.0,
//boolean 默认为 false
//除了基本类型,其他默认都为null
String str=“hello world”; // 实例变量
public void method(){
//必须声明和初始化值
int i =0; // 局部变量
}
}
2.成员变量与局部变量的区别
1.作用于不同
- 局部变量的作用域仅限于定义它的方法
- 成员变量的作用域在整个类的内部都是可见的
2. 初始值不同
- java会给成员变量一个初始值
- java不会给局部变量赋予初始值
3.在同一个方法中,不允许有同名局部变量;在不同方法中,可以有同名局部变量
4.在同一个类中,成员变量和局部变量同名时,此时程序会采用“就近原则”,则局部变量具有更高的优先级
3.命名规范
- 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束
反例:_name / __name / n a m e / n a m e _ / n a m e name / name\_ / name name/name_/name / name__
- 严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式
正例:ali / alibaba / taobao / cainiao/ aliyun等国际通用的名称,可视同英文。
反例:DaZhePromotion [打折] / getPingfenByName() [评分] / int 某变量 = 3
- 类名使用每个单词首字母大写的方法,但以下情形例外:DO / BO / DTO / VO / AO / PO / UID 等。
正例:ForceCode / UserDO / HtmlDTO / XmlService
反例:forcecode / UserDo / HTMLDto / XMLService
- 方法名、参数名、成员变量、局部变量使用驼峰命名法
正例: localValue / getHttpMessage() / inputUserId
- 常量命名全部大写,单词间用下划线隔开
正例:MAX_STOCK_COUNT / CACHE_EXPIRED_TIME
反例:MAX_COUNT / EXPIRED_TIME
4.常量
初始化后不能再改变的值!不会变动的值,Java 语言使用 final 关键字来定义一个常量
final修饰符
final代表最终状态,可以修饰在类、属性、方法中。如果修饰了类,就代表该类不能够被继承,被称为“终态类”。如果修饰了属性或变量,就变成了常量了,一般会和static联用,不可被修改,如果修饰了方法,则该方法不可被重写。
final 修饰的方法不可被重写 final 修饰的类不能被继承 final修饰的量会变为常量,并且只能在初始化时可以被赋值
5.运算符
- 算术运算符:+ - * / %
- 关系运算符:> < >= <= == !=
- 逻辑预算符:&& || !
- 其他运算符
自增:i++(先执行后自增) ++i(先自增再执行)
自减:i–(先执行后自减) --i(先自减再执行)
//++ -- 自增,自减 一元运算符
int a = 3;
int b = a++; //执行代码后,先给b赋值,再自增
//a++ a = a+1;
int c = ++a; //执行完这行代码前,先自增,再给c赋值
System.out.println(a); //输出5
System.out.println(b); //输出3
System.out.println(c); //输出5
- 赋值运算符:= += -= *= /= %=
- 条件运算符:?
- 三元运算符
// x ? y :z
//如果x==true,则结果为y,否则结果为z
int score = 80;
String type = score>60?"及格":"不及格";
System.out.println(type); // 及格
****优先级最高的是带有小括号的表达式,其次是算术运算符,之后是关系运算符,然后是逻辑运算符,最后是赋值运算符。****
6.位运算****
- 左移(<<):一元运算符,按位左移一定的位置。高位溢出,低位补符号位,符号位不变。```
public class Test {
public static void main(String[] args) {
System.out.println(5<<2);//运行结果是20
}
}
首先会将5转为2进制表示形式(java中,整数默认就是int类型,也就是32位):
0000 0000 0000 0000 0000 0000 0000 0101 然后左移2位后,低位补0:
0000 0000 0000 0000 0000 0000 0001 0100 换算成10进制为20
- 右移(>>):一元运算符,按位右移一定的位置。高位补符号位,符号位不变,低位溢出。```
System.out.println(5>>2);//运行结果是1
先将5转为2进制表示形式:
0000 0000 0000 0000 0000 0000 0000 0101 然后右移2位,高位补0:
0000 0000 0000 0000 0000 0000 0000 0001换算成10进制为1
- 无符号右移( >>> ):一元运算符,符号位(即最高位)保留,其它位置向右移动,高位补零,低位溢出。
正数换算成二进制后的最高位为0,负数的二进制最高为为1
public class Test {
public static void main(String[] args) {
System.out.println(5>>3);//结果是0
System.out.println(-5>>3);//结果是-1
System.out.println(-5>>>3);//结果是536870911
}
}
5换算成二进制: 0000 0000 0000 0000 0000 0000 0000 0101
5右移3位后结果为0,0的二进制为: 0000 0000 0000 0000 0000 0000 0000 0000 // (用0进行补位)
-5换算成二进制: 1111 1111 1111 1111 1111 1111 1111 1011
-5右移3位后结果为-1,-1的二进制为 1111 1111 1111 1111 1111 1111 1111 1111 // (用1进行补位)
-5无符号右移3位后的结果 536870911
换算成二进制: 0001 1111 1111 1111 1111 1111 1111 1111 // (用0进行补位)
正数右移,高位用0补,负数右移,高位用1补,当负数使用无符号右移时,用0进行部位(自然而然的,就由负数变成了正数了),正数或者负数左移,低位都是用0补。
- 位与(&):二元运算符,两个为1时结果为1,否则为0```
public class Test {
public static void main(String[] args) {
System.out.println(5 & 3);//结果为1
}
}
5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101
3转换为二进制:0000 0000 0000 0000 0000 0000 0000 0011
1转换为二进制:0000 0000 0000 0000 0000 0000 0000 0001
第一个操作数的的第n位于第二个操作数的第n位如果都是1,那么结果的第n为也为1,否则为0
- 位或(|):二元运算符,两个其中有一个为1时结果就为1,否则为0```
public class Test {
public static void main(String[] args) {
System.out.println(5 | 3);//结果为7
}
}
5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101
3转换为二进制:0000 0000 0000 0000 0000 0000 0000 0011
7转换为二进制:0000 0000 0000 0000 0000 0000 0000 0111
第一个操作数的的第n位于第二个操作数的第n位 只要有一个是1,那么结果的第n为也为1,否则为0
- 位异或(^):二元运算符,两个数同时为1或0时结果为1,否则为0```
public class Test {
public static void main(String[] args) {
System.out.println(5 ^ 3);//结果为6
}
}
5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101
3转换为二进制:0000 0000 0000 0000 0000 0000 0000 0011
6转换为二进制:0000 0000 0000 0000 0000 0000 0000 0110
第一个操作数的的第n位于第二个操作数的第n位 相反,那么结果的第n为也为1,否则为0
- 位取非(~):一元运算符,取反操作
四.数据类型与数组
1.Java引用数据类型
类、接口、数组、 String Byte Integer ……
2.Java基本数据类型


3.类型转换
//---------强制转换
//强制转换 高-->低
int i = 128;
byte b = (byte)i; // -128 内存溢出
//---------自动转换
//自动转换 低-->高
int i2 = 128;
double d = i2;
//精度丢失
System.out.println((int)23.7); //输出23
System.out.println((int)-45.89f); //输出-45
char c = 'a';
int d = c+1;
System.out.println(d); // 输出 98
System.out.println((char)d); // 输出b
转换中需要注意的问题
-
自动类型转换需要两种类型兼容
-
数值类型(整型和浮点型)互相兼容 -
目标类型大于源类型
-
强制类型转换会导致精度缺失的问题
4.数组概述
5.数组声明创建及初始化
-
数据类型 数组名[ ]```
int score2[]; //C#成绩 -
数据类型[ ] 数组名```
int[] score1; //java成绩 -
声明数组并分配空间(数据类型[ ] 数组名 = new 数据类型[大小] )```
score = new int[30];
avgAge = new int[6];
6.数组赋值
方法一:边声明边赋值(元素类型\[\] 数组名 = {元素1, 元素2, ..., 元素n};)
int[] myArray = {10, 20, 30, 40};
方法二:动态地从键盘录入信息并赋值
Scanner input = new Scanner(System.in);
for(int i=0;i<30;i++){
score[i] = input.nextInt();
}
7.数组的默认值
数组在动态初始化后,每个类型的元素会有一个默认值。例如,int 类型的默认值为0,double 类型的默认值为0.0,对象引用类型的默认值为null。
8.数组长度
使用数组的length属性来获取数组的长度,即其中的元素数量。语法:数组名.length;。
int length = myArray.length;//获取myArray的长度
9.数组应用
int[] array = {5, 3, 9, 1};
int max = Arrays.stream(array).max().getAsInt();
int min = Arrays.stream(array).min().getAsInt();
方法二:遍历数组并比较每个元素。以求最大值为例:
public class Test {
public static void main(String[] args) {
int[] numbers = {3, 7, 1, 15, 2, 6};
// 求最大值
int max = numbers[0];
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] > max) {
max = numbers[i];
}
}
System.out.println("最大值: " + max);
}}
public class Test{
public static void main(String[] args) {
int[] numbers = {3, 7, 1, 15, 2, 6};
// 数组排序
Arrays.sort(numbers);
System.out.println("排序后的数组: " + Arrays.toString(numbers));
}
}
-
向数组中插入元素
import java.util.Arrays; public class InsertArray { public static void main(String[] args) { //将它们按升序排列。要增加一个学员的成绩,将它插入成绩序列,并保持升序 //插入数据64 int[] array = {99,85,82,63,60} ; System.out.println("排序前的数组:" + Arrays.toString(array)); //升序排序 Arrays.sort(array); System.out.println("排序后的数组:" + Arrays.toString(array)); //copyof扩展数组 int[] newArray = Arrays.copyOf(array,array.length + 1) ; //要插入的数据 int data = 64 ; //位置 int index = 0 ; //将内容插入到数组中 for (int i = 0; i < newArray.length; i++) { if(newArray[i] > data) { index = i ; break ; } } //将数组后面的数据向后面移动一位 for(int i = newArray.length-1 ; i > index ; i--) { newArray[i] = newArray[i-1] ; } //将值插入到数组的索引位置 newArray[index] = data ; System.out.println("插入数据后的数组:" + Arrays.toString(newArray)); } }
10.二维数组
元素类型\[\]\[\] 数组名 = new 元素类型\[第一维长度\]\[第二维长度\];
int[][] matrix = new int[3][4];//声明一个3行4列的二维整型数组
五.流程控制语句
1.分支结构
类型一:基本if结构(处理单一或组合条件的情况)
//只做一些基础判断时可以采用简单的if结构
if(条件表达式) { //表达式返回的结果必须是boolean类型
}
类型二:if-else结构(处理简单的条件分支情况)
//可以完成两种不同相反条件的判断
if(条件表达式) { //表达式返回的结果必须是boolean类型
}else{
}
类型三:多重if条件判断(处理复杂的条件分支情况)
//可以针对于多种不同的条件进行组合判断
if(条件表达式1) { //表达式返回的结果必须是boolean类型
}else if(条件表达式2){
}else if(条件表达式3){
}else if n...{
}else{ //最后一个else可以省略
}
if语句的嵌套(用于较为复杂的流程控制)
//只有满足外层的条件,才能进入到内层继续执行判断
if(条件表达式) { //表达式返回的结果必须是boolean类型
if(条件表达式) { //表达式返回的结果必须是boolean类型
}
}else{
if(条件表达式) { //表达式返回的结果必须是boolean类型
}
}
-
switch结构(多重分支并且条件判断是等值判断的情况)
switch结构能够作用在****等值判断情况****下比较适合。能够对int、short、byte、char、enum(枚举)、String(字符串)类型判断,其他类型无法执行判断。enum与String类型必须是JDK5以上的版本才能使用。
switch(变量) {
case 常量:
//代码段
break ;
case n:
break;
default:
}
- case中如果不包含break关键字,就会一直向下执行,直到遇到break或者是整段程序结束
- default是可以随意更改为位置,一定要根据业务流程适时添加break关键字。
2.循环结构
-
While循环(当型循环)
-
先执行判断,之后再执行循环体
-
注意避免出现死循环,代码的规范和缩进```
while(条件表达式) {
//循环体
}int i = 0 ;
while(i < 10) {
System.out.println(“hello”) ;
i++ ;
} -
Do-while循环(直到型循环)
-
先至少执行一次,然后再进行判断
-
注意避免出现死循环,代码的规范和缩进
do{
循环体; //至少执行一次
}while(条件表达式) ;
int i = 0 ;
do{
System.out.println("hello") ;
i++ ;
}while(i < 10) ;

for(初始化变量 ; 条件 ; 迭代步长) { //迭代步长: ++ += -= *= /= //初始化变量,可以同时初始化多个变量
//循环体
}
for(初始化变量;;) { //死循环
}
for(;;) { //死循环
}
for(int i = 0 ; i < xxx ; i+=2) {
}
-
Foreach循环
-
语法简洁,减少了传统for循环的代码量
-
foreach内部使用迭代器实现,能够自动处理集合或数组的边界情况,避免了常见的越界错误
-
foreach语法可读性高,更符合自然语言描述集合遍历的过程。
-
无法在遍历过程中修改集合或数组的长度
-
无法直接访问当前元素的索引
-
二重循环,以for循环为例
for(循环条件1){ //循环操作1 for(循环条件2){ 循环操作2 } } -
循环条件1和循环操作1对应的循环称为外层循环,循环条件2和循环操作2对应的循环称为内层循环,
-
内层循环结束后才执行外层循环的语句
-
在多重循环中,外层循环变量变化一次,内层循环变量要从初始值到结束值变化一遍
-
外层循环一次,内层全部循环一次(外层循环一次,内层for循环全部执行完成再进行外层的一次循环)
-
在内循环中的continue和break都不能终止二重循环的执行,只能跳出或终止所在的内循环
3. 跳转结构
-
break
-
中断程序运行!能够在switch中和循环中使用。
-
在单循环结构中,一旦碰到,就会退出整个循环体,不会再执行下一次循环。```
switch() {
case 1:
break; //程序会在此处直接退出switch结构
}
for() {
if() { //循环中都是和if判断结合使用
break ; // 彻底退出循环
}} -
continue
-
只能作用在循环体内,当碰触到该关键字时,会终止本次循环,继续执行下一次循环。```
for() {
if() {
continue ; //在此处结束本次循环,进入下一次循环
}
} -
return
从当前方法中退出,并返回到调用该方法的语句处继续执行
-
如果方法声明了返回值类型(比如int、String等),则return语句后面可以跟随一个表达式,该表达式的值类型必须与方法声明中的返回类型一致。例如:```
public int add(int a, int b) {
return a + b;
}如果方法声明为void类型,则return语句可以不跟任何表达式,仅用于提前结束方法的执行。例如:public void Test(String message) {
if (message == null) {
return;
}
System.out.println(message);
}
六.Java常见异常
- NullPointerException: 空指针异常,当对象不存在没有分配空间时,调用了对象的属性或方法,就会导致出现该异常。
- InputMismatchException:输入不匹配异常,当使用Scanner对象后,如果接收的数据类型与目标数据类型不匹配时,会出现异常。
- ArrayIndexOutOfBoundsException:数组下标越界异常。当存储数组元素时,向一个超出了数组空间大小的下标处插入或者是查询内容,就会出现该异常。
七.类和对象
1.对象
- 对象是用来描述客观事物的一个实体,由一组属性和方法构成
- 对象的两个特征:属性和方法
- 属性:对象具有的各种特征
- 每个对象的每个属性都拥有特定值
- 方法:对象执行的操作,即所执行的操作

2.如何创建和使用对象
使用对象的步骤
创建对象
类名 对象名=**new** 类名();
Student stu1 = new Student() ;
Student stu2 = new Student() ;
引用对象成员:使用 “.” 进行以下操作
- 引用类的属性:对象名.属性
- 引用类的方法:对象名.方法名()
//引用类的属性
stu1.studentNO = "20241101" ;
//引用类的方法
stu1.show() ;
3.面向对象(OO)的优点
面向对象设计中,主要包括以下三部分,且层次和难度逐级提升:
-
OOP:Object Oriented Programming,面向对象程序编程
-
OOD: Object-Oriented Design,面向对象设计
-
OOA:Object Oriented Analyzing,面向对象分析
面向对象(OO)的优点
- 与人类的思维习惯一致
- 提高了程序的可重用性
- 信息隐藏,提高了程序的可维护性和安全性
4.封装
对象同时具有属性和方法两项特性,属性和方法通常被封装在一起,共同体现事物的特性, 二者相辅相承,不可分割。(详细见第十章)
5.类
- 类是模子,定义对象将会拥有的特征(属性)和行为(方法)
- 类是对象的类型
- 类是抽象的概念,仅仅是模板
- 对象是一个你能够看得到、摸得着的具体实体
- Java是面向对象的语言
所有java程序都以类class为组织单元
关键字class定义自定义的数据类型
类将现实世界中的概念模拟到计算机程序中,此过程也是业务模型抽取建立的过程

类的基本模板:
public class 类名 {
//定义属性部分
属性1的类型 属性1;
属性2的类型 属性2;
…
属性n的类型 属性n;
//定义方法部分
方法1;
方法2;
…
方法m;
}
6.类的定义

类的定义步骤
步骤一:定义类名
public class 类名(每个单词首字母大写,例如Student) {
...
}
步骤二:编写类的属性
public class Student {
String studentNO ;
String studentName ;
...
}
步骤三:编写类的方法
public class Student {
String studentNO ;
String studentName ;
...
public void show() {
//方法体
}
public void add() {
//方法体
}
}
类的方法编写步骤
类的方法定义类的某种行为(或功能)

步骤一:定义方法名,使用关键字class以及返回值类型
步骤二:编写方法体
public 返回值类型 方法名(){
//方法的主体
}
方法返回值
如果方法具有返回值,方法中必须使用关键字return返回该值,返回值类型为该返回值的类型,return的作用:跳出方法、返回结果,例如:
public String add(){
return 返回值(类型为String)
}
public int add(){
return 返回值(类型为int)
}
public boolean add(){
return 返回值(true或false)
}
...
如果方法没有返回值,返回值类型为void,例如:
public void add(){
...
}
7.方法的调用
方法之间允许相互调用,不需要知道方法的具体实现,就可以实现重用,提高效率
- 同类中的方法间调用:直接调用,例如:
public class Student(){
public void a(){
b();//调用b()
}
public void b(){
a();//调用a()
}
}
- 调用不同类中的方法:现创建类对象,然后使用“.”调用,例如:
public class Student(){
public void a(){
...
}
}
public class Teacher(){
public void b(){
Student() student=new Student();//先实例化类对象
student.a();//调用Student类中的a()
}
}
8.带参方法
当我们需要调用方法的同时进行数据的传输,就可以采用带参方法形式实现参数的传递。
参数列表:可以在方法声明时,放置多个对应的参数类型,放置的参数类型可以是不同的。
public 返回值类型 方法名(形式参数列表) {
方法体
}
//参数类型可以多个,可以不同
public 返回值类型 方法名(int a,String b,double c) {
方法体
}
形参与实参
-
形参
形参是在定义方法时对参数的称呼```
public int add(int num1,int num2(这里是形参)) {
return num1 + num2 ;
} -
实参
实参是在调用方法时传递给方法的实际的值```
int num = xxx.add(1,3) ;
//1与3作为调用端传入,该数值就是实参。
//基本数据类型传参,会将实际参数的值赋值给形参。如果对形参进行了数据的修改,不会对实参造成影响。
参数传递注意事项
1.形参与实参数据类型要一致(下列代码中包含错误示范,注意辨别)
2.形参与实参数量要一致
//方法定义
public void add(int a,String b){
方法体//该方法有两个参数,则应该传递两个对应数据类型的参数
}
//方法调用
int num=1;
int num2=3;
String name="张三";
//正确传参,参数保持一致
对象名.add(num,name)
//错误示范
对象名.add(num,num2)//数据类型不匹配
对象名.add(num,name,num2)//参数个数不匹配
3.调用方法时不能指定实参类型
//错误示范
对象名.add(Srting "张三");
//正确调用
对象名.add("张三");
4.调用方法后应有相应的返回值,使用return返回相应数据类型的值,如果是void类型,则无返回值
9.引用数据类型传参
除了基本数据类型可以作为参数外,还可以在声明或调用方法时传入引用数据类型作为参数。引用数据类型在传参时与基本数据类型不同,会将自身的引用地址位置复制给形式参数,所以会导致形参和实参同时指向同一地址空间,所以当其中一个参数对数据进行了修改,就会导致另一方数据也发生变化。
public void hello(int[] array) {
array[0] = 10 ;
}
public void world(Person person) {
person.age = 20 ;
}
public class Person {
String name ;
int age ;
}
main{
int[] array = new int[5] ;
array[0] = 20 ;
Hello hello = new Hello() ;
hello.hello(array) ;
System.out.println(array[0]) ; //10
Person person = new Person() ;
person.name = "zhangsan" ;
person.age = 10 ;
hello.world(person) ;
System.out.println(person.age) ; //20
}
10.构造方法
基本概念
- 构造方法定义:构造方法的名称与类名相同,并且没有返回类型(包括
void)。 - 作用:构造方法用于初始化对象的状态。它可以接受参数,并根据这些参数对对象进行初始化。
public class MyClass {
private int value;
// 构造方法
public MyClass() {
}
}
构造方法的类型
无参构造方法:没有参数的构造方法。在没有定义任何构造方法时,编译器会自动提供一个默认的无参构造方法。 当在类中自定义构造方法之后,默认的无参构造方法自动消失,如果需要无参构造方法需要手动添加。
public class MyClass {
private int value;
// 无参构造方法
public MyClass() {
this.value = 0;
}
}
有参构造方法:接受参数的构造方法,用于初始化对象的字段。
public class MyClass {
private int value;
// 有参构造方法
public MyClass(int value) {
this.value = value;
}
}
构造方法的重载
构造方法可以被重载,即一个类可以有多个构造方法,只要它们的**参数列表不同**。
public class MyClass {
private int value;
private String name;
// 无参构造方法
public MyClass() {
this.value = 0;
this.name = "Default";
}
// 一个有参数的构造方法
public MyClass(int value) {
this.value = value;
}
// 另一个有参数的构造方法
public MyClass(int value, String name) {
this.value = value;
this.name = name;
}
}
构造方法的调用
当创建一个对象时,构造方法被自动调用。
MyClass obj1 = new MyClass(); // 调用无参构造方法
MyClass obj2 = new MyClass(10); // 调用有一个参数的构造方法
MyClass obj3 = new MyClass(10, "Example"); // 调用有两个参数的构造方法
this关键字
在构造方法中,`this` 关键字用于引用当前对象的字段和方法。它也可以用来调用其他构造方法(构造方法重载)。 但是一个构造方法调用另一个构造方法时需**写在代码块第一行**。
public class MyClass {
private int value;
private String name;
public MyClass() {
this(0, "Default"); // 调用另一个构造方法
}
public MyClass(int value, String name) {
this.value = value;
this.name = name;
}
}
父类构造方法的调用
子类构造方法在创建子类对象时,会先调用父类的构造方法。如果父类没有无参构造方法,子类必须显式调用父类的构造方法。
public class ParentClass {
public ParentClass(int value) {
// 父类构造方法
}
}
public class ChildClass extends ParentClass {
public ChildClass() {
super(10); // 显式调用父类的构造方法
}
}
构造方法的特点
- 不能被
static、final或abstract修饰:来自@al_littleworld博主的修饰符abstract、static、final为何不用于修饰构造方法?
https://blog.csdn.net/al_littleworld/article/details/105115574?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95%E4%B8%8D%E8%83%BD%E6%9C%89%E4%BF%AE%E9%A5%B0%E7%AC%A6%20static%E3%80%81final%20%E6%88%96%20abst&utm_medium=distribute.pc_search_result.none-task-blog-2blogsobaiduweb~default-0-105115574.nonecase&spm=1018.2226.3001.4450static:static和对象没有关系,但是构造方法是用于创建对象的,相互矛盾;同时static修饰的方法可以直接通过类名.静态方法名(实参);调用,但是构造方法不允许手动调用。
final :final方法是约束子类不能覆盖,但是构造方法本身不允许子类继承
`abstract:`抽象方法只有方法的声明,没有方法的实现,实现部分让子类完成;但是构造方法是不能被子[类继承](https://so.csdn.net/so/search?q=%E7%B1%BB%E7%BB%A7%E6%89%BF&spm=1001.2101.3001.7020 "类继承"),如果构造方法被abstract修饰,则子类无法完成构造方法的实现内容。
- 构造方法没有返回类型:构造方法没有返回类型,即使是
void也不能写。- 父类的构造方法是不会被子类继承的,但是子类的构造方法中会有一个隐式的super()来调用父类中的无参数构造方法。
- 构造方法不能被重写。由于构造方法用于初始化类本身的实例,重写构造方法在逻辑上是没有意义的。
八.包
包是一个Java工程中的最小组织单元。
-
允许类组成较小的单元(类似文件夹),易于找到和使用相应的文件
-
防止命名冲突
-
更好的保护类、属性和方法(因为面向对象中存在访问修饰符)
1.包的声明
用package声明包,以分号结尾。作为Java源代码第一条语句声明。
package com.xxx.project ;
// 一般是将公司的域名进行倒置,组合对应部门或者是机构,再有可能使用项目名。要根据公司的规定设计。
public class Hello {
}
2.包的引入
当所需要使用的类,不在同一个包中,或者是该类并不是来自于java.lang包,都需要进行导包操作。导包使用**“import”**关键字。
package com.xxx.project ;
import java.util.Scanner ; //如果一个包中导入了多个类,可以使用"*"替代。
public class Hello {
}
九.String字符串
1.Stirng的声明
String是一个不可变的引用对象,底层采用的是**字符(JDK8及以下版本)**或者是**字节数组(JDK9)**实现,String声明一共存在三种不同的形式:
String str = "hello" ;
String str1 = new String() ;
String str2 = new String("hello") ;
2.String的一些特性
String由于其设计的是一个不可变性,所以当大量拼接字符串时就会创造非常多的内存对象。这样对于性能会有一定的损耗。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence,
Constable, ConstantDesc {
//字符串存储的数组
private final byte[] value;
//代表当前的字符编码形式 0: Latin 1:utf16
private final byte coder;
}
3.字符串的length()
代表字符串的长度。获取到当前字符串存储的字符数量。数组当中的长度是使用属性表示。
//字符串.length()
"hello".length() ;//直接调用
底层代码
public int length() {
//根据对应的字符编码进行向右位移,获取完整的字符内容
return value.length >> coder();
}
4.字符串的equals()
equals() 方法的定义在 Object 类中 ,默认情况下,equals() 方法比较的是对象的内存地址,即它比较的是对象的引用是否相同。
public boolean equals(Object obj) {
return (this == obj);
}
equals() 方法的代码逻辑
该方法主要比较两个字符串的内容是否一致。在jdk8以前,通过字符进行比较,jdk9起采用字节进行比较,还会判断对应的字符编码。
底层代码
JDK8
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
return (anObject instanceof String aString)
&& (!COMPACT_STRINGS || this.coder == aString.coder)
&& StringLatin1.equals(value, aString.value);
}
JDK11以后
public static boolean equals(byte[] value, byte[] other) {
if (value.length == other.length) {
for (int i = 0; i < value.length; i++) {
if (value[i] != other[i]) {
return false;
}
}
return true;
}
return false;
}
在JDK8中,首先判断两个对象是否是相同的,采用的是“==”判断,如果结果为true,说明两个地址空间一致。如果为false,就会继续向下判断,首先会判断另一个对象是否是一个字符串类型,如果是一个字符串类型,就会进行字符串强转,之后使用长度进行判断,如果长度也一致,就会将字符串转换为字符数组,之后使用循环一一对比,如果都一致,就会返回true,其中以上的任何一步返回false,都代表两个字符串内容不一致!
在JDK9以上的版本中,首先判断两个对象是否是相同的,采用的是“==”判断,如果结果为true,说明两个地址空间一致。如果为false,就会继续向下判断,首先会判断另一个对象是否是一个字符串类型,此处因为底层设计使用字节数组,所以要知晓是一个字节还是一个字符。根据不同的编码开始进行循环的判断,将字符串转换为字符数组,之后使用循环一一对比,如果都一致,就会返回true,其中以上的任何一步返回false,都代表两个字符串内容不一致!
equals()的规范
- 自反性:对于任何非空引用
x,x.equals(x)应该返回true。 - 对称性:对于任何非空引用
x和y,如果x.equals(y)返回true,则y.equals(x)也应该返回true。 - 传递性:对于任何非空引用
x、y和z,如果x.equals(y)返回true,并且y.equals(z)返回true,则x.equals(z)应该返回true。 - 一致性:对于任何非空引用
x和y,如果x.equals(y)返回true,那么多次调用x.equals(y)应该始终返回true,前提是对象的状态没有发生改变。 - 非空性:对于任何非空引用
x,x.equals(null)应该返回false。
5.==比较
-
如果是一个基本类型对比,就会直接比较两个基本数据类的值,如果一致返回true,否则返回false。
-
如果比较的是两个对象,此时会比较两个对象的堆中的内存地址是否相同,相同返回true,否则返回false。
6.常用其他API方法
拼接字符串使用,相对于传统字符串使用“+”号连接,看起来会更加美观。但是性能提升不大。
//采用链式引用,可以一直使用“.”
System.out.println("hello".concat(",").concat("world"));
提取(截取)字符串。可以从一个完整的字符串中,截取部分的内容,返回依然是新字符串类型。
//提取从位置索引开始的字符串部分
public String substring(int index)
//提取从beginindex到endindex之间的字符串部分,注意不包含endindex位置的字符
public String substring(int beginindex,int endindex)
String s="喜羊羊与灰太狼";
System.out.println(s.substring(2,5))
//输出结果为:羊与灰
根据所给的字符或者是字符串查找对应的字符在字符串中的索引位置。如果没有找到就会返回-1。
根据所给的字符或者是字符串查找最后对应的字符在字符串中的索引位置。如果没有找到就会返回-1。
String musicName = "d:\\music\\珊瑚海.mp3.mp4" ;
int index = musicName.lastIndexOf("珊瑚海.mp3") ;
System.out.println(musicName.substring(index,musicName.lastIndexOf(".")));
能够实现去除字符串两端的空格。
String str = " hello, world " ;
//结果:hello, world
System.out.println(str.trim());
判断数组中的长度是否为零,如果包含了空格,并不会认为是空的。
判断非空白的字符串内容,如果包含了空格,还会认为是空的。
String str = " " ;
//str.isEmpty():判断数组中的长度是否为零,如果包含了空格,并不会认为是空的。
//str.isBlank():判断非空白的字符串内容,如果包含了空格,还会认为是空的。
System.out.println(str.isEmpty()); // 返回false
System.out.println(str.isBlank()); // 返回true
按正则表达式分割字符串。返回值为字符串数组
String str = "长亭外,古道边,芳草碧连天" ;
String[] s = str.split(",");
for (String string : s) {
System.out.println(string);
}
/*
输出结果
长亭外
古道边
芳草碧连天
*/
两个方法都能够实现字符串的替换。replace方法可以直接使用字符串进行替换。replaceAll替换的内容采用的是正则表达式形式。
replace(String target, String replacement)
//regex:正则表达式
replaceAll(String regex, String replacement)
String str = "别看我只是一只羊!别看我只是一只羊" ;
System.out.println(str.replaceAll("羊", "狼"));
/*
输出结果
别看我只是一只狼!别看我只是一只狼
*/
匹配字符串的正则表达式。
String regex = "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$" ;
String telephone = "zhangsan@163.com" ;
boolean flag = telephone.matches(regex) ;
System.out.println(flag);
7.StringBuffer与StringBuilder
StringBuffer类与StringBuilder类都是字符串的增强类。能够在字符串拼接方面提供对应的方法,实现性能的提升。其内部拥有一个缓冲区,可以将拼接的字符串全部放置在该缓冲区的内部,需要返回时,会将这个区域内容全部返回。
-
StringBuffer对方法加了同步锁(synchronized)或者调用的方法加了同步锁(线程安全,性能较差)
-
StringBuilder性能较高,安全性较差)
StringBuffer与StringBuilder的区别
当需要对字符串大量拼接时,可以使用StringBuffer与StringBuilder来接解决。这两个类最大的区别就在线程安全性。方法基本上相同。 _如果在线程不安全的场景下使用字符串拼接,可以使用StringBuffer类来保障线程的安全性。同时可以提升字符串拼接下的性能。_如果在线程安全下的场景中,优先使用StringBuilder类。其设计是非同步锁,所以性能相对StringBuffer要好。
常用方法
toString():转换成String类型
sppend():连接字符串
insert():插入字符串
十.继承
1.类的定义
通过对象的共性可以实现分类,分好的类就是Java的类型定义(名词),通过代码的"class"来进行定义。之后通过查找该类型的特性形成属性(名词),再通过该类型的行为动作(动词),生成方法。
类图
类图由三部分组成,第一个部分是类的名称,第二个部分是类的属性,如果属性是私有的则会采用"-"标识,第三个部分是类的方法。(**剔除与业务无关的属性和方法**)

2.方法重载(Overload)
重载是在同一个类中,包含具有相同名称的方法。
重载的特点
- 方法名一致
- 参数列表不同(参数类型、参数个数、参数数据类型顺序各不相同)
- 与返回值和访问修饰符无关
- 与final、static无关
//参数类型不同
public int add(int num1, int num2) {
}
public int add(long num1, long num2) {
}
//参数个数不同
public int add(long num1, long num2, int num3) {
}
//参数数据类型顺序不同
public int add(int num3, long num2, long num1) {
}
3.static关键字
static是表示静态,就意味着被修饰了static归为类所有。非静态归为对象所有。static可以修饰**字段、方法以及内部类和静态代码块**。当需要调用静态修饰的方法及字段时,可以通过“类名.字段(方法)”。
静态方法
- 不需要依赖任何对象实例,可以直接通过类名访问或调用静态方法
- 静态方法无法访问依赖于对象实例的非静态成员
- 使用static关键字修饰,不需要创建实例对象
static代码块
- 静态代码块在类加载时执行,并且仅执行一次。
- 可以访问类中的静态成员(静态字段、静态方法等),无法直接访问非静态成员(实例字段、实例方法等)
- 使用一对大括号{}表示,内部可以包含任意java代码
public class StaticTest {
public static int num1 = 1 ;
public StaticTest() {
StaticTest.num1 ++ ;
}
public static void main(String[] args) {
//调用num1
StaticTest.num1 = 2 ;
StaticTest staticTest1 = new StaticTest() ;//num1=1,num1++,num1=2
StaticTest staticTest2 = new StaticTest() ;
执行结果: 4
System.out.println(StaticTest.num1) ;
}
}
在上述代码中,由于 num1 是一个静态变量,它的值在所有对象实例之间是共享的。在创建每个对象时,构造函数都会修改 num1 的值,因此每次创建新对象时 num1 都会增加 1。
具体来说:
num1初始值为1。- 在
main方法中,将num1设置为2。 - 第一个对象的创建使
num1增加到3。 - 第二个对象的创建使
num1增加到4。
因此,最后输出的结果是 4。
static的特点及应用场景
1.修饰静态变量(静态字段)
特点:静态变量属于类而不是类的实例。所有实例共享同一个静态变量,静态变量在类加载时被初始化。
public class Example {
public static int count = 0; // 静态变量
public Example() {
count++; // 每创建一个实例,count 值加 1
}
public static void displayCount() {
System.out.println("Count: " + count); // 访问静态变量
}
}
public class Main {
public static void main(String[] args) {
Example e1 = new Example();
Example e2 = new Example();
Example.displayCount(); // 输出 Count: 2
}
}
2.修饰静态方法
特点: 静态方法属于类本身,而不是类的某个实例。静态方法不能直接访问类的实例变量和实例方法,但可以访问其他静态变量和静态方法。
public class Example {
public static int square(int x) {
return x * x; // 静态方法可以访问静态变量和其他静态方法
}
public static void main(String[] args) {
int result = Example.square(5); // 通过类名调用静态方法
System.out.println("Square of 5: " + result); // 输出 Square of 5: 25
}
}
3.修饰静态块(静态初始化块)
特点:静态块用于初始化静态变量或执行其他静态初始化操作。静态块在类加载时执行,并且只执行一次。
public class Example {
public static int count;
static {
count = 10; // 静态块初始化静态变量
System.out.println("Static block executed");
}
public static void main(String[] args) {
System.out.println("Count: " + count); // 输出 Count: 10
}
}
4.修饰静态内部类
特点:静态内部类属于外部类,并且可以直接访问外部类的静态成员。静态内部类与外部类的实例无关。
public class OuterClass {
private static String staticField = "Static Field";
public static class StaticInnerClass {
public void display() {
System.out.println(staticField); // 访问外部类的静态成员
}
}
public static void main(String[] args) {
StaticInnerClass inner = new StaticInnerClass();
inner.display(); // 输出 Static Field
}
}
总结:
- 静态变量: 类的所有实例共享,初始化时机在类加载时。
- 静态方法: 属于类本身而不是实例,不能直接访问实例变量。
- 静态块: 用于类的静态初始化,只执行一次。
- 静态内部类: 与外部类的实例无关,可以访问外部类的静态成员。
静态的资源尽量避免使用,会带来线程共享的安全问题。
static与非static修饰的区别

4. 静态代码块,实例代码块,构造方法的执行顺序
执行顺序: 静态代码块->实例代码块->构造方法
静态代码块
- 执行时机: 静态代码块在类被加载到 JVM 时执行。一个类只会被加载一次,所以静态代码块也只会执行一次。
- 用途:用于类级别的初始化,比如初始化静态变量或者进行一些类级别的设置。
public class Example {
static {
System.out.println("执行静态代码块");
}
public static void main(String[] args) {
Example e = new Example();
}
}
实例代码块
- 执行时机: 实例代码块在每次创建对象时执行,且在构造方法之前执行。每创建一个新对象,实例代码块都会被执行。
- 用途:用于对象级别的初始化,可以在对象创建时执行一些通用的初始化操作。
public class Example {
{
System.out.println("执行实例代码块");
}
public Example() {
System.out.println("执行构造函数");
}
public static void main(String[] args) {
Example e = new Example();
}
}
构造方法
- 执行时机:构造方法在对象创建完成后执行,主要用于初始化对象的实例变量。
- 用途:初始化对象的状态或执行其他构造操作。
public class Example {
public Example() {
System.out.println("执行构造函数");
}
public static void main(String[] args) {
Example e = new Example();
}
}
执行顺序示例
public class Example {
static {
System.out.println("执行静态代码块");
}
{
System.out.println("执行实例代码块");
}
public Example() {
System.out.println("执行构造函数");
}
public static void main(String[] args) {
Example e = new Example();
}
}
输出顺序:
执行静态代码块
执行实例代码块
执行构造函数
解释:
- 静态代码块在
main方法中的Example类被加载时执行,所以它首先执行。- 当你创建一个
Example对象时,实例代码块首先执行,因为它在构造方法之前。- 最后,构造方法执行以完成对象的初始化。
这种执行顺序确保了类的静态部分在对象创建之前被正确初始化,而对象的实例部分在构造方法执行之前被初始化。
5.封装
封装是将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法(getter/setter)来实现对隐藏信息的操作和访问。
封装的优点
-
隐藏类的实现细节
-
只能通过规定方法访问数据
-
方便加入控制语句
-
方便修改实现(更好的可维护性)
封装的步骤

6.继承
Java 中的继承是面向对象编程 (OOP) 的一个核心特性,它允许一个类(子类)继承另一个类(父类)的属性和方法。
当多个类中拥有相同的属性或方法,此时如果能够满足于与某个类的"has-a"以及"is-a"的关系,即可以设置为继承关系。继承关系一方面可以将子类中的相同属性和方法抽取到父类中,以节省代码提高运行效率(提升代码的复用性),另一方面,可以通过重写机制提升类的可扩展性。

-
继承(Inheritance):继承是一种机制,通过它一个类可以继承另一个类的字段(属性)和方法。子类可以使用父类的公共和保护成员,同时还可以对它们进行扩展或修改。
-
父类(Super Class):也称为基类或超类,是被继承的类。
-
子类(Sub Class):也称为派生类或子类,是继承父类的类。
继承的语法
在 Java 中,通过使用 extends 关键字来实现继承,而且在Java当中,只能实现单继承关系,不能够同时继承多个类型。如果一个类被声明为 final,它不能被继承。如果方法被声明为 final,子类不能重写这个方法。
public class ParentClass {
// 父类的字段和方法
}
public class ChildClass extends ParentClass {
// 子类的字段和方法
}
构造函数
父类构造函数:子类在创建对象时,首先会调用父类的构造函数,然后才会调用自己的构造函数。如果父类没有无参构造函数,则子类必须显式调用父类的构造函数。
public class ParentClass {
public ParentClass() {
// 父类构造函数
}
}
public class ChildClass extends ParentClass {
public ChildClass() {
super(); // 显式调用父类构造函数
// 子类构造函数
}
}
重写 (Override)
子类可以重写(覆盖)父类的方法,以提供特定的实现。
- 必须拥有继承性关系
- 子类的方法要与父类完全一致(方法名称、参数、返回值)。
- 访问权限不能严于父类
- 子类不能够抛出比父类更多的异常。
public class ParentClass {
public void display() {
System.out.println("Parent class display method");
}
}
public class ChildClass extends ParentClass {
@Override
public void display() {//方法重写
System.out.println("Child class display method");
}
}
super关键字
super是指向于父类的一颗指针。可以通过super关键字实现父类的属性和方法的调用,同时还能调用父类的构造方法。
- 调用父类构造函数:
super()用于调用父类的构造函数。 - 调用父类方法:
super.methodName()用于调用被子类重写的父类方法。 - 访问父类字段:
super.fieldName用于访问被子类隐藏的父类字段。 - super只能出现在子类的方法和构造方法中
- super调用父类构造方法时,只能是第一句
- super不能访问子类的private成员
Object类
**所有类都直接或间接继承自 `Object` 类**:`Object` 是所有类的根类。它提供了一些通用的方法,如 `toString()`、`equals()` 和 `hashCode()`。
抽象类 与抽象方法
抽象类就是**不能够被实例化**的类。在抽象类中不一定会包含抽象方法,但是抽象方法所在类的一定是一个抽象类。
抽象方法只有方法声明,而不具备方法体,由子类重写该抽象方法,或者是将抽象方法所在的类改为抽象类,再由子类重写。
抽象类使用“abstract”来定义,方法定义也相同。
- 抽象类****不能被实例化
- 抽象类****可以有0~多个抽象方法
- 非抽象子类必须重写父类的所有抽象方法
public abstract class AbstractClass {//抽象类
public abstract void abstractMethod(); // 抽象方法
}
思维导图





Java开发的就业市场正在经历结构性调整,竞争日益激烈
传统纯业务开发岗位(如仅完成增删改查业务的后端工程师)的需求,特别是入门级岗位,正显著萎缩。随着企业技术需求升级,市场对Java人才的要求已从通用技能转向了更深入的领域经验(如云原生、微服务)或前沿的AI集成能力。这也导致岗位竞争加剧,在一、二线城市,求职者不仅面临技术内卷,还需应对学历与项目经验的高门槛。
大模型为核心的AI领域正展现出前所未有的就业热度与人才红利
2025年,AI相关新发岗位数量同比激增543%,单月增幅最高超过11倍,大模型算法工程师位居热门岗位前列。行业顶尖人才的供需严重失衡,议价能力极强,跳槽薪资涨幅可达30%-50%。值得注意的是,市场并非单纯青睐算法研究员,而是急需能将大模型能力落地于复杂业务系统的工程人才。这使得具备企业级架构思维和复杂系统整合经验的Java工程师,在向“Java+大模型”复合人才转型时拥有独特优势,成为企业竞相争夺的对象,其薪资天花板也远高于传统Java岗位。

说真的,这两年看着身边一个个搞Java、C++、前端、数据、架构的开始卷大模型,挺唏嘘的。大家最开始都是写接口、搞Spring Boot、连数据库、配Redis,稳稳当当过日子。
结果GPT、DeepSeek火了之后,整条线上的人都开始有点慌了,大家都在想:“我是不是要学大模型,不然这饭碗还能保多久?”
先给出最直接的答案:一定要把现有的技术和大模型结合起来,而不是抛弃你们现有技术!掌握AI能力的Java工程师比纯Java岗要吃香的多。
即使现在裁员、降薪、团队解散的比比皆是……但后续的趋势一定是AI应用落地!大模型方向才是实现职业升级、提升薪资待遇的绝佳机遇!
如何学习AGI大模型?
作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
2025最新版CSDN大礼包:《AGI大模型学习资源包》免费分享**
一、2025最新大模型学习路线
一个明确的学习路线可以帮助新人了解从哪里开始,按照什么顺序学习,以及需要掌握哪些知识点。大模型领域涉及的知识点非常广泛,没有明确的学习路线可能会导致新人感到迷茫,不知道应该专注于哪些内容。
我们把学习路线分成L1到L4四个阶段,一步步带你从入门到进阶,从理论到实战。

L1级别:AI大模型时代的华丽登场
L1阶段:我们会去了解大模型的基础知识,以及大模型在各个行业的应用和分析;学习理解大模型的核心原理,关键技术,以及大模型应用场景;通过理论原理结合多个项目实战,从提示工程基础到提示工程进阶,掌握Prompt提示工程。

L2级别:AI大模型RAG应用开发工程
L2阶段是我们的AI大模型RAG应用开发工程,我们会去学习RAG检索增强生成:包括Naive RAG、Advanced-RAG以及RAG性能评估,还有GraphRAG在内的多个RAG热门项目的分析。

L3级别:大模型Agent应用架构进阶实践
L3阶段:大模型Agent应用架构进阶实现,我们会去学习LangChain、 LIamaIndex框架,也会学习到AutoGPT、 MetaGPT等多Agent系统,打造我们自己的Agent智能体;同时还可以学习到包括Coze、Dify在内的可视化工具的使用。

L4级别:大模型微调与私有化部署
L4阶段:大模型的微调和私有化部署,我们会更加深入的探讨Transformer架构,学习大模型的微调技术,利用DeepSpeed、Lamam Factory等工具快速进行模型微调;并通过Ollama、vLLM等推理部署框架,实现模型的快速部署。

整个大模型学习路线L1主要是对大模型的理论基础、生态以及提示词他的一个学习掌握;而L3 L4更多的是通过项目实战来掌握大模型的应用开发,针对以上大模型的学习路线我们也整理了对应的学习视频教程,和配套的学习资料。
二、大模型经典PDF书籍
书籍和学习文档资料是学习大模型过程中必不可少的,我们精选了一系列深入探讨大模型技术的书籍和学习文档,它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础。(书籍含电子版PDF)

三、大模型视频教程
对于很多自学或者没有基础的同学来说,书籍这些纯文字类的学习教材会觉得比较晦涩难以理解,因此,我们提供了丰富的大模型视频教程,以动态、形象的方式展示技术概念,帮助你更快、更轻松地掌握核心知识。

四、大模型项目实战
学以致用 ,当你的理论知识积累到一定程度,就需要通过项目实战,在实际操作中检验和巩固你所学到的知识,同时为你找工作和职业发展打下坚实的基础。

五、大模型面试题
面试不仅是技术的较量,更需要充分的准备。
在你已经掌握了大模型技术之后,就需要开始准备面试,我们将提供精心整理的大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)