Java 基本介绍
Java是一种通用的、高级的、面向对象的编程语言,最初由Sun Microsystems(目前为Oracle公司)于1995年发布。它被设计成一种可以在各种不同的环境中运行的语言,不论是桌面应用程序、企业级应用程序、移动设备或集群服务器,都可以使用Java来开发。
Java的特点包括:
简单性
:Java的语法相对于其他编程语言比较简单,易于学习和理解。面向对象
:Java是一种完全的面向对象编程语言,支持类、继承、封装和多态等核心特性。平台无关性
:Java编写的程序可以在不同的操作系统和硬件平台上运行。这得益于Java虚拟机(JVM),它可以把Java代码翻译成可以在任何计算机上运行的字节码。安全性
:Java具有严格的安全机制,基于运行时的检查和验证机制来保证程序的安全性,防止恶意程序对系统造成损害。可移植性
:Java语言的跨平台性保证了程序的可移植性,使得程序无需针对不同平台重新编写,只需编写一次即可在不同平台上运行。多线程
:Java在语言层面就支持多线程编程,并且提供了丰富的库函数,有效地支持并发编程。
Java编写的程序可以划分为两个部分:Java编译器将源代码转换成字节码文件,JVM则将字节码解释、编译并执行。Java有着广泛的应用领域,包括Web开发、移动应用开发、游戏开发、企业级应用开发等。
Java 学习须知
本篇文章可以实现轻松带你入门Java, 在你认真学习的前提下, 一切都不成问题
任何一门语言的学习都是漫长且枯燥的,读者本人要有足够的自制力
学习周期:看个人情况
学习目标:Java基础, Java高级
学习规划: 看个人情况
觉得本教程有某些地方存在一些问题,欢迎评论区指正!
Java 学习文档
在此,我为大家整理了一小部分的Java学习文档
韩信带净化,如果您有更好的学习文档,提前感谢您上贡 贡献到评论区!~
Java API 中文文档(百度网盘): Java基础材料, 提取码: 0621
API简单使用:点击索引tab,输入关键字,回车,点击显示
失效评论找我,随叫随到
README.md
目录中带
✨的都是有快捷方式跳转的~
本博客有某些节点都是有 文件下载
的, 若文件 过期
, 请评论区或私信 call
我
Java 基础
至2023年,Java语言仍是主流后端语言,与其他后端语言占比为:12.22%,位列第三,其中第一与第二分别为:Python,C
如果你正处于初学Java,并未配置Java环境变量,下面是推荐的Java配置环境变量的博客,配置Java环境变量为学习Java语言的首发站,希望大家都能用心学习,一起学习,一起坐大牢_(:з」∠)_
Java配置环境变量: Java配置环境变量
作者: 心猿意马归
Java Hello World
输出 Hello World
public class HelloWorld { // 类名必须与文件名相同 public static viod main(string[] args) { // main方法为程序入口 system.out.println("Hello World"); // Java的每个输出与条件语句后面必须带;结束字段 } }
使用javac HelloWorld.java,即可输出Hello World
Hello World
Java 变量
Java是一种强类型语言,在Java中,有不同类型的变量,变量一般都是这样被定义的
type * = *;
其中type为类型,type后面紧跟着的为变量名,变量名可自定义。
如:
int num = 1; float f1 = 1.22f; boolean b1 = true;
Java 数据类型
基本数据类型
在Java中,有8中基本数据类型,8中基本数据类型可以分为三类,分别为:数值型,字符型,布尔型。
类型 | 类型名称 |
数值型 | byte, short, int, long, float, double |
布尔型 | boolean |
字符型 | char |
整型: byte(字节型)、short(短整型)、int(整型)、long(长整型)
byte numA = 100; short numB = 1000; int numC = 100000; long numD = 100000L;
声明长整型时必须在结尾加L或l。
浮点型:float(单精度型/浮点型) 、double(双精度型)
float fA = 1.1f; double fB = 1.2;
声明浮点型时在结尾加F或f。
字符: char(字符型)
char cA = 'a';
声明字符型时,要加单引号,并且单引号内只能放一个符号。
布尔型:Boolean
布尔型为 true/false,一般用来做逻辑判断
引用数据类型
数组,类,接口被称为引用数据类型,共同特点:值映射一段地址,于内存中。
- 首先为 Object, 它可以由我们自己来创造,Object是一个非常重要的类型,Object类是Javajava.lang包下的核心类,Object类是所有类的父类,何一个类时候如果没有明确的继承一个父类的话,那么它就是Object的子类。
class Person {} class People {} public class OObject { public static void main(String[] args) { Object object = new Person(); } }
关于Object类型的API, 在此列举出一个,方便大家的参考,详情查看JDK1.8 API文档
大家可以在IDEA中尝试,自己做扩展才是学习的必要步骤
// toString(); 这是一个很常用的方法,该方法是为了获取对象的信息(返回对象的字符串表示形式)
- 1、数组(Array),是多个相同类型数据按一定顺序排列 的集合,并使用一个名字命名,并通过编号的方式 对这些数据进行统一管理。
2、数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括 基本数据类型和引用数据类型。
3、创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是 这块连续空间的首地址。
5、数组的长度一旦确定,就不能修改。
6、我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。
创建数组以及数组的基本使用方法
- type[] *;
- type *[];
- String[] *;
- Double *[];
// 数组的基本使用 int[] arr = new int[3]; 以上这段话的意思是: 声明一个名称为arr的数组,类型为int型,并且长度最多为3. 在输入时[3]称之为数组的动态初始化. // 为数组下标位置赋值 在这里讲一句: 下方arr[0,1,2] 中的 0, 1, 2为数组的索引,从0开始. 比如:new int[5]; 它的索引为:0, 1, 2, 3, 4, 长度为5. arr[0] = 1; arr[1] = 2; arr[2] = 3; // 数组的静态初始化 int[] arr = new int[]{5,7,8}; 或者 int[] arr = {5,7,8}; 静态初始化: 提前写好数据,{}内部的元素为数组元素
获取数组的长度
array.length 为获取数组的长度(数组元素的个数), 任何一个对象都有自己的length。
String[] arr = new String[]{"1","2","3"}; system.out.println(arr.length); // 3
数组的默认初始化值
类型 | 初始化值 |
基本类型 | 0 |
引用类型 | null |
Java 运算符
算术运算符 | 描述 |
+ | 加法: 进行两侧变量\值相加 |
- | 减法: 进两侧变量\值相减 |
* | 乘法: 进行两侧变量\值相乘 |
\ | 除法: 左侧变量\值除以右侧变量 |
% | 取模: 左侧变量\值除以右侧变量取余数 |
++ | 自增: 自身+1 |
– | 自减: 自身-1 |
Java算术运算符操作
public class Demo { public static void main(String[] args) { int a = 1; int b = 2; System.out.println(a + b); // 3 System.out.println(a \ b); // 0.5 System.out.println(a - b); // -1 System.out.println(a * b); // 2 System.out.println(a++); // 2 System.out.println(a--); // 0 } }
以下运算符就不贴代码了,减少刷新,本博客字数一多就开始卡了
关系运算符 | 描述 |
== | 判断两侧的变量\值是否相等,如果相等条件为真 |
!= | 判断两侧变量\值是否不相等,如果不相等条件为真 |
> | 判断左侧变量\ 值是否大于右侧变量\值, 如果大于条件为真 |
< | 判断左侧变量\ 值是否小于右侧变量\值, 如果小于条件为真 |
>= | 判断左侧变量\ 值是否大于或者等于右侧变量\值, 如果大于或者等于条件为真 |
<= | 判断左侧变量\ 值是否小于或者等于右侧变量\值, 如果小于或者等于条件为真 |
逻辑运算符 | 描述 |
&& | 称为逻辑与运算符。当且仅当两个操作数都为真,条件才为真。 |
|| | 称为逻辑或操作符。如果任何两个操作数任何一个为真,条件为真。 |
! | 称为逻辑非运算符。用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算符将得到false。 |
Java 修饰符
初学者看一下public和private就行了...,以后需要用到再翻回来看别的修饰符,不急,记得多敲代码哦
Java语言提供了很多修饰符,主要分为以下两类:
访问修饰符
非访问修饰符
修饰符用来定义类、方法或者变量,通常放在语句的最前端
Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java支持4种不同的访问权限。
访问修饰符
访问控制修饰符
默认的,也称为 default,在同一包内可见,不使用任何修饰符。
私有的,以 private 修饰符指定,在同一类内可见。
共有的,以 public 修饰符指定,对所有类可见。
受保护的,以 protected 修饰符指定,对同一包内的类和所有子类可见。
修饰符 | 当前类 | 同一包内 | 子孙类 | 其他包 |
public | Yes | Yes | Yes | Yes |
protected | Yes | Yes | Yes | No |
default | Yes | Yes | No | No |
private | Yes | No | No | No |
默认访问修饰符-不使用任何关键字
前缀不带修饰符 String version = "0.0.1"; boolean processOrder() { return true; }
私有访问修饰符-private
私有访问修饰符是最严格的访问级别,所以被声明为 private 的方法、变量和构造方法只能被所属类访问,并且类和接口不能声明为private。
声明为私有访问类型的变量只能通过类中公共的 getter 方法被外部类访问。
Private 访问修饰符的使用主要用来隐藏类的实现细节和保护类的数据。
public class Logger { // 对于某些敏感数据的获取以及赋值,需要用到private修饰符 private String format; // 其他类不能直接得到和设置该变量的值。为了使其他类能够操作该变量,定义了两个 public 方法 public String getFormat() { // getFormat() (返回 format的值) return this.format; } public void setFormat(String format) {// setFormat(String)(设置 format 的值) this.format = format; } }
(。・∀・)ノ゙嗨
公有访问修饰符-public
被声明为 public 的类、方法、构造方法和接口能够被任何其他类访问 =-=
// Java 程序的 main() 方法必须设置成公有的,否则,Java 解释器将不能运行该类 public static void main(String[] arguments) { ... }
``
被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问,也能够被不同包中的子类访问
Protected 访问修饰符不能修饰类和接口 TvT
方法和成员变量能够声明为 protected,但是接口的成员变量和成员方法不能声明为 protected。
子类能访问 Protected 修饰符声明的方法和变量,这样就能保护不相关的类使用这些方法和变量。
下面的父类使用了 protected 访问修饰符,子类重载了父类的 openSpeaker() 方法 class AudioPlayer { protected boolean openSpeaker(Speaker sp) { // 实现细节 } } class StreamingAudioPlayer { boolean openSpeaker(Speaker sp) { // 实现细节 } }
非访问修饰符
非访问修饰符可以先不用看,先把Java基础语法之类的看会了,回来再了解什么意思
为了实现一些其他功能,Java也提供了许多非访问修饰符。
静态变量声明符-static
static表示“静态的”,它也是一种修饰符,可以修饰属性、方法、代码块和内部类. static修饰成员变量,表示该成员变量只在内存中存储一份,可以被访问,修改(共享). static修饰的成员变量,归属于类. 被static修饰的属性(成员变量)称为静态变量,也叫做类变量. 被static修饰的常量称为静态常量. 被static修饰的方法称为静态方法,也叫做类方法. 被static修饰的代码块叫做静态代码块. 被static修饰符的内部类,叫做静态内部类.
// 只存储一份,比如:在线人数 // Num类 public class Num { public static int onlineNum = 100; } // 推荐使用 类名.成员变量 进行访问 // Demo.java public class Demo { public static void main(String[] args) { // 访问static修饰的成员变量 System.out.println(Num.onlineNum); // 不推荐使用对象访问, 虽然是可以的 Num n = new Num(); System.out.println(n.onlineNum); } }
实例成员变量与静态成员变量到底有什么区别?
静态成员变量:(有static修饰,归属于类,内存中只加载一次),通常表示一些可以被共享的信息,比如:人数,热度。。。 静态成员变量可以被共享访问
实例成员变量:(无static修饰,存在于每个对象中),通常表示姓名,年龄之类的个人(每个对象)的信息
常量声明符-final
final 用在变量的前面表示变量的值不可以改变,此时该变量可以被称为常量 final 修饰的变量即成为常量,只能赋值一次,但是 final 所修饰局部变量和成员变量有所不同。 final 修饰的局部变量必须使用之前被赋值一次才能使用。 final 修饰的成员变量在声明时没有赋值的叫“空白 final 变量”。空白 final 变量必须在构造方法或静态代码块中初始化。
注意
:final 修饰的变量不可被改变,一旦获得了初始值,该 final 变量的值就不能被重新赋值
// 此处代码为摘抄 public class FinalDemo { void doSomething() { // 1.声明常量时并没有被直接赋值 final int e; // 如果未赋值,只能赋值一次 e = 100; System.out.print(e); // 2.声明常量时赋值 final int f = 200; } // 实例常量 final int a = 5; // 直接赋值 final int b; // 空白final变量 // 静态常量 final static int c = 12;// 直接赋值 final static int d; // 空白final变量 // 静态代码块 static { // 初始化静态变量 d = 32; } // 构造方法 FinalDemo() { // 初始化实例变量 b = 3; // 第二次赋值,会发生编译错误 // b = 4; } }
当使用 final 修饰基本类型变量时,不能对基本类型变量重新赋值,因此基本类型变量不能被改变。 但对于引用类型变量而言,它保存的仅仅是一个引用,final 只保证这个引用类型变量所引用的地址不会改变,即一直引用同一个对象,但这个对象完全可以发生改变
不要忘记引用类型是存在于内存中
Java 表达式 & 语句 & 代码块
表达式
表达式,是由数字、运算符、数字分组符号(括号)、自由变量和约束变量等以能求得数值的有意义排列方法所得的组合。
约束变量是在表达式中已被指定数值,而自由变量则可以在表达式之外另行指定数值。
在 Java 中,表达式是根据 Java 语法由 变量 、 运算符 和 方法调用 组成的结构,表达式的结算结果为 单个值 。
public class Demo { public static void main(String[] args) { int a = 10; int b = 14; int c = a / (b - 1); // a / (b - 1) 为算术表达式 if (c < b) { // if语句将在下一小节讲到,此处只需知道 c > b 是一个布尔表达式即可 System.out.println("c小于b"); } } }
语句
类似于平时说话时的一句话,由表达式组成,以 ; 结束。int a = 3; y = a + 9; System.out.println(y); 都是语句。
代码块
一对大括号括起来的内容就是一个代码块。
Java 注释
Java 注释分为几种: 单行注释,多行注释,文档注释
被注释的代码不会被运行
- 单行注释
// 单行注释
- 多行注释
/* 多 行 注 释 */
- 文档注释
文档注释通常是对程序中某个类或类中的方法进行的系统性的解释说明,开发人员可以使用JDK提供的javadoc工具将文档注释提取出来生成一份API帮助文档。文档注释以符号“/**”开头,并以符号“*/”结尾。
/** * 功能:*** * 作者:xxx * 日期: */
--------------------------------------------------------------------------
Java 控制语句
控制语句
Java if | else if | else 条件
针对if | else if | else嘛… 欸嘿嘿,可以这么理解, if 就是如果的意思, else if就是再如果的意思, else显而易见,当if 与 else 都不为真的情况下,才会走 else
我觉得应该注意的点:
规范建议大家写 if 的时候都要带 else,这是一种避免有安全隐患的方法
我的理解:
其实if 后面带不带 else,要取决于实际应用场景,如果只有一种情况的话,我觉得使用return;
来替代else,可以使代码看起来更加整洁
但是:
代码这东西仁者见仁,希望大家都能具备良好的编码风格
下面是一个 if | else if | else 的代码块
public class Demo { public static void main(String[] args) { int a = 10; int b = 14; int c = 20 if (a < b) { // 如果 a 小于 b,那么就执行 if 代码块的内容 System.out.println("a小于b"); } else if (a == b) { // 如果 a 等于 b,那么就执行 else if 代码块的内容 System.out.println("a等于b"); } else { // 如果 a既不小于b也不等于b,就执行 System.out.println("a大于b"); } } }
Java switch case 条件
switch case 也是一种条件判断语句,用于判断一个变量或是一个系列内的值是否相等,是一种多分支结构,如果switch与某个case相匹配,就从该条件分支开始执行,直到遇到 break 跳出执行🙈
执行流程: switch表达式中的值与case分支与条件进行逐条匹配👀,如果某个分支相匹配就会执行对应case语句的内容,若都不匹配,则执行Default语句中的内容,执行完毕跳出
switch(条件语句) { case 1: System.out.println("1"); break; // break的意思为跳出 case 2: System.out.println("2"); break; default: System.out.println("default"); }
Java for 循环
for (循环变量类型 循环变量名称;循环条件;更新语句) 循环体
注意: for循环本身就是用来循环的,循环某个数组的长度,根据长度循环多少次
public class Demo { public static void main(String[] args) { int arr = new int[]{1, 3, 4, 5}; // for循环,打印出数组的每个元素 // 下面小括号内循环多少次表达式是基于数组的长度循环多少次,就是循环数组 for(int a = 0; a < arr.length; a++) { System.out.println(arr[a]); // a为arr每一项的下标,所以arr[a]就是循环arr的每一项 } } }
增强型for循环
public class Demo { public static void main(String[] args) { int arr = new int[]{1, 3, 4, 5}; // 增强for循环,意义与前端的forEach不能说是完全一致,只能说是一模一样 for(int item: arr) { // 循环arr数组,每一个元素为item System.out.println(item); // 循环item,输出为: 1 3 4 5 } } }
Java while 循环
while是最基本的循环
while(条件控制语句) { 循环体; 条件控制语句; }
比如说:打印 5 次 HelloWorld
public class Demo { public static void main(String[] args) { int count = 5; while(i <= 5) { System.out.println("HelloWorld"); } } }
while循环作业: 以下是一个非常简单的while循环小作业,想做的话可以做一做,并且希望你把作业发送到评论区,以供小白参考
public class Demo { public static void main(String[] args) { // 1. 定义一个变量,表示一栋楼的高度 // 2. 定义一个变量,表示一个人的身高 // 3. 定义一个计数器,用来统计次数 // 长高高 // 每次循环人的身高都会长高至自身原身高的2倍 // 楼的高度 > 人的身高 循环才继续, 否则循环就会停止 while() { // 请作答 } // 4. 打印一下一共长高了多少次 System.out.println(); } }
Java break 与 continue 语句
break和continue都是用来控制循环结构的,主要作用是停止循环
break: break用于跳出一个循环体或者完全结束一个循环,不仅可以结束其所在的循环,还可结束其外层循环。
continue: 只跳过本次循环
break的例子:
一个简单的例子,一天又34小时,如果到了晚上12点,就要睡觉了
public class Demo{ public static void main(String[] args){ for (int i = 1; i <= 24; i++) { System.out.println("正在度过一天!!"); if(i == 24) { // 24点了 System.out.println("24点啦,睡觉啦~~"); break; // 跳出并结束当前循环的执行 } } } }
continue 小作业:
在学校,一个小周期为7天,每当周六周天的时候,都为休息时间,要求:只跳过周六周天,并打印周一到周五的日期,控制台输入示例:
周1 周2 周3 周4 周5 周六啦! 周天啦!
public class Demo{ public static void main(String[] args){ for (int i = 1; i <= 7; i++) { // 请作答 } } }
小案例别忘了发到评论区哦!
--------------------------------------------------------------------------
Java 数组 ✨
- 数组详细文章:数组详细介绍
--------------------------------------------------------------------------
Java 日期与时间(Java8新增)
看了看,这个博主的时间写的挺好的,先推荐,以后时间专门出个专栏吧!
Java 正则表达式 ✨
嗯.... 我的专栏我记得之前写过正则表达式,不过那个写的比较烂,当时分在前端专栏里了. 写一个新的,正好学一学,正则这个东西对我来说,可以算得上是魔鬼了 = -=
- Java 正则表达式:Java 正则表达式
Java Scanner(获取用户输入)
java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入。
下面是创建 Scanner 对象的基本语法:
// 构造一个Scanner 类的对象,并且与标准输入流System.in关联 Scanner s = new Scanner(System.in); //创建了一个Scanner对象,Scanner为类名,s为对象名。
接下来我们演示一个最简单的数据输入,并通过 Scanner 类的 nextInt(), nextLine() 方法获取输入的字符串.
nextLine()可以扫描到一行内容(当前行,光标所在行的内容,包括空格、回车)并作为一个字符串而被获取到 next()获得有效字符串后遇到的第一个空格就会结束读取。比如,输入hello world.最终的输出结果为hello
import java.util.Scanner; public class demo04 { public static void main(String[] args) { //创建一个扫描器对象,用于接收键盘数据 Scanner scan = new Scanner(Scanner.in); System.out.println("使用next方式接收:"); //使用next方式接收 String str = Scanner.nextLine(); System.out.println("输出的内容为:"+str); //及时关闭IO流的类,否则会一直占用资源 Scanner.close(); } }
nextInt()只读取数值,读取完后 没有读取并且光标放在本行。nextDouble()的用法同理nextInt(),注意:nextInt无法读取小数,否则会报错
Scanner scan=new Scanner(System.in); int i = scan.nextInt(); double d = scan.nextDouble();
这个博主的文章不错的,代码就抄下来了 嘻嘻
———————————————— 版权声明:(Java Scanner(获取用户输入))本文为CSDN博主「海螺炒面」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/hailuochaofan/article/details/125885322
--------------------------------------------------------------------------
Java 面向对象详解
Java语言作为面向对象的编程语言,提供了面向对象的四种基本性质:抽象性、封装性、继承性和多态性。万事万物皆对象,Java面向对象编程是以人类最好理解的方向去编程(客观世界中的对象为中心)
什么是面向对象?
《Java编程思想》中提到“万物皆为对象”的概念。它将对象视为一种奇特的变量,它除了可以存储数据之外还可以对它自身进行操作。它能够直接反映现实生活中的事物,例如人、车、小鸟等,将其表示为程序中的对象。每个对象都具有各自的状态特征(也可以称为属性)及行为特征(方法),java就是通过对象之间行为的交互来解决问题的。
面向对象就是把构成问题的事物分解成一个个对象,建立对象不是为了实现一个步骤,而是为了描述某个事物在解决问题中的行为。
面向过程和面向对象的区别
面向过程
优点:性能比面向对象好,因为类调用时需要实例化,开销比较大,比较消耗资源。
缺点:不易维护、不易复用、不易扩展
面向对象
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护
缺点:性能比面向过程差
Java 面向对象 第一大部分
Java 类与对象
类:
是抽象的概念集合,表示的是一个共性的产物,类之中定义的是属性和行为(方法).
对象:
类可以表示是一个独立的个体,也可以表示为一个集体,每个对象都有自己的属性.
例如: 一个人, 就等于一个对象, 脸,身体,腿部为这个对象的属性. 说话,动作为这个对象的一些方法.
类是如何定义的?
class ClassName { ...属性; ...方法; }
类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类成员变量。 方法主要说明类具有哪些功能,称为类的成员方法。
定义一个学生类
class Students { int age = 16; String name = "xiaoming"; int id = 1; public void getInfo() { System.out..println("姓名:" + name + ",年龄:" + age + ",学号:" + id) } }
通过 javac 编译为 .class 文件,在JVM的基础上计算机就可以识别
- 声明并实例化对象
类名称 对象名称 = new 类名称();
引用数据类型与基本数据类型最大的不同在于:引用数据类型需要内存的分配和使用。所以,关键字new的主要功能就是分配内存空间,也就是说,只要使用引用数据类型,就要使用关键字new来分配内存空间。
当一个实例化对象产生之后,可以按照如下的方式进行类的操作:
对象.属性:表示调用类之中的属性;
对象.方法():表示调用类之中的方法。
下面我们来操作上方提到的那个Students类
class Student { int age; String name; int id = 1; public void getInfo() { System.out..println("姓名:" + name + ",年龄:" + age + ",学号:" + id) } } public class GetInfo() { public static void main(String[] args) { Student student = new Student(); // 实例化对象 student.name = "张三"; // 声明属性 student.age = 15; student.getInfo(); // 调用类方法 } }
执行之后,终端应该输入这样一句
姓名:张三,年龄:15,学号:1
Java 方法
首先,什么是方法?
java的方法相当于其他语言的函数(func),使用方法来完成一些特定的功能
方法有什么好处呢?
- 提高代码可读性
- 提高代码可维护性
- 代码的重用
注意:
方法必须在main方法里调用运行,因为main方法是程序的入口方法,你不调用在main方法里,你就没有程序运行,而其他方法与方法之间可以相互调用使用
方法 的 语法:
访问权限修饰符 其他修饰符 返回值类型 方法名称(参数...) { ...操作 // 如果返回值类型为 void, 则不用写return // 如果为方法体(函数体) 则 return 返回值; }
public class Demo { public static void main(String[] args) { getA("zhangsan", 1); // 调用方法 } public static void getA(String a, int b) { // 方法 System.out.println("姓名:" + a + "年龄" + b); } }
Java 方法重载 ✨
✨ 下面文章介绍了 Java方法重载 使用以及注意事项 ✨
- 方法重载:Java方法的重载示例
Java 构造方法 ✨
✨ 下面文章介绍了 Java构造方法 使用以及注意事项 ✨
- 构造方法:Java 构造方法
Java 字符串
在Java中,字符串是一种引用数据类型,它是由零个或多个字符组成的序列。Java中的字符串是不可变的,也就是说,一旦字符串对象被创建,它的值就不能被修改。如果需要修改字符串,需要创建一个新的字符串对象。
字符串是使用Unicode字符集来表示的。Unicode字符集是一种可以表示几乎所有已知语言的字符集。因此,Java字符串可以处理多种语言的字符。
Java中的字符串有两种方式可以创建:
- 使用字符串字面量
使用字符串字面量创建一个新的字符串对象,并在运行时对其进行初始化。字符串字面量是放在双引号内的字符序列,例如:
// 字面量创建字符串 String str = "Hello World!";
- 使用String类的构造函数
可以通过使用String类的构造函数来创建字符串对象。例如:
// String类的构造函数来创建字符串对象 String str = new String("Hello World!");
注意:
这种方式将创建一个新的字符串对象,即使存在相同的字符串字面量。
Java字符串中常用的方法有许多,以下是一些常见的方法:
- length():返回字符串的长度。
String str = "Hello World!"; int len = str.length(); // len的值将是12
- charAt():返回指定索引处的字符。
String str = "Hello World!"; char c = str.charAt(4); // c的值将是o
- concat():将两个字符串连接起来。
String str1 = "Hello"; String str2 = "World"; String str3 = str1.concat(str2); // str3的值将是HelloWorld
- substring():返回一个新的字符串,该字符串从指定的开始索引到指定的结束索引(不包括结束索引)之间的字符。
String str = "Hello World!"; String subStr = str.substring(6,11); // subStr的值将是World
- replace():返回一个新的字符串,其中所有出现的旧字符串被替换为新字符串。
String str = "Hello World!"; String newStr = str.replace("World","Java"); // newStr的值将是Hello Java!
- toUpperCase() 和 toLowerCase():将字符串转换为大写或小写。
String str = "Hello World!"; String upStr = str.toUpperCase(); // upStr的值将是HELLO WORLD! String lowStr = str.toLowerCase(); // lowStr的值将是hello world!
- contains():返回一个布尔值,表示是否包含指定的子字符串。
String str = "Hello World!"; boolean containsStr = str.contains("World"); // containsStr的值将是true
以上只是Java字符串中的一部分常用方法,更多的方法可以参见Java官方文档。
在使用字符串时,需要注意以下事项:
- Java中的字符串是不可变的,因此在对字符串进行操作时,总是会创建新的字符串对象。如果需要对字符串进行大量操作,最好使用StringBuilder或StringBuffer类, 因为它们比字符串更高效。
- 在使用字符串时,应注意区分大小写。
- 在使用字符串时,应避免使用==运算符。相反,应使用equals()方法进行比较。
Java this 关键字 ✨
- Java this关键字: Java this
Java 递归(恐怖故事) ✨
- Java 递归: Java递归
- 本篇文章详细介绍Java中的递归用法,注意点,使用场景
Java instanceof 操作符
instanceof是Java中的二元运算符,作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型;左边是对象,右边是类;当左边的对象是右边的类或子类所创建的对象时,返回true;否则,返回false。
import java.util.ArrayList; import java.util.Vector; // java.util.Vector类是Java中的一个集合类,它实现了可调整大小的数组,可以动态地添加或删除元素。Vector类可以用来存储任何类型的对象,而不只是基本数据类型。 public class Main { public static void main(String[] args) { Object array = new ArrayList();//创建ArrayList类的对象array Check(array);//调用函数判断 } public static void Check(Object array) { //判断对象 是哪个类实例化产生的 if (array instanceof Vector){ System.out.println("对象array 是 java.util.Vector 类的实例"); } if (array instanceof ArrayList){ System.out.println("对象array 是 java.util.ArrayList 类的实例"); } } }
Java 面向对象 第二大部分
Java 继承 ✨
继承(Inheritance)是指子类继承父类的特征和行为,使得子类具有父类的所有属性和方法。继承可以减少代码量,提高代码的复用性。在Java中,使用关键字“extends”来表示一个类继承自另一个类。
- Java 继承详细文章: Java继承(click me)
Java 方法重写 ✨
方法重写(Method Overriding)是指在子类中重新定义与父类中同名、同参数列表的方法,以实现子类对该方法的自定义实现。通常情况下,方法重写的目的是为了实现多态性,即在运行时根据对象的实际类型来调用相应的方法。
- Java 方法重写: Java 方法の重写(click me)
抽象类 & 抽象方法 ✨
- Java抽象类&抽象方法:抽象类&抽象方法
Java 接口 ✨
- Java 接口:Java 接口
Java 多态 ✨
多态(Polymorphism)是指同一种类型的对象在不同情况下表现出不同的行为。多态分为编译时多态和运行时多态。编译时多态指方法重载,即同一个类中的方法名相同但参数列表不同的方法;运行时多态指方法覆盖,即子类重写了父类的同名方法,并且在调用时只知道父类的引用,而具体调用哪个方法要根据实际对象来决定。
Java 封装
封转是指属性私有化,根据需要提供
setter
和getter
方法来访问属性,隐藏具体属性和实现细节,仅对外开放接口,控制程序中属性的访问级别。继承是指将多个相同的属性和方法提取出来,新建一个父类,java中一个类只能继承一个父类,且只能继承访问权限非private属性和方法,子类可以重写父类中的方法,命名与父类中同名的属性。💨💨💨
Java中的封装是指将类的属性和方法进行访问控制,以保证数据的安全性和代码的可维护性。具体来说,封装包括三个访问控制修饰符:
public、private
和protected
,分别表示公开、私有和受保护的访问级别。下面是一个简单的Java封装案例,其中定义了一个Person类,包含了姓名和年龄两个私有属性,以及对这两个属性进行访问的公开方法。
public class Person { private String name; // 姓名,私有属性 private int age; // 年龄,私有属性 // 构造方法 public Person(String name, int age) { this.name = name; this.age = age; } // 公开方法,获取姓名 public String getName() { return name; } // 公开方法,设置姓名 public void setName(String name) { this.name = name; } // 公开方法,获取年龄 public int getAge() { return age; } // 公开方法,设置年龄 public void setAge(int age) { this.age = age; } }
Person类
的属性name
和age
都被声明为private
,外部无法直接访问。而对于这两个属性的访问,通过公开的getName、setName、getAge和setAge
方法来实现。这样,外部就可以通过这些方法来获取和设置Person对象
的属性,而无法直接访问这些属性,从而保证了数据的安全性和代码的可维护性。例如,我们可以通过以下代码来创建一个Person对象,并通过公开方法来获取和设置其属性:
public class Main { public static void main(String[] args) { Person person = new Person("张三", 20); System.out.println("姓名:" + person.getName() + ",年龄:" + person.getAge()); person.setName("李四"); person.setAge(25); System.out.println("姓名:" + person.getName() + ",年龄:" + person.getAge()); } }
输出结果为
:
姓名:张三,年龄:20 姓名:李四,年龄:25
可以看到,通过公开方法来获取和设置Person对象的属性,而无法直接访问这些属性,从而保证了数据的安全性和代码的可维护性。
Java 面向对象高级(第三大部分)
Java static 关键字
在Java中,static关键字可以用于变量、方法和代码块中。它的作用是将这些元素与类相关联,而不是与类的实例相关联。这意味着,无论创建多少个类的实例,这些元素都只有一份副本。
具体来说,有static和无static的区别如下: 1. 静态变量:有static关键字的变量是类变量,也称为静态变量。它们在类加载时被初始化,可以通过类名直接访问,不需要创建类的实例。而无static的变量是实例变量,每个类的实例都有自己的一份副本。 2. 静态方法:有static关键字的方法是类方法,也称为静态方法。它们可以通过类名直接调用,不需要创建类的实例。而无static的方法是实例方法,只能通过类的实例调用。 3. 静态代码块:有static关键字的代码块是静态代码块。它们在类加载时执行,只执行一次。而无static的代码块是实例代码块,每次创建类的实例时都会执行。
总之,static关键字可以将变量、方法和代码块与类相关联,使它们在类加载时被初始化,而不是在创建类的实例时被初始化。这样可以节省内存空间,提高程序的执行效率。
嵌套 & 内部类
Java中的嵌套类指的是一个类定义在另一个类的内部,可以分为静态嵌套类和非静态嵌套类(也称为内部类)。内部类可以访问外部类的成员变量和方法,而外部类不能访问内部类的成员变量和方法。
class OuterClass { // 外部类的成员变量和方法 class InnerClass { // 内部类的成员变量和方法 } }
OuterClass
是外部类的名称,InnerClass
是内部类的名称。内部类可以访问外部类的成员变量和方法,可以使用OuterClass.this
来引用外部类的实例。
public class OuterClass { private int x = 10; // 非静态内部类 class InnerClass { private int y = 5; public void print() { System.out.println("x = " + x); // 访问外部类的成员变量 System.out.println("y = " + y); // 访问内部类的成员变量 } } // 静态内部类 static class StaticInnerClass { private int z = 3; public void print() { System.out.println("z = " + z); // 访问内部类的成员变量 } } public static void main(String[] args) { OuterClass outer = new OuterClass(); InnerClass inner = outer.new InnerClass(); // 创建内部类的实例 inner.print(); // 调用内部类的方法 StaticInnerClass staticInner = new StaticInnerClass(); // 创建静态内部类的实例 staticInner.print(); // 调用静态内部类的方法 } }
在上面的案例中,
OuterClass
是外部类,包含一个非静态内部类InnerClass
和一个静态内部类StaticInnerClass
。InnerClass
可以访问外部类的成员变量x
,StaticInnerClass
不能访问外部类的成员变量。在main
方法中,首先创建了外部类的实例outer
,然后通过outer.new InnerClass()
创建了内部类的实例inner
,最后调用了inner.print()
方法,输出了x
和y
的值。同时,还创建了静态内部类的实例staticInner
,并调用了staticInner.print()
方法,输出了z
的值。
Java 匿名内部类
Java中的匿名内部类是一种特殊的内部类,它没有名字,可以直接在代码中定义和使用。通常情况下,匿名内部类用于创建实现某个接口或继承某个类的对象,可以简化代码的编写,解决取名的烦恼
public class Calculator { public static void main(String[] args) { // 创建一个匿名内部类实现加法运算 Operation add = new Operation() { @Override public int operate(int a, int b) { return a + b; } }; // 创建一个匿名内部类实现减法运算 Operation subtract = new Operation() { @Override public int operate(int a, int b) { return a - b; } }; // 使用匿名内部类实现的加法运算 int result1 = add.operate(10, 5); System.out.println("10 + 5 = " + result1); // 使用匿名内部类实现的减法运算 int result2 = subtract.operate(10, 5); System.out.println("10 - 5 = " + result2); } } // 定义一个接口,用于实现不同的运算 interface Operation { int operate(int a, int b); }
我们定义了一个接口
Operation
,用于实现不同的运算。然后我们使用匿名内部类实现了加法和减法运算在匿名内部类中,我们需要重写接口中的方法,并且在创建匿名内部类的时候,需要使用
new
关键字来创建一个对象
Java 单例(Singleton)
单例模式,是一种常见的设计模式,在 Java 应用中,单例对象能保证在一个 JVM 中,该对象只有一个实例存在
单例模式分为两类:饿汉式,懒汉式
- 饿汉式
饿汉式是一种单例设计模式,它的实现方式是在类加载的时候就创建一个实例对象,因此也被称为“饿汉式单例模式”
public class Demo { // 单例第一步 构造器私有 private Demo() { } // 定义静态变量 private static Demo instance = new Demo(); public static Demo getInstance() { return instance; } }
Singleton类中定义了一个静态变量instance,用于保存类的唯一实例对象, 在类加载的时候,静态变量instance就会被初始化
- 懒汉式
懒汉式是一种常见的单例模式实现方式,它的特点是在第一次使用时才会创建实例
public class Demo { // 单例第一步 构造器私有 private Demo() { } private static Demo instance = null; public static Demo getInstance() { if (instance == null) { instance = new Demo(); } return instance } }
将
Demo类
的构造器私有化,这样外部就无法通过new关键字
创建Demo
实例。定义一个静态的
Demo
类型的instance
变量,初始值为null
。提供一个静态的
getInstance()
方法,用于获取Demo
实例。在该方法中,首先判断instance
是否为null
,如果为null
,则创建一个新的Demo实例
并赋值给instance
,否则直接返回instance
。
Java 枚举类 ✨
Java 的枚举类
- Java 枚举类 , 更多泛型扩展方法请自行查找,应用不多,就不介绍太细了
Java 泛型 | 模拟ArrayList集合操作
Java的泛型是一种在编译时期对代码进行类型检查和类型安全的机制
它允许在定义类、接口和方法时使用一个或多个类型参数,这些参数在使用时可以被实际的类型替代,从而实现代码的复用性和灵活性
泛型基础使用
先给大家来一个简单的泛型改变数据类型的例子
package arraylist; import java.util.ArrayList; public class ArrayListDemo { public static void main(String[] args) { ArrayList arr = new ArrayList(); arr.add("123"); arr.add("456"); arr.add("789"); // arr.add(new Cat()); // 不用管这一行 for (int i = 0; i < arr.size(); i++) { String e = (String) arr.get(i); // (String) 为强转为字符型的意思 System.out.println(e); } System.out.println("----------------------------"); ArrayList<String> arr2 = new ArrayList<>(); // 在java1.7之后,允许前面定义泛型类型之后,后面可不填写 arr2.add("999"); for (int i = 0; i < arr2.size(); i++) { String e = arr2.get(i); System.out.println(e); } } } class Cat {} // cat类 | 不用管这一行
泛型类的使用 模拟ArrayList
Test 类
package fanxingClass; public class Test { public static void main(String[] args) { // 泛型类的定义和使用 // 如果不使用泛型E, 则为Object类型 MyArrayList<String> list = new MyArrayList<>(); list.add("Java1"); list.add("Java2"); // list.add(23); 报错 // 取值操作 String element = list.get(1); System.out.println(element); } }
MyArrayList类
package fanxingClass; public class MyArrayList<E> { // 为什么一定要是Object类型? Object可装任意类型的数据 private Object[] arr = new Object[10]; private int size; public boolean add(E e) { // add 方法 arr[size++] = e; return true; } public E get(int index) { // get 方法 // return arr[index]; // 报错, 要强转类型 下方代码 return (E) arr[index]; } }
泛型方法 ✨
--------------------------------------------------------------------------
常用的JavaAPI(挺全的) ✨
以思维导图的方式传输,俺自己手写的,若文件失效,记住 Class Me
内含
Object类
,Objects类
,包装类
StringBuilder, StringBuffer,StringJoiner
Math,System,Runtime
BigDecimal
JDK8之前的传统日期、时间 | JDK8开始新增得日期、时间
等等等等...
- 常用的JavaAPI: JavaAPI 整合
--------------------------------------------------------------------------
Java 异常处理 ✨
- Java的异常处理详细文章:Java异常处理
--------------------------------------------------------------------------
Java 集合
Java 集合框架
什么是集合框架?
Java集合框架是Java编程语言的核心部分之一。集合几乎在每一种编程语言中都使用。大多数编程语言都支持各种类型的集合,如
List、Set、Queue、Stack
等集合框架(Collections Framework)是Java编程语言提供的一组接口,用于存储和操作一组对象。它提供了一种通用的方式来处理集合数据,包括列表(List)、集合(Set)、映射(Map)等
集合框架的设计目标是为了提供一组高效、灵活和可扩展的数据结构,以便处理不同类型的数据集合。它提供了一些核心接口,如Collection、List、Set和Map,以及一些实现这些接口的具体类,如ArrayList、HashSet和HashMap等。
通过集合框架,可以轻松地执行一些常见的操作,如添加、删除、查找、排序和遍历对象。它还提供了一些算法和工具类,以便更方便地处理集合数据。集合框架为开发人员提供了一种统一的方式来处理数据集合,简化了代码的编写和维护
总而言之,集合框架是Java中用于存储和操作一组对象的一套接口和类,它提供了高效、灵活和可扩展的数据结构,方便开发人员处理集合数据。它是Java中非常重要和常用的一部分
集合框架类图
Java 集合接口 ✨
--------------------------------------------------------------------------
Java Map,Set,队列 一些实现类
Map(映射)
HashMap:
使用哈希表实现的无序键值对存储。允许null键和null值
LinkedHashMap:
基于哈希表和双向链表实现,提供了按插入顺序或访问顺序迭代的特性
TreeMap:
基于红黑树实现,按键有序存储的映射。根据键的自然顺序或自定义比较器排序
Hashtable:
使用哈希表实现的线程安全的映射,不允许null键和null值
ConcurrentHashMap:
使用分段锁实现的线程安全映射,支持高并发操作
Set(集合)
HashSet:
使用哈希表实现的无序集合。允许存储null元素
LinkedHashSet:
基于哈希表和双向链表实现,提供了按插入顺序迭代的特性
TreeSet:
基于红黑树实现的有序集合。根据元素的自然顺序或自定义比较器排序
Queue(队列)
LinkedList:
双向链表实现的队列。可用作队列、栈或双端队列
PriorityQueue:
基于优先级堆实现的优先队列。元素按照优先级排序
ArrayDeque:
双端队列的数组实现。可用作队列、栈或双端队列
ConcurrentLinkedQueue:
非阻塞并发队列的链表实现,适合高并发场景
LinkedBlockingQueue:
基于链表的阻塞队列,支持多线程操作
以上是Java中常见的 Map、Set和Queue
的实现类。除了这些,Java还提供了其他实现类和接口供使用者选择
请注意,每种实现类在不同的使用场景中可能会有不同的性能表现和特性
--------------------------------------------------------------------------
Java IO流 💦
什么是流 ❓
I: Input |
输入
O: Output |
输出
流的分类 💤
- 按照数据的流向
- 输入流:读数据
- 输出流:写数据
- 按照数据类型来分
- 字节流
- 字节输入流
- 字节输出流
- 字符流
- 字符输入流
- 字符输出流
输入流
,输出流
字节流
,字符流
Java FileInputStream
FileInputStream
package FileInput; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; /** * Author: _LJaXi * @author ASUS */ class FileInput { public static void main(String[] args) throws IOException { try { FileInputStream fis = new FileInputStream("d:\\aaa.txt"); // 一次读取多个字节,存到数组中 // 创建一个长度为3的数组 / 字节类型 byte[] buf = new byte[3]; int count = 0; // 条件判断循环 while ((count = fis.read(buf)) != -1) { System.out.print(new String(buf,0,count)); } // 3. 关闭 fis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
1. 条件循环解决
package main.java.com.mycode; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; /** * Author: _LJaXi * @author ASUS */ class MyIo { public static void main(String[] args) throws IOException { try { FileInputStream fis = new FileInputStream("d:\\aaa.txt"); // 读取 System.out.println(fis.read()); int data = 0; // 循环打印字节 while ((data = fis.read()) != -1) { System.out.print((char) data); } // 3. 关闭 fis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
1 (2) 读取特性
package main.java.com.mycode; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; /** * Author: _LJaXi * @author ASUS */ class MyIo { public static void main(String[] args) throws IOException { try { FileInputStream fis = new FileInputStream("d:\\aaa.txt"); // 一次读取多个字节,存到数组中 // 创建一个长度为3的数组 / 字节类型 byte[] buf = new byte[3]; // 返回实例读取的个数 int count = fis.read(buf); // 打印字符串 buf System.out.println(new String(buf)); System.out.println(count); // 多次读取 int count2 = fis.read(buf); System.out.println(new String(buf)); System.out.println(count2); int count3 = fis.read(buf); System.out.println(new String(buf)); System.out.println(count3); // 若文件内字符太短,可能会出现读取数组you多余元素问题,那是你的上次buf数组没有清空导致的 // 可以使用 // System.out.println(new String(buf, index(索引), count3)); 来清理多余的元素 // new String(buf)参数: // 1. param1 是一个字节数组,用于构建新的字符串对象 // 2. param2 是偏移量(offset),表示从 param1 的索引为 param2 的位置开始构建字符串 // 3. param3 是长度(length),表示构建字符串的长度 // 3. 关闭 fis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
2. 数组存储解决
package main.java.com.mycode; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; /** * Author: _LJaXi * @author ASUS */ class MyIo { public static void main(String[] args) throws IOException { try { FileInputStream fis = new FileInputStream("d:\\aaa.txt"); // 一次读取多个字节,存到数组中 // 创建一个长度为3的数组 / 字节类型 byte[] buf = new byte[3]; int count = 0; // 条件判断循环 while ((count = fis.read(buf)) != -1) { System.out.print(new String(buf,0,count)); } // 3. 关闭 fis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
Java FileOutputStream
FileOutputStream
package main.java.com.mycode; import java.io.FileOutputStream; /** * Author: _LJaXi * @author ASUS */ public class FileOutput { public static void main (String[] args) throws Exception { // 1. 创建文件字节输出流对象 // 若不想覆盖原本内容,将构造方法append,设置为true FileOutputStream fos = new FileOutputStream("d://aaa.txt", true); // 2. 写入文件 // fos.write(97); // fos.write('b'); // fos.write('c'); String str = "helloworld"; // 获取字符串所对应的字节数组 fos.write(str.getBytes()); // 3. 关闭 fos.close(); System.out.println("执行完毕"); } }
输出流构造方法
// 某个构造方法有个形参 append,这个构造方法的 append 若为true 表明不覆盖原本内容 public FileOutputStream(String name, boolean append) throws FileNotFoundException { this(name != null ? new File(name) : null, append); }
字节流复制文件
package CopyFile; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; /* * 使用文件字节流实现文件的复制 * */ public class CopyFile { public static void main(String[] args) throws IOException { // 1. 先用文件字节输入流读到内存中 FileInputStream fis = new FileInputStream("C:\\Users\\ASUS\\Desktop\\凌波.png"); // 2. 再用一个文件字节输出流写入到硬盘 FileOutputStream fos = new FileOutputStream("C:\\Users\\ASUS\\Desktop\\凌波丽.jpg"); // 3. 一边读 一边写 byte[] buf = new byte[1024]; int count = 0; while((count=fis.read(buf)) != -1) { fos.write(buf,0,count); } // 4. 关闭流 fis.close(); fos.close(); System.out.print("复制完毕"); } }
字节缓冲流
BufferedInputStream
/Buffered0utputStream
提高IO效率,减少访问磁盘的次数;
数据存储在缓冲区中,flush是将缓存区的内容写入文件中,也可以直接close;
Java BufferInputStream
package Buffered; import java.io.FileInputStream; import java.io.BufferedInputStream; import java.io.IOException; /* * 使用字节缓冲流读取 * BufferedInputStream * @author 符韬是谁? * */ public class BufferedStream { public static void main(String[] args) throws IOException { // 1. 创建BufferedInputStream FileInputStream fis = new FileInputStream("d:\\aaa.txt"); // 增强底层流 BufferedInputStream bis = new BufferedInputStream(fis); // 2. 读取 bis 读文件会放在缓冲区,提高效率 int count = 0; // bis.read() 并不是读一个字节,先把一部分数据读到bis缓冲区内,调用已经读了8k了 // private static int DEFAULT_BUFFER_SIZE = 8192; // 当然你也可以自己定义把一部分数据读取到缓冲区, 下方注释写法 byte[] buf = new byte[6000]; while ((count=bis.read(buf)) != -1) { System.out.print(new String(buf, 0, count)); } // 3. 关闭 bis.close(); // 缓冲流close之后, 会自动帮你关闭输入流 fis.close() } }
BufferedInputStream 自定义读取部分数据
package Buffered; import java.io.FileInputStream; import java.io.BufferedInputStream; import java.io.IOException; /* * 使用字节缓冲流读取 * BufferedInputStream * @author 符韬是谁? * */ public class BufferedStream { public static void main(String[] args) throws IOException { // 1. 创建BufferedInputStream FileInputStream fis = new FileInputStream("d:\\aaa.txt"); // 增强底层流 BufferedInputStream bis = new BufferedInputStream(fis); // 2. 读取 bis 读文件会放在缓冲区,提高效率 int count = 0; // bis.read() 并不是读一个字节,先把一部分数据读到bis缓冲区内,调用已经读了8k了 // private static int DEFAULT_BUFFER_SIZE = 8192; // 当然你也可以自己定义把一部分数据读取到缓冲区, 下方注释写法 byte[] buf = new byte[6000]; while ((count=bis.read(buf)) != -1) { System.out.print(new String(buf, 0, count)); } // 3. 关闭 bis.close(); // 缓冲流close之后, 会自动帮你关闭输入流 fis.close() } }
Java BufferOutputStream
package Buffered; import java.io.*; /* * 使用字节缓冲流写入 * BufferedOutputStream * @time 2023年9月11日14:19:47 * @author _LJaXi * @tip 想秀阿卡丽 * */ public class OutputStream { public static void main(String[] args) { try { FileOutputStream fos = new FileOutputStream("d:\\aaa.txt", true); BufferedOutputStream bos = new BufferedOutputStream(fos); String data = "LOL"; bos.write(data.getBytes()); // 写入 8k 到缓冲区 fos.flush(); // 刷新到硬盘 /*--------------------------------------------------------------- * bos.flush()的作用是将缓冲区中的数据立即刷新(写入)到硬盘中 * 当使用BufferedOutputStream写入数据时,数据通常会先被存储在内部的缓冲区中,直到缓冲区达到一定的容量或者手动调用flush()方法 * --------------------------------------------------------------- * flush()方法的使用是为了确保数据被及时写入硬盘,而不是一直停留在缓冲区 * 在调用flush()方法后,任何未写入的数据将被立即写入到硬盘中,这样可以避免数据丢失的风险 * --------------------------------------------------------------- * 在流关闭之前或发生异常时,也会自动调用flush()方法,确保所有数据都被写入硬盘 * ---------------------------------------------------------------*/ bos.close(); // 内部也会调用 flush() 方法 } catch (IOException e) { e.printStackTrace(); } } }
对象流
- 增强了缓冲区功能
- 增强了读写8种基本数据类型和字符串功能
- 增强了读写对象的功能 {
readObject()
从流中读取一个对象
writeObject(Object obj)
向流中写入一个对象
使用流传输对象的过程称为序列化(写入)、反序列化(读取)
Student 类(需要用到)
package ObjectStream; import java.io.Serializable; // 要想序列化,类必须实现一个接口,为标记接口 public class Student implements Serializable { private String name; private int age; public Student() { } public Student(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } // this is 重写 toString 方法 @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
Java ObjectOutputStream
package ObjectStream; import java.io.*; /* * 序列化类必须要实现 Serializable 接口(标记接口) * ObjectOutputStream * @time 2023年9月14日13:49:52 * @author _LJaXi * @tip 阿卡丽5连败 * */ public class OutStream { public static void main(String[] args)throws IOException { // 1. 创建对象流 FileOutputStream fos = new FileOutputStream("d:\\aaa.bin"); ObjectOutputStream oos = new ObjectOutputStream(fos); // 2. 序列化(写入操作) Student zs = new Student("张三", 20); oos.writeObject(zs); // 3. 关闭 oos.close(); System.out.println("序列化完毕"); } }
Java ObjectInputStream
package ObjectStream; import java.io.*; /* * ObjectInputStream 反序列化(读取重构成对象) * @time 2023年9月14日23:31:23 * @author _LJaXi * @tip 阿卡丽排位3连胜 * */ public class InputStream { public static void main(String[] args) throws IOException, ClassNotFoundException { // 1. 创建对象流 FileInputStream fis = new FileInputStream("d:\\aaa.bin"); ObjectInputStream ois = new ObjectInputStream(fis); // 2. 读取文件(反序列化) Student s = (Student)ois.readObject(); // Student s2 = (Student)ois.readObject(); // 不能读取多次 // 3. 关闭 ois.close(); System.out.println("执行完毕"); System.out.println(s.toString()); } }
序列化和反序列化注意点
序列化类必须实现 Serializable 接口
序列化类中对象属性要求实现 Serializable 接口
序列化类中对象属性要求实现 Serializable 接口意思为:
public class Student implements Serializable { private String name; private int age; private Class class; // Class类要实现 Serializable 接口 // ... 其他内容 }
serialVersionUlD 警告
警告:
添加一个 serialVersionUlD 常量(Java内置,可在设置中打开)
The serializable class Student does not declare a static final serialVersionUlD field of type long
在类中添加:
private static final long serialVersionUID = 100L;
意义: 序列化版本号ID
作用:保证序列化的类和反序列化的类是同一个类
对于没有显式声明 serialVersionUID 的类,Java会自动生成一个默认值
transient 禁止序列化某属性
若不相信序列化类中的某个属性,可使用
transient
(瞬间的, 瞬时的) 关键字修饰
// Student package ObjectStream; import java.io.Serializable; public class Student implements Serializable { private String name; private transient int age; // age禁止被序列化 public Student() { } // ....其他操作 }
序列化读取多次
序列化可写入多个对象,在反序列化时读取多个即可
// 序列化 public class OutStream { public static void main(String[] args)throws IOException { // 1. 创建对象流 FileOutputStream fos = new FileOutputStream("d:\\aaa.bin"); ObjectOutputStream oos = new ObjectOutputStream(fos); // 2. 序列化(写入操作) Student zs = new Student("张三", 20); Student ls = new Student("李四", 20); // 定义ls对象 ⭕ oos.writeObject(zs); oos.writeObject(ls); // 写入ls ⭕ // 3. 关闭 oos.close(); System.out.println("序列化完毕"); } } // 反序列化 public class InputStream { public static void main(String[] args) throws IOException, ClassNotFoundException { // 1. 创建对象流 FileInputStream fis = new FileInputStream("d:\\aaa.bin"); ObjectInputStream ois = new ObjectInputStream(fis); // 2. 读取文件(反序列化) Student s = (Student)ois.readObject(); Student s2 = (Student)ois.readObject(); // 读取多次 ⭕ // 3. 关闭 ois.close(); System.out.println("执行完毕"); System.out.println(s.toString()); } }
借助集合实现多个对象的序列化
// 序列化 public class OutStream { public static void main(String[] args)throws IOException { // 1. 创建对象流 FileOutputStream fos = new FileOutputStream("d:\\aaa.bin"); ObjectOutputStream oos = new ObjectOutputStream(fos); ArrayList<Student> list = new ArrayList<>(); // ⭕定义集合 // 2. 序列化(写入操作) Student zs = new Student("张三", 20); Student ls = new Student("李四", 20); // ⭕ 添加元素 list.add(zs); list.add(ls); oos.writeObject(list); // ⭕写入 // oos.writeObject(zs); // oos.writeObject(ls); // 3. 关闭 oos.close(); System.out.println("序列化完毕"); } } // 反序列化 public class InputStream { public static void main(String[] args) throws IOException, ClassNotFoundException { // 1. 创建对象流 FileInputStream fis = new FileInputStream("d:\\aaa.bin"); ObjectInputStream ois = new ObjectInputStream(fis); // 2. 读取文件(反序列化) ArrayList<Student> l = (ArrayList<Student>) ois.readObject(); // ⭕强转 // Student s = (Student)ois.readObject(); // Student s2 = (Student)ois.readObject(); // 3. 关闭 ois.close(); System.out.println("执行完毕"); // System.out.println(s.toString()); System.out.println(list.toString()); // ⭕打印 } }
字符流
字符流以字符为单位读写数据,提供了更高层次的操作,能够方便地处理文本数据
文件字符输入流 FileReader
package FileReaderAndWriter; import java.io.FileReader; public class FileRead { public static void main(String[] args)throws Exception { // 1. 创建 FileReader 文件字符输入流 FileReader fr = new FileReader("d:\\aaa.txt"); // 2. 读取 // int data = 0; // while((data = fr.read()) != -1) { // System.out.print((char) data); // } // 创建缓冲区 char[] buf = new char[1024]; int count = 0; while((count = fr.read(buf)) != -1) { System.out.print(new String(buf, 0, count)); } // 3. 关闭 fr.close(); } }
文件字符输出流 FileWriter
package FileReaderAndWriter; import java.io.FileWriter; public class FileWrite { public static void main(String[] args)throws Exception { // 1. 创建文件字符输出流 FileWriter fw = new FileWriter("d:\\write.txt"); // 2. 写入 for (int i = 0; i < 10; i++) { fw.write("Java是世界上最好的语言\r\n"); // 换行写入 \r\n fw.flush(); } // 3. 关闭 fw.close(); } }
使用 FileReader
和 FileWriter
复制文本文件
package FileReaderAndWriter; import java.io.FileReader; import java.io.FileWriter; /* * 使用 FileReader 和 FileWriter 复制文本文件,不能复制图片或者二进制文件 * =============== 使用字节流才可以复制任何文件 ================= * @author _LJaXi * */ public class CopyFile { public static void main(String[] args)throws Exception { // 1. 创建 FileReader FileWriter FileReader fr = new FileReader("d://write.txt"); FileWriter fw = new FileWriter("d://write2.txt"); // 2. 读写 int data = 0; while((data = fr.read()) != -1) { fw.write(data); } // 3. 关闭 fr.close(); fw.close(); System.out.println("执行完毕"); } }
字符缓冲流 BufferedReader \ BufferedWriter
高效读取, 高效写入
字符缓冲流读取文件 BufferedReader
package FileReaderAndWriter; import java.io.BufferedReader; import java.io.FileReader; /* * 使用字符缓冲流读取文件 * 高效读取 * BufferedReader * */ public class BufferedReaderStream { public static void main(String[] args)throws Exception { // 1. 创建缓冲流 FileReader fr = new FileReader("d:\\write.txt"); BufferedReader br = new BufferedReader(fr); // 2. 读取 // char[] buf = new char[1024]; // int count = 0; // while ((count = br.read(buf)) != -1) { // System.out.println(new String(buf, 0, count)); // } // 2.1 第二种方式 一行一行的读取 // readLine() BufferedReader提供的API String line = null; while ((line = br.readLine()) != null) { System.out.println(line); } // 3. 关闭 br.close(); } }
字符缓冲流写入文件 BufferedWriter
package FileReaderAndWriter; import java.io.BufferedWriter; import java.io.FileWriter; /* * 字符缓冲流 * BufferedWriter * */ public class BufferedWriterStream { public static void main(String[] args)throws Exception { FileWriter fw = new FileWriter("d:\\buffer.txt"); BufferedWriter bw = new BufferedWriter(fw); // 2. 写入 for (int i = 0; i < 10; i++) { bw.write("好好学习。"); bw.newLine(); // 换行符,等同于 \r\n bw.flush(); } // 3. 关闭 bw.close(); } }
打印流 PrintWriter
package PrintWriterStream; import java.io.PrintWriter; /* * PrintWriter * */ public class Print { public static void main(String[] args)throws Exception { // 1. 新建 打印流 PrintWriter pw = new PrintWriter("d:\\print.txt"); // 2. 打印 pw.println(97); pw.println(true); pw.println(3.14); pw.println('a'); // 3. 关闭 pw.close(); } }
转换流
InputStreamReader
和OutputStreamWriter
是用于处理字符流(文本)的桥接类, 它们将字节流转换为字符流
使用 InputStreamReader
读取指定文件并指定使用的编码
import java.io.*; public class InputStreamReaderExample { public static void main(String[] args) { try { // 创建 InputStreamReader 指定编码读取文件 FileInputStream fileInputStream = new FileInputStream("input.txt"); // 指定文件路径 InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8"); // 指定编码 BufferedReader bufferedReader = new BufferedReader(inputStreamReader); // BufferedReader 字符缓冲流读取文件 String line; while ((line = bufferedReader.readLine()) != null) { System.out.println(line); } // 关闭资源 bufferedReader.close(); inputStreamReader.close(); fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } // e.printStackTrace()方法会将异常的堆栈跟踪信息打印到标准错误流(System.err)。堆栈跟踪信息包含了异常发生的位置、方法调用的轨迹以及导致异常的原因等详细信息,有助于开发者定位和解决问题。 } }
使用 OutputStreamWriter
写入文件并指定使用的编码
import java.*; public class OutputStreamWriterExample { public static void main(String[] args) { // 输出流 FileOutputSteam fps = new FileOutputSteam("output.txt"); OutputStreamWriter osw = new OutputStreamWriter(fps, "UTF-8"); // 写入 for (int i = 0; i < 10; i++) { osw.write("OutputStreamWriterExample\r\n"); osw.flush(); } // 关闭流 osw.close(); } }
File 类
java.io.File
是Java
标准类库中用于表示文件和目录路径的类。它提供了一组方法,可以操作文件和目录,如创建、删除、重命名、检查文件属性等
API | 作用 |
createNewFile() | 创建一个新文件 |
mkdir() | 创建一个新目录 |
delete() | 删除文件或空目录 |
exists() | 判断File对象所代表的对象是否存在 |
getAbsolutePath() | 获取文件的绝对路径 |
getName() | 取得名字 |
getParent() | 获取文件 / 目录所在的目录 |
isDirectory() | 是否是目录 |
isFile | 是否为文件 |
length() | 获得文件的长度 |
listFiles() | 列出目录中的所有内容 |
renameTo() | 修改文件名 |
获取文件路径分隔符和名称分隔符
import java.io.File; public class GetSeparator { public static void main(String[] args) { separator(); } public static void separator() { // 获取路径分隔符 System.out.print("路径分隔符" + File.pathSeparator); // 获取名称分隔符 System.out.print("路径分隔符" + File.separator); } }
文件操作
创建文件
import java.io.File; public class FileOpe { public static void main(String[] args) throw Exception { fileOp(); } public static void fileOp() throw Exception { File file = new File("D:\\file.txt"); // System.out.print(file.toString()); // d:\file.txt if(file.exists()) { boolean b = file.createNewFile(); System.out.print("创建结果" + b); } } }
删除文件
import java.io.File; public class FileOpe { public static void main(String[] args) throw Exception { fileOp(); } public static void fileOp() throw Exception { File file = new File("D:\\file.txt"); if(file.exists()) { boolean b = file.createNewFile(); System.out.print("创建结果" + b); } // 删除文件 // 1. 直接删除 // file.delete(); // 2. jvm退出时删除 file.deleteOnExit(); Thread.sleep(5000); } }
获取文件信息
import java.io.File; public class FileOpe { public static void main(String[] args) throw Exception { fileOp(); } public static void fileOp() throw Exception { File file = new File("D:\\file.txt"); if(file.exists()) { boolean b = file.createNewFile(); System.out.print("创建结果" + b); } // 获取文件信息 System.out.print("文件名称" + file.getName()); System.out.print("获取父目录" + file.getParent()); System.out.print("获取长度" + file.length()); System.out.print("获取文件绝对路径" + file.getAbsolutePath()); System.out.print("获取路径" + file.getPath()); System.out.print("获取文件创建时间" + new Date(file.lastModified()).toLocaleString()); } }
判断文件信息
import java.io.File; public class FileOpe { public static void main(String[] args) throw Exception { fileOp(); } public static void fileOp() throw Exception { File file = new File("D:\\file.txt"); if(file.exists()) { boolean b = file.createNewFile(); System.out.print("创建结果" + b); } // 判断 System.out.print("文件是否可写" + file.canWrite()); System.out.print("是否为文件" + file.isFile()); System.out.print("文件是否隐藏" + file.isHidden()); } }
文件夹操作
创建文件夹
import java.io.File; public class FileOpe { public static void main(String[] args) throw Exception { directoryOpe(); } public static void directoryOpe() throw Exception { File dir = new File("d:\\aaa\\bbb\\ccc"); // System.out.print(dir.toString()); // d:\aaa\bbb\ccc if (!dir.exists()) { // dir.mkdir(); // 只能创建单级目录 System.out.print("创建状态: " + dir.mkdirs()); // true } } }
删除文件夹
import java.io.File; public class FileOpe { public static void main(String[] args) throw Exception { directoryOpe(); } public static void directoryOpe() throw Exception { File dir = new File("d:\\aaa\\bbb\\ccc"); // System.out.print(dir.toString()); // d:\aaa\bbb\ccc if (!dir.exists()) { // dir.mkdir(); // 只能创建单级目录 System.out.print("创建状态: " + dir.mkdirs()); // true } // 1. 直接删除 // System.out.print("删除结果" + dir.delete()); // 注意删除空目录 // 2. 使用jvm删除 dir.deleteOnExit(); Thread.sleep(5000); } }
获取文件夹信息
import java.io.File; public class FileOpe { public static void main(String[] args) throw Exception { directoryOpe(); } public static void directoryOpe() throw Exception { File dir = new File("d:\\aaa\\bbb\\ccc"); // System.out.print(dir.toString()); // d:\aaa\bbb\ccc if (!dir.exists()) { // dir.mkdir(); // 只能创建单级目录 System.out.print("创建状态: " + dir.mkdirs()); // true } // 获取文件信息 System.out.print("文件名称" + dir.getName()); System.out.print("获取父目录" + dir.getParent()); System.out.print("获取文件绝对路径" + dir.getAbsolutePath()); System.out.print("获取路径" + dir.getPath()); System.out.print("获取文件创建时间" + new Date(dir.lastModified()).toLocaleString()); } }
判断文件夹信息
import java.io.File; public class FileOpe { public static void main(String[] args) throw Exception { directoryOpe(); } public static void directoryOpe() throw Exception { File dir = new File("d:\\aaa\\bbb\\ccc"); // System.out.print(dir.toString()); // d:\aaa\bbb\ccc if (!dir.exists()) { // dir.mkdir(); // 只能创建单级目录 System.out.print("创建状态: " + dir.mkdirs()); // true } // 判断 System.out.print("是否为文件夹" + dir.isDirectory()); System.out.print("文件夹是否隐藏" + dir.isHidden()); } }
遍历文件夹内容
import java.io.File; public class FileOpe { public static void main(String[] args) throw Exception { directoryOpe(); } public static void directoryOpe() throw Exception { File dir = new File("d:\\aaa\\bbb\\ccc"); // System.out.print(dir.toString()); // d:\aaa\bbb\ccc if (!dir.exists()) { // dir.mkdir(); // 只能创建单级目录 System.out.print("创建状态: " + dir.mkdirs()); // true } // 遍历文件夹 File dir2 = new File("d:\\图片"); String[] files = dir2.list(); for(String item : files ) { System.out.println(item); } } }
FileFilter 接口
FileFilter 接口
是 Java 标准库中的一个接口,位于java.io
包下. 它用于筛选文件列表的方法,使得可以选择性地选择需要的文件.
FileFilter 接口
是一个函数式接口,只有一个抽象方法accept(File pathname)
,该方法接收一个待测试的文件对象(File类型)作为参数,返回一个布尔值. 如果文件符合条件,返回 true,否则返回 false.
public interface FileFilter - boolean accept(File pathname)
import java.io.File; import java.io.FileFilter; public class FileFilterExample { public static void main(String[] args) { File directory = new File("path/to/directory"); // 创建一个 FileFilter 匿名内部类来筛选以 ".txt" 结尾的文件 FileFilter txtFileFilter = new FileFilter() { @Override public boolean accept(File pathname) { // endsWith 字符串方法筛选文件是否以 txt 结尾 return pathname.isFile() && pathname.getName().endsWith(".txt"); } }; // 获取目录下所有满足筛选条件的文件 File[] txtFiles = directory.listFiles(txtFileFilter); // 输出结果 for (File file : txtFiles) { System.out.println(file.getName()); } } }
递归遍历和递归删除
递归遍历
import java.*; public class FileDemo { public static void main(String[] args) throw Exception { FileOpe(new File("d:\\demo")); } /** * @ File dir 接收一个 File 类型参数, 用于递归判断 */ public static void FileOpe(File dir) throw Exception { File[] files = dir.listFile(); // 如果数组不为 null 并且 数组不为 [] if (files != null && files.length > 0) { for(File file : files) { if (file.isDerectory()) { FileOpe(file); // 如果某一项为文件夹,那就对某个文件夹进行递归操作 } else { System.out.print(file.getAbsolutePath()); } } } } }
递归删除
找 chatGPT 改了一下,懒得手敲了
import java.io.*; public class FileDemo { public static void main(String[] args) throws Exception { FileOpe(new File("d:\\demo")); } /** * @param dir 接收一个 File 类型参数,用于递归判断 */ public static void FileOpe(File dir) throws Exception { File[] files = dir.listFiles(); // 如果数组不为 null 并且数组不为空 if (files != null && files.length > 0) { for (File file : files) { if (file.isDirectory()) { FileOpe(file); // 如果某一项为文件夹,那就对该文件夹进行递归操作 } else { System.out.println(file.getAbsolutePath()); file.delete(); // 删除文件 } } } dir.delete(); // 删除文件夹 } }
Properties
Java
的Properties
是一种用于管理配置信息的类它继承自
Hashtable
类,因此它具有Hashtable
的所有特性和方法
Properties
类以键值对的形式存储配置数据,其中键和值都是字符串类型
遍历Properties集合
import java.*; public class PropertiesDemo { public static void main(String[] args) { // 创建 Properties Proerties p = new Properties(); // 添加key value p.setProperty("name", "Jerry"); p.setProperty("age", "3"); // 遍历 Set<String> propNames = p.stringPropertyNames(); for(String pro : propNames) { System.out.println(pro + " === " + p.getProperty(pro)); } // 和流有关的方法 PrintWriter pw = new PrintWriter("d:\\a.txt"); p.list(pw); pw.close(); // store 方法 // store() 是 Properties 类的一个方法,用于将属性列表存储到输出流中 // 第一个参数是输出流对象,可以是 FileOutputStream、BufferedOutputStream 等 // 第二个参数是一个字符串,表示对存储的属性列表进行注释 FileOutputStream fos = new FileOutputStream("d:\\a.txt"); p.store(fos, "注释"); fos.close(); // load 方法加载 Properties p2 = new Properties(); FileInputStream fis = new FileInputStream("d:\\config.properties"); p2.load(fis); fis.close(); System.out.println(p2.toString()); } }
--------------------------------------------------------------------------
Java 并发编程 ✨
并发编程: NULL
--------------------------------------------------------------------------
Java 虚拟机
虚拟机
Java 内存结构
堆
栈
Java 垃圾回收
JVM 内存区域
Java 虚拟机栈
class 文件
字节码指令
JVM 参数调优
Java 对象模型
HotSpot
类加载机制
编译和反编译
反编译工具(javap)
JIT
虚拟机性能监控和故障处理工具(jps、jstack、jmap、jstat、jconsole、javap)
--------------------------------------------------------------------------
后话
规划学习路线以及建议