目录
Java语言发展状况
版本 | 年份 | 语言新特性 | 类与接口数量 |
---|---|---|---|
1.0 | 1996 | 语言本身 | 211 |
1.1 | 1997 | 内部类 | 477 |
1.2 | 1998 | strictfp 修饰符 | 1524 |
1.3 | 2000 | 无 | 1840 |
1.4 | 2002 | 正则表达式,异常链,NIO,日志类,XML解析器,XLST转换器 | 2723 |
5.0 | 2004 | 动态注解、泛型、“ for each” 循环、 可变元参数、 自动装箱、元数据、 枚举、 静态导入 | 3279 |
6 | 2006 | 提供动态语言支持、提供编译API和卫星HTTP服务器API,改进JVM的锁,同步垃圾回收,类加载 | 3793 |
7 | 2011 | 基于字符串的 switch、 钻石操作符、 二进制字面量、异常处理改进、提供GI收集器、加强对非Java语言的调用支持(JSR-292,升级类加载架构) | 4024 |
8 | 2014 | Lambda 表达式、方法引用、默认方法、新工具、Stream API、Date Time API 、Optional 类、Nashorn, JavaScript 引擎 | 4240 |
… |
Java简介
Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言。
2009年,Sun 公司被 Oracle (甲骨文)公司收购,Java 也随之成为 Oracle 公司的产品。
Java语言的特点
- 简单性
- 面向对象
- 分布式
- 健壮性
- 安全性
- 体系结构中立
- 可移植性
- 解释型
- 高性能
- 多线程
- 动态性
JRE和JDK
JRE(Java Runtime Environment),Java运行环境;
包含JVM标准实现及Java核心类库,不包含任何开发工具(如编译器和调试器)。
JDK(Java SE Development Kit),Java开发工具包;
JDK包含了JRE,同时还包含了编译java源码的编译器javac,还包含了很多java程序调试和分析的工具。
JVM(Java Virtual Machine),Java虚拟机;
Java运行时的环境,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。调用Java命令运行java程序时,该命令会启动一个Java虚拟机进程,不管该程序多么负责,启动了多少个线程,它们都处于该Java虚拟机进程里。
JDK目录介绍:
bin: 最主要的是编译器(javac.exe)
include: java和JVM交互用的头文件
lib:类库
jre: java运行环境
src.zip 文件中包含了所有公共类库的源代码。
Java数据类型和运算符
Java标识符
标识符就是用于给程序中变量,方法,类命名的符号。Java语言的标识符必须是以 字母、下画线(_)、美元符 开头,后面可以跟任意数目的字母、数字、下画线(_)和美元符。此处的字母并不限于26个英文字母,而且可以包含中文字符、日文字符等。
Java语言是区分大小写的。 因此abc和ABC是两个不同的标识符。
使用时,注意以下规则:
- 标识符可以由字母、数字、下画线(_)和美元符组成,其中数字不能开头。
- 标识符不能是Java关键字和保留字,但可以包含关键字和保留字。
- 标识符不能包含空格。
- 标识符只能包含美元符号,不能包含@,#等其他特殊符号。
Java关键字
Java语言中有一些具有特殊用途的单词被称为关键字(keyword)。当定义标识符时,不要让标识符和关键字相同,否则会引起错误。
Java的所有关键字都是小写。TRUE,FALSE和NULL 都不是java关键字。
Java中一共包含50个关键字。
分类 | 关键字 | 个数 |
---|---|---|
访问控制 | private, default, protected, public | 4个 |
类,方法,变量控制符 | new, class, abstract, implements, extends, interface, final, static, native, strictfp, volatile, synchronized, transient | 13个 |
程序控制 | break, continue, return, do, while, if, else, for, instanceof, switch, case , default | 12个 |
错误处理 | try, catch, throw, throws, finally | 5个 |
包相关 | import, package | 2个 |
基本类型 | byte, short, int, long, char, float, double, boolean | 8个 |
变量引用 | super, this, void | 3个 |
保留字 | goto, const (Java还未使用这两个关键字) | 2个 |
Java 5新增 | enum | 1个 |
Java数据类型分类
Java语言是强类型(strongly typed)语言,强类型包含两个方面的含义:
- 所有变量必须先声明,后使用
- 指定类型的变量只能接受类型与之匹配的值。(这意味着,每个变量和每个表达式都有一个在编译时就确定的类型)
Java语言支持的类型分为两类: 基本类型(Primitive Type)和 引用类型(Reference Type)
8种基本类型 ( primitive type )
在 Java 中,一共有 8种基本类型 ( primitive type ) :
- 4种整数类型(byte, short, int, long)
整型用于表示没有小数部分的数值, 它允许是负数。在 Java 中, 整型的范围与运行 Java 代码的机器无关。长整型数值有一个后缀L 或 l
。 - 2种浮点类型(float, double)
Java的浮点类型有固定的表数范围和字段长度,与机器无关。
浮点类型用于表示有小数部分的数值。float 类型的数值有一个后缀F 或 f
(例如, 3.14F)。没有后缀 F 的浮点数值(如 3.14 ) 默认为 double 类型。当然,也可以在浮点数值后面添加后缀D 或 d
。 - 1 种用于表示 Unicode 编码的字符单元的字符类型 char
表示单个的字符,字符型值必须使用单引号(')括起来。
Java语言使用16位的Unicode的字符集作为编码格式,而Unicode被设计成支持世界上所有书面语言的字符,包括中文字符,因此Java程序支持各种语言的字符。 - 1 种用于表示真值的 boolean 类型。
在基本JAVA类型中,如果不明确指定,整数型的默认是int类型,带小数的默认是double类型。
例如,当定义32位的二进制整数时,最高位就是符号位,当符号位是1时,只表明它是一个负数。
尽管他们的默认值看起来不一样,但在内存中都是 0。
包装类在下面有介绍。
引用类型
包括: 类, 接口和数组类型,还有一种特殊的null类型。 所谓引用数据类型就是对一个对象的引用。对象包括实例和数组两种。实际上引用类型就是一个指针(java语言中不再使用指针这个说法)。
空类型(null type)就是null值的类型,这种类型没有名称。因为null类型没有名称,所以不可能声明一个null类型的变量或者转换到null类型。
空引用(null)是null类型变量唯一的值。空引用(null)可以转换为任何引用类型。不能转换成基本类型,因此不要把一个null值赋给基本数据类型的变量。
变量和常量
变量:
声明一个变量之后,必须用赋值语句对变量进行显式初始化, 千万不要使用未初始化的变量。例如, Java 编译器认为下面的语句序列是错误的:
int a;
System.out.println(a);
常量:
在 Java 中,经常希望某个常量可以在一个类中的多个方法中使用,通常将这些常量称为类常量。可以使用关键字 static final设置一个类常量,常量名使用全大写。
Java基本类型的类型转换
自动类型转换
当把一个表数范围较小的数值或变量直接赋值给另一个表数范围的大的变量时,系统会进行自动转换。
强制类型转化
与自动类型转换相反。
强制类型转换的语法格式是:(targetType)value,强制类型转换的运算符是圆括号()。
在圆括号中给出想要转换的目标类型,后面紧跟待转换的变量名。
double b = 9.997;
int c = (int) b;
System.out.println(c);
// 强制类型转换通过截断小数部分将浮点值转换为整型
// 9
// 如果想对浮点数进行舍人运算, 以便得到最接近的整数(在很多情况下, 这种操作更有用,) 那就需要使用 Math.round 方法
int d = (int) Math.round(b);
System.out.println(d);
// 10
表达式类型的自动提升
当一个算术表达式包含多个基本类型的值时,整个算术表达式的数据类型将会自动提升:
- 所有的byte类型、short类型和char类型将被提升到int类型
- 整个算术表达式的数据类型自动提升到与表达式中最高等级操作数同样的类型。具体看上面自动类型转换的图。
运算符
Java 语言中的运算符可分为如下几种:
- 算术运算符
- 赋值运算符
- 比较运算符
- 逻辑运算符
- 位运算符
- 类型相关运算符
算术运算符
分别有:+、-、*、/、%、++、-- 等。
注意,自加和自减只能用于操作变量。
自加
++: 自加。
要点:
- 自加是单目运算符,只能操作一个操作数
- 自加运算符,只能操作单个数值型(整型、浮点型都行)的变量,不能操作变量或表达式
详细解释:
count++是一个表达式,是有返回值的,它的返回值就是count自加前的值,Java对自加是这样处理的:首先把count的值(注意是值,不是引用)拷贝到一个临时变量区,然后对count变量加1,最后返回临时变量区的值。
运算符可以出现在操作数的左边或者右边,效果不同。
- 如果把++放在左边,则先把操作数加1,然后才把操作数放入表达式中运算
- 如果把++放在右边,则先把操作数放入表达式中运算,然后才把操作数加1
Java中for循环的i++和++i区别
++i是先执行 i = i +1 再使用 i 的值;
而 i++ 是先使用 i 的值再执行 i = i + 1;
语法格式:
for(a; b; c){
d;
}
for循环的执行顺序如下:
1. 进入循环执行a;只是进入的时候执行
2. 执行b; //条件为真才执行d,不然跳出for了
3. 执行d;
4. 执行c;
5. 再回到第2步开始执行
来看下面的实例:
for(int i = 0; i < 10;i++){
System.out.println(i);
}
相当于:
for(int i = 0; i < 10;){
System.out.println(i);
i++;
}
或者
for(int i = 0; i<10; ++i){
System.out.println(i);
}
相当于:
for(int i =0; i < 10;){
System.out.println(i);
++i;
}
打印出来的信息是:
打印信息证明了,在循环体中,i++和++i的作用是一样的。
但是肯定有一定区别的,所以把循环耗时也打印出来了。
/**
* 对比性能
*/
public static void perf() {
long start1 = System.nanoTime();
for (int i = 0; i < 10000; i++) {
if (i == 9999) {
System.out.println(i);
}
}
long end1 = System.nanoTime();
System.out.println("i++执行耗时:" + (end1 - start1));
long start2 = System.nanoTime();
for (int i = 0; i < 10000; ++i) {
if (i == 9999) {
System.out.println(i);
}
}
long end2 = System.nanoTime();
System.out.println("++i执行耗时:" + (end2 - start2));
}
输出:
9999
i++执行耗时:297393
9999
++i执行耗时:157018
可以看出,就是运行时间的差别。
在Java中i++语句是需要一个临时变量取存储返回自增前的值,而++i不需要。这样就导致使用i++时系统需要先申请一段内存空间,然后将值塞如进去,最后不用了才去释放。多了这么一系列操作时间。
所以要仔细理解这句话:++i是先执行 i = i +1 再使用 i 的值,而 i++ 是先使用 i 的值再执行 i = i + 1;
自减
也是单目运算符,用法和自加基本相似,只是将操作数的值减1。
赋值运算符
用=作为赋值运算符
比较运算符
分别有:>、>=、<、<=、== 等
逻辑运算符
分别有:&&、&、||、|、!、^ 等
^: 异或。当两个操作数不同时才返回true,如果两个操作数相同则返回false。
位运算符
分别有:&、|、~、<<、>>、>>>、^ 等
符号 | 作用 |
---|---|
& | 按位与。当两位同时为1时才返回1 |
| | 按位或。只要有一位为1时即可返回1 |
~ | 按位非。单目运算符,将操作数的每个位(包括符号位)全部取反 |
^ | 按位异或,当两位相同时返回0,不同时返回1 |
<< | 左移运算符 |
>> | 右移运算符 |
>>> | 无符号右移运算符 |
流程控制与数组
switch分支语句
switch语句由一个控制表达式和多个case标签组成,switch语句后面的控制表达式的数据类型只能是:
- byte、short、char、int四种基本类型
- 枚举类型
- java.lang.String类型 (从Java7才允许)
不能是boolean类型。
语法格式如下:
switch (expression)
{
case condition1:
{
statement(s);
break;
}
case condition2: