diff --git "a/\345\201\232\351\242\230\346\203\205\345\206\265\347\273\237\350\256\241--\350\275\257\344\273\266\347\274\226\347\250\213\347\237\245\350\257\206\344\270\216\345\272\224\347\224\250.md" "b/\345\201\232\351\242\230\346\203\205\345\206\265\347\273\237\350\256\241--\350\275\257\344\273\266\347\274\226\347\250\213\347\237\245\350\257\206\344\270\216\345\272\224\347\224\250.md" new file mode 100644 index 0000000000..a26e92fd8b --- /dev/null +++ "b/\345\201\232\351\242\230\346\203\205\345\206\265\347\273\237\350\256\241--\350\275\257\344\273\266\347\274\226\347\250\213\347\237\245\350\257\206\344\270\216\345\272\224\347\224\250.md" @@ -0,0 +1,388 @@ + + +# 做题情况统计--软件编程知识与应用 + +| 编程规范理解与应用(JAVA) | 合计 | 总题数 | 正确答题数 | 正确率 | +| ------------------------------------------------------------ | ------------------------------------------------------------ | ------ | ---------- | ------ | +| 核心类库:掌握集合与泛型、多线程编程、反射相关规范 | 集合与泛型:规范相关; 并发与多线程:规范相关,ArrayList动态数组、Vector | 4 | 4 | 100.0% | +| 代码风格:掌握命名、注释、代码格式规范 | 命名 | 1 | 1 | 100.0% | +| 扩展类库**:掌握IO编程、日志、正则表达式、数据库编程、网络编程相关规范** | IO编程:规范相关; 数据库编程:规范相关; 序列化:规范相关 | 4 | 3 | 75.0% | +| 语法知识:掌握变量、数据类型、表达式、控制语句、方法、面向对象、异常相关规范 | 面向对象:规范相关; 数据类型:规范相关 | 6 | 3 | 50.0% | + +| 编程语言能力(JAVA) | 合计 | 总题数 | 正确答题数 | 正确率 | +| ------------------------------------------------------------ | ------------------------------------------------------------ | ------ | ---------- | ------ | +| **JVM**:理解Class格式与类加载过程,**掌握运行时数据区结构与定位方法**,**理解GC原理与常用GC回收器,了解JIT机制** | 运行时数据区; Class格式; JIT; GC; 类加载 | 10 | 8 | 80.0% | +| 语法知识:深入理解变量、数据类型、表达式、控制语句、方法、面向对象、异常的语法特性 | 方法; 数据类型; 语法知识:深入理解变量、数据类型、表达式、控制语句、方法、面向对象、异常的语法特性; 异常体系; 控制语句 | 10 | 8 | 80.0% | +| **性能优化**:掌握代码级性能优化方法,**理解JVM的性能调优方法** | 集合:性能相关; GC:性能相关; 性能优化:掌握代码级性能优化方法,理解JVM的性能调优方法; 方法:性能相关; 表达式:性能相关; 运行时数据区:性能相关; 控制语句:性能相关; IO编程:性能相关 | 8 | 4 | 50.0% | +| 核心类库:熟练掌握集合与泛型、多线程编程、反射的实战用法 | 反射; 线程; 集合与泛型 | 6 | 3 | 50.0% | +| 扩展类库:熟练运用IO编程、正则表达式、安全类库等重要类库,掌握数据库编程、网络编程。 | 正则表达式; IO编程; 数据库编程 | 4 | 1 | 25.0% | + + + +# 题目回顾 + +1. 类加载的~~几个~~**7**个阶段: + + > (1)加载(字节码转换为方法区的运行时存储结构) + > + > (2)验证( Class 文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚机自身安全) + > + > (3)准备(为类变量--static修饰--的变量分配内存并设置初始值--方法区) + > + > (4)解析(将常量池的符号引用替换为直接引用) + > + > (5) 初始化(虚拟机执行类构造器的过程;**虚拟机会保证一个类的 () 方法在多线程环境下被正确的加锁和同步**) + > + > (6)使用(类被创建实例并被使用--实例化是分配在堆中) + > + > (7)卸载(当类不再被使用时,JVM对其进行垃圾回收,并释放其占用的内存空间) + > + > 一般(2)到(4)这三个阶段又叫链接阶段。 + +* 类加载——双亲委派机制(如果一个类加载器收到了类加载请求,先看父类加载器能否加载,一直如此到顶端加载器判断能否加载,如果顶端可以加载,则顶端加载,如果不行,则本类加载器加载) + + 1) 类加载时,判断两个类是否是同一个类,除了要求它们的名字相同外,还要求加载它们的类加载器实例是同一个,只有两者同时满足的情况下,JVM才认为这两个class是相同的。 + + 2)ClassLoader的loadClass方法加载不存在的类会抛ClassNotFoundException,并不是说返回NULL。 + + 3)自定义类加载器实现**继承****ClassLoader**后**,重写了**findClass方法加载指定路径上的class;** + + 4)BoostrapClassLoader加载核心库类(%JAVA_HOME%/lib目录下的jar包和类或者被-Xbootclasspath参数指定的路径中的所有类)--它是用**原生代码(使用C++)**来实现的,**并非继承java.lang.ClassLoader** + + 5)Extension加载器加载%JRE_HOME%/lib/ext下的类和jar包,或者java.ext.dirs系统变量所指定的路径下的jar包,System加载器加载CLASSPATH环境指定路径的类, + + 6)AppClassLoadrer负载加载当前应用classpath下的所有jar包和类。 + +1. + +2. jinfo,info 查看运行环境参数、查看JVM系统参数、命令行参数---**不能看内存** + +3. **值不可变类型: Integer、String,在Java 8中,Integer缓存池的大小默认为-128~127。不可变类型有:Boolean, Byte, Character,Short, Double, Float, Integer, Long, String, BigDecimal** + +4. 反射相关: + + > * getType() 方法返回的是对象的运行时类型,即 Class 对象,而 getGenericType() 方法返回的是对象的泛型类型,即 Type 对象。 + > + > * 具体来说,getType() 方法返回的是 Class 对象,它代表了对象的实际类型,例如 String、Integer、List 等。而 getGenericType() 方法返回的是 Type 对象,它代表了对象的泛型类型,例如 List、Map 等。 + > + > 因此,getType() 方法只能获取对象的实际类型,而无法获取对象的泛型类型信息;而 getGenericType() 方法则可以获取对象的泛型类型信息,包括泛型参数的类型、数量等。 + +5. Java集合类 + + * ArrayList——当内部存储空间不够时,扩大50%。默认长度是10。 + + * Vector—— 当内部存储空间不够时,扩大1倍。默认长度是10。 + + * StringBuffer——默认长度是16 + + * StringBuilder——默认长度是16 + + * HashSet——默认长度是16 + + * HashMap——默认长度为16,允许key和value都为null + + * HashTable——默认长度是11 + + * XxxBlockingQueue(array的要手工指定,linked默认是Integer.MAX_VALUE) + + **线程安全的集合:**vector、hashtable、StringBuffer、ConcurrentMap(不可存放key和value都为null的对象) + + 非线程安全的集合: ArrayList、LinkeList(双队列)、HashMap、StringBuilder、LinkedHashSet、LinkedHashMap——保持了插入的顺序-->LRU、PriorityQueue + + + +6. 重写与重载: + + **重写(Override)**: + + * 发生在**父子类**之间,方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常 + + * 重写的返回类型与被重写的返回类型可以不相同,但必须是父类返回值的派生类 + + * 声明为**final**或**static**的**方法**不能被重写 + + **重载(Overload)** + + ​ 发生在同一个类中 + + + +7. 在java中关于抽象类的描述正确的是() + + A、抽象类必须包含一个抽象方法 ——这个我很容易认为是对的,抽象类可以包含抽象方法,也可以包含非抽象方法 + + B、抽象类的方法必须是抽象的 ——这个我很容易认为是对的 + + C、声明抽象类必须带有abstract ——这个我很容易认为是错的 + + D、抽象类可以被实例化 —— 这个显然错误。抽象方**法必须在子类**中被实现。**抽象类的声明必须带有abstract关键字**。主要作用是**为了被其他类继承**。 + + interface中的属性的默认修饰权限:public static final,方法属性:public abstract + +8. JVM: + + 以下程序运行结果如何,micro.yam文件不存在。 + + 考察异常类及其继承关系: + + ``` + /** + * 科目二 题目,如代码,程序运行结果如何: + * A、文件路径, finish + * B、ooo,打印异常堆栈,finish + * C、ooo,打印异常堆栈 + * D、直接抛出类加载异常 + * + * @author h00284904 + * @since 2021-09-27 + */ + public class JVM_FileParse_Verify { + public static final String A = JVM_FileParse_Verify.class.getClassLoader().getResource("micro.yam").getPath(); + public static void main(String[] args) { + try { + System.out.println(JVM_FileParse_Verify.A); + } catch (Throwable e) { + System.out.println("ooo"); + e.printStackTrace(); + } + System.out.println("finish"); + // Exception in thread "main" java.lang.ExceptionInInitializerError + // Caused by: java.lang.NullPointerException + // at com.huawei.hqh.JVM_FileParse_Verify.(JVM_FileParse_Verify.java:14) + } + } + ``` + + 因为A就在主类中,且是静态,所在调用main之前就已抛出异常 + + ``` + package com.huawei.hqh; + + class JVM_FileParser { + public static final String A = JVM_FileParser.class.getClassLoader().getResource("micro.yam").getPath(); + } + /** + * 功能描述 + * + * @author h00284904 + * @since 2021-09-28 + */ + public class JVM_FileParser_Verify2 { + public static void main(String[] args) { + try { + System.out.println(JVM_FileParser.A); + } catch (Throwable e) { + System.out.println("ooo"); + e.printStackTrace(); + } + System.out.println("finish"); + } + //ooo + // java.lang.ExceptionInInitializerError + // at com.huawei.hqh.JVM_FileParser_Verify2.main(JVM_FileParser_Verify2.java:15) + // Caused by: java.lang.NullPointerException + // at com.huawei.hqh.JVM_FileParser.(JVM_FileParser_Verify2.java:4) + // ... 1 more + //finish + } + ``` + +9. 线程: + + java 中断线程, 下面哪些情况可能导致中断当前线程的运行? (A、B、D) + + A. 抛出一个异常 + + B. 当前线程调用wait()方法等待竞争资源 + + C. 当前线程创建一个新线程时 + + D. 当前线程调用sleep()方法时 + + https://zhuanlan.zhihu.com/p/149205707 + + https://www.cnblogs.com/paddix/p/5381958.html + +10. **类文件**: + + ClassFile { + + u4 magic; ——固定为“0xCAFEBABE”,作用是确定该文件为一个可被JVM加载的Class文件。 + + u2 minor_version; ——Class文件的副版本 + + u2 major_version; ——Class文件的主版本 + + u2 constant_pool_count; + + cp_info constant_pool[constant_pool_count-1]; + + u2 access_flags; + + u2 this_class; + + u2 super_class; + + u2 interfaces_count; + + u2 interfaces[interfaces_count]; + + u2 fields_count; field_info fields[fields_count]; + + u2 methods_count; method_info methods[methods_count]; + + u2 attributes_count; attribute_info attributes[attributes_count]; + + } + + 其中,u1、u2、u4分别代表1、2、4个字节无符号数。 + +  说明: +   javac -g TestClass.java-g:生成所有的调试信息,包括局部变量名和行号信息。 + javap -c TestClass > TCC.txt, + + 对于javap常用的参数:-c:输出字节码Code-l(小写L):输出Code、LineNumberTable与LocalVariableTable-s:输出方法签名(方法的接收参数列表和返回值)-verbose:包含-c、-l以及输出class文件的编译版本,常量池,Stack, Locals, Args_size对于javap而言,常用的就是-c或-verbose + 作者:徐家三少 + 链接:https://juejin.cn/post/6844903464481325064 + +11. **泛型**使用之PECS(Producer Extends Consumer Super)原则:**当只想从集合中获取元素,请把这个集合看成生产者,请使用,这就是Producer extends原则,PECS原则中的PE部分。** + + **泛型与PECS:https://www.jianshu.com/p/e5b8cd33ec94?u_atoken=b39aa8a6-b196-4d41-9782-7c25662c0cc9&u_asession=01BjCr_1l-lFSEGUHFjg5OsLL3pscZ9J7HCTj7CD9shJSrg_xVl5cUdEmfKxgML9ipX0KNBwm7Lovlpxjd_P_q4JsKWYrT3W_NKPr8w6oU7K-eTQ6hLYwsFz-l_HWOSEkocCO_LNVcRl1Qbia_a5plzmBkFo3NEHBv0PZUm6pbxQU&u_asig=05WsD83ID0Tr7mSzPvQnLSMC7_9WEyYVY8Q0d4iFV0VaqFLtDNGi6xzsFcPbJg6RBo-VQeq2NrTZ_RTkeuVVUtppPLivPJBTV_CPH31hd3Lk9XVuwQ6ImA-4GrwQ-pYJgYvCAChf9--VSC925Oa2ydvUzNZFdNwYN16nMxAeCwSH39JS7q8ZD7Xtz2Ly-b0kmuyAKRFSVJkkdwVUnyHAIJzQhDv5RpUbAmToYFDMC0YyH-SIxHNXAMYgQIJs2NKSYja2GRgmoIOFBw7FYOdgQIyu3h9VXwMyh6PgyDIVSG1W_ladG6YsfXrB7slA80ltmTMcP86Dpk-9o5WW2hT6bxqq2XrK0uO2qG0zzYpsjVKEj0v_O4rXVVATYuGBfXtkIFmWspDxyAEEo4kbsryBKb9Q&u_aref=Q%2BYoK3NQIQx85iMjzFEOmRFHgdc%3D** + + 总结PECS原则如果你只需要从集合中获得类型T , 使用通配符如果你只需要将类型T放到集合中, 使用通配符如果你既要获取又要放置元素,则不使用任何通配符。例如ListPECS即 Producer extends Consumer super, 为了便于记忆。(《effective java》第28条)为何要PECS原则?你还记得前面提到泛型是不可变(**协变、逆变、不变**概念)吗?即List和List之间没有任何继承关系。API的参数想要同时兼容2者,则只能使用PECS原则。这样做提升了API的灵活性。 + 在java集合API中,大量使用了PECS原则,例如java.util.Collections中的集合复制的方法:`public static void copy(List dest, List src) { ... } `集合复制是最典型的用法:复制源集合src,主要获得元素,所以用复制目标集合dest,主要是设置元素,所以用**当然,为了提升了灵活性,自然牺牲了部分功能。鱼和熊掌不能兼得。**补充说明这里的错误全部是编译阶段不是运行阶段,编译阶段程序是没有运行。所以不能用运行程序的思维来思考。使用泛型,就是要在编译阶段,就找出类型的错误来。 + 作者:安静的猫咪先生 + 链接: https://www.jianshu.com/p/e5b8cd33ec94 + +12. 考察**NIO**: + + 要从文件中读出第10个字节—FileInputStream,与FileChannel关系等 + + readAllLines + + 哪些**不属于**NIO的buffer: StringBuffer,CharBuffer,IntBuffer,FloatBuffer + + skip(9), + +13. **Netty**的高性能体现在哪?ABCDE + + A、非阻塞IO + + B、内存零拷贝 + + C、内存池 + + D、串行化处理读写 + + E、高性能序列化协议 + + 解读 Netty的高性能表现: + + (1)IO线程模型:**同步非阻塞**,用最少的资源做更多的事情?何解 + + (2)内存零拷贝:尽量减少不必要的内存拷贝,实现了更高效率的传输 + + (3)内存池设计:申请的内存可以重用,主要指直接内存。内部实现是通过一棵二叉查找树来管理内存分配情况。 + + (4)串行化处理读写:避免使用锁带来的性能开销。即消息的处理尽可能在同一个线程内完成,期间不进行线程切换,这样避免了多线程竞争和同步锁。表面上看,串行化设计似乎CPU利用率不高,并发程度不够。但是,通过调整NIO线程池的线程参数,可以同时启动多个串行化的线程并行运行,这种局部无锁化的串行线程设计相比一队列里多个工作线程模型性能更优。 + + (5)高性能序列化协议:支持ProtoBuf等高性能序列化协议 + + (6)高效并发编程的体现:volatile的大量、正确使用; CAS和原子类的广泛使用;线程安全容器的使用;通过读写锁提升并发性能。 + +14. 关于**Java8 Stream**的描述正确的是: **Stream跟迭代器类似,再次遍历需要重新生成。** + + Stream的特点: + + 1) 无存储,Stream不是一种数据结构,也不保存数据,数据源可以是数组、容器、I/O或Channel等; + 2) 为函数式编程而生,对Stream的任何修改都不会修改数据源; + 3) 惰性执行,Stream上的中间操作并不会立即执行,只有等到用户真正需要结果时才会执行; + 4) 一次消费,Stream只能被消费一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成 + + + +15. 字符流 和 字节流: + + * **字节流**的基类**InputStream/OutputStream**,**字符流**是**Reader/Writer** + * 字符流最终都会按照字节流处理 + +16. Optional——主要用来处理每个程序员都会碰到的空指针异常问题,Java9还补充了or()、IfPresentOrElse()及stream()。属于可选值的封装类,即可以为空,也可以包含对象。 + + 关于java optional参照 https://www.jianshu.com/p/63830b7cb743 + +17. **Java 本地方法**的正确定义:"它一般在本地声明,异地用C和C++来实现。它的声明有几点要注意:1)native与访问控制符前后的关系不受限制。2)必须在返回类型之前。3)它一般为非抽象类方法。4)native方法在异地实现,象抽象方法一样,所以没有方法体,以分号结束。如下列5种声明: native public void f(); 正确。 + private native void f(); 正确。 + protected int native f(); 错误,返回类型位置不对,返回类型必须在native之后。 + public abstract native void f(); native必然不是abstract的。 + native int f(){} 错误,因为存在方法体{} + public static native f(); 正确。static与native方法位置随意。" + + 可参照 https://blog.csdn.net/x_panda/article/details/17120479 + +18. **正则表达式** + + 正则表达式/a+(bab)?(caac)*/,下列选项中该正则表达式的子集是?A + + A. /a{2} B. /a+(bab){0,1}(ca)+(ca)/ C. /(bab)(caca)/ D. /a(bab){2}(caac)*/ + + FutureTask : https://pdai.tech/md/java/thread/java-thread-x-juc-executor-FutureTask.html + +19. 加解密 + + **推荐使用的对称加密算法有: AES** + + **推荐使用的非对称算法有: RSA 推荐使用的数字签名算法有: DSA ECDSA** + +20. 若程序中要获取当前操作系统登录的用户名,应采用如下哪种方法?() + + A、提示用户输入 + + B、由环境变量获取:System.getEnv('USER') + + C、由JVM获取:System.getProperty('user.name') + + D、启动程序的时候,由程序输入参数输入 + + 从安全考虑和正确性考虑,A和D不行,我错误的选了B,但查规范,没有这样用的,直接获取“USER”,而且B也与操作系统相关。看来答案应该是C,JVM屏蔽了操作系统细节,且规范文档中倒是其它例子有用到。 + + + + http://ilearning.huawei.com/edx/subportal/portal/tseacademy?tab_name=tsea-software-development + +21. 安全编程规范 + + | 序号 | 类型 | 提要 | + | ---- | --------------- | ------------------------------------------------------------ | + | 1 | 安全目标 | 机密、完整、可用 | + | 2 | 不可信数据 | 文件、注册表、网络、环境变量、命令行、用户输入、用户态数据、进程间通信、函数参数、全局变量 | + | 3 | 可信数据校验 | 1、标准(文件路径)、归一(NFD编码 或 字符串java.text.Normalizer.normalize()/Normalizer.Form.NFKC) 2、输入正则清理,不推荐断言 3、黑白校验 4、输出脱敏 | + | 4 | SQL注入 | RDBMS:SQL注入(绕过检查、篡改数据、探测数据库结构、控制系统) 1、注入案例 ●没有引号,直接拼接字段的(拼接字段如果强转int可避免注入,但强转会出异常) ●order by 后拼接sql的 ●仅校验数据长度无效 2、措施 1、参数化预编译,重复调用效率高,推荐 (拼接后再预编译也可导致注入) 1.1、myBatis '$key$'替换**可注入**,#key#不可注入 1.2、存储过程也可注入 2、输入黑白校验 (黑、白并非推荐,无特殊要求时可优先考虑白) 3、转码,仅针对引号限制字段 | + | 5 | OS注入 命令注入 | OS注入(Dos攻击、篡改数据,隐藏恶意活动) 1、使用jdk的API、输入校验、转码(推荐,对参数注入无效) 2、使用&拼接命令注入,Runtime.exec()避免shell方式执行,Runtime.loadLibrary(用户输入)可能导致注入 3、ping.exe后的均为参数 4、目录遍历攻击,getCanonicalPath()替代getAbsolutePath() 5、POSIX下可使用exec,建议使用WIN32 API CreateProcess 6、外部输入禁止特殊字符对命令注入无效 | + | 6 | XML | 白名单、安全xml库(如dom4j)、转码 1、XXE(外部实体注入) 1.1、危害: ●获取服务端数据:]> ●探测内部网络:]> ●引用无限文件DOS ]> 1.2、措施【entities限定 或 重写 的都是XXE】 ●禁止包含实体 .setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);//DOCTYPE ●禁止使用外部实体和参数实体.setFeature("http://xml.org/sax/features/external-general-entities", false); .setFeature("http://xml.org/sax/features/external-parameter-entities", false); ●覆写解析器解析实体的方法 XMLReader resolveEntity(String publicId, String systemId) ●提取实体内容校验 比较基础数据值替代=/!=,防止异常时数值为负 4、内部类要么是static的,要么就不要实现接口 | + | 18 | 加密 | 1、不安全的加密算法: 分组加密DES、 哈希算法MD5 2、推荐的对称密码算法 AES, 非对称加密 RSA | + +22. 开发者测试 + + | 序号 | 类型 | 提要 | + | ---- | ------------ | ------------------------------------------------------------ | + | 1 | DT基础概念 | 1、UT(功能/函数单元测试,注重黑盒测试,关注的是功能、接口,可以DevOps中CI门禁)、IT(集成测试)、ST(系统/子系统测试) | + | 2 | DT测试设计 | 1、根据需求为达到性价比的测试设计,设计测试用例+;
2、测试要识别因子、因子值、方法。因子值要归类——等价类划分、边界;
因子值组合设计测试用例——AC(全排列组合,测试用例个数=各个因子的取值个数相乘)
BC(基础组合,测试用例个数=**各个因子的取值个数相加 - 因子个数 + 1** )
EC(Each Comosite, 测试用例个数=最多因子值的因子值个数) | + | 3 | 测试基础框架 | ( http://ilearning.huawei.com/edx/next/micro/course-v1:HuaweiX+CNE202007271113018-242+microcourse?blockID=8b4313d932774f83b749e38abaca493f )
Java测试基础框架——Junit,是Xunit中的实例:
Maven框架,Junit4.11及以上。一般流程为:(1)数据准备;(2)调用函数(测试);(3)断言
@Test ,函数命名一般为when…then…
高级断言——assertThat,统一了API,包括is\not\allof\anyof\…
Fixture——BeforeClass->RunWith->Before->TestMethod—>After->AfterClass
异常测试——(1)Try/Catch中要有断言;(2)assertThrow (3)@Test ExceptedException (4)@Test Except
超时——由于测试用例要满足F.I.R.S.T,其中Fast要求不能一直超时阻塞,@Test(timeout=X milliseconds)——适用于方法; @ Rule public Timeout globalTimeout = Timeout.seconds(3)
异常忽略说明——@Ignore(String description)
Junit4 参数化查询——{(输入,输出),},@RunWith(Parameterized.class)
Junit 进阶优化——Rules : @Rule, Suite:把目前用例都归档
Java测试框架——Mockito: | + +23. Java程序调试 + + http://ilearning.huawei.com/edx/courses/course-v1:HuaweiX+CNE050000006949+Self-paced/courseware/46151a32eb0e49969a4ab2da6e3f2a56/a181bd2cd9c145509d9434fbc02a1f39/?child=first + +24. +