第1阶段 JAVA开篇知识
JAVA初始
JAVA简史
- SUN公司 ,美国SUN(Stanford University Network)公司;
- 1991年,由Patrick Naughton 及其伙伴James Gosling带领的Sun公司的工程师小组想要设计一种小型的计算机语言,主要用于像有线电视转换盒这类的消费设备。这个项目被命名为 “Green”。
- 由于消费设备的处理能力和内存有限,所以语言必须非常小且能够生成非常紧凑的代码。另外,由于不同的厂商会选择不同的中央处理器(CPU),因此这种语言的关键是不能与任何特定的体系结构捆绑在一起。即,需要一种代码短小、紧凑且与平台无关的语言。
- Sun公司的人都有UNIX的应用背景。因此,所开发的语言以C++为基础。是Gosling率先创造了这个语言,把这种语言称为“Oak"(橡树)。后来发现Oak是一种已有的计算机语言的名字,于是,将其改名为Java。Java语言发展到今天经历了一系列的过程:
- 1991年,SUN公司的Green项目,Oak
- 1995年,推出Java测试版
- 1996年,JDK1.0
- 1997年,JDK1.1
- 1998年,JDK1.2,大大改进了早期版本缺陷,是一个革命性的版本,更名为Java2
- 2004年,J2SE 5.0 (1.5.0) Tiger老虎 成为Java语言发展史上的又一里程碑。为了表示该版本的重要性,J2SE1.5更名为Java SE 5.0
- 2005年,Java的各种版本已经更名,以取消其中的数字"2": J2ME更名为Java ME, J2SE更名为Java SE, J2EE更名为Java EE
- 2006年,JavaSE6.0 (1.6.0) Mustang野马
- 2009年,甲骨文(oracle)收购SUN,交易高达价格74亿
- 2011年,JavaSE7.0 Dolphin海豚
- 2014年,JavaSE8.0
- 2017年,JAVA 9.0
- 2018年9月,JAVA 11
- 2019年3月,JAVA 12
- 2019年9月,JAVA 13
- 2020年3月,JAVA 14
JAVA体系结构
- JavaSE(Java Standard Edition):标准版,定位在个人计算机上的应用这个版本是Java平台的核心,它提供了非常丰富的API来开发一般个人计算机上的应用程序,包括用户界面接口AWT及Swing,网络功能与国际化、图像处理能力以及输入输出支持等。
- JavaEE(Java Enterprise Edition):企业版,定位在服务器端的应用,JavaEE是JavaSE的扩展,增加了用于服务器开发的类库。如:JDBC是让程序员能直接在Java内使用的SQL的语法来访问数据库内的数据;Servlet能够延伸服务器的功能,通过请求-响应的模式来处理客户端的请求;JSP是一种可以将Java程序代码内嵌在网页内的技术。
- JavaME(Java Micro Edition):微型版,定位在消费性电子产品的应用上, JavaME是JavaSE的内伸,包含J2SE的一部分核心类,也有自己的扩展类,增加了适合微小装置的类库。该版本针对资源有限的电子消费产品的需求精简核心类库,并提供了模块化的架构让不同类型产品能够随时增加支持的能力。
JAVA的特性和优势
- 跨平台/可移植性
这是Java的核心优势。Java在设计时就很注重移植和跨平台性。比如:Java的int永远都是32位。不像C++可能是16,32,可能是根据编译器厂商规定的变化。这样的话程序的移植就会非常麻烦。 - 安全性 Java适合于网络/分布式环境,为了达到这个目标,在安全性方面投入了很大的精力,使Java可以很容易构建防病毒,防篡改的系统。
- 面向对象 面向对象是一种程序设计技术,非常适合大型软件的设计和开发。由于C++为了照顾大量C语言使用者而兼容了C,使得自身仅仅成为了带类的C语言,多少影响了其面向对象的彻底性!Java则是完全的面向对象语言。
- 简单性 Java就是C++语法的简化版,我们也可以将Java称之为“C+±”,指的就是将C++的一些内容去掉;比如:头文件,指针运算,结构,联合,操作符重载,虚基类等等。同时,由于语法基于C语言,因此学习起来完全不费力。
- 高性能 Java最初发展阶段,总是被人诟病“性能低”;客观上,高级语言运行效率总是低于低级语言的,这个无法避免。Java语言本身发展中通过虚拟机的优化提升了几十倍运行效率。比如,通过JIT(JUST IN TIME)即时编译技术提高运行效率。将一些“热点”字节码编译成本地机器码,并将结果缓存起来,在需要的时候重新调用。这样的话,使Java程序的执行效率大大提高,某些代码甚至接近C++的效率。
- 分布式 Java是为Internet的分布式环境设计的,因为它能够处理TCP/IP协议。事实上,通过URL访问一个网络资源和访问本地文件是一样简单的。Java还支持远程方法调用(RMI,Remote Method Invocation),使程序能够通过网络调用方法。
- 多线程 多线程的使用可以带来更好的交互响应和实时行为。 Java多线程的简单性是Java成为主流服务器端开发语言的主要原因之一。
- 健壮性 Java是一种健壮的语言,吸收了C/C++ 语言的优点,但去掉了其影响程序健壮性的部分(如:指针、内存的申请与释放等)。Java程序不可能造成计算机崩溃。即使Java程序也可能有错误。如果出现某种出乎意料之事,程序也不会崩溃,而是把该异常抛出,再通过异常处理机制加以处理。
核心机制
垃圾回收机制
- 不再使用的内存空间应回收—>垃圾收集;
- Java消除了程序员回收无用内存空间的职责;提供一种系统级线程跟踪存储空间的分配情况。在JVM的空闲时,检查并释放可被释放的存储器空间;相比c++,开发人员需要要自己收回无用内存。
- 垃圾收集在Java程序运行过程中自动进行,程序员无法精确控制和干预;
- GC的自动回收,提高了内存空间的利用效率,也提高了编程人员的效率,很大程度上减少了因为没有释放空间而导致的内存泄露。
JAVA的跨平台原理
JAVA的跨平台原理示意图
在程序执行时,表面上调用的是java.exe,实际上当调用java.exe时,会去动态调用JVM,所以真正起到执行作用的时JVM,JVM将字节码文件逐行解释成为当前操作系统认识的可执行文件的格式----->Java是一种“解释型”语言
C语言跨平台与Java语言跨平台的区别
- Java的字节码文件与平台无关,可以用这个字节码文件到不同平台上运行
- C语言不同的平台有不同的编译器,编译器与平台相关,编译后的可执行文件也与平台相关
- C语言的效率更高:因为C语言产生的可执行文件可以直接在平台上运行。而Java产生的字节码文件需要经过不同平台上对应的虚拟机执行/翻译后,才能在平台上运行。
- 通常说的语言跨平台是编译后的文件跨平台,而不是源程序跨平台。C语言是编译执行的,编译器与平台相关,编译生成的可执行文件与平台相关;Java是解释执行的,编译为字节码的编译器与平台无关,编译生成的字节码也与平台无关(一次编译,到处运行),字节码码再由解释器解释执行,解释器是与平台相关的,也就是不同的平台需要不同的解释器.
JVM
JVM(Java Virtual Machine)是一个虚拟的用于执行bytecode字节码的”虚拟计算机”。它也定义了指令集、寄存器集、结构栈、垃圾收集堆、内存区域。JVM负责将Java字节码解释运行,边解释边运行,这样,速度就会受到一定的影响。
常用DOS命令
- DOS操作系统
DOS(Disk Operating System)的中文含义是磁盘操作系统。是单用户、单任务的操作系统(一次执行一个任务)。
是由Microsoft公司推出的操作系统,是在Windows之前的操作系统 - DOS命令
在DOS操作系统中,要通过DOS命令来操作系统,DOS命令是一种面向磁盘的操作命令,不区分大小写。 - 常用DOS命令
- 切换盘符:c: d: 不分大小写
- 磁盘内的详细信息展示: dir
- 改变当前目录: cd
- .当前目录 …代表上一层目录
- 清屏:cls
- 切换历史命令:上下箭头
- 补全命令:tab按键
- 创建 / 删除目录: md / rd
环境变量的配置
1.Path环境变量的配置
【出错原因】:HelloWorld.java 文件在D:\Java目录下;而javac文件不在D:\Java目录下。现在需要在D:\Java目录下执行Javac.exe文件,找不到,所以出错。
【解决办法】:将Javac.exe所在的路径配置到Path环境变量中。
【配置Path环境变量的作用】:在编译源文件时,首先在当前路径下找Javac.exe,找不到时再去配置的Path环境变量下找。从而实现在任意路径下执行Javac.exe,便于java源文件的编译。
2.ClassPath环境变量的配置
E\:traiin_code>java HelloWorld :java.exe在train_code路径下找HelloWorld字节码文件
若HelloWorld字节码文件在train_code路径下则翻译成功
若HelloWorld字节码文件不在train_code路径下则不成功
【配置ClassPath环境变量的作用】:针对java执行字节码文件而产生的环境变量,只要配置了字节码文件所在的路径以后,就能够在任意路径下找到java字节码文件。
3.JAVA_HOME环境变量的配置
在使用Java的过程中会出现闪屏问题。为了解决这个问题,必须配置JAVA_HOME 环境变量,变量路径为jdk的安装路径。
JAVA_HOME环境变量路径:C\:Program Files\java\jak1.8.0_151
Parth环境变量路径:C\:Program Files\java\jak1.8.0_151\bin
可以通过引用的方式写成:%JAVA_HOME%\bin
JDK,JRE与JVM
三者关系
- JDK(开发工具包) > JER(运行环境) > JVM(java虚拟机)
- JDK(Java Development Kit),JRE(Java Runtime Enviroment),JVM( java virtual machine)
- JDK:面向开发者,程序员的开发工具;JRE:面向使用JAVA程序的用户,运行程序的环境
- JDK与JRE
- 安装JDK之后在会生成一个jre和一个jdk文件夹,打开jdk文件夹发现里面也有一个jre文件,且两个jre文件中的内容基本一致。
- 程序编译过程中,javac命令不是去jdk中bin目录去找的javac.exe,而是去jdk中lib目录中的tools.jar中com.sun.tools.javac.Main中执行,因此javac.exe只是一个包装器(Wrapper),存在的目的是为了让开发者免于输入过长的指命。
- jdk里的工具几乎都是用Java语言编写,同属于Java应用程序。如果要使用jdk所附的工具来开发Java程序,那么自身必须附一套jre才能运行。所以jdk目录下的jre用来运行jdk的内部程序,与jdk同级目录下的jre则是用来运行一般的Java程序。
- JRE与JVM
- java程序被编译为.class的类文件,这种类文件可以在虚拟机上执行,但是class文件并不直接与机器的操作系统相对应,而是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。
- JVM不能单独解释/执行class文件,解释class的时候JVM需要调用解释所需要的类库lib。在JDK下面的的jre目录里面有两个文件夹bin和lib,bin目录下的jvm.doll文件与lib中jvm工作所需的类库合起来就是JRM。
- 可以认为:bin里面的是jvm,lib中是jvm工作所需的类库。jvm + lib = jre
数据类型
标识符与关键字
标识符
- 概念:包,类,变量,方法…等等,只要是起名字的地方,那个名字就是标识符。
- 标识符定义规则:
① 四个可以(组成):数字,字母,下划线_,美元符号$(注:字母指的是英文字母,汉字,日语,俄语…)
② 两个不可以:不可以以数字开头,不可以使用java中的关键字
③ 大小写敏感
④ 遵照驼峰命名法
类名:首字母大写,其余遵循驼峰命名
方法名,变量名:首字母小写,其余遵循驼峰命名
包名:全部小写,不遵循驼峰命名
⑤ 见名知意;长度适宜
关键字
变量与常量
常量
- 字面常量:1,2,3,‘a’,‘b’,true、"Hi World"等
- 使用final修饰的Π(pi)等为符号常量(字符常量)
变量
- 变量本质是代表一个”可操作的存储空间”,空间位置是确定的,但是里面放什么值不确定。我们可通过变量名来访问“对应的存储空间”,从而操纵这个“存储空间”存储的值。
- 变量的数据类型决定了变量占据存储空间的大小。 比如,int a=3; 表示a变量的空间大小为4个字节。变量作为程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。变量在使用前必须对其声明, 只有在变量声明以后,才能为其分配相应长度的存储空间。
- 变量的声明:变量如果没有进行赋值的话,那么使用的时候会出错。显示:尚未初始化变量
- 变量的赋值:变量的值可以改变;变量不可以重复定义。
- 变量的作用域:变量的作用域是离它最近的{}
- 局部变量:定义在方法中;成员变量:定义在类中,方法外
基本数据类型
整型数据类型
public class TestVar05{
public static void main(String[] args){
//定义整数类型的变量:
//给变量赋值的时候,值可以为不同进制的:
int num1 = 12 ;//默认情况下赋值就是十进制的情况
int num2 = 012;//前面加上0,这个值就是八进制的
int num3 = 0x12;//前面加上0x或者0X,这个值就是十六进制的
int num4 = 0b10;//前面加上0x或者0B,这个值就是二进制的
//定义byte类型的变量:
byte b = 126;//定义了一个byte类型的变量,名字叫b,赋值为12
System.out.println(b);//注意:超范围的赋值会报错。
short s = 30000;
System.out.println(s);
int i = 1234;
ystem.out.println(i);
//整数类型默认就是int类型的,所以12345678910是一个int类型的数,对于int类型来说,它超出范围了
//要想把一个数给long类型变量,那么后面加上L(推荐)或者l就可以了
long num5 = 12345678910L;
System.out.println(num5);
//注意:只有这个数超出int类型的范围了后面才需要加上L,否则无需加L也可以赋值给long类型:
long num6 = 12;
System.out.println(num6);
浮点数据类型
-
float类型又被称作单精度类型,尾数可以精确到7位有效数字,在很多情况下,float类型的精度很难满足需求。
-
double表示这种类型的数值精度约是float类型的两倍,又被称作双精度类型,绝大部分应用程序都采用double类型。
-
float类型的数值有一个后缀F或者f ,没有后缀F/f的浮点数值默认为double类型。
-
public class TestVar06{
public static void main(String[] args){
//浮点类型的常量有两种形式:
//十进制形式:
double num1 = 3.14;
//科学计数法形式:
double num2 = 314E-2;
//浮点类型的变量:
//注意:浮点型默认是double类型的,要想将一个double类型的数赋给float类型,必须后面加上F或者f
float f1 = 3.14234567898623F;
//注意:double类型后面可以加D或者d,但是一般我们都省略不写
double d1 = 3.14234567898623D;
//注意:我们最好不要进行浮点类型的比较:
float f2 = 0.3F;
double d2 = 0.3;
System.out.println(f2==d2);
/*
区别:
= 赋值运算: 将等号右侧的值赋给等号左侧
== 判断==左右两侧的值是否相等 :结果要么相等 要么不相等
==运算符的结果就是要么是true,要么是false
*
}
}
字符型数据类型
由权威机构形成的编码表才可以称之为:字符集
ASCII:英文字符集,用一个字节的7位表示
IOS8859-1:西欧字符集,用一个字节的8位表示
GB2312:简体中文字符集,最多使用两个字节编码。GB2312兼容了ASCII中的字符。
GBK:GB2312的升级,加入了繁体字,最多使用两个字节编码。
Unicode: 国际通用字符集,融合了目前人类使用的所有字符。为每个字符分配唯一的字符码。推出了UTF标准:三种编码方式:UTF-8,UTF-16,UTF-32
布尔型数据类型
boolean类型有两个常量值,true和false,在内存中占一位(不是一个字节),不可以使用 0 或非 0 的整数替代 true 和 false ,这点和C语言不同。 boolean 类型用来判断逻辑条件,一般用于程序流程控制 。
public class TestVar09{
public static void main(String[] args){
boolean flag1 = true;
boolean flag2 = false;
boolean flag3 = 5==9;
boolean flag4 = 5<9;
}
}
基本数据类型的转换
- 类型转换的种类:自动类型转换与强制类型转换
- 类型转换的内存演示
- 代码
public class TestVar10{
public static void main(String[] args){
//类型转换的两种形式:
double d = 6;//int-->double 自动类型转换
System.out.println(d);
int i = (int)6.5;//double--->int 强制类型转换 (强转)
System.out.println(i);
//多种数据类型参与运算时:整数类型,浮点类型,字符类型都可以参与运算,布尔类型不可以参与运算。
//double d2 = 12+1294L+8.5F+3.81+'a'+true;
double d2 = 12+1294L+8.5F+3.81+'a';
System.out.println(d2);
/*
类型级别:(从低到高的)
byte,short,char-->int--->long--->float--->double
当一个表达式中有多种数据类型的时候,要找出当前表达式中级别最高的那个类型,然后其余的类型都转换为当前表达式中级别最高的类型进行计算。
double d2 = 12+1294L+8.5F+3.81+'a';
= 12.0+1294.0+8.5+3.81+97.0
*/
int i2 = (int)(12+1294L+8.5F+3.81+'a');
System.out.println(i2);
/*
在进行运算的时候:
左=右 : 直接赋值
左<右 :强转
左>右 :直接自动转换
*/
//以下情况属于特殊情形:对于byte,short,char类型来说,只要在他们的表数范围中,赋值的时候就不需要进行强转,直接赋值即可。
byte b = 12;12未超出了byte的范围,不需要强转
System.out.println(b);
byte b2 = (byte)270;//270超出了byte的范围,需要强转
System.out.println(b2);
}
}
final,字符常量与Scanner的使用
import java.util.Scanner;//导包
public class TestVar11{
public static void main(String[] args){
//实现功能:求圆的周长和面积
//【1】提取变量:改变变量的值,后面用到这个变量的地方,取值也会跟着发生变化
//【2】一个变量被final修饰,这个变量就变成了一个常量,值就不可变了
// 这个常量就是字符常量 ---》pi
// 约定俗成的规定:字符常量的名字全部大写
final double PI = 3.14;
Scanner sc = new Scanner(System.in);
//给一个友好性的提示:
System.out.print("请录入一个半径:");
int r = sc.nextInt();//录入Int类型数据
//求周长:
double c = 2*PI*r;
System.out.println("周长为:"+c);
//求面积:
//PI = 9.29;被finally修饰。错误: 无法为最终变量pi分配值
double s = PI*r*r;
System.out.println("面积为:"+s);
}
}