Java语言基础总结
- Java的创建
- Java 的创立者
Java 语言主要由詹姆斯・高斯林(James Gosling)主导开发,他被称为 Java 之父,核心开发团队还有 Mike Sheridan 与 Patrick Naughton,团队隶属于 Sun Microsystems(太阳微系统公司)。
- Java 的由来
1991 年,Sun 公司启动了 Green 项目。项目最初目标是开发一套可以运行在机顶盒、各类智能家电等消费电子设备上的软件系统。当时 C、C++ 语言和硬件平台绑定紧密,嵌入式设备芯片种类繁多,代码移植十分困难,所以高斯林团队计划设计一种能够跨硬件平台运行的编程语言。项目最初设计出来的语言命名为 Oak,中文译为橡树,名字来源于高斯林办公室窗外的橡树。
等到项目准备注册商标的时候,团队发现 Oak 这个名称已经被其他公司注册,无法使用。团队经过讨论,选用 Java 作为新的语言名称,这个名字来源于印度尼西亚爪哇岛出产的咖啡,寓意像咖啡一样充满活力。
这个项目原本面向嵌入式家电市场,但市场推广并不顺利,项目一度停滞。90 年代中期互联网快速发展,团队发现 Java 天生具备跨平台的能力,十分适合互联网场景,于是开发了 Applet 网页小程序技术,可以把程序嵌入网页中运行,无论用户使用什么操作系统都可以访问。
1995 年 5 月 23 日,Sun 公司正式对外发布 Java 语言,提出了著名口号:一次编写,到处运行(Write Once, Run Anywhere)。Applet 技术让 Java 迅速在互联网领域走红。2009 年,甲骨文公司 Oracle 收购 Sun Microsystems,Java 的商标与相关版权归属甲骨文公司。现在除了官方 JDK 之外,还有开源版本 OpenJDK,也是 Java 主流的开源实现。Java 的语法参考了 C 语言和 C++,但并不是 C++ 的升级版本,开发团队主动去掉了 C++ 中复杂、容易出错的语法特性,重新完成语言设计。
- Java 的特点
- 简单性
Java 借鉴了 C++ 的基础语法,学习门槛相对友好,同时移除了 C++ 很多容易产生程序错误的复杂机制。Java 取消了指针,程序员无法直接操作内存地址,避免野指针、内存越界等问题;不支持类的多继承,改用接口来实现多继承的效果,降低类结构的复杂度。Java 拥有垃圾回收机制 GC,系统会自动回收不再使用对象占用的内存,程序员不需要手动申请和释放内存,减少内存相关 bug。同时保留了 C、C++ 熟悉的分支、循环、运算符等基础语法。
- 面向对象
Java 是一门纯面向对象的编程语言,具备面向对象三大核心特性:封装、继承、多态。封装是将类的属性和方法封装在一起,通过访问权限控制隐藏内部实现细节,只对外提供访问接口;继承可以让子类复用父类已经写好的代码,实现代码复用,Java 只支持单继承,一个类只能直接继承一个父类;多态指同一个方法调用,会根据对象实际类型执行对应的方法实现。Java 遵循一切皆对象的思想,除了 byte、short、int、long、float、double、char、boolean 这八种基本数据类型,其余全部都是对象;基本类型也配套有包装类,可以转换成对象。
- 跨平台(可移植性)
跨平台是 Java 最核心的特性,依靠 JVM 也就是 Java 虚拟机实现。Java 的源代码文件后缀为.java,通过 javac 编译器编译之后,会生成.class 后缀的字节码文件。字节码不属于操作系统原生的机器码,不能直接在操作系统上运行,需要交给 JVM 来解释执行。Windows、Linux、Mac 操作系统都有对应版本的 JVM。同一个.class 字节码文件,只要运行环境安装了对应系统的 JVM,就可以在该系统上运行,实现一次编写到处运行。需要注意,JVM 本身是和操作系统绑定的,并不跨平台,真正实现跨平台的是字节码。除此之外 Java 中基本数据类型占用内存大小是固定不变的,例如 int 永远占用 4 个字节,不像 C 语言会随操作系统变化,进一步增强代码可移植性。
- 健壮性(鲁棒性)
健壮性代表程序稳定性强,不容易崩溃。Java 属于强类型语言,变量定义时必须声明数据类型,编译阶段就会做类型校验,类型不匹配会直接编译失败。Java 取消指针,禁止程序员直接访问内存地址,避免非法内存访问。Java 提供 try-catch-finally 异常处理机制,当程序运行发生错误时,可以捕获并处理异常,防止程序直接退出崩溃。加上 GC 自动管理内存,减少人为内存操作引发的各类错误。
- 安全性
Java 最初设计面向网络环境,十分重视安全。字节码加载的时候,JVM 会对字节码进行校验,检查字节码是否存在非法指令或者被恶意篡改。早期 Java 提供安全管理器 SecurityManager,可以限制代码访问本地文件、网络等系统资源,也就是 Applet 沙箱机制。没有指针,程序无法随意篡改内存空间,防止恶意代码破坏本地计算机系统。虽然 Applet 技术现在已经被淘汰,但这套安全设计思想仍然保留。
- 多线程
Java 在语言层面原生支持多线程,不需要依赖操作系统或者第三方库。可以通过 Thread 类、Runnable 接口快速创建多个线程。同时内置 synchronized 同步机制,用来解决多线程并发运行时的数据竞争问题。借助多线程,程序可以同时执行多项任务,充分利用 CPU 多核性能,适合开发服务器、后端服务类程序。
- 分布式
Java 内置 Socket 等丰富的网络编程 API,方便开发网络相关应用。还支持 RMI 远程方法调用,可以直接调用远程计算机上对象的方法,天然适配分布式系统开发,很适合互联网后端程序开发。
- 高性能
早期 Java 采用纯解释方式执行,逐条解释字节码,运行速度比 C、C++ 慢。后续引入 JIT 即时编译器。程序运行时,JVM 会识别反复执行的热点代码,把热点字节码编译成当前操作系统对应的本地机器码并且缓存起来,后续再次执行这段代码时,直接运行机器码,大幅提升执行效率。现代版本 Java 的运行性能已经十分接近传统编译型语言。
- 开源与丰富生态
OpenJDK 作为 Java 的开源实现,可以免费使用。经过数十年发展,Java 拥有庞大完善的生态,存在大量成熟开源框架和中间件,例如 Spring、MyBatis、Maven 等,广泛应用于网站后端、大数据开发、安卓应用开发、各类中间件等众多领域。
- 基础知识
- 标识符与关键字
Java的标识符与C、C++相比,多了一个‘$’符号,称之为美元符号,然后其他是相同的,要由下划线、字母、数字组成,首字母不能以数字开头,且不能与关键字相同。
命名法有驼峰命名法和蛇形命名法等,驼峰就是后续每一个单词首字母都大写,蛇形命名法是在单词之间加上‘_’————下划线。
关键字有很多,例如:int、double、class、public、if等,他们有着自己的含义。
注释和C、C++相同,有‘//’单行注释,‘/**/’多行注释。
- 基本数据类型
基本数据类型有:整型、浮点型、字符型、布尔型和引用数据类型。
- 整型:
byte:字节型,1字节
short:短整型,2字节
int:整型,4字节
二进制:前缀为0b/0B;
八进制:前缀为0;
十六进制:前缀为0x/0X
long:长整型,8字节
它们的范围都是-(2n-1)~2n-1-1,n是类型的位
- 布尔型
boolean:1字节,值只有true和false
- 字符型
char:2字节,范围:0~65535;
它的范围是0~216-1-1
- 引用类型
string:字符串,默认值为null;
- 浮点型
float:单精度,4字节,需要在末尾加f/F
double:双精度,8字节,在末尾加d/D,可以省略
注意:高精度到低精度要强制转换,低精度到高精度是自动转换
例如:int X=(int)3.14
X的值就是3
它们的精度从低到高为:
byte short char int long float double
当这些类型转换成字符串时,可以前面加双引号空格,再加要转换的数据
例如:System.out.print(“”+100+200);
输出的结果就为:100200
- 输入与输出
输入:在最前面需要加入类包:import java.util.Scanner;
扩充:导入全部类包:import java.util.*;
其次写Scanner 变量名=new Scanner(System.in);
这样就创建了一个Scanner对象,用来接收键盘输入
然后变量名.next数据类型();
数据类型根据需要选择
注意:数据类型首字母要大写!
例如:double x=sc.nextDouble();
常用的还有next()用于都字符串,不读空格;nextLine()用于读取一整行,可以读取空格,只有回车作为结束标志
要读取字符串中的第n个元素用charAt(n-1);
例如:sc.next().char(n-1); 无空格字符串
sc.nextLine.char(n-1); 有空格字符串
输出用System.out.println() 有换行
System.out.print() 无换行
括号内字符串与其他数据一起输出用加号’+’拼接,变成字符串被输出
在eclipse里如果不想输入System.out.println();这么长的英文可以用快捷键
sysout+alt键+‘/’得到
- 数组
在Java中,数组声明与C、C++不同,它不在[]里面写数组的长度
例如:int[]a; 这个是标准写法,也可以写为int a[];
Int[][]a; 二维数组标准写法,也可以写为int a[][];
特殊的:int []a,b[]; 实际上时a[],b[][];
为数组分配元素个数:
例:int a[]=new int[个数]
和C、C++不同的一点是,Java数组可以用int变量的指定值
例:int size=10;
double a[]=new double[size]; 这样是正确的
还可以这样声明二位数组:
int [][]a=new int[3][] 后面的[]先不写,相当于现在知识一维数组
然后写 a[0]=new int[2];
a[1]=new int[3];
a[2]=new int[4];
这样分配了多个不同长度的二维数组
数组的初始化写法:
int []a=new int[]{0,1,2,3,···}数据前面的[]不能写值
int []a={0,1,2,3,···} 这是上面这个的简写
想获取数组的长度,可以用关键字length,数组名.length
注意:一维数组使用后是元素个数,二维数组使用后是列的个数,相当于只能获取一维长度
- 数组引用
数组属于引用型变量,因此两个相同类型的数组如果有相同的引用,他们会有完全相同的元素
例:int[]a={1,2,3};
Int[]b={4,5,6};
a=b;
则a的引用里面存的地址被b覆盖掉,用a相当于用b了
System.out.print(a); 相当于输出b
假设输出的是[I@def879
[:代表是数组
I:代表类型
@:分隔符
Def879:十六进制哈希码
之所以会这样,是因为数组引用变量它是存放在栈里的,然后数组实体是存放在堆里的,通过栈保存的地址在堆中找到数组,如果用上述的a=b就相当于把b在栈中存放的地址赋值给了a,导致使用a直接是引用到b身上了,而原来a失去引用,等待垃圾回收,虽然在数据还在堆内存中,但是已经不能访问了。
- 运算符
运算符有算数运算符、赋值运算符、关系运算符、逻辑运算符、位运算符、三目运算符(只有一个三目运算符:?)
- 算数运算符
+、-、*、/、%、++、--
注意:整数相处,小数部分会被舍弃
++称为自增,a++为后缀自增,先用a的原始值a在加1;++a是前缀自增,先把a的值加1再使用
--称为自减,同自增一样,a--,先使用再把a减1;--a先减1再使用
- 赋值运算符
=、+=、-=、*=、/=、%=
例:a+=2;等价于a=a+2;
- 关系运算符
>、<、>=、<=、==、!=
它们的结果一定是boolean类型:true或者false
注意:引用类型使用==,比较的是地址
- 逻辑运算符
&&、||、&、|、!
短路:
&&:两边都为真结果为真,如果左边为假,右边不会执行直接结束
||:两边都为假结果为假,如果左边为真,右边也不会执行直接结束
非短路:
&:无论左边是什么,两边都会执行
|:无论左边是什么,两边都会执行
如果两边是布尔值是逻辑运算,两边是数字,就是位运算
注意:用作判断的表达式可以为任意表达式
- 位运算
&、|、^、~、<<、>>
都是先转换为二进制,再做运算
&:都为1才为1
例:18&6=2;
|:只要有1就为1
例:18|6=22;
按位与按位或可以理解为1&1==1,0|0==0,方便记忆;
^:相异为1,相同为0
例:18^6=20;
~:先取反,结果再减1,再转换成原码,最后添加负号;
用公式:~X=-(X+1)
例:~18=-19;
这是转换后的原码
<<:高位丢掉,低位补0,左移几位就是乘2的几次方
例:60<<3=60*23
>>:正数高位补0,负数高位补1,右移几位就是除以2的几次方
例:60>>3=60/23
- 语句
- 顺序:代码从上到下,按书写的顺序依次执行
- 选择:根据条件判断,选择执行不同的代码块
形式有:if/if-else/switch
- 循环:满足条件时,重复执行一段代码
形式有for/while/do-while
与C、C++不同的是在Java中条件判断只能写布尔值true或者false,不能直接写数字
遍历数组时可以直接用for(声明变量:数组名)
优点:速度快
缺点:功能单一,只能访问
注意:声明必须在括号里面
任何复杂的结构都是顺序、选择、循环这三种基本结构组合而成的