程序本质

程序本质

代码是如何被执行的?CPU、操作系统、虚拟机各司何职?

在开篇词中,我们讲到,专栏并非讲解Java语法如何使用,而是探究更本质的东西,本节,我们就来探讨一下,代码是如何被执行的?在执行的过程中,CPU、操作系统、虚拟机都起了什么样的作用?不过,本节的内容偏向整体的、粗略的介绍,对于各个知识点更加详细的讲解,我们会在专栏后面的内容中慢慢输出。

一、解释型、编译型、混合型语言

要回答上述问题,我们要从最基础的讲起。

我们知道,CPU只认识机器指令(也叫做CPU指令、机器码),用像Python、C++、Java这样的高级语言编写的代码,需要编译(编译的意思实际上就是“翻译”)为机器指令之后,才能被CPU执行。而不同类型的语言,其编译过程也是不同的,据此我们将其分为三类。


Mr.ZhangJava基础大约 25 分钟
关键字

关键字

静态内部类实现的单例如何做到线程安全且可延迟加载?

Java中的关键字有50多个,比如private、public、protected、class、interface、switch等等,大部分用法都比较简单,所以,我们不做讲解。本节,我们重点讲解final和static这两个关键词。这两个关键字既在开发中经常使用,也在面试中经常被考察。它们看似非常简单,但彻底搞懂却不容易,不信?我们来看下面这段代码。

public class Singleton {
  private Singleton() {}
  
  private static class SingletonHolder {
    public static final Singleton instance = new Singleton();
  }

  public static Singleton getInstance() {
    return SingletonHolder.instance;
  }
}

Mr.ZhangJava基础大约 14 分钟
基础语法

基础语法

从CPU角度看变量、数组、类型、运算、跳转、函数等语法

对于绝大部分编程语言来说,不管是Python、Ruby、PHP、JavaScript,还是Go、C/C++、Java,其包含的基本语法无外乎这样几种:变量、类型、数组、运算(赋值、算术、逻辑、比较等)、跳转(条件、循环)、函数,而其他语法(比如类、容器、异常等)在CPU眼里只不过是语法糖。本节,我们就来看下,编程语言中的这些基本语法,在CPU眼里是什么样子的。


Mr.ZhangJava基础大约 23 分钟
引用

引用

同样都是存储地址,为何Java引用比C/C++指针更安全?

本节我们学习一下Java中的引用。我们知道,C/C++中有指针语法,指针用来存储一块内存的首地址。我们通过指针来访问这块内存。Java中没有指针语法,取而代之是引用。那么,Java中的引用和C/C++中的指针有什么区别?同样是存储地址,为什么Java中的引用比C/C++中的指针更安全?

一、Java类型:基本类型 vs 引用类型


Mr.ZhangJava基础大约 17 分钟
基本类型

基本类型

既然Java一切皆对象,那又为何要保留int等基本类型?

上一节课,我们讲到,Java中的类型可以分为两类:基本类型和引用类型,并且,重点讲解了引用类型。本节,我们重点讲一下基本类型。作为面向对象编程语言,在Java语言中,有一个比较流行的说法,那就是“一切皆对象”,这也是Java语言的设计理念之一。但基本类型的存在似乎与此相矛盾,因此也有人说,Java是非纯的面向对象编程语言。既然已经有了Integer、Long等类,为什么Java语言又保留了int、long等基本类型呢?本节,我们就详细讲解一下Java中的基本类型以及对应的包装类。


Mr.ZhangJava基础大约 18 分钟
位运算

位运算

位运算:>>>和>>有何区别?(原码/反码/补码、算术位移/逻辑位移)

在开始学习本节的内容之前,我们先来看一段代码,如下所示,其中countOneBits()函数用来统计num在计算机中表示为二进制之后,为1的二进制位的个数。仔细分析下面的代码,你觉得这段代码的运行结果是什么?

public class Demo5_1 {
  public static void main(String[] args) {
    int count = countOneBits(-3);
    System.out.println(count);
  }

  public static int countOneBits(int num) {
    int count = 0;
    while (num != 0) {
      if ((num & 1) == 1) count++;
      num >>= 1;
    }
    return count;
  }
}

Mr.ZhangJava基础大约 17 分钟
浮点数

浮点数

计算机如何用二进制表示浮点数?为何0.1+0.1不等于0.2?

上一节课,我们讲了整型数的表示方法:补码,今天我们讲讲浮点数的表示方法。浮点数在平时的开发中也经常用到,比如用来表示金额等。浮点数并不能精确地表示整数或小数,所以,在使用时,要多加小心,稍有不慎就会引入bug。因此,了解浮点数的表示方法等相关理论知识,就相当有必要了。

一、实数的二进制科学记数法

浮点数是计算机中用来表示实数的数据类型。实数是一个数学概念,这里我们可以简单理解为小数。不过,整数也可以看做实数,比如5可以看做5.0,也算是实数。


Mr.ZhangJava基础大约 17 分钟
字符

字符

为何C/C++中char占1个字节,而Java中char占2个字节?

字符、字符串是编程语言中必不可少的语法,Java和C/C++都用char来存储字符,用char数组(char[])来存储字符串,当然,在Java中,存储字符串还可以使用String类,这个下节再讲。在处理字符、字符串时,绝大多数程序员都遇到过乱码问题。因为对底层原理掌握不牢,很多程序员面对乱码手足无措,乱改瞎试。所以,本节我们就详细讲讲字符和字符编码。在开始之前,我们还是留一个思考题给你:为什么C/C++中char类型占1个字节长度,而Java中的char类型占2个字节长度。


Mr.ZhangJava基础大约 16 分钟
字符串

字符串

除了int、long等基本类型,及其Integer、Long等包装类之外,在项目开发中,字符串也是应用得非常多的数据类型。Java提供了String类,封装了字符数组(char[]),并提供了大量操作字符串的方法,比如toUpperCase()、split()、substring()等。除此之外,Java String也是面试中常考的知识点,比如,Java String为什么设计成final不可变类?早期JDK中的substring()函数为什么会出现内存泄露?intern()方法的作用和底层实现原理是什么?等等。本节我们就来详细聊聊String类型。


Mr.ZhangJava基础大约 18 分钟
对象

对象

请描述一下Java对象的内存结构,以及如何统计对象大小?

在平时的开发中,在项目上线之前,我们需要合理的预估项目运行所需的内存空间,以便合理地设置JVM内存的大小。JVM内存分为很多部分:栈内存、堆内存、方法区等,栈内存中存储的数据的生命周期很短,函数结束之后就释放了。方法区存储的是代码,几乎是固定不变的,而且占用的空间也比较少。所以,分析的重点就成了堆内存。堆内存中主要存储对象。 所以,想要合理估算项目运行所需的内存空间,就需要知道如何计算一个对象所占内存的大小。本节,我们就来讲一讲,Java对象在内存中的存储结构,以及如何统计对象大小。


Mr.ZhangJava基础大约 14 分钟