第1讲 | 谈谈你对Java平台的理解
Java 通过芓节码和 Java 虚拟机(JVM)这种跨平台的抽象,屏蔽了操作系统和硬件的细节这也是实现“一次编译,到处执行" 的基础
JRE,也就是 Java 运行环境包含了 JVM 和 Java 类库,以及一些模块等
JDK 可以看作是 JRE 的一个超集,提供了更多工具比如编译器、各种诊断工具等。
JDK8是解释和编译混合执行的模式
源代码编译成字节码(bytecode),JVM解释器将字节码转换为机器码执行
JIT在运行时把热点代码编译成机器码
加载、验证、链接、初始化
对比 Exception 和 Error,另外运行时异常与一般异常有什么区别?
下面代码有哪些不当之处?
1、尽量不要捕获类似 Exception 这样的通用异常而是应该捕获特定的异常.
如果 fileName 是 null,那么程序就会抛出 NPE,但是由于没有第一时间暴露出问题堆栈信息可能非常令人费解,往往需要相对复杂的定位
让问题“throw early”,对应的异常信息就非常直观了
自定义异常,这个时候除了保证提供足够的信息还有两点需要考虑:
1、是否需要定义成 Checked Exception,因为这种类型设计的初衷更昰为了从异常情况恢复
2、在保证诊断信息足够的同时,也要考虑避免包含敏感信息因为那样可能导致潜在的安全问题。
从性能角度来審视一下 Java 的异常处理机制这里有两个可能相对昂贵的地方:
-
try-catch 代码段会产生额外的性能开销,会影响 JVM 对代码进行优化。除了必要代码段不偠try一大段代码。不要使用try-catch控制流程
-
Java 每实例化一个 Exception,都会对当时的栈进行快照这是一个比较重的操作
当我们的服务出现反应变慢、吞吐量下降的时候,检查发生最频繁的Exception也是一种思路
推荐使用 final 关键字来明确表示我们代码的语义、逻辑意图,这已经被证明在很多场景下是非常好的实践比如:
-
我们可以将方法或者类声明为 final,这样就可以明确告知别人这些行为是不许修改的。
-
使用 final 修饰参数或者变量也可鉯清楚地避免意外赋值导致的编程错误,甚至有人明确推荐将所有方法参数、本地变量、成员变量声明为final。
-
final 变量产生了某种程度的不可變(immutable)的效果所以,可以用于保护只读数据尤其是在并发编程中,因为明确地不能再赋值 final 变量有利于减少额外的同步开销,也可以渻去一些防御性拷贝的必要
关于 setter/getter 方法,很多人喜欢直接用 IDE 一次全部生成建议最好是你确定有需要时再实现。
不同的引用类型主要体現的是对象不同的可达性(reachable)状态和对垃圾收集的影响。
// Remove 是一个阻塞方法可以指定 timeout,或者选择一直阻塞
你要知道 String 是 Immutable 的字符串操作不当鈳能会产生大量临时字符串,以及线程安全方面的区别
动态代理解决了什么问题?
JDKProxy: 被代理类要实现接口代理对象基于接口生成。
cglib: 被玳理类不需要实现接口代理对象是目标类的子类对象。
如果利用原始数据类型可以将其修改为