第一张 Java程序设计概述
第一章 Java程序设计概述
二零二四年六月月三十日 周二 农历五月廿五
1.1 Java 程序设计平台
Java核心技术1版中如何描述Java的:
Java有非常多优秀的语言特新,但是他确实是也有缺点,由于兼容性的需求,新增的一些特性就没有原有发的特性那么精巧。但是 ,Java并不只是一种语言。Java语言出现之前,那么多种语言都没有引起那么大的轰动。Java是一种完整的平台,有一个庞大的库,其中包含了大量的可重复使用的代码,还有一个提供诸如**安全性、跨操作系统的可移植性以及垃圾自动回收。
作为一个程序设计者,你希望能有一种这样一种语言,既要有令人舒适的语法,也要有易于理解的语义,(C++就不是这样的语言)。Java完全满足这样的需求,另外还有很多其他的语言也能满足要求。不过尽管有些语言听提供给了可移植性、垃圾收集等特性,但是他没有提供一个丰富的库。如果你想要网络连接或者数据库存取特性,就必须自己动手编写代码。Java一应俱全,它具备所有这些特性,是一种功能齐全的出色语言的和一个高质量的执行环境,同时具有一个庞大的库。正式因为Java集多种优势于一身,所以对广大程序设计人员有着不可抗的吸引力。
可以看出,虽然 Java不是一种完美的语言,但是是一种优秀的语言。Java有可移植,性垃圾回收特性、一个丰富的库、舒适的语法、易于理解的语义,它一应俱全,对于程序设计者有着不可抵抗的吸引,Java的成功就来自它的全面性。
1.2 Java白皮书的关键术语
Java的设计者编写了一个颇有影响力的白皮书,来解释设计初衷以及完成情况,他们还发布了一个简短的摘要。这个摘要按照以下11个关键术语进行组织:
- 简单性
- 面向对象
- 分布式
- 健壮性
- 安全性
- 体系结构中立
- 可移植性
- 解释性
- 高性能
- 多线程
- 动态性
关于上关键术语,白皮书有相关说明,另外一下会根据使用Java当前版本的经验,各处对于这些术语的理解。
1.2.1 简单性
我面希望构建一个无须深奥的专业训练就可以进行编程的系统,并且要符合当经的标准惯例,因此,尽管我们发现 C++不太适用,但是在设计Java的时候还是尽可能的接近C++,以使得系统更易于理解。Java剔除了C++中许多的很少使用,难以理解,容易混淆的特性。在我们开来,这些特性带来的问题一远远多于它们的好处。
的确,Java语法是C++的一个“纯净”版本。这里没有头文件,指针运算(甚至没有指针语法)、结构、联合、操作符重载、虚基类(不了解C++跳过)。
Java发布时,实际上C++并不是最常用的程序设计语言。很多开发者都在使用Visual Basic和它的拖放式编程环境。这些开发人员并不觉得Java有多简单。很多年之后Java在迎头赶上。如今,Java开发环境已经远远超越了大多数其他编程语言的开发环境。
个人理解:
Java语言的语法是参考了C++,并在此基础上进行了裁剪,相对C++来说,的确是简单很多。Java发展快30年,现在需要更多的去了解Java才能找到一份工作。主要是对Java的底层实现、JVM如何执行优化和Spring系列框架;Spring框架的源码、理论、分布式理论等。所以说简单性只是对于语法来说,而不是整个Java平台,前面Java 程序设计平台介绍,Java更多的不是语言出色而是体系构建的平台出色。
1.2.2 面向对象
简单的讲,面向对象设计是一种程序设计技术。它的重点放在数据上(即对象)和对象接口上。用木匠打一个比方:一个“面向对象”木匠关注的是所制作的椅子,其次才是使用的工具;一个“非面向对象”木匠所考虑的则是使用的工具。在本质上,Java的面向对象能力与C++是一样的。
开发Java时面向对象技术已经相当的成熟。Java面向对象的特性与C++旗鼓相当,Java与C++的主要的不同在于多重继承,在Java中取而代之的是更简单的接口概念。与C++相比,Java提供了更丰富的运行时自省功能。(关于自省功能后续篇章会写到)
1.2.3 分布式
Java有一个丰富的例程库,用于处理HTTP和FTP之类的TCP/IP协议。Java应用程序能够通过URL打开访问网上的对象,其便捷程度就好像访问本地文件夹一样。
在如今这一点被认为时理所当然的,不过在1995年主要还是使用C++和Visual Basic程序链接Web服务器的。
咨询Chat GPT给出以下答复:
在计算机科学中,分布式系统指的是一个由多个独立计算机(节点)组成的系统,这些节点通过网络互相通信和协调来完成任务。分布式系统的关键特性之一是资源共享和协同工作,节点可以分布在不同的物理位置,但它们可以共同完成一个任务或一系列任务。
关于Java语言特性中的“分布式”的描述,其主要原因是:
1. **网络通信能力**:Java提供了丰富的类库来处理网络通信协议(如HTTP和FTP),使得应用程序能够方便地与其他计算机上的资源进行交互。这种通过网络进行资源访问和操作的能力,是分布式系统的一个基本特征。
2. **URL访问机制**:Java应用程序能够通过URL访问远程资源,就像访问本地文件一样。这种透明的资源访问机制,隐藏了底层网络通信的复杂性,使得开发人员可以轻松地编写分布式应用程序。
3. **分布式计算模型**:Java支持多线程编程和远程方法调用(RMI),允许不同计算节点之间进行任务分配和协同处理。RMI使得一个Java对象可以调用另一个远程Java对象的方法,从而实现分布式计算。
因此,Java被称为“分布式”的原因在于其语言和库的设计,使得开发人员可以方便地创建跨网络协同工作的应用程序,从而实现资源共享和分布式计算。这种能力对于构建现代分布式系统(如微服务架构、大数据处理系统等)非常重要。
个人理解:
分布式特性是非常具有前瞻性的,如今互联网超大并发量和数据交互,完全可以使用分布式这一特性来处理。衍生出的分布式框架,Spring Cloud、Dubbo和Alibaba等分布式框架,不在简单的使用TCP/IP做一些简单的访问,而是基于分布式特性来构建分布式应用来处理超大并发量和数据交互。单一硬件是有上限的,而分布式是用一群硬件。
1.2.4 健壮性
Java设计的目标之一就是要让Java编写的程序具有多方面的可靠性。Java非常强调进行早期的问题检测,后期的动态(运行时)检测,以消除容易出错的情况…………Java与C/C++最大的不同在于Java采用了指针模型可以消除重写内存和损坏数据的可能性
Java编译器能够检测许多其它语言中仅在运行时才能检测出来的问题。至于第二点,对于曾经花费几个小时来检查由于指针bug而引起内存冲突的人来说,一定很喜欢Java这一特性。
个人理解:
Java是静态强类型语言,并且,因为Java的语法严谨,Java的IDE可以做的非常强大,在开发阶段就可以避免很多问题。使用Java有IDE和语言本身兜底,在开发中可以减少很多的错误。健壮性与简单性相辅相成,简单性剔除了繁琐的难以理解的语法提供了健壮性的基础,而健壮性更进一步的加强了简单性,这使得程序员更加的轻松开发设计程序。实现了健壮性,虽然是牺牲了在极端情况下的性能,但是大大提高了程序的安全性和下限。
1.2.5 安全性
Java适用于网络/分布式环境下。为了实现这个目标,安全性颇受重视。使用Java可以构建防病毒、防篡改系统。
从一开始,Java就设计出能够防范各种攻击手段,其中包括:
- 运行时堆栈溢出,这是蠕虫和病毒常用的攻击手段。
- 破坏自己的进程空间之外的内存
- 未经授权读写文件
起初Java对下载代码的态度是”尽管来吧!“不可信代码在沙箱环境中执行,在这里他不会影响主系统。用户可以确信不会发生不好的事情,因为Java代码不论来自哪里,都不能逃离这个沙箱。
不过,Java的安全模型很复杂。Java开发包(Development Kit,JDK)的第一版发行之后不久,普林斯顿大学的一些安全专家就发现了一些小bug会允许不可信代码攻击主系统。
最初的bug可以快速修复,遗憾的是,经过一段时间后,黑客已经可以很擅长找出安全体系结构实现中的小漏洞,Sum公司以及之后的Oracle公司为此不断修复bug经历了一段很是艰难的日子。
遭遇到多次高调攻击之后,浏览器和开发商变得越来越谨慎。有一段时间,远程代码必须有数字签名。如今通过浏览器交付Java应用是一段很遥远的记忆了。
### Java的安全模型
Java的安全模型主要由以下几部分组成:
1. **沙箱模型(Sandbox Model)**:
- 沙箱模型是Java安全性的基础,它确保了未经授权的代码无法访问和修改系统资源。所有从网络或其他不可信来源加载的代码都运行在沙箱中,受限于安全管理器和策略文件的约束。
2. **类加载器(Class Loader)**:
- 类加载器的层次结构使得系统类和用户类可以分离,从而避免恶意代码替换或修改系统类。不同来源的代码由不同的类加载器加载,并且可以设置不同的权限。
3. **安全管理器(Security Manager)和策略文件(Policy File)**:
- 安全管理器负责在运行时检查代码请求的权限。开发人员可以通过策略文件定义安全策略,指定不同代码源(如本地文件、网络等)的权限。
4. **访问控制列表(Access Control List, ACL)**:
- ACL定义了资源(如文件、网络端口等)访问的权限。安全管理器通过ACL判断代码是否有权限访问某个资源。
5. **加密和认证机制(Cryptography and Authentication)**:
- Java提供了丰富的加密库,支持各种加密算法和协议(如SSL/TLS)。这些库可以用于确保数据传输的安全性和完整性。
### 实际应用中的安全机制
1. **Java Applet的安全性**:
- Applet在浏览器中运行,受限于沙箱模型。未签名的Applet只能在受限的环境中运行,而签名的Applet可以获得更多权限。
2. **Java Web应用的安全性**:
- Java EE提供了丰富的安全机制,如身份验证、授权、数据加密等,确保Web应用的安全性。
3. **Java SE的安全性**:
- Java SE提供了安全管理器、策略文件和安全API,帮助开发人员构建安全的桌面和服务器应用。
通过上述多层次的安全机制,Java确保了代码执行的安全性,防止恶意代码攻击和资源滥用,为开发人员提供了一个安全、可靠的编程环境。
以上可以对类加载器、加密和认证机、Java Web应用的安全性可以多了解
对于浏览器交付Java程序的历史了解
Java程序通过浏览器交付的概念在1995年Java首次发布时引入。这个概念主要通过Java Applet实现,Java Applet是一种嵌入在网页中的小程序,可以通过浏览器下载并运行。以下是一些关键的时间节点和背景信息:
### 关键时间节点
1. **1995年5月23日**:
- Sun Microsystems在SunWorld大会上首次公开发布Java编程语言。Java的一个重要卖点是其可以通过浏览器运行Java Applet,从而实现跨平台的分布式计算。
2. **1995年年底**:
- Netscape Navigator 2.0发布,成为第一个支持Java Applet的主流浏览器。Netscape的支持极大推动了Java Applet的普及,使得通过浏览器交付Java程序成为可能。
3. **1996年**:
- Java Development Kit (JDK) 1.0发布,正式为开发者提供了创建和运行Java Applet的工具。
### Java Applet的特点
- **平台独立性**:Java Applet编译成字节码,可以在任何支持Java虚拟机(JVM)的浏览器上运行。
- **沙箱安全模型**:Applet在一个受限的环境(沙箱)中运行,限制其访问本地系统资源,增强了安全性。
- **动态加载**:Applet可以在用户访问网页时动态加载和执行,适合实现交互式和动态网页内容。
### Java Applet的衰退
尽管Java Applet在1990年代后期和2000年代初期取得了一定的成功,但其使用逐渐减少,主要原因包括:
- **安全问题**:尽管Applet运行在沙箱中,但仍存在安全漏洞和风险,导致用户和浏览器厂商逐渐失去信任。
- **性能问题**:Applet加载时间较长,启动速度较慢,用户体验不佳。
- **技术替代**:随着Flash、JavaScript、HTML5等技术的发展,它们提供了更高效、更安全的解决方案,逐渐取代了Java Applet的地位。
### 现代浏览器
如今,现代浏览器如Chrome、Firefox、Edge等已经不再支持Java Applet。Java的应用更多转向服务器端和独立的桌面应用程序,而不是通过浏览器交付。
### 总结
Java通过浏览器交付程序的概念起源于1995年Java首次发布时,主要通过Java Applet实现。然而,由于安全性和性能等问题,Java Applet的使用逐渐减少,并最终被现代的Web技术所取代。
Java安全性主要在两方面,一个是安全设计,一个是JVM。对于JVM后续会更多的深入了解
1.2.6 体系结构中立
编译器生成一个体系结构中立的目标文件格式,这是一种编译型代码,这些编译型代码可以在很多处理器上运行(只要它们有Java运行时系统),Java编译器通过生成与特定计算机体系结构无关的字节码指令来实现这一特性。精心设计的字节码不仅可以很容易在人和机器上解释运行,而且很容易的动态转换为原生机器代码。
当时,为”虚拟机“生成代码并不是一个新思路,诸如Lisp、Smalltalk和Pascal等编程语言多年前就采用了这种技术。当然,解释虚拟机指令肯定比全书运行机器指令很慢,不过,虚拟机有一个选项,可以将执行最频繁的字节码序列转换成机器码,这一过程被称为即时编译(just-in-time compilation)
Java虚拟机还有其他优点。他可以检查指令序列行为,从而增强安全性。
关于体系与结构中立这是 Java比较重要的一部分,需要研究。
Java语言的一个重要特性是其体系结构中立性,这使得Java程序可以在不同的平台上运行,而无需修改代码。这一特性主要得益于Java虚拟机(JVM)的设计和实现。以下是对Java体系结构中立性的详细解释,以及对Java虚拟机的讲解。
体系结构中立性
#### 1. **字节码(Bytecode)**
- Java源代码编译成一种中间表示形式,称为字节码。这些字节码存储在.class文件中。字节码是一种中立的、与硬件和操作系统无关的二进制格式,确保了编译后的Java程序可以在任何实现了JVM的系统上运行。
#### 2. **Java虚拟机(JVM)**
- JVM是一个抽象的计算机,它定义了一组字节码指令集、寄存器、堆栈、垃圾收集堆、方法区等。JVM负责将字节码解释或编译成本地机器码并执行,使得相同的字节码可以在不同的硬件和操作系统上运行。
#### 3. **平台无关性**
- Java程序的编译过程与传统的编译器不同。传统的编译器将源代码直接编译成特定平台的机器码,而Java编译器将源代码编译成与平台无关的字节码。JVM在不同平台上解释这些字节码,从而实现了“一次编写,处处运行”的目标。
### Java虚拟机(JVM)
#### 1. **JVM的结构**
- **类加载器系统(Class Loader Subsystem)**:负责加载.class文件到内存中,并将它们转换为JVM可以理解的类对象。类加载器有三个主要类型:启动类加载器(Bootstrap Class Loader)、扩展类加载器(Extension Class Loader)和应用程序类加载器(Application Class Loader)。
- **运行时数据区(Runtime Data Areas)**:包括方法区(Method Area)、堆(Heap)、栈(Stack)、程序计数器(Program Counter Register)和本地方法栈(Native Method Stack)。
- **方法区**:存储类信息、常量、静态变量和编译后的代码等。
- **堆**:用于动态分配对象和数组,垃圾收集器管理堆中的内存。
- **栈**:每个线程都有自己的栈,存储局部变量、操作数栈和帧数据等。
- **程序计数器**:保存当前线程执行的字节码指令地址。
- **本地方法栈**:为本地方法服务,用于调用非Java方法(如C/C++)。
#### 2. **JVM的工作过程**
- **类加载**:类加载器将字节码加载到JVM中。
- **字节码验证**:字节码验证器检查字节码的合法性和安全性,确保其符合JVM的规范。
- **解释和即时编译(JIT)**:JVM解释字节码或将其即时编译成本地机器码以提高执行速度。JIT编译器在运行时将频繁使用的字节码编译成本地代码,从而提高性能。
- **执行**:JVM执行编译后的字节码或本地机器码。
- **垃圾收集(Garbage Collection)**:JVM自动管理内存,通过垃圾收集器释放不再使用的对象所占用的内存,避免内存泄漏。
#### 3. **JVM的优点**
- **平台独立性**:字节码和JVM的设计确保Java程序可以跨平台运行。
- **安全性**:字节码验证和沙箱模型提供了安全保障,防止恶意代码对系统的威胁。
- **性能**:JIT编译和高效的垃圾收集机制提高了Java程序的执行效率。
- **多线程支持**:JVM本身对多线程提供了良好的支持,简化了并发编程。
### 小结
Java的体系结构中立性和JVM的设计共同实现了Java程序的跨平台能力和高性能执行。JVM不仅提供了解释和执行字节码的机制,还通过JIT编译和高效的内存管理机制提升了程序的运行效率。这些特性使得Java成为一种广泛使用的编程语言,适用于各种应用场景,从桌面应用到大型企业级应用。
这里知识作为了解,后续关于虚拟机会出现在 Java高级篇中再次不在过多了解,字节码.class文件可以看看算是前期比较基础的知识点,要是深究的话,我没有深究过,有兴趣的可以深究一下。
1.2.7 可移植性
与C和C++不同,Java规范中没有”依赖具体实现“的地方,基本数据类型的大小以及关系运算的行为都是明确的。
例如,Java中int整数类型总是32位,而在C/C++中,int可能是16位、32位整数,也可能是编译器开发商指定的任何其他大小,唯一的是int类型的字节数不能低于short int,并且不能高于long int。在Java中,数值类型都是固定的字节数,这消除了代码移植时一个令人头痛的主要问题。二进制数据以固定格式传输和存储,消除有关字节顺序的困扰。字符串则采用Unicode格式存储。
除了GUI,Java其他的库有很好的支持平台的独立性。你可以处理文件的正则表达式、XML、日期和时间、数据库、网络连接、线程等,而不用操心底层操作系统。不仅程序是可移植的,Java API往往也比原生API质量更高。
1.2.8 解释性
Java解释器可以在任何移植了解释器的机器上执行Java字节码。由于链接(Linking)是一个增量式的轻量级过程,所以,开发过程也会更加快捷,具有探索性。
这看上去很不错。道用过 Lisp、Smalltalk、Visual Basic、Python、R或Scala的人都知道”快捷且具有探索性“的开发过程是什么样子的。你可以做出一些尝试,然后立即看到结果。在Java发展的二十年里,开发环境并没有把重点放在这种体验上面。知道Java9才提供了jshell工具来支持快捷且有探索性的编程。
1.2.9 高性能
尽管解释型字节码的性能通常已经足够令人满意,但有些场合还是需要更高的性能,字节码(在运行时)动态的转换为面向运行这个应用的特定CPU的机器码。解释器能够在任何移植了解释器的机器上直接执行Java字节码。
使用 Java 的头几年,许多用户不同意“性能已经足够让人满意”的说法。不过,现在的即时编译器已经非常出色,可以与传统编译器相美,而且在某些情况下甚至超越了传统编译器,原因是它们有更多的可用信息。例如,即时编译器可以监控哪些代码频繁执行,并优化这些代码以提高速度。更为复杂的优化是消除函数调用(即“内联”)。即时编译器知道已经加载了哪些类。基于当前加载的类集合,如果一个特定的函数不会被覆盖,就可以使用内联。必要时,以后还可以撤销这种优化。
1.2.10 多线程
多线程可以带来更好的交互响应
如今,我们非常的关注并发性,因为摩尔定律即将走到尽头。我们不再追求更快的处理器,而是着眼于获取更多的处理器,而且要让他们保持繁忙。不过,可以看到,大多数编程语言对于这个问题没有显示出足够的重视。
Java当时很超前,它是当时第一个支持并发程序的主流语言。从白皮书可以看到,它的出发点稍有些不同。当时多核处理器还很神秘,而Web编程刚刚起步,处理器要等很长时间等服务器响应,需要并发程序来确保用户界面没有被”冻住“。
并发程序设计绝非易事,不过Java在这一方面表现很出色,可以很好的管理这个工作。
成大事者,往往运气与实力兼备。
1.2.11 动态性
从很多方面来看,Java与C++相比具有更多的动态性。Java设计为了适应不断演进的环境。库可以自由的添加新的方法与实例变量,对于客户端没有任何的影响,在Java中找出运行时类型信息十分方便。
需要为正在运行时的程序增加代码时,动态性是一个非常重要的特性,一个很好的例子是:在浏览器中运行从Internet下载的代码。如果使用C/C++,这确实难度很大,不过Java语言设计者很清楚动态语言可以很容易地在一个正在运行的程序实现演进。最终,他们将这一特性引入到这个主流程序设计语言中。
以上部分内容来自Java核心技术12版卷I Java程序设计概述
浙公网安备 33010602011771号