0 Java语言概述
0.1 Java的特点
-
面向对象,Java程序“一切都在类中”,支持继承、多态机制
-
语法来自C++,取消了指针,多重继承和运算符重载,设立了自动内存回收机制,提供丰富类库
-
跨平台,一遍编译,到处执行
-
Java程序具有半编译,半解释的特性,由编译器将源程序编程成字节码文件,再由JVM将字节码文件解释执行。比解释性语言的执行效率高,比编译型语言更具灵活性(可移植)
-
支持分布式(数据分布和操作分布)
-
引入多级安全措施(内存使用、字节码验证器)
-
支持多线程
0.2 Java体系结构
虚拟机原理
C++ 和 Java 这两种编译型语言都是跨平台的,只是它们跨平台的层次不同而已: 前者是源码层(Fortran 和 Pascal 也是),后者是可执行文件层。 也就是说,要移植的话,C++ 程序必须在目的平台上重新编译,Java 则只需把可执行文件拷到目的平台上去,不必在那里重新编译。此处 “可执行文件” 的定义是 “编译器的输出文件”(C++ 的是 .exe,Java 的是 .class)。
当编译C或者C++,所获取的二进制文件只能适合指定的硬件平台和操作平台的(这个二进制文件包含了一些机器码,而且字节顺序还依赖特定平台,比如高位在前,低位在前等),而编译java形成的是java class文件,而class文件适合任何支持Java虚拟机的硬件平台和操作系统上的二进制的文件。
-
class文件是Java源程序编译后得到的文件,也称作字节码文件,它是在Java虚拟机之上运行的目标代码。
-
Java字节码文件可以在任何安装了Java虚拟机的平台上运行。
-
Java虚拟机是实现平台无关性的关键,位于Java程序和用户的计算机系统之间。它与具体的软硬件平台有关,从而保证了在它上运行的Java字节码与具体软硬件平台是无关的。
Java API
Java API(Application Program Interface,应用程序接口)是运行库的集合,它是已编译好的的程序代码库,可以直接使用。它提供了一套访问主机系统资源的标准方法。
Java API的class文件是与主机平台密切相关的。由于在程序执行的时候Java API调用了本地方法,Java源程序就不用调用他们了,通过这种方法,Java API 的class文件为底层提供了具有平台无关性,标准接口的Java程序。这样对于Java程序而言,无论平台内部如何,Java API都会有同样的表现和预测行为。正是由于在每个特定的平台都明确实现了Java虚拟机和Java API,才或有Java的无关性。
Java开发执行流程
关于编码:Java的字符使用Unicode编码,使用两个字节(16位),所以它几乎包括所有字符,中文、日文、…,它支持世界上所有语言。
大多数语言使用ASCII码,用8位表示一个字符。ASCII码是Unicode码的一个子集,Unicode表示ASCII码时,其高位为0,它是其前255个字符。Unicode字符通常用十六进制。例如“\u0000”-“\u00ff” 表示ASCII码集。”\u”表示转义字符,它用来表示其后四个十六进制数字是Unicode代码。
老师还讲到,我们在写代码时,用到的编码是我们电脑自带的编码格式,一般是GBK,只有编译后也就是生成字节码文件后才成为Unicode编码。
1 关于Java安装
1.1 JRE还是JDK?
JRE(JavaRuntimeEnvironment)包括Java虚拟机(JVM)和 Java API,如果只需要运行Java程序或Applet,下载并安装它即可。如果要自行开发 Java软件,就需要下载JDK,在JDK中附带有JRE。
可以到官网下载,不用下载最新版本,一般用JDK8的比较多。
1.2 JDK文件说明
bin | 一些可执行文件和动态链接库,如Javac、Java、javah等运行程序 |
---|---|
demo | Java程序实例文件 |
include | 固有方法(Native Methods)专用文件 |
jre | Java运行时环境相关的文件 |
lib | Java的库文件 |
src.zip | Java函数库的源代码 |
doc | 存放以HTML格式的Java的库参考和帮助文档 |
1.3 配置环境变量
操作系统的环境变量是指在操作系统中定义的变量,它可以被所有运行在该操作系统中的程序所访问。
系统变量对所有操作系统用户都有效,用户变量:只对该用户有效。某个用户所能使用的环境变量=该用户变量+系统变量。
当我们在命令行界面中执行某个命令时,操作系统首先在当前目录下查找,如果没有,则操作系统将在Path所指定的目录下依次查找,以最先找到的那个为准。
我们需要在 “系统变量” 中设置 3 项属性,JAVA_HOME、PATH、CLASSPATH(大小写无所谓),若已存在则点击"编辑",不存在则点击"新建"。1.5 以上版本的 JDK,不用设置 CLASSPATH 环境变量,也可以正常编译和运行 Java 程序。JDK8也就是1.8版本不用设置CLASSPATH。
变量名 | 变量值 |
---|---|
JAVA_HOME | D:\Development\Java\JDK8 //以自己JDK的安装路径为准 |
Path | %JAVA_HOME%\bin |
Path | %JAVA_HOME%\jre\bin |
CLASSPATH | .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar; |
可能会见到这样配置Path变量的:
Path %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
好像这是Win7这样的老机子上的写法。在 Windows10 中,Path 变量里是分条显示的,所以用上面表格里的方式就行了。
关于CLASSPATH变量:
CLASSPATH变量值,前面有个"."表示还会在当前目录下查找该类,不加的话只在CLASSPATH所指定的路径中查找该类并运行。
CLASSPATH的作用:当用java命令运行一个class文件时,系统要通过CLASSPATH找到对应的字节码文件;或者在要运行程序中还用到了第三方的类库(jar),系统也要通过CLASSPATH找到这个类库。
下面是操作步骤供参考:
右键【此电脑】→【属性】,下拉找到并点击【高级系统设置】,然后配置【环境变量】
下图演示添加JAVA_HOME路径,需要新建一个系统变量。
变量名Path是系统已经建好的,我们只需要点击它,然后添加新的变量值就行了,添加两个变量值,分别是%JAVA_HOME%\bin
和 %JAVA_HOME%\jre\bin
。
CLASSPATH变量就不添加了。
完成上述工作后,打开一个命令行窗口,输入java -version
,如果显示你的java版本信息就说明安装成功了。
2 使用Java进行编程
2.1 记事本编写代码
在桌面新建一个文件夹,然后用记事本写一个文本文档命名为HelloWorld
,并将后缀名改为.java
。内容如下
public class HelloWorld
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}
打开命令行,使用cd
命令将路径切换到当前文件夹,先使用javac
命令将HelloWorld.java
翻译为字节码文件
javac HelloWorld.java
如果没有报错,会生成一个HelloWorld.class
字节码文件,接着使用java
命令来执行该文件(不要带.class
后缀)
java HelloWorld
进展顺利的话命令行窗口就会输出Hello World!
2.2 集成开发环境
-
jetbrains全家桶系列IntelliJ IDEA ,功能强大。社区版免费,专业版在校大学生使用学校给的邮箱也可以申请免费使用。
-
还有就是Eclipse,也很好用。
3 Java语言基础
很多东西都跟C++差不多,只有一些特殊的地方需要注意。
3.1 标识符、注释
定义标识符的规则
- 由字母、 数字、下划线、 $组成。不能由数字开头
- 不能是Java中的保留字(关键字)。
- 大小写敏感,长度无限制
三种注释形式
//
单行注释。表示从此向后,直到行尾都是注释。/*……*/
块注释。在/*
和*/
之间都是注释。/**……*/
文档注释。所有在/**
和*/
之间的内容可以用来自动形成文档。
//元旦快乐
/*
元旦快乐
元旦快乐
元旦快乐
*/
/**
* 演示文档注释
* @author gylic
* 你可以包含一个或多个各种各样的@标签。
* 每一个@标签必须在一个新行的开始或者在一行的开始紧跟星号(*)。
* 多个相同类型的标签应该放成一组。
* 例如,如果你有三个@see标签,可以将它们一个接一个的放在一起。
* 使用javadoc工具可以可以识别特定标签,然后生成文档。
*/
3.2 变量和常量
变量的使用
变量的使用规则
Java的变量有两种:局部变量 类成员变量
变量必须先定义后使用。
局部变量在使用前必须给定初值,否则,将编译出错,而类成员变量无此要求。
变量的命名方法
程序员应该为变量取有意义的名称,以利于程序的阅读和理解。习惯上,变量名以小写字母开头,若一个变量名由超过一个单词所组成,则第一个单词之后的所有单词都以大写字母开头,以便于理解该变量名。(小驼峰命名法)。
变量的作用域
类成员变量作用域是整个类
类成员函数的参数作用域是该成员函数
局部变量作用域是该变量所在代码块
常量的使用
常量是指在程序运行过程中其值不变的量。分为数值常量和符号常量。
数值常量如下:
整型常量:42、052、0x2A、0X2A //分别表示十进制、八进制、十六进制整数
实型常量:12.1f
布尔常量:true
字符常量:’x’
字符串类型常量:“Test”
-
采用十进制表示实型常量时,小数点的两侧都必须有数字, 缺一不可,如+123.和 .56都是不合法的。
-
科学表示法: <尾数> E <阶码 >
- 尾数必须有,但小数部分可无
- 阶码必须有,必须是整数
- 基数是10
符号常量
使用修饰符final
可以定义符号常量。常量的值一旦确定不可更改。
final int a=10;
//a=20;
//错误用法,因为常量只能赋值一次(初始化)
System.out.println(a);
类静态成员常量只能在定义时初始化;方法中的常量(局部常量)可以在定义时初始化,也可以先定义,以后再初始化。
3.3 基本数据类型
八种基本数据类型
数据类型名 | 占用内存空间 | 数值范围 | 缺省值 | 说明 |
---|---|---|---|---|
byte | 1字节 | (-128)—127 | 0 | 整型 |
short | 2字节 | (-32768)—32767 | 0 | 整型 |
int | 4字节 | (-2147483648)—2147483647 | 0 | 整型 |
long | 8字节 | (-9223372036854775808)—9223372036854775807 | 0 | 整型 |
float | 4字节 | (±3.4028347E+38)—(±1.40239846E-45) | 0.0F | 实型 |
double | 8字节 | (±1.79769313486231570E+308)—(±4.94065645841246544E-324) | 0.0D | 实型 |
char | 2字节 | \u0000—\uFFFF | \u0000 | 字符型 |
boolean | 1字节 | true或false | False | 布尔型 |
注意
-
缺省值就是默认的初值,只对成员变量有用.局部变量在使用前必须人为地给定初值。
-
一个整型常量在机器中默认以int类型存储。整型常量后面加上后缀 L 或 l,在机器中以long类型存储。
-
一个实型常量在机器中默认以double类型存储。实型常量后加后缀F或f在机器中以float类型存储。
-
布尔型数据只有两个值:true和false。Java中不可将布尔类型看做整型值。
-
字符类型用来表示单个字符,采用16位二进制Unicode 编码表示
-
字符常量是用两个单引号括起来的一个字符
枚举类型 enum
语法格式
enum 枚举名{常量列表}
其中的“常量列表”是用逗号分割的字符序列,称为枚举类型的常量(其要符合标识符的规定),举例:
enum Season{
spring, summer, autumn, winter}
Season x = Season.spring;
//定义一个枚举变量x,枚举变量x只能取枚举类型中的常量
//通过使用枚举名和“.”运算符获得枚举类型中的常量
动态类型var
动态类型var是Java10新特性,用它来定义局部变量。 var动态类型是编译器根据变量所赋的值来推断类型, 声明时必须初始化,不能用作方法参数。
3.4 表达式及运算符优先级
算术运算
整数
int a=10/0 //编译无错,运行报错,异常
int a=10%0 //运行报错,异常
浮点数
double a=10.0/0 //Infinity(正无穷大)
double a=-10.0/0 //-Infinity(负无穷大)
double a=0.0/0 //NaN
double a=0.0%0 //NaN
字符串运算
String 类型在“+”运算中,+表示连接符,其他类型先转换成字符串类型,再进行连接运算。
System.out.println(‘a’+1);
System.out.println(“”+’a’+1);
System.out.println(“12”+12);
移位运算
运算符 | 用法 | 说明 |
---|---|---|
>> | op1>>op2 | 将op1的二进制表示向右移op2位,左边填充符号位 |
<< | op1<<op2 | 将op1的二进制表示向左移op2位,左边填充0 |
>>> | op1>>>op2 | 将op1的二进制表示向右移op2位,左边填充0 |
注意:
-
右移n位后的结果与除以2的n次方效果相同
-
左移n位后的结果与乘以2的n次方效果相同
-
无符号右移要慎重
-
在进行移位之前,java系统首先把移的位数与被移位的位数求余数,然后移动这个位数。也就是说,整型向右移动 32 位结果是其本身。
三元运算
Java 中唯一的三元运算符,其格式如下:
变量 = <布尔表达式> ? <表达式1> : <表达式2>
当<布尔表达式>为真时,变量的值为<表达式1>的值,否则为<表达式2>的值。
赋值运算
boolean型的只能赋给boolean型,其他七种类型如果能自动转换则可直接赋值,否则要进行强制类型转换
运算符优先级
( )>单目运算符>双目运算符>三目运算符>赋值运算符
双目:算术>关系>逻辑
大多数运算符结合性为从左至右,赋值运算符的结合性为从右至左。
3.5 类型转换
自动类型转换
运算过程中,Java自动把精度较低的类型转换为另一种精度较高的类型。
手动强制类型转换
在Java中直接将高精度的值赋给低精度的变量会导致编译出错。这时可用强制类型转换来解决。形式为:(类型名)表达式
。强制类型转换可能造成信息的丢失 。布尔型与其它基本类型之间不能转换。
隐含强制类型转换
Java中允许把int类型的常量赋给byte、short变量时不需要强制类型转换,但是把int类型的变量赋给byte、short类型的变量时必须强制转换,否则会出错。
3.6 输入输出
输入
- 通过main(String[] args)中的形参
class test
{
public static void main(String[] args)
{
System.out.println(args[0]);
System.out.println(args[1]);
}
}
>java test s1 s2
s1
s2
- System.in是字节流,作用是从标准输入读一个字节,常用的方法如下:
//从流中读取一个字节并将该字节作为整数返回,若没有数据则返回-1
int read();
//从流中读取多个字节放到b中, 返回实际读取到的字节数
int read(byte b[]);
//从流中读取最多len字节的数据, 放到数组b的下标off开始的单元中,返回读取到的字节数
int read(byte b[],int off,int len);
要将数字串转换成实数,则:
//转成单精度数
float f=Float.parseFloat(str.trim());
//转成双精度数
double d=Double.parseDouble(str.trim());
读取示例
//读取一个字符
char ch=(char)System.in.read();
//读取一个数字
byte buf[]=new byte[20];
System.in.read(buf);
int anInt=Integer.parseInt(str.trim());
//读一串字符
char c;
try
{
do
{
c=(char)System.in.read();
System.out.print(c);
}
while(c!='\n');
}
catch(IOException e){
}
- 借助java.util.Scanner类完成输入
//使用next():
Scanner scan = new Scanner(System.in);
if (scan.hasNext())
{
String str1 = scan.next();
System.out.println