2024年Java IO流超详细笔记,java线程常见面试题

最后

由于文案过于长,在此就不一一介绍了,这份Java后端架构进阶笔记内容包括:Java集合,JVM、Java并发、微服务、SpringNetty与 RPC 、网络、日志 、Zookeeper 、Kafka 、RabbitMQ 、Hbase 、MongoDB、Cassandra 、Java基础、负载均衡、数据库、一致性算法、Java算法、数据结构、分布式缓存等等知识详解。

image

本知识体系适合于所有Java程序员学习,关于以上目录中的知识点都有详细的讲解及介绍,掌握该知识点的所有内容对你会有一个质的提升,其中也总结了很多面试过程中遇到的题目以及有对应的视频解析总结。

image

image

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

使用步骤:

  1. 创建节点流并设置字符编码集

  2. 读写数据

  3. 关闭流

public class OutputStreamWriterDemo {

public static void main(String[] args) throws IOException{

//创建一个字符输出对象

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“osw.txt”),“UTF-8”);

//写操作

osw.write(“卡卡”);

//释放资源

osw.close();

}

}

public class InputStreamReaderDemo {

public static void main(String[] args) throws IOException{

//创建一个字符输入流对

InputStreamReader isr = new InputStreamReader(new FileInputStream(“osw.txt”),“UTF-8”);

//读的操作

int ch = 0;

while((ch = isr.read()) != -1){

System.out.print((char)ch);

}

//关闭资源

isr.close();

}

}

  • 可设置字符的编码方式但是编码和解码要一致;

5.2 写文件


针对字符输出流写数据的功能:

  • public void write(int c):写入单个字符
  • public void write(char[] cbuf):给当前输出流写入一个字符数组
  • public abstract void write(char[] cbuf, int off,int len):写入字符数组的一部分
  • public void write(String str):写入字符串内容
  • public void write(String str, int off,int len):写入字符串的一部分内容

public class OutputStreamWriterDemo {

public static void main(String[] args) throws IOException {

//创建字符输出流对象

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“osw.txt”));

//写入单个字符

osw.write(‘a’);

//给当前输出流写入一个字符数组

char[] chs = {‘a’,‘b’,‘c’,‘d’};

osw.write(chs);

//写字符数组的一部分

osw.write(chs,0,2);

//写入字符串内容

String str = “不断学习的卡卡”;

osw.write(str);

//写字符串的一部分

osw.write(str,1,3);

//刷新

osw.flush();

//关闭资源

osw.close();

}

}

5.3 读文件


针对字符输入流读数据的功能:

  • public int read(){}:一次读取一个字符
  • public int read(char[] c){}:一次读入一个字符数组
  • public int read(char[] b,int off,int len){}:将字符读入一个字符数组的一部分

public class InputStreamReaderDemo {

public static void main(String[] args) throws IOException {

//创建一个字符输入流对象

InputStreamReader isr = new InputStreamReader(new FileInputStream(“a.txt”));

//m1(isr);//一次读取一个字符

m2(isr);//一次读取一个字符数组

}

private static void m2(InputStreamReader isr) throws IOException {

//一次读取一个字符数组

//创建字符数组:长度:1024或者1024整数倍

char[] chs = new char[1024] ;

int len = 0;

while((len=isr.read(chs))!=-1) {

System.out.println(new String(chs,0,len));

}

//关闭资源

isr.close();

}

private static void m1(InputStreamReader isr) throws IOException {

//一次读取一个字符

int ch = 0;

while((ch = isr.read()) != -1){

System.out.print((char)ch);

}

//关闭资源

isr.close();

}

}

5.3.1 Copy案例_字符流

需求:使用字符流进行操作,在当前项目下a.txt文件 (源文件)---->将内容复制到当前项目下的b.txt文件中(目的地)

public class CopyTest {

public static void main(String[] args) throws IOException {

//封装原文件 创建字符输入流对象

InputStreamReader isr = new InputStreamReader(new FileInputStream(“a.txt”));

//封装目的地 创建字符输出流对象

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“b.txt”));

//chars(isr, osw);

charArray(isr,osw);

//刷新流

osw.flush();

//释放资源

osw.close();

isr.close();

}

//一次读取一个字符数组

private static void charArray(InputStreamReader isr, OutputStreamWriter osw) throws IOException{

int len = 0;

char[] chs = new char[1024];

while((len = isr.read(chs))!= -1){

//写的操作

osw.write(chs,0,len);

}

}

//一次读取一个字符

private static void chars(InputStreamReader isr, OutputStreamWriter osw) throws IOException {

int ch = 0;

while((ch = isr.read()) != -1){

osw.write(ch);

}

}

}

5.4 字符节点流


简化代码书写操作:字符流的便捷类:FileReader和FileWriter

FileWriter:

  • public void writer(String str):一次写入多个字符,将b数组中所有字符写入输出流;

FileReader:

  • public int read(cahr[] c):将流中读取多个字符,将读到内容存入c数组中,返回实际读到的字符数;如果达到文件尾部,返回-1;

需求:将当前项目下的b.txt文件内容复制到当前目录copy.txt文件中

public class CopyTest {

public static void main(String[] args) throws IOException {

//封装源文件:b.txt

//创建字符输入流对象

FileReader fr = new FileReader(“b.txt”);

//封装目的地

FileWriter fw = new FileWriter(“copy.txt”);

//读写操作

char[] chs = new char[1024];

int len = 0 ;

while((len=fr.read(chs))!=-1) {

fw.write(chs, 0, len);

}

//刷新该流

fw.flush();

//关闭

fw.close();

fr.close();

}

}

5.5 close()和flush()方法的区别


close()

  • 关闭资源,目的是释放跟系统相关的资源 ,一旦流关闭了,不能再给流中写入数据,否则会出现异常;

flush()

  • 描述的刷新该流,将一些缓冲的字节进行写入(写入指定流中),在关闭流之前需要刷新字符流对象,仅仅刷新该流,刷新完毕之后依然可以写入数据;

5.6 字节流字符流


字节流

  • 读:InputStream
  • 写:OutputStream

字符流:

  • 读:Reader
  • 写:Writer
  • 需要把磁盘上的文件内容展示控制台 (InputStream)

  • 使用Java程序给磁盘上输出一个文件使用OutputStream

6. 字符缓冲流

============================================================================

字符流为了提高读写效率,在最基本的字符流的基础上,提供了字符缓冲流;

6.1 字符缓冲输出流


  • ​ BufferedWriter(Writer w):提供一个默认大小的缓冲区,字符输出流(足够大)

public class BufferedWriterDemo {

public static void main(String[] args) throws IOException {

//创建一个字符缓冲输出对象

BufferedWriter bw = new BufferedWriter(new FileWriter(“bw.txt”));

//写数据

bw.write(“hello”);

bw.write(“world”);

bw.write(“java”);

//关闭流对象

bw.close();

}

}

6.2 字符缓冲输入流


  • BufferedReader(Reader r):创建一个缓冲输入流对象,提供默认的缓冲区大小(足够大)

public class BufferedReaderDemo {

public static void main(String[] args) throws IOException {

//创建一个缓冲输入流对象

BufferedReader br = new BufferedReader(new FileReader(“bw.txt”)) ;

//一次读取一个数组

int len = 0;

char[] buffer = new char[1024];

while((len = br.read(buffer)) != -1){

System.out.println(new String(buffer,0,len));

}

//关闭资源

br.close();

}

}

6.3 字符缓冲流中的特有功能


BufferedReader:

  • public String readLine() :一次读取一行内容,返回字符串内容,如果读完毕,则返回值为null

BufferedReader:

  • public void newLine(): 写入一个行分隔符(新行):换行操作

public class BufferedDemo {

public static void main(String[] args) throws IOException {

write();

read();

}

//读的操作

private static void read() throws IOException {

//创建一个字符缓冲输入流对象

BufferedReader br = new BufferedReader(new FileReader(“bw.txt”));

//读数据:public String readLine() :

String line = null ;

while((line=br.readLine())!=null) {

System.out.println(line);

}

//释放资源

br.close();

}

//写的功能

private static void write() throws IOException {

//创建一个字符缓冲输出流

BufferedWriter bw = new BufferedWriter(new FileWriter(“bw.txt”));

for(int i = 0 ; i < 10 ; i ++) {

bw.write(“hello”+i);

//针对字符缓冲输出流newLine()

bw.newLine();

bw.flush();

}

//关闭资源

bw.close();

}

}

6.4 Copy案例_字符缓冲流


需求:当前项目下a.java文件的内容----复制到当前下的b.java文件中

思路:

  • BufferedReader 一次读取一个字符数组/一次读取一个字符 操作 a.java
  • BufferedWriter :操作b.java文件 给文件中写内容

public class CopyDemo {

public static void main(String[] args) throws IOException {

method1() ;

method2() ;

}

//一次读取一行内容

private static void method2() throws IOException {

BufferedReader br = new BufferedReader(new FileReader(“a.java”)) ;

BufferedWriter bw = new BufferedWriter(new FileWriter(“b.java”)) ;

//readLine()

String line = null ;

while((line=br.readLine())!=null) {

bw.write(line);

//一次写一行

bw.newLine();

//刷新

bw.flush();

}

//关闭资源

bw.close();

br.close();

}

//正常方法

private static void method1()throws IOException {

//创建字符缓冲输入流对象

BufferedReader br = new BufferedReader(new FileReader(“a.java”)) ;

//创建字符缓冲输出流对象

BufferedWriter bw = new BufferedWriter(new FileWriter(“b.java”)) ;

//一次读取一个字符数组

char[] chs = new char[1024] ;

int len = 0 ;

while((len=br.read(chs))!=-1) {

bw.write(chs, 0, len);

bw.flush();

}

//关闭资源

bw.close();

br.close();

}

}

7. 内存操作流

============================================================================

处理内存中的临时数据,比如变量;当前程序结束之后,这些数据就不存在了,程序结束,内存数据就消失了,不需要关闭资源

ByteArrayOutputStream: 内存输出流,给内存中写入数据

  • public ByteArrayOutputStream()

步骤:

  1. 创建ByteArrayOutputStream对象
  1. 写数据

ByteArrayInputStream: 内存输入流,将内存中的数据读出来

  • public byte[] toByteArray() :通过内存操作输出流对象将内存中的数据转换成字节数组
  • ByteArrayInputStream(byte[] byte)

步骤:

  1. 创建内存操作输入流对象
  1. 读数据:一次读取一个字节/一次读取一个字节数组

public class ByteArrayStream {

public static void main(String[] args) throws IOException{

//创建一个内存操作输出流对象

ByteArrayOutputStream bos = new ByteArrayOutputStream();

//写数据

for(int i = 0; i < 10; i++){

//数据写到内存中

bos.write((“kaka” + i + “\t”).getBytes());

}

//通过内存操作输出流对象将内存中的数据转换成字节数组

byte[] bytes = bos.toByteArray();

//创建内存操作输入流对象

ByteArrayInputStream bis = new ByteArrayInputStream(bytes);

//一次读一个字节

int by = 0;

while((by = bis.read()) != -1){

System.out.print((char)by);

}

}

}

8. PrintWriter流

===================================================================================

封装了print()/ptintln()方法,后者支持写入后换行;

  • 字节打印流:PrintStream
  • 字符打印流:PrintWriter

特点:

  • 只能操作目的地文件,不能操作原文件

  • 字符打印流: 可以实现自动刷新

public PrintWriter(Writer out,boolean autoFlush)

  • 参数2:如果为true,开启自动刷新功能

比BufferedWriter更为方便;提供了println()打印后换行

public class PrintWriterDemo {

public static void main(String[] args) throws IOException {

//创建字符打印流对象,不自动刷新

PrintWriter pw = new PrintWriter(new FileWriter(“pw.txt”));

//写数据,换行

pw.println(“hello”);

pw.println(“world”);

pw.println(“java”);

//刷新流

pw.flush();

//关闭流

pw.close();

}

}

Copy案例_打印流


当前项目a.txt复制到c.txt文件中

public class PrintCopyTest {

public static void main(String[] args) throws IOException{

//封装源文件

BufferedReader br = new BufferedReader(new FileReader(“a.txt”));

//封装目的地

PrintWriter pw = new PrintWriter(new FileWriter(“c.txt”),true);

//读写操作

String line = null;

while((line = br.readLine()) != null){

pw.println(line);

}

//释放资源

pw.close();

br.close();

}

}

9. 键盘录入的另一种方法

=================================================================================

使用BufferedReader(Reader in) :使用字符缓冲输入流的方式进行录入数据

  • BufferedReader:利用字符缓冲输入流进行键盘录入(录入字符串居多:public String readLine())

public static void main(String[] args) throws IOException {

//录入字符串

//分步走

//创建一个字符缓冲 输入流对象

InputStream in = System.in ;

//创建一个基本的字符输入流对象

InputStreamReader isr = new InputStreamReader(in) ;

BufferedReader br = new BufferedReader(isr) ;

//一步走

BufferedReader br = new BufferedReader(new InputStreamReader(System.in)) ;

System.out.println(“请您输入一个字符串数据:”);

String line = br.readLine() ; //读取一个行内容

System.out.println(“您录入的字符串数据是:”+line);

//录入整数 int

//创建一个字符缓冲 输入流对象

BufferedReader br2 = new BufferedReader(new InputStreamReader(System.in)) ;

System.out.println(“请你输入一个整数数据:”);

String str = br2.readLine() ;

int number = Integer.parseInt(str) ;

System.out.println(number);

}

10. 字节合并流

=============================================================================

顾名思义就是将两个文件合并到一个文件中,继承自字节流;

10.1 合并两个文件


  • public SequenceInputStream(InputStream s1, InputStream s2):将s1和s2合并

需求:

将a.txt以及b.txt的文件内容复制到 Copy.txt文件中

public class SequenceInputStreamDemo_01 {

public static void main(String[] args) throws IOException {

//封装a.txt文件和b.txt文件

InputStream s1 = new FileInputStream(“a.txt”);

InputStream s2 = new FileInputStream(“b.txt”);

//创建合并输入流对象

SequenceInputStream sis = new SequenceInputStream(s1,s2);

//封装目的地Copy.java

//创建一个字节缓冲输出流对象

BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(“Copy.java”)) ;

//一次读取一个字节数组

byte[] bytes = new byte[1024] ;

int len = 0 ;

while((len=sis.read(bytes))!=-1) {

bos.write(bytes, 0, len);

}

//释放资源

bos.close();

sis.close();

}

}

10.2 合并三个文件


  • public SequenceInputStream(Enumeration<? extends InputStream> e):可以将两个以上的文件合并到一个流中

需求:

当前项目路径下的a.java , b.java,c.java三个文件的内容复制到d.java文件中

利用Enumeration:接口 Vector集合的特有迭代器(向量的枚举组件)

public class SequenceInputStreamDemo_02 {

public static void main(String[] args) throws IOException {

//Vector

//创建三个基本字节输入流对象

InputStream s1 = new FileInputStream(“a.java”);

InputStream s2 = new FileInputStream(“b.java”);

InputStream s3 = new FileInputStream(“c.java”);

//创建一个Vector集合

Vector ve = new Vector() ;

//添加到集合中

ve.add(s1);

ve.add(s2);

ve.add(s3);

//获取Enumeration:接口

Enumeration en = ve.elements();

//创建字节输入合并流对象

SequenceInputStream sis = new SequenceInputStream(en);

//封装目的地

BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(“d.java”));

//读写复制操作

byte[] bytes = new byte[1024];

int len = 0;

while((len=sis.read(bytes))!=-1) {

bos.write(bytes, 0, len);

}

//释放资源

bos.close();

sis.close();

}

}

11. 对象序列化

=============================================================================

使用流传输对象的过程称为序列化、反序列化;序列化就是把对象写出到文件中;反序列化就是从文件中把对象读到程序里来;

  • 序列化:将某个对象按照流的方式存入文本文件中或者在网络中传输
  • 反序列化:将文本文件中流的数据或者网络中传输的数据还原成对象

11.1 对象流


ObjectOutputStream:写入OutputStream,输出流

  • public final void writeObject(Object obj):将指定的对象写入流中

ObjectInputStream:读取(重构)对象

  • public final Object readObject():将流读取为一个指定的对象

为了防止频繁的去更改类的成员(比如类的成员有很多),部分成员不想进行序列化,Java提供关键字transient

好处:

  • 增强了缓冲区功能

  • 增强了读写8种基本数据类型和字符串功能

  • 增强了读写对象的功能:

  • readObject():从流中读取一个对象;

  • writeObject(Object obj):向流中写入一个对象

需求:使用序列化和反序列化来操作一个对象 (定义一个Person类)

public class Person implements Serializable {

/*

  • 点击黄色警告线---->每次生产的SeriavalVersionUID产生一个固定的!

*/

private static final long serialVersionUID = 1L; //常量

private String name ;

//private int age;

private transient int age;

public Person() {

super();

// TODO Auto-generated constructor stub

}

public Person(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;

}

@Override

public String toString() {

return “Person [name=” + name + “, age=” + age + “]”;

}

}

public class ObjectStreamDemo {

public static void main(String[] args) throws Exception {

//序列化: 对象---->流数据

// write();

//反序列化

read() ;

}

private static void read() throws Exception{

//创建反序列化流对象

ObjectInputStream ois = new ObjectInputStream(

new FileInputStream(“oos.txt”)) ;

// public final Object readObject():将流读取为一个指定的对象

Object obj = ois.readObject() ;

System.out.println(obj);

//关闭资源

ois.close();

}

private static void write() throws Exception {

//创建序列化流对象

ObjectOutputStream oos = new ObjectOutputStream(

new FileOutputStream(“oos.txt”)) ;

//将指定的对象写入流中

//创建一个Person对象

Person p = new Person(“高圆圆”,30) ;

oos.writeObject§;

//释放资源

oos.close();

}

}

注:

a) 必须实现Serializable接口;

b) 必须保证其所有属性均可序列化;

c) Transient修饰为临时属性,不参与序列化;

d) 读取到文件尾部标志:java.io.EOFException

12. Properties类

===================================================================================

12.1 Properties概述


继承自Hashtable<K,V> 表示一个持久的属性集,属性列表中每个键及其对应值都是一个字符串,有一些成员方法保存在流中或从流中加载;

特点:

  • 不需要带泛型的

  • 键和值都是字符串数据String

  • 可以持久化的属性集。键值可以存储到集合中,也可以存储到持久化设备中

使用Map集合的功能进行添加元素和遍历属性集合

public class PropertiesDemo {

public static void main(String[] args) {

//创建一个属性集合类对象

Properties prop = new Properties();

//利用Map集合的添加功能

prop.put(“卡卡_01”, “23”);

prop.put(“卡卡_02”, “25”);

prop.put(“卡卡_03”, “28”);

//keySet() :获取所有的键的集合

Set set = prop.keySet() ;

for(Object key :set) {

//通过键获取值

Object value = prop.get(key);

System.out.println(key+“—”+value);

}

}

}

卡卡_03—28

卡卡_02—25

卡卡_01—23

12.2 属性集合类的特有功能


  • public Object setProperty(String key,String value):添加元素
  • public Set< String > stringPropertyNames():获取属性集合中所有的键的集合
  • public String getProperty(String key):通过键获取对应的值

public class PropertiesDemo {

public static void main(String[] args) {

//创建一个属性集合类对象

Properties prop = new Properties();

//添加元素

prop.setProperty(“卡卡”, “小卡”);

prop.setProperty(“糖糖”, “小糖”);

prop.setProperty(“安安”, “小安”);

//遍历

//获取属性集合中所有的键的集合

Set set = prop.stringPropertyNames();

for(String key :set) {

//通过键获取值

String value = prop.getProperty(key) ;

System.out.println(key+“=”+value);

}

}

}

12.3 流相关的应用(重要)


  • public void store(Writer writer, String comments):将属性集合类中内容(键值对)保存在指定的文本文件中
*   参数1:指定的字符输出流
*   参数2:属性列表的描述:如果不指定,为null
  • public void load(Reader reader):将指定的文本文件中内容加载到属性集合列表中

public class PropertiesDemo3 {

public static void main(String[] args) throws IOException {

myStore();

// myLoad();

}

//将文本文件中的内容加载到属性集合类中

private static void myLoad() throws IOException {

//创建属性集合类对象

Properties prop = new Properties();

//将指定的文本文件中内容加载到属性集合列表中

FileReader fr = new FileReader(“a.txt”);

prop.load(fr);

//释放资源

fr.close();

System.out.println(prop);

}

//将属性集合中的列表数据保存到指定文本文件中

private static void myStore() throws IOException {

//创建属性集合类对象

Properties prop = new Properties();

//添加元素

prop.setProperty(“卡卡_01”, “23”);

prop.setProperty(“卡卡_02”, “24”);

prop.setProperty(“卡卡_03”, “26”);

prop.setProperty(“卡卡_04”, “28”);

//将属性集合类中内容(键值对)保存在指定的文本文件中

FileWriter writer = new FileWriter(“name.txt”);

prop.store(writer, “name list”);

//释放资源

writer.close();

}

总结

蚂蚁面试比较重视基础,所以Java那些基本功一定要扎实。蚂蚁的工作环境还是挺赞的,因为我面的是稳定性保障部门,还有许多单独的小组,什么三年1班,很有青春的感觉。面试官基本水平都比较高,基本都P7以上,除了基础还问了不少架构设计方面的问题,收获还是挺大的。


经历这次面试我还通过一些渠道发现了需要大厂真实面试主要有:蚂蚁金服、拼多多、阿里云、百度、唯品会、携程、丰巢科技、乐信、软通动力、OPPO、银盛支付、中国平安等初,中级,高级Java面试题集合,附带超详细答案,希望能帮助到大家。

蚂蚁金服5面,总结了49个面试题,遇到的面试官都是P7级别以上

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

;

for(String key :set) {

//通过键获取值

String value = prop.getProperty(key) ;

System.out.println(key+“=”+value);

}

}

}

12.3 流相关的应用(重要)


  • public void store(Writer writer, String comments):将属性集合类中内容(键值对)保存在指定的文本文件中
*   参数1:指定的字符输出流
*   参数2:属性列表的描述:如果不指定,为null
  • public void load(Reader reader):将指定的文本文件中内容加载到属性集合列表中

public class PropertiesDemo3 {

public static void main(String[] args) throws IOException {

myStore();

// myLoad();

}

//将文本文件中的内容加载到属性集合类中

private static void myLoad() throws IOException {

//创建属性集合类对象

Properties prop = new Properties();

//将指定的文本文件中内容加载到属性集合列表中

FileReader fr = new FileReader(“a.txt”);

prop.load(fr);

//释放资源

fr.close();

System.out.println(prop);

}

//将属性集合中的列表数据保存到指定文本文件中

private static void myStore() throws IOException {

//创建属性集合类对象

Properties prop = new Properties();

//添加元素

prop.setProperty(“卡卡_01”, “23”);

prop.setProperty(“卡卡_02”, “24”);

prop.setProperty(“卡卡_03”, “26”);

prop.setProperty(“卡卡_04”, “28”);

//将属性集合类中内容(键值对)保存在指定的文本文件中

FileWriter writer = new FileWriter(“name.txt”);

prop.store(writer, “name list”);

//释放资源

writer.close();

}

总结

蚂蚁面试比较重视基础,所以Java那些基本功一定要扎实。蚂蚁的工作环境还是挺赞的,因为我面的是稳定性保障部门,还有许多单独的小组,什么三年1班,很有青春的感觉。面试官基本水平都比较高,基本都P7以上,除了基础还问了不少架构设计方面的问题,收获还是挺大的。


经历这次面试我还通过一些渠道发现了需要大厂真实面试主要有:蚂蚁金服、拼多多、阿里云、百度、唯品会、携程、丰巢科技、乐信、软通动力、OPPO、银盛支付、中国平安等初,中级,高级Java面试题集合,附带超详细答案,希望能帮助到大家。

[外链图片转存中…(img-dhimo2jQ-1714838684610)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 22
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值