Java核心技术36讲

第1讲 | 谈谈你对Java平台的理解?

Java两大特性
1、跨平台能力:书写一次,到处运行(Write once, run anywhere)
2、垃圾收集

Java 通过字节码和 Java 虚拟机(JVM)这种跨平台的抽象,屏蔽了操作系统和硬件的细节,这也是实现“一次编译,到处执行" 的基础。

JRE,也就是 Java 运行环境,包含了 JVM 和 Java 类库,以及一些模块等。
JDK 可以看作是 JRE 的一个超集,提供了更多工具,比如编译器、各种诊断工具等。

JDK8是解释和编译混合执行的模式
1、解释执行
源代码编译成字节码(bytecode),JVM解释器将字节码转换为机器码执行。
2、编译执行
JIT在运行时把热点代码编译成机器码

类加载机制

Class-Loader
Bootstrap、 Extension Class-Loader 、 Application

类加载过程
加载、验证、链接、初始化

常见的垃圾收集器
SerialGC、Parallel GC、 CMS、 G1

image.png
image.png
image.png

第2讲 | Exception和Error有什么区别?

对比 Exception 和 Error,另外,运行时异常与一般异常有什么区别?

1、理解 Throwable、Exception、Error 的设计和分类

image.png

NoClassDefFoundError与ClassNotFoundException之间的区别
https://blog.csdn.net/u012208784/article/details/79564414

2、理解 Java 语言中操作 Throwable 的元素和实践
try-with-resource & multiple catch
https://www.cnblogs.com/itZhy/p/7636615.html

try (BufferedReader br = new BufferedReader(…);
     BufferedWriter writer = new BufferedWriter(…)) {// Try-with-resources
// do something
catch ( IOException | XEception e) {// Multiple catch
   // Handle it
} 

下面代码有哪些不当之处?

try {
  // 业务代码
  // …
  Thread.sleep(1000L);
} catch (Exception e) {
  // Ignore it
}

1、尽量不要捕获类似 Exception 这样的通用异常,而是应该捕获特定的异常.

  • 隐藏了真正目的
  • RuntimeException也被捕获
  • 不要捕获Throwable, 否则OOM无法处理

2、不要生吞异常

再看看第二段代码

try {
   // 业务代码
   // …
} catch (IOException e) {
    e.printStackTrace();
}

printStackTrace:Prints this throwable and its backtrace to the **standard error stream".
在稍微复杂一点的生产系统中,标准出错(STERR)不是个合适的输出选项,很难判断出到底输出到哪里。

Throw early, catch late 原则
public void readPreferences(String fileName){
     //...perform operations... 
    InputStream in = new FileInputStream(fileName);
     //...read the preferences file...
}

如果 fileName 是 null,那么程序就会抛出 NPE,但是由于没有第一时间暴露出问题,堆栈信息可能非常令人费解,往往需要相对复杂的定位。
让问题“throw early”,对应的异常信息就非常直观了。

public void readPreferences(String filename) {
    Objects. requireNonNull(filename);
    //...perform other operations... 
    InputStream in = new FileInputStream(filename);
     //...read the preferences file...
}
image.png

自定义异常,这个时候除了保证提供足够的信息,还有两点需要考虑:
1、是否需要定义成 Checked Exception,因为这种类型设计的初衷更是为了从异常情况恢复。
2、在保证诊断信息足够的同时,也要考虑避免包含敏感信息,因为那样可能导致潜在的安全问题。

从性能角度来审视一下 Java 的异常处理机制,这里有两个可能相对昂贵的地方:

  • try-catch 代码段会产生额外的性能开销,会影响 JVM 对代码进行优化。除了必要代码段,不要try一大段代码。不要使用try-catch控制流程。

  • Java 每实例化一个 Exception,都会对当时的栈进行快照,这是一个比较重的操作

当我们的服务出现反应变慢、吞吐量下降的时候,检查发生最频繁的Exception也是一种思路。

第3讲 | 谈谈final、finally、 finalize有什么不同?

image.png

推荐使用 final 关键字来明确表示我们代码的语义、逻辑意图,这已经被证明在很多场景下是非常好的实践,比如:

  • 我们可以将方法或者类声明为 final,这样就可以明确告知别人,这些行为是不许修改的。

  • 使用 final 修饰参数或者变量,也可以清楚地避免意外赋值导致的编程错误,甚至,有人明确推荐将所有方法参数、本地变量、成员变量声明为final。

  • final 变量产生了某种程度的不可变(immutable)的效果,所以,可以用于保护只读数据,尤其是在并发编程中,因为明确地不能再赋值 final 变量,有利于减少额外的同步开销,也可以省去一些防御性拷贝的必要。

image.png

知识扩展

1. final 并不等同于 immutable

 final List<String> strList = new ArrayList<>();
 strList.add("Hello");
 strList.add("world");  
// java 9支持
 List<String> unmodifiableStrList = List.of("hello", "world");
 unmodifiableStrList.add("again");
image.png

关于 setter/getter 方法,很多人喜欢直接用 IDE 一次全部生成,建议最好是你确定有需要时再实现。

2.finalize 真的那么不堪?

image.png

3. 有什么机制可以替换 finalize 吗?

image.png
public class CleaningExample implements AutoCloseable {
        // A cleaner, preferably one shared within a library
        private static final Cleaner cleaner = <cleaner>;
        static class State implements Runnable { 
            State(...) {
                // initialize State needed for cleaning action
            }
            public void run() {
                // cleanup action accessing State, executed at most once
            }
        }
        private final State;
        private final Cleaner.Cleanable cleanable
        public CleaningExample() {
            this.state = new State(...);
            this.cleanable = cleaner.register(this, state);
        }
        public void close() {
            cleanable.clean();
        }
    }

image.png

第4讲 | 强引用、软引用、弱引用、幻象引用有什么区别?

不同的引用类型,主要体现的是对象不同的可达性(reachable)状态和对垃圾收集的影响。

image.png
image.png
image.png

所有引用类型,都是抽象类 java.lang.ref.Reference的子类,你可能注意到它提供了 get() 方法:


image.png
image.png

引用队列(ReferenceQueue)使用

image.png
Object counter = new Object();
ReferenceQueue refQueue = new ReferenceQueue<>();
PhantomReference<Object> p = new PhantomReference<>(counter, refQueue);
counter = null;
System.gc();
try {
    // Remove 是一个阻塞方法,可以指定 timeout,或者选择一直阻塞
    Reference<Object> ref = refQueue.remove(1000L);
    if (ref != null) {
        // do something
    }
} catch (InterruptedException e) {
    // Handle it
}

第5讲 | String、StringBuffer、StringBuilder有什么区别?

image.png

你要知道 String 是 Immutable 的,字符串操作不当可能会产生大量临时字符串,以及线程安全方面的区别。

image.png
image.png

2. 字符串缓存

image.png

3.String 自身的演化

image.png

第6讲 | 动态代理是基于什么原理?

image.png

动态代理解决了什么问题?

image.png

JDK Proxy实现动态代理

public class MyDynamicProxy {
    public static  void main (String[] args) {
        HelloImpl hello = new HelloImpl();
        MyInvocationHandler handler = new MyInvocationHandler(hello);
        // 构造代码实例
        Hello proxyHello = (Hello) Proxy.newProxyInstance(HelloImpl.class.getClassLoader(), HelloImpl.class.getInterfaces(), handler);
        // 调用代理方法
        proxyHello.sayHello();
    }
}
interface Hello {
    void sayHello();
}
class HelloImpl implements  Hello {
    @Override
    public void sayHello() {
        System.out.println("Hello World");
    }
}
 class MyInvocationHandler implements InvocationHandler {
    private Object target;
    public MyInvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("Invoking sayHello");
        Object result = method.invoke(target, args);
        return result;
    }
}
image.png
image.png
image.png

JDKProxy: 被代理类要实现接口,代理对象基于接口生成。
cglib: 被代理类不需要实现接口,代理对象是目标类的子类对象。

image.png

第7讲 | int和Integer有什么区别?

image.png
image.png
image.png
class Counter {
    private final AtomicLong counter = new AtomicLong();  
    public void increase() {
        counter.incrementAndGet();
    }
}

如果利用原始数据类型,可以将其修改为

 class CompactCounter {
    private volatile long counter;
    private static final AtomicLongFieldUpdater<CompactCounter> updater = AtomicLongFieldUpdater.newUpdater(CompactCounter.class, "counter");
    public void increase() {
        updater.incrementAndGet(this);
    }
}
image.png
image.png

第8讲 | 对比Vector、ArrayList、LinkedList有何区别?

image.png
image.png
image.png
image.png

第9讲 | 对比Hashtable、HashMap、TreeMap有什么不同?

image.png
image.png
image.png
image.png
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容