01 Java基础
Java 基础
0 引言
本笔记主要介绍java提供的语言级别的支持,不包括标准库的内容。
如何快速掌握一门语言
一个语言应该包括以下几个部分
- 语言基础:数据类型和变量、控制流程、数据结构、函数、面向对象、其他
- 标准工具库:数学、日期、字符串、系统、序列化等
- 内置高阶库:文件IO、网络编程、并发编程
- 生态库:Web框架、客户端、分布式
- 编译原理:虚拟机、内存管理、类加载等
- 问题排查和性能优化:产业实践的经验
Java特性和优势
write once run anywhere
- 面向对象
- 可移植性
- 高性能(即时编译和预编译)
- 分布式
- 动态性
- 多线程
- 安全性、健壮性(没有指针和内存的管理、垃圾回收机制)
JDK、JRE和JVM

- JRE:Java Runtime Environment,Java 运行环境的简称,为 Java 的运行提供了所需的环境。它是一个 JVM 程序,主要包括了 JVM 的标准实现和一些 Java 基本类库。
- JDK:Java Development Kit,Java 开发工具包,提供了 Java 的开发及运行环境。JDK 是 Java 开发的核心,集成了 JRE 以及一些其它的工具,比如编译 Java 源码的编译器 javac 等。
编译和解释
Java既需要编译也需要解释执行。
- Java编译器,将源代码转换成虚拟机能够识别的字节码。
- Java解释器,编译器识别字节码,转换为机器能够识别的机器码。

Java 各版本的新特性
New highlights in Java SE 8
- Lambda Expressions
- Pipelines and Streams
- Date and Time API
- Default Methods
- Type Annotations
- Nashhorn JavaScript Engine
- Concurrent Accumulators
- Parallel operations
- PermGen Error Removed
New highlights in Java SE 7
- Strings in Switch Statement
- Type Inference for Generic Instance Creation
- Multiple Exception Handling
- Support for Dynamic Languages
- Try with Resources
- Java nio Package
- Binary Literals, Underscore in literals
- Diamond Syntax
Java 与 C++ 的区别
- Java 是纯粹的面向对象语言,所有的对象都继承自 java.lang.Object,C++ 为了兼容 C 即支持面向对象也支持面向过程。
- Java 通过虚拟机从而实现跨平台特性,但是 C++ 依赖于特定的平台。
- Java 没有指针,它的引用可以理解为安全指针,而 C++ 具有和 C 一样的指针。
- Java 支持自动垃圾回收,而 C++ 需要手动回收。
- Java 不支持多重继承,只能通过实现多个接口来达到相同目的,而 C++ 支持多重继承。
- Java 不支持操作符重载,虽然可以对两个 String 对象执行加法运算,但是这是语言内置支持的操作,不属于操作符重载,而 C++ 可以。
- Java 的 goto 是保留字,但是不可用,C++ 可以使用 goto。
What are the main differences between Java and C++?
第一个Java程序

位、字节、字符、字长
- 位,bit
- 字节,8,16位
- 字符,计算机中使用的字母、数字和符号
- 字、字长,操作系统的寻址空间。
1 注释、标识符和关键字
注释
1 | //单行注释 |
1 | /** |
标识符
标识变量、方法、类和对象的名字。
- 所有的标识符都应该以字母(A-Z 或者 a-z),美元符($)、或者下划线(_)开始
- 首字符之后可以是字母(A-Z 或者 a-z),美元符($)、下划线(_)或数字的任何字符组合
- 关键字不能用作标识符
- 标识符是大小写敏感的
关键字
| abstract | assert | boolean | break |
|---|---|---|---|
| byte | case | catch | char |
| class | const | continue | default |
| do | double | else | enum |
| extends | final | finally | float |
| for | goto | if | implements |
| import | instanceof | int | interface |
| long | native | new | package |
| private | protected | public | return |
| short | static | strictfp | super |
| switch | synchronized | this | throw |
| throws | transient | try | void |
| volatile | while |
2 数据类型
强类型语言,所有变量必须先定义后使用。可以分为
- 基本类型
- 引用类型
- 基本类型对应的引用类型,称为包装类型
基本类型
- 整数类型
- byte/8
- short/16
- int/32
- long/64
- 浮点数类型
- float/32
- double/64
- 字符类型
- char/16
- 布尔类型
- boolean/1
boolean 只有两个值:true、false,可以使用 1 bit 来存储,但是具体大小没有明确规定。JVM 会在编译时期将 boolean 类型的数据转换为 int,使用 1 来表示 true,0 表示 false。JVM 支持 boolean 数组,但是是通过读写 byte 数组来实现的。
float和double的比较问题
- java里的相等判断是检查类型的。float和double之间无法直接判断是否相等。
- float和double采用科学技术发进行存储,对较大的值有很高的舍入误差。无法直接判断相等。
- 银行业务中数据应该使用BigDeceimal来表示钱,防止舍入误差的影响。
字符和数值类型可以相互转换
- 所有字符类型可以强制转换为数字, 本质上也是一种数字。
- 默认使用unicode编码,占用两个字节。
char c = '\u0061'表示字母a。
布尔类型
1
2
3
4 boolean flag = true;
if(flag == true){}
if(flag){}
//代码精简
整数类型
0b二进制
0八进制
0十六进制
引用类型
由基本数据类型按照某种方式组合出来的类型。
- 类(随机组合变量和方法)
- 接口(随机组合方法)
- 数组(顺序排列的变量)
包装类型
基本类型都有对应的包装类型,基本类型与其对应的包装类型之间的赋值使用自动装箱与拆箱完成。包装类型是基本类型对应的引用类型。
- byte,Byte
- short,Short
- int,Integer
- long,Long
- float,Float
- double,Double,
- char,Char
- boolean,Boolean
1 | Integer x = 2; // 装箱 调用了 Integer.valueOf(2) |
字面值和转义字符
- 不同进制的整数
1 | int i=10;//十进制 |
- 不同编码的字符串
1 | "这是一个字符串"//字符串的字面值 |
- 不同的转移字符
1 | \t 制表位 |
3 基本类型转换
转换规则
运算中不同类型的数据首先转换为同一类型然后进行运算。
- 默认转换规则
1 | byte/short/char->int->long->float->double |
- 自动类型转换,隐式类型转换,由低到高会自动进行类型转换
- 强制类型转换,从高到低需要进行强制类型转换
注意事项
- 不能对布尔值进行转换
- 不能把对象转换为不相关的类型
- 转换的时候会存在内存溢出或者精度问题
float 与 double
Java 不能隐式执行向下转型,因为这会使得精度降低。
1.1 字面量属于 double 类型,不能直接将 1.1 直接赋值给 float 变量,因为这是向下转型。
1 | // float f = 1.1; |
1.1f 字面量才是 float 类型。
1 | float f = 1.1f; |
隐式类型转换
因为字面量 1 是 int 类型,它比 short 类型精度要高,因此不能隐式地将 int 类型向下转型为 short 类型。
1 | short s1 = 1; |
但是使用 += 或者 ++ 运算符会执行隐式类型转换。
1 | s1 += 1; |
上面的语句相当于将 s1 + 1 的计算结果进行了向下转型:
1 | s1 = (short) (s1 + 1); |
显示类型转换
StackOverflow : Why don’t Java’s +=, -=, *=, /= compound assignment operators require casting?
4 变量常量
变量
可以变化的量。
- Java是一种强类型语言,每个变量都必须声明其类型。
- Java变量是程序中最基本的存储单元,其元素包括变量名,变量类型和作用域。
1 | 数据类型 变量名 = 变量值; |
不建议在一行中定义多个值。提高程序的可读性。
变量作用域
- 类变量,static修饰的变量
- 实例变量,从属于对象的变量
- 局部变量,方法中的变量
1 | public class Variable{ |
变量的范围是程序中该变量可以被引用的部分。
- 方法内定义的变量被称为局部变量。局部变量的作用范围从声明开始,直到包含它的块结束。
- 局部变量必须声明才可以使用。
- 方法的参数范围涵盖整个方法。参数实际上是一个局部变量。
- for循环的初始化部分声明的变量,其作用范围在整个循环。循环体内声明的变量其适用范围是从它声明到循环体结束。它包含如下所示的变量声明:
变量初始化
实例变量初始化规则
- 如果没有初始化函数默认初始化Wie0
- 布尔值默认是false
- 引用变量的默认初始值都是null
常量
- 初始化后不能改变的值。
- 特殊的变量,值被设定后不能进行改变。
- 使用final声明常量。
变量的命名规则
- 见名知意
- 类成员变量、局部变量,首字母小写驼峰命名helloWrold
- 常量,大写字母+下划线HELLO_WORLD
- 类名,HelloWorld
- 方法名,首字母小写+驼峰命名 helloWorld()
5 运算符
算术运算符
| 操作符 | 描述 | 例子 |
|---|---|---|
| + | 加法-相加运算符两侧的值 | A+B等于30 |
| - | 减法-左操作数减去右操作数 | A–B等于-10 |
| * | 乘法-相乘操作符两侧的值 | A*B等于200 |
| / | 除法-左操作数除以右操作数 | B/A等于2 |
| % | 取余-左操作数除以右操作数的余数 | B%A等于0 |
| ++ | 自增:操作数的值增加1 | B++或++B等于21(区别详见下文) |
| – | 自减:操作数的值减少1 | B–或–B等于19(区别详见下文) |
- 前缀自增自减法(++a,–a): 先进行自增或者自减运算,再进行表达式运算。
- 后缀自增自减法(a++,a–): 先进行表达式运算,再进行自增或者自减运算
关系运算符
| 运算符 | 描述 | 例子 |
|---|---|---|
| == | 检查如果两个操作数的值是否相等,如果相等则条件为真。 | (A == B)为假。 |
| != | 检查如果两个操作数的值是否相等,如果值不相等则条件为真。 | (A != B) 为真。 |
| > | 检查左操作数的值是否大于右操作数的值,如果是那么条件为真。 | (A> B)为假。 |
| < | 检查左操作数的值是否小于右操作数的值,如果是那么条件为真。 | (A <B)为真。 |
| >= | 检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。 | (A> = B)为假。 |
| <= | 检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。 | (A <= B)为真。 |
- 基本类型的值可以直接使用关系运算符判断大小和相等。
- 引用类型(类的对象、类的实例)的变量,需要通过重写equals方法来判断两个变量是否相等。引用类型的等于判断,是判断两个对象的地址是否相等。
位运算符
Java定义了位运算符,应用于整数类型(int),长整型(long),短整型(short),字符型(char),和字节型(byte)等类型。
| 操作符 | 描述 | 例子 |
|---|---|---|
| & | 如果相对应位都是1,则结果为1,否则为0 | (A&B),得到12,即0000 1100 |
| | | 如果相对应位都是 0,则结果为 0,否则为 1 | (A | B)得到61,即 0011 1101 |
| ^ | 如果相对应位值相同,则结果为0,否则为1 | (A ^ B)得到49,即 0011 0001 |
| 〜 | 按位取反运算符翻转操作数的每一位,即0变成1,1变成0。 | (〜A)得到-61,即1100 0011 |
| << | 按位左移运算符。左操作数按位左移右操作数指定的位数。 | A << 2得到240,即 1111 0000 |
| >> | 按位右移运算符。左操作数按位右移右操作数指定的位数。 | A >> 2得到15即 1111 |
| >>> | 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。 | A>>>2得到15即0000 1111 |
- 运算效率极高,可以用来实现高级的乘法、加法和指数运算。
逻辑运算符
| 操作符 | 描述 | 例子 |
|---|---|---|
| && | 称为逻辑与运算符。当且仅当两个操作数都为真,条件才为真。 | (A&&B)为假。 |
|| |
称为逻辑或操作符。如果任何两个操作数任何一个为真,条件为真。 | (A||B)为真。 |
| ! | 称为逻辑非运算符。用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算符将得到false。 | !(A&&B)为真。 |
- 短路运算。当使用与逻辑运算符时,在两个操作数都为true时,结果才为true,但是当得到第一个操作为false时,其结果就必定是false,这时候就不会再判断第二个操作了。
赋值运算符
| 操作符 | 描述 | 例子 |
|---|---|---|
| = | 简单的赋值运算符,将右操作数的值赋给左侧操作数 | C = A + B将把A + B得到的值赋给C |
| + = | 加和赋值操作符,它把左操作数和右操作数相加赋值给左操作数 | C + = A等价于C = C + A |
| - = | 减和赋值操作符,它把左操作数和右操作数相减赋值给左操作数 | C - = A等价于C = C - A |
| * = | 乘和赋值操作符,它把左操作数和右操作数相乘赋值给左操作数 | C * = A等价于C = C * A |
| / = | 除和赋值操作符,它把左操作数和右操作数相除赋值给左操作数 | C / = A,C 与 A 同类型时等价于 C = C / A |
| (%)= | 取模和赋值操作符,它把左操作数和右操作数取模后赋值给左操作数 | C%= A等价于C = C%A |
| << = | 左移位赋值运算符 | C << = 2等价于C = C << 2 |
| >> = | 右移位赋值运算符 | C >> = 2等价于C = C >> 2 |
| &= | 按位与赋值运算符 | C&= 2等价于C = C&2 |
| ^ = | 按位异或赋值操作符 | C ^ = 2等价于C = C ^ 2 |
| = | 按位或赋值操作符 |
1 |
|
条件运算符(?:)
条件运算符也被称为三元运算符。该运算符有3个操作数,并且需要判断布尔表达式的值。该运算符的主要是决定哪个值应该赋值给变量。
instanceof 运算符
该运算符用于操作对象实例,检查该对象是否是一个特定类型(类类型或接口类型)。
运算符优先级
| 类别 | 操作符 | 关联性 |
|---|---|---|
| 后缀 | () [] . (点操作符) | 左到右 |
| 一元 | expr++ expr– | 从左到右 |
| 一元 | ++expr –expr + - ~ ! | 从右到左 |
| 乘性 | * /% | 左到右 |
| 加性 | + - | 左到右 |
| 移位 | >> >>> << | 左到右 |
| 关系 | > >= < <= | 左到右 |
| 相等 | == != | 左到右 |
| 按位与 | & | 左到右 |
| 按位异或 | ^ | 左到右 |
| 按位或 | ` | ` |
| 逻辑与 | && | 左到右 |
| 逻辑或 | ` | |
| 条件 | ?: | 从右到左 |
| 赋值 | = + = - = * = / =%= >> = << =&= ^ = | = |
| 逗号 | , | 左到右 |
6 包机制和JavaDoc
包机制
- 包是一种文件夹。利用公司域名倒置作为包名package
- 包是默认的作用域。当前类会自动导入当前包作用域中的类和变量。
- 通过导入包中的类,可以使用其他包中的类。import
JavaDoc
1 | /** |









