Java

  • 一、异常
    • 1.1 异常概述
    • 1.2 异常的体系
    • 1.3 异常的分类
      • 1.3.1 运行时异常
      • 1.3.2 非运行时异常
    • 1.4 异常的处理
      • 1.4.1 异常向上抛出处理
      • 1.4.2 异常自行处理
    • 1.5 finally关键字
    • 1.6 异常处理注意事项
    • 1.7 自定义异常
      • 1.7.1 概念
      • 1.7.2 创建异常类
      • 1.7.3 使用
  • 二、Log4j
    • 2.1 概念
    • 2.2 日志分类
    • 2.3 日志级别
    • 2.4 使用
      • 2.4.1 导入jar包
      • 2.4.2 书写配置文件
      • 2.4.3 使用
    • 2.5 配置文件的修改
      • 2.5.1 根配置
      • 2.5.2 输出位置配置
      • 2.5.3 根据输出位置进行配置
      • 2.5.4 配置输出格式
      • 2.5.5 根据选择格式设置布局

一、异常

1.1 异常概述

异常 :指的是在程序书写与运行过程中,由于非语法产出的非正常情况,最终会导致JVM的非正常停止。

异常的本质是一个类,在程序运行过程中根据发生的异常类型创建对应的异常对象并返回

1.2 异常的体系

异常机制其实是帮助我们找到程序中的问题,异常的根类是java.lang.Throwable,其下有两个子类:java.lang.Errorjava.lang.Exception,平常所说的异常指java.lang.Exception

Throwable体系

  • Error:严重错误Error,无法通过处理的错误,只能事先避免,好比绝症。
  • Exception:表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。好比感冒、阑尾炎。
  • 错误一定会使程序终止运行,异常则不一定

1.3 异常的分类

异常就是指Exception,因为这类异常一旦出现,我们就要对代码进行更正,修复程序。

1.3.1 运行时异常

也叫非受检异常,runtime异常。在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)。(如数学异常)

1.3.2 非运行时异常

也叫受检异常、编译异常,checked异常。在编译时期,就会检查,如果没有处理异常,则编译失败。(如日期格式化异常)

1.4 异常的处理

1.4.1 异常向上抛出处理

将异常向上抛出,交由调用方进行处理,一般用于代码无法解决,是由于代用方使用不当导致的异常

throws方式处理异常 又被称之为声明异常,将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理(稍后讲解该方式),那么必须通过throws进行声明,让调用者去处理。

关键字 throws 运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常).

  • 格式
     修饰符 返回值类型 方法名() throws 异常类名 {}
  • 书写
 //使用throws关键字在方法上抛出声明异常//在调用这个方法时  就知道可能会出现的异常 在使用时尽量避免public static void main(String[] args) throws ParseException {SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");sdf.parse("1999-01-01");}

1.4.2 异常自行处理

使用关键字捕获处理对应异常,将处理的代码预先书写,这样不会导致程序的终止try...catch

  • 语法
     try {可能出现异常的代码;} catch(异常类名 变量名) {异常的处理代码;}

try后的大括号中包含可能出现异常的代码,当对应代码出现异常时进行捕获,根据出现异常的类型在对应catch中进行处理,如果出现异常系统会自动创建对应的异常对象,在catch中声明对应异常变量,如果与出现的异常匹配时进行处理

  • 执行流程
  • 程序从 try 里面的代码开始执行
  • 出现异常,就会跳转到对应的 catch 里面去执行
  • 执行完毕之后,程序还可以继续往下执行
     SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-ddasda");try {sdf.parse("1999-01-0112");} catch (ParseException e) {//进行异常处理的代码}System.out.println("执行");

面试题


处理异常两种方式的区别

  • 抛出异常使用 throws 关键字,自行处理 try...catch
  • 抛出异常时调用方处理,自行处理自己书写处理代码进行处理
  • 抛出异常书写在方法上,标识当期方法可能出现的异常,自行处理使用try将可能出现的异常代码包裹对于出现的异常使用catch进行匹配处理
  • 抛出异常会导致程序的停止运行,自行处理可能不会停止

1.5 finally关键字

在异常发生时,虽然可以书写处理方法使程序继续执行,但是大多时候我们还是会终止后续的执行,但是如果后续代码中有释放资源的代码可能导致内存的占用,当我们在try语句块中打开了一些物理资源(磁盘文件/网络连接/数据库连接等),我们都得在使用完之后,最终关闭打开的资源。所以可以使用finally关键字进行资源的关闭

  • 注意

finally不能单独使用。必须配合着try…catch使用
书写在try...catch之后,无论代码是否发生异常都会执行

  • 格式
     try {可能出现异常的代码;} catch(异常类名 变量名) {异常的处理代码;} finally{释放资源}
  • 代码演示
             try {int[] arr = {1,2,3};System.out.println(arr[3]);} catch (Exception e) {e.printStackTrace();return;} finally {System.out.println("finally代码块执行了.....");}System.out.println("最后代码块执行了.....");

最后的代码由于return不会执行,但是finally中的代码会执行

面试题


1、final finallyfinalize()的区别

  • final:java中的关键字,修饰符。
    A).如果一个类被声明为final,就意味着它不能再派生出新的子类,不能作为父类被继承。因此,一个类不能同时被声明为abstract抽象类的和final的类。
    B).如果将变量或者方法声明为final,可以保证它们在使用中不被改变.
      1)被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。
      2)被声明final的方法只能使用,不能重载。
  • finally:java的一种异常处理机制。
    finally是对Java异常处理模型的最佳补充。finally结构使代码总会执行,而不管无异常发生。使用finally可以维护对象的内部状态,并可以清理非内存资源。特别是在关闭数据库连接这方面,如果程序员把数据库连接的close()方法放到finally中,就会大大降低程序出错的几率。
    finally书写在try…catch之后,无论代码是否发生异常都会执行(除非在catch中调用System.exit(0)退出系统的执行)。
  • finalize:Java中的一个方法名。
    Java技术使用finalize()方法在垃圾收集器将对象从内存中清除出去前,做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没被引用时对这个对象调用的。它是在Object类中定义的,因此所的类都继承了它。子类覆盖finalize()方法以整理系统资源或者执行其他清理工作。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的。

2、return执行后finally代码块是否还会执行

  • 执行,finally代码块一定会执行无论是否在处理中使用return结束当前方法,也会在方法结束之前执行,除非在catch中调用System.exit(0)退出系统的执行

1.6 异常处理注意事项

1、多个异常使用捕获又该如何处理呢

  • 1.如果try中出现多个异常,只处理第一个出现的异常
  • 2.catch只处理对应出现的异常(可能一个try出现多个异常进行对应处理)
  • 3.通常在最后使用Exception进行处理(可以匹配所有的异常)
 try{编写可能会出现异常的代码}catch(异常类型A  e){  // 当try中出现A类型异常,就用该catch来捕获.处理异常的代码//记录日志/打印异常信息/继续抛出异常}catch(异常类型B  e){  // 当try中出现B类型异常,就用该catch来捕获.处理异常的代码//记录日志/打印异常信息/继续抛出异常}catch (Exception e) {//使用Exception最终处理防止存在没有匹配的异常e.printStackTrace();}
  • 注意: 这种异常处理方式,要求多个catch中的异常不能相同,并且若catch中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的catch处理,父类异常在下面的catch处理。

2、运行时异常被抛出可以不处理。即不捕获也不声明抛出。
3、如果finally有return语句,永远返回finally中的结果,避免该情况.
4、如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常。
5、父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出
可以理解为:子类必须使用try...catch进行异常捕获处理(子类重写不能额外抛出异常)

1.7 自定义异常

1.7.1 概念

在Java中已经根据不同的功能定义了很多的异常类,并且出现问题时,自动创建异常对象并返回,但是,随着业务的增多,提供的异常类已经不能满足我们的开发需求,所以需要我们自定义满足需求的异常类

1.7.2 创建异常类

自定义异常类只需要创建类继承Exception 或者RuntimeException就可以创建对应的受检异常以及运行时异常

  • 格式
     public class 异常类 extends Exception | RuntimeException {public 异常类() {}public 异常类(String message) {super(message);}}

1.7.3 使用

在发生符合异常的代码位置,使用 throw 关键字 抛出一个新的异常对象

public class StudentTest {public static void main(String[] args) throws AgeException  {Studnet s=new Studnet();try {s.setAge(-15);} catch (AgeException e) {s.setAge(18);}s.setName("张三");System.out.println(s);}
}class Studnet{private String name;private int age;public Studnet() {super();}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) throws AgeException {//在设置年龄时根据判断是否抛出异常if(age<1){//创建年龄异常输出年龄过低throw new AgeException("年龄"+age+"过低");}else if(age>=150){//创建年龄异常输出年龄过高throw new AgeException("年龄"+age+"过高");}else{this.age = age;}}@Overridepublic String toString() {return "Student [name=" + name + ", age=" + age + "]";}
}

throw与throws的区别


  • throw用在方法体内,根的是异常对象名;throws用在方法声明后面,跟的是异常类名
  • throw表示抛出异常,由方法体内的语句处理;throws表示抛出异常,由该方法的调用者来处理
  • throw执行throw约定抛出了某种异常;throws表示出现异常的一种可能性,并不一定会发生这些异常

二、Log4j

2.1 概念

Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台文件等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。在apache网站:jakarta.apache.org/log4j 可以免费下载到Log4j最新版本的软件包。

2.2 日志分类

日志分类:


  • 诊断日志
  • 请求入口和出口

    • 外部服务调用和返回
    • 资源消耗操作: 如读写文件等
    • 容错行为: 如云硬盘的副本修复操作
    • 程序异常: 如数据库无法连接
    • 后台操作:定期执行删除的线程
    • 启动、关闭、配置加载
  • 统计日志

    • 用户访问统计:用户IP、上传下载的数据量,请求耗时等
    • 计费日志(如记录用户使用的网络资源或磁盘占用,格式较为严格,便于统计)
  • 审计日志
    • 管理操作
      对于简单的系统,可以将所有的日志输出到同一个日志文件中,并通过不同的关键字进行区分。而对于复杂的系统,将不同需求的日志输出到不同的日志文件中是必要的,通过对不同类型的文件采用不同的日志格式(例如对于计费日志可以直接输出为Json格式),可以方便接入其他的子系统。

2.3 日志级别

日志级别:


Log4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:OFFFATALERRORWARNINFODEBUGTRACEALL

  • ALL:最低等级的,用于打开所有日志记录。
  • TRACE:很低的日志级别,一般不会使用。
  • DEBUG:主要输出调试性质的内容,该级别日志主要用于在开发、测试阶段输出。
  • INFO:主要记录系统关键信息。
  • WARN:主要输出警告性质的内容。
  • ERROR:主要针对于一些不可预知的信息,诸如:错误、异常等。
  • FATAL:重大错误,这种级别你可以直接停止程序了。
  • OFF:最高等级的,用于关闭所有日志记录。

2.4 使用

2.4.1 导入jar包

将需要导入的包粘贴到项目src下,右键点击build path选择Add to Build Path

添加成功会在JRE System Library下方额外出现一个Referenced Libraries

2.4.2 书写配置文件

在src下创建log4j.properties配置文件

log4j.properties配置文件解析

  • 输出到控制台
log4j.rootLogger =ALL,systemOut
log4j.appender.systemOut = org.apache.log4j.ConsoleAppender
log4j.appender.systemOut.layout = org.apache.log4j.PatternLayout
log4j.appender.systemOut.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n
log4j.appender.systemOut.Threshold = DEBUG
log4j.appender.systemOut.ImmediateFlush = TRUE
log4j.appender.systemOut.Target = System.out
  • 输出到文件
log4j.rootLogger =ALL,logFile
log4j.appender.logFile = org.apache.log4j.FileAppender
log4j.appender.logFile.layout = org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n
log4j.appender.logFile.Threshold = DEBUG
log4j.appender.logFile.ImmediateFlush = TRUE
log4j.appender.logFile.Append = TRUE
log4j.appender.logFile.File = D://log.log
log4j.appender.logFile.Encoding = UTF-8
  • 按DatePattern输出到文件
log4j.rootLogger =ALL,logDailyFile
log4j.appender.logDailyFile = org.apache.log4j.DailyRollingFileAppender
log4j.appender.logDailyFile.layout = org.apache.log4j.PatternLayout
log4j.appender.logDailyFile.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n
log4j.appender.logDailyFile.Threshold = DEBUG
log4j.appender.logDailyFile.ImmediateFlush = TRUE
log4j.appender.logDailyFile.Append = TRUE
log4j.appender.logDailyFile.File = D://log.log
log4j.appender.logDailyFile.DatePattern = '.'yyyy-MM-dd-HH-mm'.log'
log4j.appender.logDailyFile.Encoding = UTF-8
  • 设定文件大小输出到文件
log4j.rootLogger =ALL,logRollingFile
log4j.appender.logRollingFile = org.apache.log4j.RollingFileAppender
log4j.appender.logRollingFile.layout = org.apache.log4j.PatternLayout
log4j.appender.logRollingFile.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n
log4j.appender.logRollingFile.Threshold = DEBUG
log4j.appender.logRollingFile.ImmediateFlush = TRUE
log4j.appender.logRollingFile.Append = TRUE
log4j.appender.logRollingFile.File = D://log.log
log4j.appender.logRollingFile.MaxFileSize = 1MB
log4j.appender.logRollingFile.MaxBackupIndex = 10
log4j.appender.logRollingFile.Encoding = UTF-8

2.4.3 使用

创建logger日志类对象调用对应方法

     public static void main(String[] args){Logger log =Logger.getLogger(Test.class);log.debug("测试");log.info("信息");log.error("错误");log.fatal("毁灭");}

2.5 配置文件的修改

2.5.1 根配置

用于配置当前日志输出的级别以及输出的位置

         log4j.rootLogger = [level],appenderName1,appenderName2,... 
  • level:设置检测的最低级别All
  • appenderName:设置生效的输出位置每个appenderName都可以配置一个不同的输出位置

2.5.2 输出位置配置

log4j.appender.appenderName=位置

位置的书写如下:

  • org.apache.log4j.ConsoleAppender(输出到控制台)
  • org.apache.log4j.FileAppender(输出到文件)
  • org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
  • org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
  • org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

2.5.3 根据输出位置进行配置

ConsoleAppender选项属性

  • Threshold = DEBUG:指定日志消息的输出最低层次
  • ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出
  • Target = System.err:默认值System.out,输出到控制台(err为红色,out为黑色)

FileAppender选项属性

  • Threshold = INFO:指定日志消息的输出最低层次
  • ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出
  • File = C:\log4j.log:指定消息输出到C:\log4j.log文件
  • Append = FALSE:默认值true,将消息追加到指定文件中,false指将消息覆盖指定的文件内容
  • Encoding = UTF-8:可以指定文件编码格式

DailyRollingFileAppender选项属性

  • Threshold = WARN:指定日志消息的输出最低层次
  • ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出
  • File = C:\log4j.log:指定消息输出到C:\log4j.log文件
  • Append = FALSE:默认值true,将消息追加到指定文件中,false指将消息覆盖指定的文件内容
  • DatePattern='.'yyyy-ww:每周滚动一次文件,即每周产生一个新的文件。还可以按用以下参数:
    '.'yyyy-MM:每月
    '.'yyyy-ww:每周
    '.'yyyy-MM-dd:每天
    '.'yyyy-MM-dd-a:每天两次
    '.'yyyy-MM-dd-HH:每小时
    '.'yyyy-MM-dd-HH-mm:每分钟
  • Encoding = UTF-8:可以指定文件编码格式

RollingFileAppender选项属性

  • Threshold = ERROR:指定日志消息的输出最低层次
  • ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出
  • File = C:/log4j.log:指定消息输出到C:/log4j.log文件
  • Append = FALSE:默认值true,将消息追加到指定文件中,false指将消息覆盖指定的文件内容
  • MaxFileSize = 100KB:后缀可以是KB,MB,GB.在日志文件到达该大小时,将会自动滚动.如:log4j.log.1
  • MaxBackupIndex = 2:指定可以产生的滚动文件的最大数
  • Encoding = UTF-8:可以指定文件编码格式

2.5.4 配置输出格式

log4j.appender.appenderName.layout=布局样式

布局样式的书写如下:

  • org.apache.log4j.HTMLLayout(以HTML表格形式布局)
  • org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
  • org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
  • org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
  • org.apache.log4j.xml.XMLLayout(以XML形式布局)

2.5.5 根据选择格式设置布局

一般使用灵活布局的格式进行自定义设置,其他格式都有默认的布局

log4j.appender.appenderName.layout.ConversionPattern=布局格式

Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,打印参数如下:

  • %m 输出代码中指定的消息
  • %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
  • %c 输出所属的类目,通常就是所在类的全名
  • %t 输出产生该日志事件的线程名
  • %n 输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n”
  • %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式
    如: %d{yyyy年MM月dd日 HH:mm:ss,SSS},输出类似:2012年01月05日 22:10:28,921
  • %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数
    如: Testlog.main(TestLog.java:10)
  • %F 输出日志消息产生时所在的文件名称
  • %L 输出代码中的行号
  • %x 输出和当前线程相关联的MDC(嵌套诊断环境),像java servlets多客户多线程的应用中
  • %% 输出一个"%"字符

可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:

  • %5c 输出category名称,最小宽度是5,category<5,默认的情况下右对齐
  • %-5c 输出category名称,最小宽度是5,category<5,"-"号指定左对齐,会有空格

每日一点点进步
不进则退

异常和Log4j日志相关推荐

  1. log4j 日志配置

    Log4j教程 - Log4j安装 Log4j API包是根据Apache软件许可证分发的. 最新的log4j版本,包括全源代码,类文件和文档可以在http://logging.apache.org/ ...

  2. Log4j 日志输出学习(Eclipse)

    学习网址1:http://www.cnblogs.com/licheng/archive/2008/08/23/1274566.html 一.快速入手 1.官网下载log4j压缩包,本地加压 2.Ec ...

  3. log4j日志输出性能优化-缓存、异步

    1.log4j已成为大型系统必不可少的一部分,log4j可以很方便的帮助我们在程序的任何位置输出所要打印的信息,便于我们对系统在调试阶段和正式运行阶段对问题分析和定位.由于日志级别的不同,对系统的性能 ...

  4. 使用filebeat和logstash解析java的log4j日志

    目的:我们使用filebeat来接受日志,并将日志做一个简单的处理,然后发给logstash,使用logstash的filter的grok来匹配日志,将日志解析成json格式并将日志输出在logsta ...

  5. Spring、Mybatis整合Service优化思路,DAO层、Service层最终编码以及log4j日志的使用

    5. Spring.Mybatis整合Service层事务控制优化思路分析 # spring中处理事务的两种方式1. 编程式事务处理定义:通过在业务层中注入事务管理器对象,然后通过编码的方式进行事务控 ...

  6. Log4j日志输出详细

    日志论 在应用程序中输出日志有有三个目的: (1 )监视代码中变量的变化情况,把数据周期性地记录到文件中供其他应用进行统计分析工作. (2 )跟踪代码运行进轨迹,作为日后审计的依据. (3 )担当集成 ...

  7. 利用spring aop统一处理异常和打日志

    利用spring aop统一处理异常和打日志 spring aop的概念,很早就写博客介绍了,现在在工作中真正使用. 我们很容易写出的代码 我们很容易写出带有很多try catch 和 logger. ...

  8. log4j中调试与错误日志分开_idea中log4j日志插件报错

    visual studio code权威指南计算机 65.34元 包邮 (需用券) 去购买 > idea中log4j日志插件报错 在运行测试代码的时候,出现以下错误! 在 src/ main / ...

  9. java自定义日志级别_自定义log4j日志级别

    因为项目中需要输出一些特别的日志来做数据统计.如果开启log4j提供的INFO日志级别,每天生成的日志文件就会变得越来越大.这样就得写个定 时任务来删除这个文件.为了只输出所需的日志级别,唯有自己定义 ...

  10. linux日志文件存放目录,Log4j 日志文件Linux/Mac/Windows通用存放位置设置方法

    log4j1/log4j2中category的配置以及log的输出位置(windows和linux通用的log输出位置) 一.场景和需求 假设我现在有3个独立的用project(暂时用maven关联起 ...

最新文章

  1. Bi-LSTM-CRF for Sequence Labeling
  2. boost::int64_t模块int64 范围的测试程序
  3. HDU多校6 - 6836 Expectation(矩阵树定理+高斯消元求行列式)
  4. express登录例子
  5. 工业相机硬汉!这款相机被NASA选择,全程记录毅力号登陆火星
  6. 自监督学习的一些思考
  7. leetcode - Anagrams
  8. 朗科32G TF卡的读写测试
  9. ubuntu下查看USB摄像头参数以及摄像头测试
  10. 5学工坊整理|关于大数据发展趋势
  11. 如何使用虚拟专用网络登录网络设备?
  12. C# 实现蓝牙检测及蓝牙设备信息获取代码
  13. Fisher's exact test( 费希尔精确检验)
  14. 计算机设备和打印机打不开,Windows7设备和打印机窗口打不开如何解决
  15. 联想E420麦克风没有声音的方案
  16. c语言期末复习专项——编程题
  17. 阿里最强 Python 自动化工具开源了!
  18. 转载: 房贷的两种还款方式介绍
  19. 鲍尔默离开后,微软还能东山再起吗?
  20. 编译Chromium OS

热门文章

  1. Java SSM 商户管理系统 客户管理 库存管理 销售报表 项目源码
  2. 研磨java系列_研磨设计模式 之 工厂系列(一)简单工厂模式
  3. 软件开发人月成本估算方法
  4. UPC 条形码的介绍及计算校验码
  5. pch文件找不到的解决办法
  6. 如何查看IOS系统APP的包名
  7. Winform开发框架主界面设计展示
  8. Java生成32位全局唯一id
  9. 【微信小程序开发】 踩坑 抽奖幸运大转盘 完美实战
  10. IAR EWARM教程