Java 基础知识点 笔记总结 (七),我凭着这份《Kafka源码实战》碾压面试官

  • 比较字符串内容值是否相同。

    package com.holmes.java04;

    import org.junit.Test;

    public class StringTest {

    @Test

    public void test1(){

    String s1 = “abc”;

    String s2 = “abc”;

    System.out.println(s1 == s2);//比较s1和s2的地址是否相同。

    System.out.println(s1.equals(s2));//比较字符串内容值是否相同。

    }

    }


    String字符串,什么情况下,重新指定内存区域进行赋值:

    无论,重复赋值,还是拼接字符串,还是修改指定替换字符串等,都是要重新指定内存区域进行赋值!!!

    2. String的字面量创建 和 new 对象形式

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


    String对象创建的四种方式:

    整体上,也就两种方式:一种字面量,一种new创建对象。

    • 通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。

    • 通过 new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对象的值。

      package com.holmes.java04;

      import org.junit.Test;

      public class StringTest {

      @Test

      public void test1(){

      //通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。

      String s1 = “javaEE”;

      String s2 = “javaEE”;

      //通过 new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对象的值。

      String s3 = new String(“javaEE”);

      String s4 = new String(“javaEE”);

      System.out.println(s1 == s2);//true

      System.out.println(s1 == s3);//false

      System.out.println(s3 == s4);//false

      }

      }

      3. String 字符串 内存存储原理

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


      字面形式和new + 对象的内存存储原理:

      面试题:String s = new String(“abc”);方式创建对象,在内存中创建了几个对象?

      两个,一个是堆空间中new的对象,另一个是char[]对应常量池中的数据:“abc”。

      4. String 不同拼接对比 效果

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

      下面的拼接效果必须牢记!!!!

      package com.holmes.java04;

      import org.junit.Test;

      public class StringTest {

      @Test

      public void test1(){

      String s1 = “javaEE”;

      String s2 = “hadoop”;

      String s3 = “javaEEhadoop”;

      String s4 = “javaEE”+“hadoop”;

      String s5 = s1 + “hadoop”;

      String s6 = “javaEE” + s2;

      String s7 = s1 + s2;

      String s8 = (s1 + s2).intern();

      //没有变量相加,仅仅只是字符串,这样声明的s4的内存地址就仅仅在常量池中。

      System.out.println(s3 == s4); //true

      //只要有变量相加的,那么该创建方式就是new对象形式,也就是要存储到堆内存地址。

      System.out.println(s3 == s5); //false

      System.out.println(s3 == s6); //false

      System.out.println(s5 == s6); //false

      System.out.println(s3 == s7); //false

      System.out.println(s5 == s7); //false

      System.out.println(s6 == s7); //false

      //通过调用intern()方法,返回值就在常量池中!

      System.out.println(s3 == s8); //true

      }

      }

      5. String 和 数组 常用的混合面试题

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

      package com.holmes.java04;

      public class StringTest2 {

      //也算涉及到了String类型的不可变性。

      //这里与下面change函数中的str的内存地址不同!

      String str = new String(“good”);

      char[] ch = {‘t’,‘e’,‘s’,‘t’};

      public void change(String str,char ch[]){

      //这里的str与上面的str不同!!地址不同,这里是形参是参数!!!

      str = “test ok”;

      ch[0] = ‘b’;

      }

      public static void main(String[] args) {

      StringTest2 ex = new StringTest2();

      ex.change(ex.str,ex.ch);

      //有人疑惑这里为什么不是test ok, 原因很简单,因为这里的ex.str是作为形参传入。

      System.out.println(ex.str); //good

      //至于数组没有不可变形,对应地址相同,只不过内容中的第一个值变化了而已。

      System.out.println(ex.ch); //best

      }

      }

      6. JVM涉及字符串 内存结构

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


      JDK1.6版本,字符串常量池都在方法区中:


      JDK除了1.7版本,字符串常量池在堆中:


      JDK1.8以及以后的版本,字符串常量池都在方法区中:

      7. String 常用方法

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


      问题一:什么情况下,indexOf(str) 和 lastIndexOf(str)返回值相同?

      **答:情况一:存在唯一的一个str。情况二:不存在str时。

      此外,indexOf 和 lastIndexOf方法如果未找到都是返回-1。**


      上面的replaceAll()函数方法,matches()函数方法,涉及到正则表达式内容,如下:

      8. 涉及到String 类与其他结构之间的转换

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

      8.1 常见的小错误



      首先,纠正一个经常犯下的错误:

      String str = “123”;

      //错误的,强转的前提必须是子父类的前提下!!!

      int num = (int)str;

      8.2 String 和 int 之间的转换



      String 转 int:(调用包装类的静态方法,Integer.parseXxx())

      String str = “123”;

      //调用包装类的静态方法,才是正确的

      int num = Integer.parseInt(str)

      int 转 String:(调用包装类的静态方法,Integer.toString() 和 String.valueOf())

      String s2;

      String s3;

      int num2 = 123;

      //方式一:Integer.toString()方法

      s2 = Integer.toString(num2);

      //方式二:String.valueOf()方法

      s3 = String.valueOf(num2);

      System.out.println(s2.getClass()+ “,” +s3.getClass());

      //class java.lang.String , class java.lang.String

      //方式三:就是通过加空字符串 “” 。

      String s4 = 123 + “”;


      8.3 String 和 char[]字符组 之间的转换


      牢记toCharArray()函数方法:

      package com.holmes.java04;

      import org.junit.Test;

      public class StringTest {

      @Test

      public void test1(){

      String str1 = “abc123”;

      //调用String的toCharArray()拆分字符串 转为 字符数组。

      char[] charArray = str1.toCharArray();

      //遍历一下charArray

      for (int i=0;i

      System.out.println(charArray[i]);

      }

      char[] arr = new char[]{‘h’,‘e’,‘l’,‘l’,‘o’};

      //直接将字符数组当作参数放入字符串对象,就直接形成了字符串

      String str2 = new String(arr);

      System.out.println(str2);

      }

      }

      8.4 String字符串 和 byte[]字节数组 之间的转换


      这里就会出现一个编码和解码的一个效果:


      **String 转为 byte[]:

      (调用String的getBytes()方法)**

      package com.holmes.java04;

      import org.junit.Test;

      import java.io.UnsupportedEncodingException;

      import java.lang.reflect.Array;

      import java.util.Arrays;

      public class StringTest {

      @Test

      public void test1() throws UnsupportedEncodingException {

      //调用String的getBytes()方法

      String str1 = “abc123中国”;

      byte[] bytes = str1.getBytes(); //使用默认的字符集(utf-8),进行转换

      //Arrays.toString()方法显示字符串。

      System.out.println(Arrays.toString(bytes));

      //[97, 98, 99, 49, 50, 51, -28, -72, -83, -27, -101, -67],这里结果就是aciII码

      //此外,在utf-8当中一个汉字是占3个字节。

      //使用gbk编码,就要添加参数

      byte[] gbks = str1.getBytes(“gbk”);

      System.out.println(Arrays.toString(gbks));

      //[97, 98, 99, 49, 50, 51, -42, -48, -71, -6] 在gbk中一个汉字包含两个字节。

      }

      }


      **byte[]字节数组 转 String字符串:

      (new对象参数传入,来转换)**

      package com.holmes.java04;

      import org.junit.Test;

      import java.io.UnsupportedEncodingException;

      public class StringTest {

      @Test

      public void test1() throws UnsupportedEncodingException {

      //调用String的getBytes()方法

      String str1 = “abc123中国”;

      byte[] bytes = str1.getBytes(); //使用默认的字符集(utf-8),进行转换

      byte[] gbks = str1.getBytes(“gbk”);

      //同样这里也是用默认的字符集(utf-8)来进行解码

      String str2 = new String(bytes);

      System.out.println(str2);

      //因为这里是通过gbk编码的,但使用utf-8来解码就会乱码

      String str3 = new String(gbks);

      System.out.println(str3);

      //abc123中国

      //abc123�й�

      }

      }

      9. String 拼接 小面试题

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

      因为一个final,就导致结果不同,牢记常量与常量拼接的结果是存储在常量池中,且常量池不会存在相同内容的常量。final声明后变量就变成了常量!

      package com.holmes.java04;

      import org.junit.Test;

      public class StringTest {

      @Test

      public void test1(){

      String s1 = “javaEEhadoop”;

      String s2 = “javaEE”;

      String s3 = s2 + “hadoop”;

      System.out.println(s1 == s3); //false

      //final声明后,s4就变成了常量,常量和常量的拼接结果就在常量池中,因此返回true。

      final String s4 = “javaEE”;

      String s5 = s4 + “hadoop”;

      System.out.println(s1 == s5); //true

      }

      }

      10. StringBuffer 和 StringBuilder 介绍

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

      本质上字符串存储规则,其实就是个char[]数组,String不可变,StringBuffer和StringBuilder可变。


      String , StringBuffer , StringBuilder三者的异同?

      String:不可变的字符序列。

      StringBuffer:可变的字符序列:线程安全的,效率偏低。

      StringBuilder:可变的字符序列:jdk5.0新增,线程不安全的,效率高。

      上面三者底层使用char[]存储。(StringBuffer和StringBuilder因为继承AbstractStringBuilder,因此也是char[] value存储。)


      11. String ,StringBuffer,StringBuilder 源码分析

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


      String源码分析:

      String str = new String();

      //执行实际源码为:char[] value = new char[0];

      String str1 = new String(“abc”);

      //执行实际源码为:char[] value = new char[]{‘a’,‘b’,‘c’};


      StringBuffer源码分析:(StringBuilder源码差不多,就是安不安全的问题)

      StringBuffer sb1 = new StringBuffer();

      //执行实际源码为:char[] value = new char[16]; 底层创建了一个长度是16的数组。

      sb1.append(‘a’); //value[0] = ‘a’;

      sb1.append(‘b’); //value[1] = ‘b’;

      StringBuffer sb2 = new StringBuffer(“abc”);

      //执行实际源码为:char[] value = new char[“abc”.length() + 16]; 字符串的长度外加16个长度数组。

      //问题1:System.out.println(sb2.length()); 输出为3呢,还是3+16呢?

      //答案:其实和加不加16没关系,因为length返回的count,是数组中有多少数据。

      //问题2:既然开始定义长度为16,一旦满了就会有一个扩容问题?

      //如果要添加的数据底层数组盛不下了,那就需要扩容底层的数组。

      //append方法中,调用了ensureCapacityInternal(确保容量完整的)方法,进而满足扩容。

      //默认情况下扩容为原来容量的2倍(向左进位1,就是乘于2)+2,同时将原有数组中的元素复制到新的数组中。

      开发中建议大家使用:StringBuffer(int capacity) 或 StringBuilder(int capacity)。可以直接定义容量大小,区别就是安全不安全。

      12. StringBuffer 和 StringBuilder类常用的方法

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

      StringBuffer和StringBuilder的常用方法差不多,都是一样:

      当append和insert时,如果原来value数组长度不够,可扩容。

      package com.holmes.java04;

      import org.junit.Test;

      public class StringBufferBuilderTest {

      @Test

      public void test1(){

      StringBuffer sb1 = new StringBuffer(“abc”);

      sb1.append(1);

      sb1.append(‘1’);

      System.out.println(sb1);

      //注意:像delete这样的方法,删除的索引是左闭右开!!

      sb1.delete(2,4);

      System.out.println(sb1);

      sb1.replace(2,4,“hello”);

      System.out.println(sb1);

      sb1.insert(2,“c”);

      System.out.println(sb1);

      sb1.reverse();

      System.out.println(sb1);

      System.out.println( sb1.indexOf(“c”));

      System.out.println(sb1.substring(2,4));

      System.out.println(sb1.charAt(5));

      sb1.setCharAt(0,‘m’);

      System.out.println(sb1);

      }

      }


      方法链是一个很重要的形式,方法链的原理:


      13. 对比String ,StringBuffer,StringBuilder的效率

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

      package com.holmes.java04;

      import org.junit.Test;

      public class StringBufferBuilderTest {

      @Test

      public void test1(){

      long startTime = 0;

      long endTime = 0;

      String text = “”;

      StringBuffer buffer = new StringBuffer(“”);

      StringBuilder builder = new StringBuilder(“”);

      startTime = System.currentTimeMillis();

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

      buffer.append(String.valueOf(i));

      }

      endTime = System.currentTimeMillis();

      System.out.println(“StringBuffer的执行时间:” + (endTime - startTime));

      startTime = System.currentTimeMillis();

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

      builder.append(String.valueOf(i));

      }

      endTime = System.currentTimeMillis();

      System.out.println(“StringBuilder的执行时间:” + (endTime - startTime));

      startTime = System.currentTimeMillis();

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

      text += i;

      }

      endTime = System.currentTimeMillis();

      System.out.println(“String的执行时间:” + (endTime - startTime));

      //String的效率远远小于前两者

      //效率从高到低排列: StringBuilder > StringBuffer > String

      //考虑是否有线程安全问题是否要同步,就要使用StringBuffer. StringBuffer线程安全,StringBuilder线程不安全。

      }

      }

      14. Java 时间日期 的相关API

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


      计算世界时间的主要标准有:


      方法一:

      java.lang.System类的日期时间:(计算时间差)

      • System.currentTimeMillis()返回当前时间于1970年1月1日0时0分0秒之间以毫秒为单位的时间差。

      • 此方法经常用来计算时间差。


        方法二:

        java.util.Date类表示特定的瞬间,精确到毫秒:

        package com.holmes.java04;

        /*

        方式一:两个构造器使用

        构造器一:Date() :创建一个对应当前时间的Date对象。

        构造器二:创建指定毫秒数(时间戳)的Date对象。

        方式二:两个方法的使用

        调用toString()方法:显示当前的年,月,日,时,分,秒。

        getTime()方法:获取当前Date对象对应的毫秒数(时间戳)。

        */

        import org.junit.Test;

        import java.util.Date;

        public class DateTimeTest {

        @Test

        public void test2(){

        //构造器一:Date() :创建一个对应当前时间的Date对象

        Date date1 = new Date();

        //调用toString()方法:显示当前的年,月,日,时,分,秒

        System.out.println(date1.toString());//Sat Nov 06 14:55:02 CST 2021

        //getTime()方法:获取当前Date对象对应的时间戳

        System.out.println(date1.getTime());//1636181996537

        //构造器二:创建指定毫秒数(时间戳)的Date对象

        Date date2 = new Date(1636181996537L);

        System.out.println(date2.toString());

        }

        }


        在sql也有一个,java.sql.Date类,对应着数据库中的日期类型的变量。

        package com.holmes.java04;

        /*

        java.sql.Date类的Date对象:

        同样调用toString()方法和getTime()方法

        */

        import org.junit.Test;

        import java.sql.Date;

        public class DateTimeTest {

        @Test

        public void test2(){

        //创建java.sql.Date的对象

        Date date1 = new Date(23453456342L);

        System.out.println(date1.toString()); //1970-09-29

        System.out.println(date1.getTime()); //23453456342

        }

        }


        怎么将sql.Date 转为 util.Date对象?

        因为多态性,直接赋值就可。

        package com.holmes.java04;

        import org.junit.Test;

        public class DateTimeTest {

        @Test

        public void test2(){

        //创建java.sql.Date的对象

        java.sql.Date date1 = new java.sql.Date(23453456342L);

        //创建java.util.Date的对象

        java.util.Date date2 = new java.util.Date();

        //sql.Date 转 util.Date 多态性直接赋值就可

        date2 = date1;

        System.out.println(date2);

        }

        }

        怎么将util.Date 转为 sql.Date对象?

        因为参数都有毫秒(时间戳),所以我们可以通过getTime()的方式来解决这种问题!!

        package com.holmes.java04;

        import org.junit.Test;

        public class DateTimeTest {

        @Test

        public void test2(){

        //创建java.sql.Date的对象

        java.sql.Date date1 = new java.sql.Date(23453456342L);

        //创建java.util.Date的对象

        //情况一:左边是util,右边是sql,多态性,这样就可以强转。

        java.util.Date date2 = new java.sql.Date(32453476342L);

        java.sql.Date date3 = (java.sql.Date)date2;

        System.out.println(date3); //1971-01-11

        //情况二:都是util直接强转会报错!!cannot be cast

        java.util.Date date4 = new java.util.Date(32453476342L);

        //java.sql.Date date5 = (java.sql.Date)date4; 错误的!

        //但是有一个方法getTime(),来获得毫秒数就可以直接当作参数传递过去,就完美解决了

        java.sql.Date date6 = new java.sql.Date(date4.getTime());

        System.out.println(date6); //2021-11-06

        }

        }

        15. IDEA 的 debug调试

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

        16. JDK8之前日期时间API SimpleDateFormat类

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

        16.1 SimpleDateFormat默认无参数情况



        SimpleDateFormat是对日期Date类的格式化和解析。

        • 使用format()方法,格式化:日期 转为 字符串。

        • 使用parse()方法,解析:格式化的逆过程,字符串 转为 日期

          package com.holmes.java05;

          import org.junit.Test;

          import java.text.ParseException;

          import java.text.SimpleDateFormat;

          import java.util.Date;

          public class DateTimeTest {

          @Test

          public void testSimpleDateFormat() throws ParseException {

          //实例化SimpleDateFormat:使用默认的构造器

          SimpleDateFormat sdf = new SimpleDateFormat();

          //格式化:日期 转为 字符串

          Date date = new Date();

          String formatStr = sdf.format(date);

          System.out.println(formatStr);

          //解析:格式化的逆过程,字符串 转为 日期

          //需要注意的是字符串的格式也必须和date格式一样,不然就抛出异常了

          String str = “21-11-7 下午3:04”;

          Date date1 = sdf.parse(str);

          System.out.println(date1);

          }

          }

          16.2 SimpleDateFormat有参数情况



          SimpleDateFormat的参数,不同格式的参数对应不同返回的结果。可以查看java参考手册这对SimpleDateFormat有参数的构造器这一节。

          jdk参考手册

          package com.holmes.java05;

          import org.junit.Test;

          import java.text.ParseException;

          import java.text.SimpleDateFormat;

          import java.util.Date;

          public class DateTimeTest {

          @Test

          public void testSimpleDateFormat() throws ParseException {

          Date date = new Date();

          SimpleDateFormat sdf = new SimpleDateFormat(“yyyy.MM.dd G ‘at’ HH:mm:ss z”);

          System.out.println(sdf.format(date));

          //常用格式如下:

          //年:小写y,月:大写M,时分秒:小写hms。

          SimpleDateFormat sdf1 = new SimpleDateFormat(“yyyy-MM-dd hh:mm:ss”);

          //格式化format:日期 转为 字符串

          System.out.println(sdf1.format(date));

          //解析,同样这里parse解析的格式也必须和参数定义的格式一样!!否则抛出异常

          System.out.println(sdf1.parse(“1999-11-07 04:07:55”));;

          //2021.11.07 公元 at 16:09:21 CST

          //2021-11-07 04:09:21

          //Sun Nov 07 04:07:55 CST 1999

          }

          }


          很多页面传字符串"2020-09-08" 转为java.sql.Date(以方便存储数据库中)。

          package com.holmes.java05;

          import org.junit.Test;

          import java.text.ParseException;

          import java.text.SimpleDateFormat;

          public class DateTimeTest {

          @Test

          public void testExer() throws ParseException {

          String str = “2020-09-08”;

          //参数格式有一种为:“yyyy-MM-dd hh:mm:ss”

          //要对应前端传过来的数据,像后面的hh:mm:ss,忽略就行。

          SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd”);

          //util下的date

          java.util.Date dateUtil = sdf.parse(str);

          java.sql.Date dateSql = new java.sql.Date(dateUtil.getTime());

          System.out.println(dateSql);

          }

          }


          总天数差的一些计算,可以用到方法类和getTime类方法。


          自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

          深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

          因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

          既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

          由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

          如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)

          难道这样就够了吗?不,远远不够!

          提前多熟悉阿里往年的面试题肯定是对面试有很大的帮助的,但是作为技术性职业,手里有实打实的技术才是你面对面试官最有用的利器,这是从内在散发出来的自信。

          备战阿里时我花的最多的时间就是在学习技术上,占了我所有学习计划中的百分之70,这是一些我学习期间觉得还是很不错的一些学习笔记

          我为什么要写这篇文章呢,其实我觉得学习是不能停下脚步的,在网络上和大家一起分享,一起讨论,不单单可以遇到更多一样的人,还可以扩大自己的眼界,学习到更多的技术,我还会在csdn、博客、掘金等网站上分享技术,这也是一种学习的方法。

          今天就分享到这里了,谢谢大家的关注,以后会分享更多的干货给大家!

          ws ParseException {

          String str = “2020-09-08”;

          //参数格式有一种为:“yyyy-MM-dd hh:mm:ss”

          //要对应前端传过来的数据,像后面的hh:mm:ss,忽略就行。

          SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd”);

          //util下的date

          java.util.Date dateUtil = sdf.parse(str);

          java.sql.Date dateSql = new java.sql.Date(dateUtil.getTime());

          System.out.println(dateSql);

          }

          }


          总天数差的一些计算,可以用到方法类和getTime类方法。


          自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

          深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

          因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

          [外链图片转存中…(img-AsXkF6vm-1711692406432)]

          [外链图片转存中…(img-mNCCYhNI-1711692406432)]

          [外链图片转存中…(img-TVZi6ous-1711692406433)]

          [外链图片转存中…(img-Ck2IB3sf-1711692406433)]

          [外链图片转存中…(img-fXdpBu5E-1711692406433)]

          [外链图片转存中…(img-I2iCfyuH-1711692406434)]

          既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

          由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

          如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)

          [外链图片转存中…(img-M4LiQdO4-1711692406434)]

          难道这样就够了吗?不,远远不够!

          提前多熟悉阿里往年的面试题肯定是对面试有很大的帮助的,但是作为技术性职业,手里有实打实的技术才是你面对面试官最有用的利器,这是从内在散发出来的自信。

          备战阿里时我花的最多的时间就是在学习技术上,占了我所有学习计划中的百分之70,这是一些我学习期间觉得还是很不错的一些学习笔记

          我为什么要写这篇文章呢,其实我觉得学习是不能停下脚步的,在网络上和大家一起分享,一起讨论,不单单可以遇到更多一样的人,还可以扩大自己的眼界,学习到更多的技术,我还会在csdn、博客、掘金等网站上分享技术,这也是一种学习的方法。

          今天就分享到这里了,谢谢大家的关注,以后会分享更多的干货给大家!

          [外链图片转存中…(img-hEE5JvTE-1711692406434)]

          [外链图片转存中…(img-FBNgKe9H-1711692406435)]

          [外链图片转存中…(img-jrnCpdeo-1711692406435)]