引自:https://www.oracle.com/technetwork/java/index-136113.html
Java设计理念1:Simple and Farmiliar
【Java语言特性】
-
原生数据类型
算术和关系运算符 - 没有unsigned关键字,所以需要<<<或者>>>来做位移运算; + 用于表示字符串拼接
数组 - 初始化数组时并未创建数组元素的对象。
字符串 - String(immutable), StringBuffer(mutable可修改)
多层break - 不支持goto,但是支持continue,break,以及label block
内存管理和垃圾回收 - Java去掉了C/C++的指针、分配和回收内存等机制,采用系统自动分配和回收内存的方式来避免掉指针机制带来的诸多系统问题,比如内存冲突、内存溢出、性能低下等。 Java的内存管理基于对象 和对对象的引用。Java机制中内存管理模块会监控对对象的引用,如果对象没有任何引用了,其内存空间,就会被自动回收。
后台垃圾回收机制
Java运行时,会启动一个低优先级的线程来进行自动的垃圾回收线程同步机制 - 在系统API层面支持多线程编程,屏蔽底层操作系统的差异。
【与C/C++不同】
C/C++中被摒弃的特性
- header文件及其中的define和typedefs
- structures和Unions(复杂结构体)- 用class代替之
- Enums
- Functions - class method代替之
- 多继承 - interface代替之
- goto语句 - 多层break和continue代替之
- 运算符重载
- 自动的强制转换 - 比例float赋值给int,不会做丢失精度的自动转换,而是报编译错误。
- 指针
Java设计理念2:Object Oriented
Object Oriented并不是包治百病的神药。
它只是解决了Procedure Oriented不能解决的一些问题。
编程语言必须至少具有如下4个特征,才能称为是面向对象的
- 封装性 - 具体的实现方式是可隐藏的,并且是可以模块化。
- 多态 - 同一个消息,发送到不同的对象,可以有不同的处理方式。
- 继承 - 通过定义新的对象可以继续原有对象的属性和行为,以获得代码的重用性
- 动态绑定 - 对于任何的对象,无论它是来自于网络任何地方,即使并不知道对象具体的类型,都可以发送消息给这个对象。
如何理解对象?
对象是对现实世界中事物的特征和行为的一种抽象和建模。
一切东西都可以抽象成一个对象,以及该对象的属性和行为。
人有高矮胖瘦等属性,也有走、停、工作、休息等等行为。
对象的基本概念
- 类 - 类中定义了同一类对象的属性(成员变量)和状态(成员方法)。 成员变量在实例创建时会copy作为实例的属性,也就是每个实例都可以有不同的属性取值。类本身并不是对象,更像是建对象的模板。就像是依据房子的同一个设计稿建好多个房子。
- 实例化一个对象 - new ClassName();
- 构造函数 - 实例化对象时,class的构造函数会被自动调用
- 成员方法和消息机制 - 通过成员方法及适当的权限控制,对象之前可以传递消息
- 类的finalize方法 - 在对象被回收之前会被调用(避免使用)
- 子类 - 重用原有代码的一种方式。Java去掉了C++里的多继承(如果两父类有相同的属性,在子类里会保存两份属性),只支持单继承。
接口 - 本质上是对相同动作的抽象,允许相同动作里做不同的实现。
只定义方法,不实现;允许某个类实现多个接口 => 好处:尽可能多地代码重用,又可以避免多继承时的混乱和系统问题权限控制
level | 作用域 |
---|---|
public | any objects |
protected | 子类 |
private | within this class |
friendly(不指定时默认) | 当前package |
包
好处1. 需要相互访问或者具有类似功能的类和接口定义在一个单元里。比如I/O相关的类都定义在java.io包里。
好处2. 包内有类可以互相访问,类的具体实现可以对包外的类不可见。类变量和类方法
对类的所有实例共享的变量和方法,用static来定义。抽象方法
对属性和方法的抽象,不提供具体实现。
Java设计理念3:Architecture Neutral, Portable and Robust
分布式计算背景下要求软件可以无缝迁移到各种软硬件系统上。而且不能靠引入支持各种系统的二进制包的方式,来解决这个问题。另外分布式系统里的各个结点都要保证高可靠性。
Architecture Neutral: java通过引入与平台无关的字节码,和JRE(运行时环境包含解析器)来把字节码解析成具体系统上可以运行的机器码,这样就避免了Java代码开发过程中需要考虑不同底层平台的差异。
Portable
引入平台无关的字节码,和在不同平台上解释执行字节码的JRE,解决了平台中立问题的同时,也提供了可移植性。
另外一方面可移植性体现在,Java对各种基本数据类型指定了标准的大小,不论采用哪种底层平台,基本数据类型所占的位数是固定的,这样就避免了C/C++里int在一个系统上可以运行,另一个系统上出错的问题。
- Robust
Java没有采用C/C++不严格的编译器检查,而是在编译期做了非常严格充分的语义检查。所以可以提前发现原本只能在运行期发现的程序问题。
而且Java与C/C++最大的不同是Java使用真正的数组和字符串,而非指针,也就是说解释器可以检查数组和字符串的索引。避免内存改写或者是内存冲突。
Java设计理念4:Interpreted and Dynamic
Java类在需要的时候才会被加载,而且可以加载从网络上下载的类。所以大大提高了动态扩展性。
另外C++在程序运行之前,有一些对象己经在分配了内存。而Java中只有在运行时,才会实际分配对象的内存。一定程序上减少了C++的Fragile Base Class问题。
Java设计理念5:Secure
Java compiler和java runtime设计了对于错误代码设计了很多层防范措施,也就是所谓java的安全模型(secure model)。
Java compiler最出色的一个保护机制,就是内存分配和引用的模型。
第一点:不同于C/C++在编译期,就设计了对象在内存中的具体存放。Java在运行期才会进行内存分配。
另一点:不同于C/C++在内存地址内会引用另一块内存地址。Java没有指针,编译好的java代码,通过symbolic handles来引用内存,这些handles之后会被jrm 解析器解析成真正的内存地址。
也就是说java中内存的分配和引用完全是由JRM来处理的。
Java程序员无法像c/c++程序员一样,有办法伪装或者制造对于内存的指针。
这不应该被理解成对程序员的限制,而是一种能够保护系统安全和健壮的好处。Class Loader的安全检查
java运行过程中需要用到的类文件,这些文件可能来自于本地文件系统或者是网络中。
加载这些文件时,首先会由字节码校验器(bytecode verifier)来检查这些被引用的类是否是安全的。然后再由字节码加载器(bytecode loader)来进一步检查。
java字节码运行一个线程所需要的环境,会被抽象成一系列的类,这些类按照来源不同,被拆分成多个命名空间。本地文件系统的类放一个命名空间,来源于网络的在另一个命名空间。
- 字节码校验流程
即使java代码本身遵守了java的规则,但是它引入的外部代码,不会被java compiler信任。而是会把它交给bytecode verificationfuc校验该代码是否格式正确,保证它遵守基本的规则:
(1). 没有伪造指针
(2). 没有违反访问权限控制
(3). 它引用的对象,都被正确使用
- [ ] java代码编译、运行流程图
- java网络包里的安全机制
java network包支持多种网络协议以及网络访问控制:
- [ ] 拒绝所有的网络访问
- [ ] 只允许访问当前代码的来源主机
- [ ] 如果代码来源于防火墙外,只允许访问防火墙外的网络
- [ ] 允许访问所有网络
Java设计理念6:Multithreading
线程安全的意思是,实现功能时始终考虑到要支持多线程执行。
多线程编程最大难点在于不能确认什么时候获得到你需要的锁,以及什么时候可以释放它。死锁是多线程编程中常见的情况。
java语言中的线程
Java支持多线程,可以有效提升交互式应用的性能。比如一个应用需要在滑动页面时播放音乐、下载文字、并且播放动画,那么它就可以使用多线程,每个线程负责一项工作,并行进行。
Java提供一个Thread类,封装了线程的创建、执行、停止等行为控制。
Java的线程同步机制是基于传统的监控和条件变量方式。
线程的具体执行方式取决于java解析器(interpreter)运行的平台,有些支持时间分片的系统上,线程是采用时间分片的方式运行的(不考虑线程的优先级,每个线程都运行一定时间 额度)。
在不支持时间分片的系统上,线程还是按照优先级来调度执行。对于这种情况,计算密集的线程需要考虑定时yield(),来给其他线程运行的机会。
- 线程同步
Java通过支持定义Thread对象以及在运行时支持多线程运行,实现了从语法层面支持多线程。在语言层面 ,被定义为synchronized的成员函数不会被并发执行。这类的函数通过monitors的控制,来保证其中定义的变量不会出现不一致的情况。 每一个类和实例化的变量都会被分配自己的monitor。
Java通过分配及释放monitor的方式,保证同一时刻,被标成synchronized的方法中只有一个会被执行。
Best Practise: 保持一个对象是线程安全的,需要在可能修改它的实例变量的所有方法上加注synchronized
Java中的monitor是re-entrant(允许重复获取),即使一个线程己经拥有一个monitor, 如果它需要的话,它还需要获得重复这个monitor。 避免了因为己经占有monitor,而导致的死锁。
- 多线程支持
Java对于多线程的支持是语法层面的,使得程序员更容易开发出线程安全的多线程程序。
【Java设计理念7:High Performance】
本章解答两个问题,其一,java语言的性能如何? 其二, 与其他语言相比,java的性能怎么样?
-
Java语言的性能
在个人电脑上Java语言本身创建对象、实例化对象、调用其他对象的方法,以及运行同步成员函数的性能大致如下:
其性能能够符合大多数程序的需求。
对于其他高性能程序来说,可以在Java运行的机器上,通过just in time compiler(瞬时编译机制)来快速翻译成机器码,进行运行。对于常规的由编译器和动态加载器组成的java环境来说,JIT compiler就像在动态加载器里的机器码生成器, 即在动态加载时,把字节码直接编译成机器码。
由字节码转换出的机器码,性能大致与C和C++相同。
-
Java与其他语言的性能比较
- Java的好处: 快速构建可靠原型
动态语言比如TCL, Lisp或者SmallTalk因为开发出的程序非常健壮(不必担心破坏内存),经常被用来构建原型。
相类似的,Java也非常适合用来构建原型,原因有两点:
Java也因为其垃圾回收机制, 使得程序员不需要考虑太多内存的分配与回收的细节。
不同于TCL/Lisp/SmallTalk提供了丰富的语义,使得你不需要太早做决定?(TBD), Java要求你必须做明确的决定,在编译期,会检查所有的方法调用是否正确。也就是说你在运行期,不用担心方法调用失败。
Java设计理念8:Java系统package
Java系统包含很多工具类以方便程序员来开发适合不同平台的应用程序。
主要的包包括:
[1]. 基础包 - java.lang
[2]. 工具包 - java.util
[3]. 抽象窗口工具包 - java.awt
-
java语言基础类 - java.lang
【1】系统相关:System, Runtime, Process
【2】基础数据类型的封装类:Byte, Short, Integer, Long, Float, Double, Character, Boolean, 额外的Number抽象类
【3】注解:SupressWarning, Override, Depercated, Inherited, Native, Repeatable, Retention, Target
【4】接口:AutoClosable, Runnable, Comparable, Interable, Readable, Cloneable
【5】字符串处理:String, StringBuffer, StringBuilder, StringCoding
【6】JMX管理: MemoryMXBean
【7】错误和异常处理:Throwable, Error, Exception 及相关子类
【8】其他重要的类: Class, Object, Math
【9】反射相关类:Method, Construnctor...
【10】引用相关类:Reference, WeakReference, SoftReference, ReferenceQueue, PhantomReference, FinalReference
【11】instrument包:Instrumentation, ClassFileTransformer Java输入输出类 - java.io
-
Java工具类 - java.util
【1】数据结构
【2】function包-函数式编程
【3】Stream包 - 流编程