Java基础扫盲知识点汇总

  1. javac 命令用于编译 *.java文件,编译后会生成*.class文件。eg. javac welcome.java。
  2. java 命令可运行*.class文件,但不需要键入后缀。eg. java welcome。
  3. java第3种注释可以用来自动生成文档,以/**开始 */结束。且/* */注释不能嵌套。
  4. Double.NaN不是一个数字,若出现计算0/0或者负数的平方根会显示此结果NaN。判断是否使用Double.isNaN(x)。
  5. char类型的字符串有单字节或多字节编码,Unicode编码机制用于解决此问题。但建议不在程序中使用char类型,可以直接使用字符串作为抽象数据类型处理。
  6. Java9中,单下划线_不能作为变量名。
  7. const是java保留字,目前并未使用。java依然使用final定义常量。
  8. strictfp关键字使用严格的浮点计算来生成可再生结果。但浮点溢出不属于大问题。
  9. &&和||采用“短路”计算方式,第一个表达式可计算出当前关系结果时,不再计算第二个表达式。而&和|不采用“短路”方式,会计算两个表达式。
  10. Java11 引入了string.repeat(times)方法。eg "java".repeat(3)  , 结果时 "javajavajava"。
  11. String的equalsIgnoreCase()就可以进行不区分大小写相等对比。
  12. 千万不要使用==运算符测试字符串的相等性。
  13. string.codePointAt(i), 获得字符串的第i个码点
  14. String trim() 删除字符串头部和尾部小于等于U+0020的字符。
  15. String trip() 删除字符串头部和尾部的空格
  16. StringBuilder类是可变类,用于多个小段字符串构建一个字符串,其用于单线程操作。若在并发线程操作,应使用StringBuffer类J
  17. System.console 可以返回一个console对象用于与用户交互。Console readPassword,读取命令行输入的密码,会隐藏输入。
  18. 格式化输出中,有一个>标志,可以指示前面格式说明的参数将再次被使用。eg.printf("%s %tB %<te", "Due date", new Date()). 则%<te也是使用new Date数据格式化输出。
  19. Java不允许内层定义的变量名与外层定义相同。即不可再嵌套的块中重定义一个变量。
  20. 使用带标签的break语句,可以跳出多重嵌套的循环语句。注意标签必须放在希望跳出的最外层的循环之前且紧跟一个冒号。eg. read_data: while() {.....break read_data;..}
  21. BigInteger和BigDecimal可以处理包含任意长度数字序列的数值。整数和浮点数。
  22. 数组的copyof方法引用的还是同一个数组。
  23. Java中,所有的类都源自超类Object类。
  24. 对象的三个主要特性:行为、状态、标识。
  25. 类之间关系 依赖(uses-a)、聚合(has-a)、继承(is-a)
  26. java10中,可以使用var关键字声明局部变量,无需指定类型。
  27. java9中,Object.requireNonNullElse(n,"unknown"),此方法用于解决null引用问题。与 if(n==null) "unknown" else n;等效
  28. 如果需要返回一个可变对象的引用,应该对他进行clone。对象克隆是指存放在另一新位置的对象副本。
  29. 原生方法可以修改final变量的值,其不是在java语言中实现的,原生方法可以绕过java语言中的访问控制机制。
  30. main方法是一个静态方法,不对任何对象进行操作,并且会执行并构造程序所需要的对象。
  31. java的方法参数总是按值调用的,但其值有两种:基本数据类型和对象引用。
  32. 方法名和参数类型,叫做方法的签名。但返回类型不是方法签名,所以不能有名字相同,参数类型相同但返回类型不同的两个方法。
  33. 在当前类的某个构造器中想调用其另一个构造器可以使用this关键字进行构造。即this(param)
  34. this的两个含义:指示隐式参数的引用;调用该类的其他构造器
  35. 类中可以设置初始化块,使用大括号包括代码块即可。在任何构造对象时,首先会运行初始化块。
  36. 在包中定位类的是编译器的工作,类文件中的字节码总是使用完整的包名引用其他类。
  37. import语句允许导入静态方法和字段,而不只是类。eg, import static java.lang.System.*; 可以使用System类的静态方法和静态字段。
  38. 类路径是包括所有包含类文件的路径的集合,其包括:基目录/home//user/classdir;当前目录(.); JAR文件 /home/user/archives/archive.jar
  39. jar cvf jarfilename file1 file2 ... 是最常用的创建一个新JAR文件命令。
  40. 每个JAR文件包含一个清单文件mainfest,用于描述归档文件的特殊特性。
  41. java9中引入了多版本JAR方法, 其中可以包含面向不同java版本的类文件。
  42. javadoc工具会从源文件生产一个html文档,其根据/** */注释方式,包括标记和自由格式文本(@param,@return,@since,@author...)
  43. @see 插入超链接至某一方法,需要使用#号分隔类名和方法名。eg. @see com.hxxx.java.Employee#getSalary(int)
  44. 为package包生成注释的两种方式:package-info.java;package.html
  45. java若不对类数据进行初始化,会默认设为0 false null
  46. java中所有的继承都是公共继承。
  47. super关键字,只是编译器调用超类方法的特殊关键字。两个作用:调用超类的方法;调用超类的构造器。
  48. java不支持多继承,但使用了扩展接口的方式实现了多继承操作。
  49. jvm预先会为每个类计算一个方法表,列出所有方法的签名和要调用的实际方法。
  50. 阻止继承:final类和final方法,不可被继承。若类声明为final,其中方法全为final,但字段不是。
  51. java访问控制修饰符默认不需要,其对本包可见。protected则是对本包和所有子类可见。
  52. java要求equals方法具有:自反性,对称性,传递性,一致性。
  53. ArrayList 的 ensureCapacity(int x) 可以分配一个包含100个对象的内部数组,降低add时候开销。
  54. ArrayList  trimToSize() 将存储容量消减到当前大小。GC就可回收多余存储空间。
  55. 基本类型转换为对象都有对应的对象包装器。Integer、Long、Float、Double、Short、Byte、Character、Boolean。
  56. 枚举类的构造器总是私有的,并且其toString方***返回枚举常量名。original会返回枚举常量位置,从0开始计数。
  57. 反射用于分析类能力的程序。Java运行时系统始终未所有对象维护一个运行时类型标识,可以跟踪每个对象所属的类。Object.getClass()会返回一个class类型的实例,其中保存了类对象信息。
  58. java.lang.relect包中有三个类Field、Method、Constructor分别用于描述类的字段、方法和构造器。而其中的Modifier类用来检测访问控制权限。
  59. 聚合优于继承,除非所有继承的方法都有意义,否则不要用继承。
  60. 尽可能使用多态降低重复代码,而不是使用类型信息。
  61. 接口中所有方法自动都是public方法。接口中的字段都是public static final。但java9中接口方法可以使private,但用法有限。
  62. 接口绝不会有实例字段。
  63. 不能使用new运算符实例化一个接口。
  64. 接口方法可以提供默认实现,必须使用default修饰符标记。
  65. 类implement两个接口,且两接口具有相同方法,且至少有一个接口的方法具有默认实现,则必须在类中覆盖这个方法解决冲突。
  66. 类implement超类和一个接口,但超类和接口具有相同方法,此时只会考虑超类方法,忽略接口方法。“类优先”
  67. clone方法可以克隆对象的一个副本,但还是浅拷贝。
  68. 类要实现clone方法,要扩展Cloneable接口,并重新定义clone方法指定public访问修饰符。
  69. Cloneable接口是标记接口,不包含任何方法,唯一作用是允许在类型查询时使用instanceof
  70. lambda表达式是一个可传递的代码块,以后可以执行一次或多次。
  71. 对于只有一个抽象方法的接口,需要此类对象,就可以提供lambda表达式,这种接口为函数式接口。
  72. 方法引用指示编译器生成一个函数式接口的实例,覆盖这个接口的抽象方法来调用给定的方法。object::instanceMethod; Class::instanceMethod; Class::staticMethod
  73. 当lambda表达式只调用一个方法而不做其他操作时,才能把lambda表达式重写为方法引用。
  74. 构造器引用,与方法引用类似,只是方法名时new。eg. int[] ::new
  75. lambda表达式可以捕获外围作用域中变量的值。但此变量必须是事实最终变量(final)
  76. lambda表达式中的this指的是创建lambda表达式的方法。不是外层对象class。
  77. 在comparator中定义比较器,若比较结果有null,可以使用nullsFirst或nullsLast适配器。
  78. 内部类的方法可以访问自身数据字段,也可以访问创建它的外围类对象的数据字段。引用外围类使用Outerclass.this
  79. 内部类所有静态字段必须是final,且不能有static方法。
  80. 局部内部类,在方法中定义,声明局部类时不能有访问说明符。
  81. 局部内部类访问的局部变量必须是事实最终变量(final)。
  82. 在局部内部类中,若只想创建类对象,而不要为类指定名字,可以使用匿名内部类。
  83. 若内部类不需要访问外围类对象,就应该使用静态内部类。有时候可以使用嵌套类表示静态内部类。其内可以有静态方法和字段。
  84. 代理类可以在运行时创建实现了一组给定接口的新类。
  85. 代理类包含指定接口所需的全部方法,Object类中全部方法。
  86. 代理类总是public和final的。若代理类实现的所有接口都是public的,则代理类不属于任何特定的包;否则,所有非公共接口必须属于同一个包。
  87. Proxy类的isProxyClass可以检测Class是否为代理类。
  88. 异常有受检异常和非受检异常。
  89. 若一个方法可能抛出多个受检异常,必须在方法首部流出所有异常类,之间用逗号隔开。
  90. 若调用一个抛出受检异常的方法,要么处理异常try-catch,要么继续传递异常throws。
  91. 在catch中使用ex.initCause(exception)可将原异常设置为新异常的原因,再在捕获异常时使用getCause获取原始异常。
  92. finally子句,不论是否有异常被捕获,其内代码都会执行。其主要用于清理资源。
  93. try-cathc-finally是异常处理链语句
  94. try-with-reources语句可能比finally语句更常用。try(Resource res = ...){....} 在try块退出时,会自动调用res.close()方法。若在finally中只关闭资源,则可以使用此语句。
  95. Throwable类的printStackTrace方法访问堆栈轨迹的文本描述信息。
  96. 对于异常而言,可以采用“早抛出,晚捕获”的规则。
  97. assert condition 计算条件,false则抛出异常。其失败是不可恢复的错误。
  98. 断言检查只在开发和测试阶段打开。
  99. 记录日志的常见用途是记录在那些意料之外的异常。
  100. 日志处理器也有级别,因此设置了日志记录器级别,也需要修改处理器级别。
  101. FileHandler和SocketHandler可以将日志记录发送至其他地方。file或服务器。
  102. 使用Thread.dumpStack()即可获得堆栈轨迹。
  103. 程序错误会发送System.err而不是out。
  104. 泛型程序设计是为了编写的代码可以对多种不同类型的对象重用。
  105. 泛型类就是有一个或多个类型变量的类。
  106. 类型变量在整个类定义中用于指定方法的返回类型以及字段和局部变量的类型。
  107. java库使用E表示集合元素类型,K V表示表的键和值的类型。T U S表示任意类型。
  108. 调用泛型方法,需要把具体类型包围在尖括号中,放在方法名前面。
  109. 对类型变量也可以进行限定设置bound。eg. <T extends Comparable>
  110. 一个类型变量或通配符可以有多个限定:<T extends Comparable & Serializable>. 限定类型用’&‘分隔,逗号分隔类型变量。
  111. 虚拟机没有泛型类型参数,所以编译器会擦除类型参数。因此,定义泛型类型时,都会自动提供一个原始类型。
  112. 原始类型用第一个限定来替换类型变量,若没有给限定,则用Object替换。
  113. 当类型擦除和多态发生冲突时,会生成桥方法保持多态。
  114. 泛型设计中,可以使用通配符类型,允许类型参数发生变化。eg List<? extends SuperClass> 可以表示任何泛型List类型,类型参数是SuperClass子类型。
  115. 无限定通配符List<?>,代表任意类型,读取时可读为Object类型。不能进行set操作。
  116. 通配符可以指定超类型限定(supertype bound) . eg. ? super AClasss, 代表所有AClass的超类型。此方式可以为方法提供参数,但不能提供返回值.set
  117. ? extends BClass, 代表BClass的子类型,此方式可以允许方法读取一个泛型对象。get
  118. 带有超类型限定的通配符运行你写入一个泛型对象,而带有子类型限定的通配符允许你读取一个泛型对象。可参考此文深入了解泛型T与?区别
  119. 只有在构造集合对象时,才会使用具体的类,可以使用接口类型存放集合引用。
  120. forEachRemaining方法并提供一个lambda表达式可以替代循环,其会对迭代器每个元素调用lambda表达式。
  121. 访问元素顺序取决于集合类型。
  122. Iterator接口中的next方法和remove方法调用之间存在依赖性。如果调用remove之前没有调用next,将是不合法操作。
  123. Collection retainAll(Collection<?> c),取两个集合的交集。
  124. ListIterator接口定义了一个add方法用于在迭代器位置前面增加一个元素。
  125. Java6 引入接口NavigableSet和NavigableMap包含用于搜索和遍历有序集合映射的方法。
  126. ListIterator接口还有两个方法,可以用来反向遍历链表 previous, hasPrevious
  127. 对于一个LinkedList,如果链表有n个元素,使用迭代器会有n+1个位置可以添加新元素。
  128. Iterator具有next和previous。add方法只依赖迭代器位置,remove方法还依赖迭代器状态(即正向还是反向,remove的是本次迭代得到的结果)。
  129. 链表不支持快速随机访问,若要按整数索引访问,程序员通常不选用链表。
  130. nextIndex和previousIndex,可以返回元素的整数索引。
  131. ArrayList的方法不是同步的。
  132. offer(类似add,但若集合满了,返回false)、poll(类似于remove,但集合空了,返回null)、peek(类似于element,但集合空了,返回null)方法,不会抛出异常。
  133. 优先队列使用堆heap数据结构,其add和remove都会让最小元素移动至根。
  134. 如果不需要按照有序顺序访问键,最好选择hashmap
  135. 如果map.get出现了null情况,可以使用getOrDefault方法。
  136. map的merge和compute方法,函数应用关联k和v。
  137. WeekHashMap使用弱引用保存键。若对象只由WeakReference引用,垃圾回收器会将其回收。
  138. LinkedHashMap使用访问顺序而不是插入顺序迭代处理映射条目。最新操作的元素放在最后。可以实现缓存中的“最近最少使用”。
  139. 对于Map接口,有一个ofEntries静态方法,能接受任意多个Map.Entry<K,V>对象。
  140. Collection.nCopies(n, anObject)会实现List接口的不可变的对象。n个anObject,list对象。
  141. SortedSet的三个方法:subSet(from,to)、headSet(to)、tailSet(from), 返回大于等于from,小于to的所有元素的子集。
  142. Collections的lookAt方法可以调用List接口中的所有方法。
  143. 归并排序是稳定的,不会改变相等元素的顺序。
  144. Collections rotate(List<?>l, int d) 旋转列表中的元素.
  145. Collections frequency(Collection<?> c, Object o), 返回c中与对象o相等的元素的个数。
  146. Collections disjoint(Collection<?> c1, Collecction<?> c2) 判断两集合是否有共同元素。
  147. toArray方法返回的数组创建一个Object[] 数组,不能改变它的类型。
  148. BitSet类用于存储一个位序列,如果称为位向量或位数。若需要高效地存储位序列,就可以使用位集。
  149. 线程:CPU调度最小单位。共享数据。
  150. Runnable也是一个函数式接口。
  151. 不应该为每个任务分别创建线程,开销太大,应该将并行运行的任务与运行机制解耦。
  152. 不要调用Thread类或Runnable对象的run方法。直接调用run方法只会执行这个方法,Thread.start方***创建一个执行run方法的新线程。
  153. 抢占式调度系统给每一个可运行线程一个时间片来执行任务。
  154. 可运行线程的含义是可能正在运行也可能没有运行。
  155. Thread已废弃的方法:stop、suspend、resume。
  156. 对一个线程调用interrupt方***设置线程的中断状态。boolean。
  157. 若在sleep或wait的线程上调用interrupt方***造成InterruptedException
  158. interrupted方法用于测试当前线程是否被中断,并进行重置。
  159. 守护线程:用途在于为其他线程提供服务。t.setDaemon(true),必须在start之前运行。
  160. 线程的run方法不能抛出任何检查型异常,但非检查型异常可能会导致线程终止。因此可以使用Thread类的静态方法setDefaultUncaughtExceptionHandler为所有线程安装一个默认处理器。
  161. 线程会继承构造此线程的线程优先级。1-10,默认为5
  162. 线程的优先级高度依赖于系统。
  163. 线程访问同一数据,出现互相覆盖情况,称为竞态条件。
  164. 防止并发访问代码块有两种机制:synchronized关键字和ReentrantLock类
  165. 使用lock机制时要把unlock操作包括在finally子句。保证临界区代码抛出异常时,锁也可以释放。
  166. 使用lock时,就不能使用try-with-resources语句
  167. 锁可以用来保证串行化访问。
  168. 使用条件对象可以管理已经获得一个锁却不能正常工作的线程。
  169. 一个锁对象可以有一个或多个相关联的条件对象,newCondition方法获得条件对象。
  170. newCondition await()方法,可以暂停当前线程并放弃锁,运行另一个线程运行。
  171. 当调用newCondition signalAll() 会重新激活等待这个条件的所有线程,这些线程中某个会得到这个锁并从暂停处继续执行。注:signalAll调用不会立即激活某线程,只是接触等待线程的阻塞。之后依然需要竞争访问。
  172. 方法声明增加synchronized关键字,对象的锁会保护整个方法。这会产生一个内部对象锁。
  173. 内部对象锁关联条件只有一个,wait方法将线程添加到等待集中,notifyAll/notify方法解除等待线程的阻塞。
  174. 静态方法可以使用synchronized关键字,当调用此方法,ClassName.class对象的锁会锁定。其他线程不可以调用此方法及其他任何同步静态方法。
  175. 同步块也可以获得锁,eg. synchronized(obj){......}
  176. volatile关键字为实例字段的同步访问提供一个免锁机制。更新时其他线程可见。但此关键字不能提供原子性。
  177. 原子操作不会被中断,可以保证并发访问的正确性。
  178. 所有线程都阻塞则表明出现死锁。deadlock
  179. ThreadLocal辅助类为各个线程提供了各自的实例。使用ThreadLocal.withInitial(()->{})方法即可
  180. 阻塞队列变体:LinkedBlockingQueue\ArrayBlockingQueue\PriorityBlockingQueue
  181. 线程安全的集合:ConcurrentHashMap\ConcurrentSkipListMap\ConcurrentSkipListSet\ConcurrentLinkedQueue
  182. 对ConcurrentHashMap可以进行批操作:search\reduce\forEach三种操作方法,操作对象包括 Keys\Values\Entries;对于此操作可以定义参数化阈值。
  183. CopyOnWriteArrayList和CopyOnWriteArraySet是线程安全的集合,其所有更改器会建立底层数组的一个副本。(乐观锁)
  184. parallelPrefix方***用一个给定结合操作的相应前缀的累加结果替换各个数组元素。
  185. 同步包装器可以将集合变成线程安全的。eg. Collections.synchronizedList(new ArrayList<E>())
  186. 线程与任务解耦,可以使用线程池 thread pool
  187. 执行Callable函数接口可以使用FutureTask。
  188. invokeAny和invokeAll, 第一个方法是返回任一对象即结束,第二个方式需要返回所有对象。
  189. 若计算结果的顺序也很重要,则需要构造一个ExcutorCompletionService,该服务会管理Future对象的阻塞队列。
  190. 使用ExecutorService管理线程,不要独立启动线程。
  191. fork-join框架采用分而治之思想,将任务分解为子任务执行,再合并结果。其采用工作密取方法来平衡可用线程的工作负载。
  192. CompletableFuture.supplyAsync\runAsync. 可以实现链式回调。默认执行器为ForkJoinPool,commonPool().具体用法可参考link
  193. CompletableFuture可以将异步任务组合成一个处理管线。
  194. Process类可以在一个单独的操作系统进程执行一个命令,允许标准交互。
  195. ProcessBuilder类则允许配置Process对象。
  196. 进程的输入流是JVM的一个输出流。但可以指定进程的流与JVM相同,使用redirectIO()方法。
  197. isAlive可查看进程是否存活,并可以调用destroy/destroyForcibly杀死进程。
  198. 要获得程序启动的一个进程更多信息,可以使用ProcessHandle接口。