1.第一章(java入门)
1.1Java起源
Java的历史是一个跨越数十年的历程,充满了技术的创新和变革。
起源
Java语言的起源可以追溯到1990年代初,当时任职于太阳微系统(Sun Microsystems)的詹姆斯·高斯林(James Gosling)等人开始开发Java语言的雏形。最初,这种语言被命名为Oak,旨在成为家用电器等小型系统的编程语言,应用于电视机、电话、闹钟、烤面包机等家用电器的控制和通信。然而,随着1990年代互联网的发展,Sun公司看到了Oak在互联网上应用的前景,于是决定对其进行改造,并于1995年5月以Java的名称正式发布。
早期演进
在Java的早期阶段,其设计目标主要是开发一种独立于平台的软件技术。然而,在网络出现之前,Java(当时还被称为Oak)并未引起太多关注。然而,当Sun公司在1995年正式以Java这个名字推出时,它迅速吸引了大量WEB开发人员的关注,他们普遍认为Java正是他们所需要的编程语言。
版本发布与特性增强
1996年1月23日,Java发布了第一个版本——Java 1.0以及对应的JDK 1.0。然而,这个版本并不能直接用于开发。直到1997年2月18日,Java发布了新的JDK版本——Java 1.0和Jdk 1.1,这个版本已经可以用于开发,并引入了JIT(即时编译器)等关键特性。
随后的几年里,Java不断发布新版本,并增加了一系列重要特性。例如,1998年的Java 1.2版本增加了集合框架、Swing用户界面组件和JDBC等特性,使得Java开始逐渐应用于企业级应用开发。2000年的Java 1.3版本则进一步增加了Java Platform Debugger Architecture(JPDA)和Java Naming and Directory Interface(JNDI)等特性,提高了开发者的开发效率。
开源与社区发展
2006年,Sun Microsystems公司发布了Java的一部分源代码,标志着Java开始走向开源。这一举措极大地促进了Java社区的发展,吸引了更多的开发者和企业参与到Java的开发和应用中来。开源也加速了Java的创新步伐,使得Java能够在更广泛的领域得到应用。
现代Java
如今,Java已经成为全球最流行的编程语言之一,广泛应用于各种领域,包括企业级应用开发、移动应用开发、大数据分析等。Java的生态系统也日益完善,包括各种框架、库和工具,使得开发者能够更高效地构建高质量的应用程序。
1.2JDK、JRE 、JVM是什么
JDK、JRE和JVM是Java技术体系中的三个核心组成部分,它们各自具有不同的功能和角色,同时又相互关联、相互依赖。
1.2.1JDK
JDK(Java Development Kit)是Java开发工具包,它包含了Java编程所需的全部工具,如编译器、调试器等。JDK的主要作用是为Java开发者提供一个完整的开发环境,使得开发者能够编写、编译和测试Java程序。简单来说,JDK是开发Java程序时所使用的工具集合。
1.2.2JRE
JRE(Java Runtime Environment)是Java运行环境,它包含了运行Java程序所必须的基本类库和Java虚拟机(JVM)。JRE的主要作用是提供一个平台,使得Java程序能够在这个平台上运行。也就是说,当Java程序被编译成字节码后,JRE会负责解释这些字节码,并在JVM上执行。
1.2.3JVM
JVM(Java Virtual Machine)是Java虚拟机,它是Java程序的运行环境。JVM的主要作用是模拟出一个计算机,这个计算机拥有完善的硬件架构,包括处理器、堆栈、寄存器等,并具有相应的指令系统。当Java程序在JRE上运行时,实际上是JVM在负责解释执行这些程序。JVM的存在使得Java程序具有“一次编写,到处运行”的特性,因为JVM可以在不同的操作系统和硬件平台上模拟出相同的计算机环境,从而确保Java程序的跨平台性。
三者之间的关系可以这样理解:JDK包含了JRE,而JRE又包含了JVM。JDK提供了完整的Java开发环境,包括JRE和其他的开发工具;JRE提供了运行Java程序所必需的环境,包括JVM和一些基本的类库;而JVM则是实际执行Java程序的核心组件。三者共同构成了Java技术的完整体系,使得Java程序能够编写、编译、运行和跨平台移植。
1.3 JShell
JShell交互式编程环境是Java 9中引入的一个功能强大的工具,它提供了一个“读取-执行-打印”循环(REPL)的交互式编程体验。在这种编程环境中,用户每输入一行代码,环境都会立即给出反馈,使得代码的开发、测试和调试过程变得更为便捷和高效。
JShell的主要特点包括:
- 即时反馈:用户输入的每个代码段(被称为片段)都能在输入的同时执行,并立即显示与代码相关的结果。这种即时反馈机制使得用户能够快速地验证代码的正确性,而无需进行传统的“编辑-编译-运行-调试”的循环。
- 状态保留:JShell会存储状态信息,因此可以在JShell中输入多行代码段,并运行它们。这对于需要构建多步骤计算或逐步开发功能的场景非常有用。
- 变量声明与自动类型推断:在JShell中,用户可以使用var关键字声明变量,而无需指定变量的类型。JShell会根据上下文自动推断变量的类型,从而简化了编程过程。
- 外部类导入与使用:JShell支持导入和使用外部的Java类,这使得用户能够利用现有的Java库和框架来扩展其功能。
2.第二章(数据类型与运算符)
2.1 Java的数据类型
整型
整型用于表示整数,根据存储大小和表示范围的不同,Java提供了四种整型:
byte
:字节型,占1个字节,取值范围是-128到127。short
:短整型,占2个字节,取值范围是-32768到32767。int
:整型,占4个字节,取值范围是-2^31到2^31-1。long
:长整型,占8个字节,取值范围是-2^63到2^63-1。对于长整型,数值后面通常需要加上字母L
,如123L
,以示区分。浮点型
浮点型用于表示带有小数点的数值,Java提供了两种浮点型:
float
:单精度浮点型,占4个字节。对于单精度浮点数,数值后面通常需要加上字母F
或者f
,如123.45F
。double
:双精度浮点型,占8个字节。双精度浮点数可以表示更大范围和更精确的数值,如果不指定F
或f
,则默认数值为双精度类型。字符型
字符型用于表示单个字符,Java中的字符型是
char
,占2个字节。字符型可以表示字母、数字、标点符号等Unicode字符集中的任意字符。例如,'A'
、'0'
和'$'
都是有效的字符型值。字符型值通常使用单引号括起来。布尔型
布尔型用于表示逻辑值,即真或假。Java中的布尔型是
boolean
,只有两个取值:true
和false
。布尔型常用于条件判断和逻辑运算。
2.2 标识符、变量、关键字规则
标识符
标识符是用来给变量、类、方法以及其它用户自定义的类型命名的符号。在Java中,标识符必须遵守以下规则:
- 字母和数字:标识符可以由字母、数字、美元符号($)和下划线(_)组成。
- 不能以数字开头:标识符的第一个字符不能是数字。
- 区分大小写:Java是区分大小写的,因此
myVar
和myvar
是两个不同的标识符。- 不能使用Java关键字:标识符不能与Java的保留关键字冲突。
- 长度限制:理论上,Java标识符没有长度限制,但在实际使用中,过长的标识符可能会降低代码的可读性。
变量
变量是存储数据的容器,它有一个名称(即标识符)和一个类型,用于存储特定类型的值。变量的声明语法如下:
dataType variableName;
其中,
dataType
是变量的数据类型(如int
、double
、String
等),variableName
是变量的标识符。声明变量后,可以使用赋值语句给变量分配一个值:variableName = value;
例如:
int age = 25; String name = "John";
关键字
关键字是Java编程语言中预定义的、具有特殊意义的单词。它们用于定义程序的结构和控制流程。Java关键字不能用作变量名、方法名或类名。常见的Java关键字包括:
- 数据类型关键字:
int
、double
、char
、boolean
等。- 控制流程关键字:
if
、else
、switch
、for
、while
等。- 访问修饰符关键字:
public
、private
、protected
等。- 其他关键字:
class
、this
、super
、static
、final
等。由于关键字是Java语言的核心组成部分,因此必须牢记它们,以避免在编程时误用或误写。
2.3 字符串和字面符
在Java中,字符串和字面符是两个经常一起出现的概念,但它们之间有一些重要的区别。
字面符 (Literals)
字面符是源代码中直接给出的值。Java支持多种类型的字面符,包括整数字面符、浮点字面符、字符字面符和字符串字面符等。
字符串字面符
字符串字面符是源代码中双引号("")括起来的字符序列。
例如:
String greeting = "Hello, World!";
在这个例子中,
"Hello, World!"
就是一个字符串字面符。字符串 (String)
字符串是Java中的一个类,位于
java.lang
包中。字符串对象可以表示文本信息,并且可以执行许多操作,比如连接、搜索、替换等。字符串对象通常是通过字符串字面符创建的,但也可以通过
String
类的构造方法或其他方式创建。字符串与字面符的关系
当你使用字符串字面符时,Java会在字符串常量池中查找是否已经存在该字符串的实例。如果存在,则返回对该实例的引用;如果不存在,则在常量池中创建一个新的字符串实例,并返回对该实例的引用。
这意味着,对于相同的字符串字面符,Java会尽可能地重用相同的字符串对象,以避免不必要的内存占用。
例如:
String s1 = "hello"; String s2 = "hello"; System.out.println(s1 == s2); // 输出 true,因为s1和s2引用的是同一个字符串对象
然而,如果你使用
new
关键字来创建字符串对象,那么每次都会创建一个新的对象,即使字符串的内容相同。String s3 = new String("hello"); System.out.println(s1 == s3); // 输出 false,因为s1和s3引用的是不同的字符串对象 System.out.println(s1.equals(s3)); // 输出 true,因为s1和s3的内容相同
在这个例子中,
s1
和s3
虽然内容相同,但它们是两个不同的对象,因此==
比较返回false
。而equals()
方法比较的是字符串的内容,所以返回true
。
2.4数据类型转换
Java数据类型转换主要包括两种:自动类型转换(也称为隐式类型转换)和强制类型转换(也称为显式类型转换)。
自动类型转换
自动类型转换发生在两种类型兼容,并且目标类型范围大于源类型范围时。例如,当你将一个小的数据类型(如
byte
、short
、char
)赋值给一个大的数据类型(如int
、long
、float
、double
)时,就会发生自动类型转换。byte b = 10; int i = b; // 自动类型转换,从 byte 到 int
同样地,当你将一个
int
类型的值赋给一个double
类型的变量时,也会发生自动类型转换。int a = 123; double d = a; // 自动类型转换,从 int 到 double
强制类型转换
当源数据类型范围大于目标数据类型范围时,需要显式地告诉编译器你想要进行类型转换,这通常被称为强制类型转换或显式类型转换。这可能会导致数据丢失或精度下降,因此在使用时需要特别小心。
double d = 123.456; int i = (int) d; // 强制类型转换,从 double 到 int,丢失小数部分
在上面的例子中,
d
是一个double
类型的变量,其值为123.456
。当我们尝试将其赋值给一个int
类型的变量i
时,由于int
类型无法存储小数部分,因此需要显式地进行类型转换。这里使用(int)
来指示编译器进行强制类型转换。转换后,i
的值将为123
,小数部分被丢弃。注意事项
- 布尔类型
boolean
不能与其他任何数据类型进行转换。- 字符类型
char
可以参与数值运算,也可以与整型进行转换。- 在进行强制类型转换时,应确保转换是安全的,并且了解可能发生的数据丢失或精度下降。
- 在进行涉及浮点数的计算时,由于浮点数的精度问题,结果可能并不总是精确的。因此,在需要精确计算的情况下,应考虑使用
BigDecimal
类。示例
下面是一个包含多种数据类型转换的示例:
public class DataTypeConversion { public static void main(String[] args) { byte b = 10; short s = 20; char c = 'a'; int i = 30; long l = 40L; float f = 50.5f; double d = 60.6; // 自动类型转换示例 long l2 = i; // int 到 long float f2 = d; // double 到 float int i2 = c; // char 到 int(字符的ASCII码值) // 强制类型转换示例 byte b2 = (byte) i; // int 到 byte,可能数据丢失 int i3 = (int) d; // double 到 int,小数部分被丢弃 short s2 = (short) l; // long 到 short,可能数据丢失 System.out.println("b2: " + b2); System.out.println("i3: " + i3); System.out.println("s2: " + s2); } }