作为一名 Java 开发者,今天唠一唠 Java 开发平台的一点基本情况。
简介
根据创始公司 Sun Microsystems 的描述,Java 是一门:
简单、完全面向对象、分布式、解释性、健壮、安全与系统无关、可移植、高性能、多线程和动态的编程语言。
我们关心的是,减少开发健壮代码所需的时间以及困难。
Java 最初被称为 Oak,是 1991 年为消费类电子产品的嵌入型芯片而设计的开发平台。1995 年 5 月更名,并重新应用于开发 Internet 应用程序。
2010 年,Sun 被甲骨文(Oracle)收购,Java 随即归于 Oracle 旗下。
Java 除了我们熟知的 Java 程序设计语言之外,还有一块大头是 Java 平台。
Java 开发平台
Java 平台(software platform)是由 Java 程序语言编写的软件赖以开发的平台,是 Java 软件和电脑系统的中介。
最初被设计用在 Applet 等桌面端程序开发,不过后来逐渐转移到服务端的运用。
主要分三类:
- Java SE(J2SE, Java 2 Platform Standard Edition):Java 平台标准【基础】版,即 Java 桌面版
- Java EE(J2EE, Java 2 Platform Enterprise Edition):Java 平台企业版,基于 J2SE 打造,用于构建大型网站;后来重命名为 Jakarta EE
- Java ME(J2ME, Java 2 Platform Micro Edition):Java 平台微型版,基于 J2SE 打造,用于构建手机移动终端。
当今最流行的 Java 开发环境:
- Eclipse
- IntelliJ IDEA
- Jbuilder
- JCreator
- Jdeveloper
- MyEclipse
- Netbeans
就拿 Eclipse 来说:Eclipse 是一款开放源代码的、基于 Java 的可扩展开发平台,其实是 Visual Age for Java
- Eclipse 本身只是一个框架和一组服务
- Eclipse 中每一样东西都是插件,用户通过不同的插件组件来构建开发环境;所以可以通过添加插件实现强大的功能
- 同时还附带了一个标准的插件集,包括 Java 开发工具
因此 Eclipse 可以支持多种语言的开发,如 C/C++,PHP 等;而许多软件开发商也以 Eclipse 为框架开发自己的 IDE。
IBM 提供了最初的 Eclipse 代码基础,包括 Platform、JDT 和 PDE。
Eclipse 分支(Eclipse 标准版 + 功能插件)如下:
Eclipse Standard | 标准版 |
Eclipse IDE for Java EE Developers | 面向 J2EE |
Eclipse IDE for Java Developers | 面向 J2SE |
Eclipse IDE for C/C++ Developers | 面向 C/C++ |
Eclipse for PHP Developers | 面向 PHP |
Eclipse for RCP and RAP Developers | 面向 Eclipse 插件开发 |
Java 特性
Object Oriented
以对象为基本粒度,对象的属性定义了这个对象,对象的方法可用来操作对象
- 使代码 human-being-like,利于代码扩展和复用
Platform Independent
Java 源代码编译后的字节码与平台无关,与底层应用打交道的事情都交给了 JVM,真正做到 write / compile once, run everywhere
Safe
包括:
- 语言级安全性(对象的封装)
- 编译时安全性(语法意义检查)
- 运行时安全性(类装载器装载及字节码校验器校验)
- 可执行代码安全性(网络访问类的时候进行了权限设置)
- 当然,总有安全漏洞躺在人们意想不到的地方
Threading
多线程提高了程序对硬件的利用率。
由此,Java 技术具有卓越的通用性、高效性、平台移植性和安全性。
Java 不同于一般的编译语言和直译语言:它首先将源代码编译成字节码,然后依赖各种不同平台上的虚拟机来解释执行字节码,从而实现 write / compile once, run everywhere。
至于语法糖更是数不胜数了:
- 泛型和类型擦除
- 自动装箱与拆箱
- 变长参数
- 增强 for 循环
- 内部类
- 枚举类
- …
Java v.s. C++
Java 很大程度上沿袭了 C++ 的一些实用结构,因此风格十分接近 C++,继承了 C++ 语言面向对象技术的核心。
Java 与 C++ 的区别在于:
- Java 运行于 JVM 上面,可移植性强,且 JVM 几乎可以安装到任何的系统;C++ 如果要在不同的系统中运行,需要不同的编码;
- 也正因如此,Java 在桌面程序应用上面不如 C++ 实用,因为 C++ 可以直接编译成 .exe 文件;
- 指针是 C++ 的优势,可直接对内存操作,因此 C++ 利用于底层程序的编程以及控制方面的编程更灵活;
- 但指针编程同时具有危险性;Java 舍弃了 C++ 中容易引起错误的指针,改用引用取代;
- 关于垃圾回收:C++ 利用析构函数,Java 是自动启动垃圾回收机制;因此相比起 C++,java 运行速度会慢一些;
- Java 移除原 C++ 的操作符重载,也移除了多重继承特性,改用接口取代;
- Java 在 web 前端的应用上具有 C++ 无法比拟的优势;
- Java 具有异常处理机制
Java v.s. C#
- Java 不允许操作符重载
- Java 没有类似于 LINQ 的特性
- Java 内部类可以直接访问外部类的实例成员,C# 不行
- C# 能被重写的方法必须添加
virtual
关键字声明为虚方法;Java 对于方法的默认行为都可以被重写 - C# 没有匿名内部类
Java 程序生命周期
编译:源文件(
.java
) -> 编译器(javac) -> 字节码 byte code(.class
)- 注:JVM 只能运行字节码文件
装载:字节码(
.class
) -> JVM 类加载器 -> JVM 中装载的类校验:JVM 中装载的类 -> JVM 字节码校验器 -> 进行校验
解释:JVM 中装载的类 -> JVM 解释器(根据 OS 解释) -> 机器码
运行:机器码 -> OS -> 运行的程序
回收:内存垃圾 -> JVM 垃圾回收器 -> 不定期垃圾回收
终止:JVM 卸载程序
注意:编写好的 Java 程序不能够直接在操作系统中运行,而是运行在 JVM 中。
每一种 Java 平台的解释器可能有不同,但实现的 JVM 是一样的:这也是 Java 为何能跨平台的重要原因之一原因。
编码风格
Java 的注释风格有单行注释、多行注释、类和方法注释:
1 | // 单行注释 |
Java 的工程包 packages 命名一般遵循以下层次:com.公司名.项目名.模块名
。
Java 变量和方法的命名有以下要求:
- 不与 Java 关键字冲突
- 不以数字开头
- 可包含
$
和_
,此外不能有其他符号 - 可以用
$
和_
开头 - 一般遵循伪驼峰命名习惯:userName, myAccount
常量命名:建议全大写,final 修饰,常配以 static 修饰符:
1 | public static final double PI = 3.141593; |
对于项目 / 类 / 接口的命名,除了使用驼峰命名(MyClass, MyInterface)之外,其它基本与变量 / 方法名相同。
JRE
JVM 是 Java 运行环境(Java Runtime Environment, JRE)的一部分。
JRE 是运行 Java 程序所必需的环境集合,包含 JVM 的标准实现及 Java 核心类库
- JRE 仅仅能够完成 Java 的运行,无法对 Java 进行编译、调试
- 它面向的是 Java 程序使用者,而非开发者
- JRE 有独立版本,如果只需要运行 Java 程序,安装 JRE 即可。
JRE 的组成:
- Java 的类库,包含了编译 Java 程序所需要的最核心文件
- 核心库文件,其中有
- 数据结构的库,包括列表、字典和树等
- XML 分析库
- 安全方面应用库
- 国际化和本地化应用库
- 综合库文件,包含了程序员和其他系统通信的功能文件
- JDBC,即 Java 数据库连接的 API
- JNDI,即 Java 命名和目录接口
- RMI 和 CORBA,用于重新分发软件
- 用户界面库文件,包含:
- AWT,即抽象窗口开发包,提供了产生图形用户界面所需要的功能
- Swing 库
- 其他用于回访媒体文件、录音、截图的库
- 核心库文件,其中有
- 一个用于执行软件的 JVM 实现
- 插件,可以在浏览器里面使用
- JWS(Java Web Service),可以让终端用户连接到互联网
- 许可文件和文档
如果要进行 Java 开发,需要安装 JDK。
JDK
JDK(Java Development Kit)是 Java 语言的开发包,包含了 JRE,可以将 .java
文件编译为可执行 Java 程序,通过加载到 JVM 然后运行。
完整的 JDK 包括以下基本组件:
/bin
目录,包括- 编译器(javac)
- 解释器(java)
- jdb 调试器(java debugger)
- 文档生成器(javadoc)
/demo
目录,包括一些代码的演示/include
目录:用于编译本地方法的文件,如 JNI 调用时所需的 C 语言头文件/JRE
目录,包含JVM 运行环境,JDK 类库,与所在平台相关/lib
目录,包含除/JRE
下之外 JDK 额外所需的类库src.zip
,里面是 JDK 的源代码- jar 打包工具
- 头文件生成器
- javap 反汇编器
- 监控工具
- …
JDK 中常用的 package:
java.lang
:系统基础类,如 String;该 package 是唯一不需要import
的 packagejava.io
:所有与输入输出有关的类java.net
:所有与网络连接有关的类java.util
:系统辅助类,包括 Collection, List, Map 等java.sql
:数据库操作类,Connection, Statement, ResultSet 等java.servlet
:JSP、Servlet 等使用到的类
下面介绍几个长期支持(LTS)的 JDK 版本。
JDK 1.5
Java 5 最重要的一个支持是泛型(generics),为了参数化类型,或者说可以将类型当作参数传递给一个类或者方法。
- 与普通的 Object 代替一切类型这样简单粗暴而言,泛型使得数据的类别可以像参数一样由外部传递进来。它提供了一种扩展能力。它更符合面向抽象开发的软件编程宗旨。
- 当具体的类型确定后,泛型又提供了一种类型检测的机制,只有相匹配的数据才能正常的赋值,否则编译器就不通过。所以说,它是一种类型安全检测机制,一定程度上提高了软件的安全性防止出现低级的失误。
- 泛型提高了程序代码的可读性,不必要等到运行的时候才去强制转换,在定义或者实例化阶段,因为
Cache<String>
这个类型显化的效果,程序员能够一目了然猜测出代码要操作的数据类型。
泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,这叫做类型擦除。
类型擦除容易带来强制类型转换和引用传递的问题。
JDK 1.7
Java 7(JDK 1.7)于 2011 年 7 月推出,是 Java 史上最大的一次更新。主要更新内容有:
- 定义二进制(
byte
)为基本类型变量
1 | byte b = (byte)0b00000001; |
- 下划线分隔数字
1 | long aLongDecimal = 1234_5678_9012L; |
- switch 语句判断 String 类型
1 | switch (dayName) { |
- 泛型实例化自动推断类型
1 | ArrayList<String> sList = new ArrayList<>(); |
- 推出
try-with-resource
:不需要手动关闭资源
1 | // java 6- |
- 单个 catch 子句可以捕获多个异常
1 | // java 6- |
JDK 1.8
Java 8 于 2014 年 3 月发布。主要更新内容:
1. 移除位于 JVM 内存中的 PermGen,新增位于本地内存中的 Metaspace
;
2. 接口扩展:给接口方法添加默认(default 关键字)或静态实现;
1 | // 默认实现 |
3. 函数式接口的定义:任何接口,如果只含一个抽象方法,就是一个函数式接口。其本质上来说,是函数式编程的应用。
可以给接口添加 @FunctionalInterface
注解。
1 | // Function<T, R> - 输入 T, 输出 R |
另外就是 Optional 类(java.util.Optional
)的应用
- 一个可以包含 null 值的容器对象,可用来代替
xx != null
的判断
4. 方法引用
- Reference to constructor, 构造方法引用
- Reference to static method, 类静态方法引用
- Reference to methods of an instance, 某个对象的方法引用
- Reference to methods of a specific class for any instance, 特定类的任意对象的方法引用
1 | // 首先定义一个基本的 entity 类 Person, nothing special |
5. Lambda Expression
- a.k.a. clousure, 闭包
- 把函数当成方法参数,可以替代匿名对象
应用于数组的 foreach:
1 | List<String> names = Arrays.asList("b", "c", "a", "d"); |
应用于字符串数组排序:
1 | List<String> names = Arrays.asList("b", "c", "a", "d"); |
JDK 1.11
Java 11 于 2018 年 9 月发布,主要的增强有:
- 增加了一些字符串的处理方法;
- 用于 Lambda 参数的局部变量语法;
- Http Client 重写,支持 HTTP/1.1 和 HTTP/2 ,也支持 websockets
- 可运行单一的 Java 源码文件,如:java Test.java
- 新的垃圾回收器 ZGC:可伸缩低延迟垃圾收集器;ZGC 可看作是 G1 之上更细粒度的内存管理策略;
- 支持 TLS 1.3 协议
- Flight Recorder(飞行记录器),基于 OS、JVM 和 JDK 的事件产生的数据收集框架
- 对 Stream、Optional、集合 API 进行增强。
挑重点:对于 JDK 1.9 和 JDK 1.10(局部变量类型 var
推断等)的完善,主要是对于 Stream、集合等 API 的增强、新增 ZGC 垃圾收集器。