ErCargo's Coffee Time

以大多数人的努力程度之低,根本轮不到拼天赋

Action Conquers Fear, Impetuous, Indolence and so on. (行动能够克服一切恐惧,浮躁,懒惰)


Welcome to star and fork my github

如何理解 java

  • java 的平台无关性
  • 面向对象
  • Java 的语言特性
  • java 类库
  • GC

对于 Java 的理解,每个程序员都会有不同的见解,而且能够说出很多不同维度的理解,如果发散开来一篇文章是说不完的。 所以,本文主要是从 Java 的几点特性出发,简单的聊聊对 Java 的理解, 会不断的补充进来

一、Java 的平台无关性

Java 平台无关性简单理解就是一次编译到处运行,即平台无关性。那么问题来了,java 是如何实现平台无关性的?
通常 Java 程序运行会分为编译期和运行时

  • 编译期:通过 Javac 指令,编译是指编译 Java 的源码(.java文件编写的),将源码编译生成字节码(存入到对应的.class文件),
  • 运行时:通过 Java 指令执行字节码文件;(将字节码翻译成对应平台的机器码)

反编译:Javap 指令是jdk自带的反汇编器,可以查看Java编译器为我们生成的字节码; Javap -c 对字节码代码进行反汇编,将从*.class到可执行程序的过程逆过来, 查看 javac 生成的 class 文件的内容,就是将二进制文件转成 class 文件的过程;

实践:下面给出一段代码,然后简单介绍一下这段代码的执行过程:

public class ByteCodeTest {
    public static void main(String[] args) {
        int i = 1;
        int j = 5;
        i++;
        System.out.println(i);
        System.out.println(j);
    }
}

javac 指令的执行方式:

  javac + 类所在的文件路径 + 类名.java

执行会在与 *.Java 文件相同路径下生成 *.class 文件

生成的 class 文件:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.ercargo.learn.concurrency.javabasic;

public class ByteCodeTest {
    public ByteCodeTest() {
    }

    public static void main(String[] var0) {
        byte var1 = 1;
        byte var2 = 5;
        int var3 = var1 + 1;
        System.out.println(var3);
        System.out.println(var2);
    }
}

反编译的过程解析一下 class 文件:

  • javap 是 jdk 自带反汇编器, 可以查看 java 编译器为我们生成的字节码;

javap指令执行方式

ps: 以上就是 java 虚拟机( HotSpot )所能理解的字节码

上述过程中 .class 文件中的字节码是 java 跨平台的核心和基础,Java 虚拟机可以解析该文件,转换成特定平台的执行指令(Linux,Windows,MacOS)

总的来说:Java 提供了各种不同平台上的虚拟机,jvm 可以将字节码文件加载到内存,并最终转换成当前操作系统能够识别的机器码去执行,从而实现了平台无关性;

二、面向对象

Java 具有面向对象语言的基本特性,封装、继承、多态,这里简单给出一点自己的见解,详细理解可以参考: 《Thinking in java》

  • 封装: 封装是抽象具有相同特性和行为的对象集合,理解成对类的内部实现进行隐藏,对外界只暴露该类的访问方法
  • 继承: 基类重用超类代码
  • 多态: 后期绑定/动态绑定,OOP 中,程序直到运行时才能确定代码的地址,所以必须通过动态绑定,当像对象发送消息时,被调用的代码直到运行时才能确定。
    涉及到泛型的概念

注意这里有一个问题,我们在真正写代码的时候会经常用继承吗?继承会导致一些什么问题?
《Effective Java》中提出一个概念:组合优于继承

为什么说组合优于继承呢?

继承:子类继承父类,即父类的内部细节(方法和属性)对子类都是可见的,如果父类发生改变,子类必然也要随之改变,所以会造成代码的耦合度非常高 而且破坏代码的封装性,一般除了使用多态的情况(需要从新类向基类进行向上转型),或者父类完全不会改变的情况(确认基类与超类之间存在的只有is-a的关系), 都是不推荐使用继承的; 组合是将现有对象进行拼装产生新的更复杂的功能,类的组合关系一般在运行期确定,如下面这段代码: ``` public class Teacher { private double salary; /** * 将User和Teacher 组合,而不是Teacher继承User, * User中的其他属性修改,不会直接影响Teacher */ private User user;

public double getSalary() {
    return salary;
}

public void setSalary(double salary) {
    this.salary = salary;
}

public String getName(){
   return user.getName();
} } ```

三、Java 语言特性

关于 Java 的语言特性,主要包括:泛型,反射,java8 提供的 Lambda 表达式等 本文简单介绍一下 java 的泛型和反射,后面深入学习之后再作总结。

  • Java 泛型,简单的理解就是将原先具体的参数类型的定义泛化,编译器负责转成特定类型。多态实际上就是一种泛化机制。
  • Java 反射: 程序运行时,对任意一个类可以获取到类中的属性,方法; 对任意一个对象,可以调用他的方法。
  • Java8 Lambda 表达式,支持函数式编程

四、Java基础类库

Java 的类库有很多很多,这里主要指的是JDK中包含的基础类库,源码下载:jdk
比较重要的有:java 集合,java 并发库(J.U.C), 网络库,IO,NIO 等等 本文就不一一展开介绍,后续文章中会依次对这些重要的包进行总结。

五、GC

GC 是 Java 特性中的重点,也是面试经常被问到的问题。 GC 简单来说就是 java 的垃圾回收,但是里面包含的内容非常多。谈到 GC, 必然要知道 JVM 的工作原理,内存结构。 在《聊聊 GC》这一篇中将会进行详细介绍。


文章内容主要是对自己学习的总结,还有很多需要深入挖掘的内容,To Be Continue

[参考引用]

  1. 《Thinking in Java》
  2. 《剑指Java面试》
  3. 《Effective Java》
最近的文章

Java 字节码学习笔记

Java 字节码 Java 字节码结构 Java 字节码增强技术Java 字节码为什么叫 Java 字节码? 字节码文件由十六进制值组成, JVM 以 2 个十六进制值为 1组 进行读取, (2个16进制值表示一个字节); Java 可以一次编译,到处运行的原因: JVM 针对各种操作系统、平台进行了定制; 无论在什么平台,都可以编译生成固定的字节码(.class 文件)供 JVM 使用 字节码很重要通过字节码可以直观的看到 Volatile 关键字如何在字节...…

继续阅读
更早的文章

数据结构造轮子

数组(ArrayList)和链表(LinkedList)数组和链表是Java中最核心的两个数据结构,对任何其他数据结构的理解,基于这两者,所以本文参照jdk8提供的源码,自己对2者进行了理解后简单的实现,给出自己的代码实现,很多不足之处有待优化。1. 数组2. 链表…

继续阅读