JAVA语言入门

JAVA语言入门

1. 语言简介

计算机语言的分类:

  • 机器语言
  • 汇编语言
  • 高级语言
    • 第一代:C语言,面向过程为编程思想,它是唯一一门可以直接操作计算机硬件的语言。
    • 第二代:C++,面向对象为编程思想,没有默认的垃圾回收机制(GC)。
    • 第三代:Java,面向对象为编程思想,有默认的GC。
    • 第四代:自然语言,面向问题为编程思想。

2. Java语言简介

为什么要学习Java语言?

  • Java是使用最广泛,且用法简单的语言。

  • Java是一门强类型的语言(对数据类型的划分很精细)。

  • Java有非常严谨的异常处理机制。

  • Java提供了对于大数据的基础性支持。hadoop的底层使用java编写。

    1995年由SUN公司推出,Java之父:詹姆斯·高斯林,SUN公司在2009年被Oracle收购。

2.1 平台版本

  • J2SE:标准版,也是其他两个版本的基础。在JDK1.5时正式更名为JavaSE。
  • J2ME:小型版,一般用来开发嵌入式程序,已经被andorid替代。在JDK1.5时正式更名为JavaME。
  • J2EE:企业版,一般开发企业级互联网程序。在JDK1.5时正式更名为JavaEE。

2.2 特点

开跨两多面:开源跨平台,多线程多态面向对象。

  • 开源
    • 源代码是开源的。
  • 跨平台
    • 用Java编写的程序可以在不同的操作系统上运行。
    • 原理:有JVM保证Java程序的跨平台性,但是JVM本身不跨平台。

3. JDK和JRE

3.1 概述

  • JDK:Java开发工具包(Java Development Kit),包含开发工具和JRE。
    • 常用的开发工具:javac,java
  • JRE:Java运行时环境(Java Runtime Environment),包含运行Java程序所需的核心类库和JVM。
    • 核心类库:java.lang, java util, java.io
  • JVM:Java虚拟机(Java Virtual Machine)
    • 作用:用来保证Java程序跨平台,但是JVM本身不能跨平台

3.2 Java环境搭建

  • JDK的下载
    • www.oracle.com

Library->Java->JavaVirtualMachines->jdk1.8.0_301.jdk

  • 目录解释
    • bin:存放编译器和工具
    • db:存放数据
    • include:编译本地方法
    • jre:java运行时文件
    • lib:类库文件
    • src.zip:源代码

4. Path环境的配置

目的:在任何路径下都可以使用JDK提供的工具。例如java,javac。

vim ~/.bash_profile

添加变量名,变量值。

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_301.jdk/Contents/Home
export CLASSPAHT=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$JAVA_HOME/bin:$PATH

验证:
在terminal中输入:java -version

5. Hello World案例

程序的开发:编写->编译->执行

  • 编写源代码:在后缀为.java的文件中编写。
  • 编译:把我们能看懂的文件编译成计算机能看懂的文件。
    • .java -> .class(字节码文件,给计算机看的)
  • 运行:计算机运行字节码文件,用过java指令实现。
javac HelloWorld.java

会产生一个HelloWorld.class文件

java HelloWorld #由于设计规范,此处无需后缀,实际执行.class文件

显示运行结果

6. IDEA

6.1 IDEA中模块和项目之间的关系

方式:新建一个JavaSE项目,每天新增一个模块(推荐)

6.2 HelloWorld案例

  1. 创建一个空的项目

在project选项中设置SDK和Project Language Level

  1. 在该项目下创建Day01模块

Modules->Java->Moduel SDK设置

  1. 在Day01模块的src(源代码包)下创建:自定义包

  1. 在自定义包下创建Java类

  2. 在Java类中写代码

  3. 运行

6.3 快捷键

7. 关键字

关键字:被java赋予了特殊含义的单词。

  • 特点
    • 关键字有纯英文小写字母组成
    • 常用开发工具会highlight关键字

7.1 常用关键字

  • public:公共的权限
  • class:表示创建一个类
  • static:静态
  • void:表示方法的返回值类型

7.2 定义java源代码文件的格式

public class 类名{
	public static void main(String[] args){
		System.out.println(这里的内容随便写);
	}
}

8. 常量

概述

在程序的执行中,其值不能发生改变的量。

分类

  • 自定义常量
  • 字面值常量
    • 整数常量 直接写
    • 小数常量 直接写
    • 字符常量 值要用’ '包裹
    • 字符串常量 值要用“ ”包裹
    • 布尔常量 值只有true和false
    • 空常量 值只有null

9. 变量

9.1 概述

在程序的执行中,其值可以在某个范围内发生改变的量。从本质上讲,变量其实是内存中的一小块区域,例如:

  • 商品的价格(1元,5元,100元)
  • 钟表的时间(5点,6点,10点半)
  • 人的年龄(10岁,20岁,50岁)
  • 程序员生涯的职位(开发工程师,开发经理,项目经理,CTO)

java中要求每个变量每次只能保存一个数据,而且必须要明确保存数据的数据类型。

9.2 变量的限制

  • 变量的值在某一个范围内发生变化。(通过数据类型来限制)

  • 能找到这一块区域。(通过变量名实现)

  • 区域内必须有数据。(初始化值)

    形式:

数据类型 变量名 = 初始化值;

9.3 数据类型

java是一门强类型语言。其对数据的划分很精细。

整型
byte1个字节-128~127
short2个字节
int4个字节
long8个字节
浮点型
float4个字节
double8个字节
字符型
char2个字节
布尔型
boolean1个字节
  1. byte类型的取值范围是:-128~127,char类型的取值范围是0~65535
  2. 默认的整型是int,默认的浮点是double
  3. 定义long型时,数据后面要加字母L
  4. 定义float型时,数据后面要加字幕F

方式一:直接初始化变量

int a = 10;

方式二:先声明,后赋值

int a;
a = 10;

9.4 注意事项

  1. 变量未赋值不能使用。
  2. 变量只在它所属的范围内有效(代码块内)。
  3. 一行可以定义多个变量,但是不建议。

10. 标识符

10.1 概述

标识符就是用来给类,接口,方法,变量,包等起名字的规则。

10.2 命名规则

  1. 标识符只能包含52个英文字母(区分大小写)、数字、$和_。
  2. 标识符不能以数字开头。
  3. 标识符不能和关键字重名。
  4. 最好做到见名知其意。

10.3 命名规范

  1. 类,接口:每个单词的首字母大写,其他小写(大驼峰命名法)。
  2. 变量,方法:从第二个单词开始,每个单词的首字母都大写,其他小写(小驼峰命名法)。
  3. 常量:所有字母都大写,单词之间用下划线连接。
  4. 包:所有字母全小写,多级包之间用.隔开,一般是把公司的域名反写。

hust.edu.cn -> cn.edu.hust

11. 数据类型转换

11.1 自动类型转换

小类型转大类型,会自动提升为大类型,运算结果时大类型。

double a = 10;
  1. int和double相加,为double
  2. char和int相加,为int
  3. boolean和int相加,报错
  • 转换规则
    • 范围小的类型向范围大的类型提升,byte, short, char运算时直接提升为int
    • boolean类型不能参与数值转换

11.2 强制类型转换

手动将大类型转换成小类型,运算结果是小类型

short s = 1;
s = (short)(s+1);
System.out.println(s);//结果为2,short类型

12. 常量和变量相加

Java中对于常量,有常量优化机制。

  • 针对于byte类型:
    • 常量相加:常量相加会直接运算,然后判断结果在不在左边的数据范围内
    • 变量相加:会自动提升数据类型,然后运算,提升规则

      byte, short, char -> int -> long -> float -> double

  • 针对于string类型:
    • 后边API解释

13. 运算符

运算符:连接常量和变量的符号。
表达式:用运算符把常量或者变量连接起来符合java语法的式子。

不同运算符连接的表达式体现的是不同类型的表达式。

13.1 算数运算符

整数相除,结果还是整数。除非有浮点型参与。
加号运算符在字符串之间表示连接。

System.out.println("Hello" + 5 + 5)//Hello55
System.out.println("Hello" + (5 + 5))//Hello10
System.out.println(5 + 5 + "Hello" + 5 + 5)//10Hello55

13.2 自增和自减运算符

i++,先运算后自增
++i,先自增后运算
++和–都隐含了强制类型转换。

byte a = 1;
a = a++;//包含了强制类型转换,等价于下行代码
a = (byte)(a + 1);

13.3 赋值运算符

基本的赋值运算符:=
拓展的赋值运算符:+=, -=, *=, /=, %=

a += b; 等价于 a = a + b;

赋值运算符的左边不能为常量。
拓展的赋值运算符默认包含了强制转换。

byte a = 1;
a += 1;//包含了强制类型转换,等价于下行代码
a = byte(a + 1);

13.4 关系运算符

==, !=, >, <, <=, >=,返回true或者false

13.5 逻辑运算符

&, |, !,^异或

短路逻辑运算符
符号作用说明
&&短路与作用和&相同,但是有短路效果,前面如果出现false,后面不执行
||短路与作用和|相同,但是有短路效果,前面如果出现true,后面不执行

13.6 三元运算符

(关系表达式)? 表达式1 : 表达式2;

首先执行关系表达式,如果true执行表达式1,如果false执行表达式2

14 键盘录入 Scanner类

14.1 使用步骤

  1. 导包

写在类上面,package下面

import java.util.Scanner;
  1. 创建Scanner类的对象
Scanner sc = new Scanner(System.in);
  1. 通过Scanner类的nextInt()方法接收用户录入的数据
int a = sc.nextlnt();

15 流程控制

15.1 概述

某些代码在满足特定条件下才会执行;有些代码在满足特定条件下重复执行。这些都需要用到流程控制语句。

15.2 分类

  • 顺序结构
  • 选择结构(if语句,switch.case语句)
  • 循环结构(for循环,while循环,do.while循环)

15.3 顺序结构

代码按照从上往下从左往右的顺序依次逐行执行。是java程序的默认结构。

System.out.println(10+10+"Hello"+10+10);

20Hello1010

15.4 选择结构

15.4.1 if语句

if语句一般用为范围的判断

  • if语句(单分支)单分支结构一般用来判断一种情况
if(条件语句){
//语句体;
}
  • if.else语句(双分支)
    一般用来判断两种情况
if(条件语句){
//语句体1;
}else{
//语句体2;
}
  • if.else if语句(多分支)
if(条件语句1){
//语句体1
}else if(条件语句2){
//语句体2
}else if(条件语句3){
//语句体3
}
···
else{
//语句体
}
15.4.2 switch语句

一般用于固定值判断

switch(表达式){	//表达式的取值类型:byte, short, int, char, JDK5以后可以是枚举,JDK7以后可以是String
	case1:		 //case后面跟的是要和表达式进行比较的值
		语句体1//语句体可以使一条或者多条语句
		break//break表示中断,结束switch语句
	case2:
		语句体2breakcase3:
		语句体3break;
	···
	default:		 //default表示所有情况都不匹配时执行,写在任何位置都是最后才执行
		语句体n;
		break}

case穿透:
在switch语句中,如果case后面不写break,将出现case穿透现象,也就是不会在判断下一个case的值,直接向后运行,知道遇到break,或者整体switch结束。

switch(month){
	case 1:
	case 2:
	case 12:
		String season = "Winter";
		break;
	···
}

思考题:break关键字可以省略吗?
答:最后一个分支的break可以省略,其他分支如果省略break可能对结果有影响。

15.5 循环结构

  • for循环
    一般适用于循环次数固定的情况。
  • while循环
    一般适用于循环次数不固定的情况。
  • do.while循环
    实际开发中基本不用,适用于先执行一次然后判断的情况。
15.5.1 for循环
for(初始化条件;判断条件;控制条件){
	//循环体
}

先执行初始化条件,然后执行判断条件,查看结果true还是false,如果true执行循环体,执行控制条件。

15.5.2 while循环
初始化条件;
while(判断条件){
	//循环体;
	//控制条件;
}
15.5.3 do.while循环
初始化条件;
do{
	循环体;
	控制条件;
}while(判断条件)

15.6 三种循环区别

  1. for和其他两个循环的区别
    for循环结束后,初始化条件就不能继续使用了。而while和dowhile可以。
  2. do.while和其他两个循环的区别
    先执行一次再判断,而其他两个循环是先判断再执行。

15.7 循环跳转

  • break:用来终止循环,循环不再继续执行。
  • continue:用来结束本次循环,进行下一次循环,循环还会继续。

15.8 循环嵌套

用得最多的是for循环的嵌套

for(初始条件;判断条件;控制条件){		//外循环
	for(初始条件;判断条件;控制条件){	//内循环
		//循环体
	}
}

16 Math生成随机数

Math类似Scanner,是Java提供好的API(Application Programming Interface),内部提供了产生随机数的工程。

16.1 格式

int num = (int)(Math.random()*100 + 1) //获取1到100之间的随机数
  1. 可以直接使用,不需要调包。
  2. 取值范围为[0.0, 1.0)

17 数组

如果需要同时存储多个同类型的数据,我们可以通过数组来实现。
数组就是用来存储多个同类型元素的容器。

17.1 格式

  • 动态初始化:给定长度,由系统给出默认初始化值。
//格式一
数据类型[] 数组名 = new 数据类型[长度]//数组名小驼峰命名法,推荐使用
//格式二
数据类型 数组名[] = new 数据类型[长度]//上述两种定义方式只是写法不同,并无其他区别。格式一应用的多一些。
  • 静态初始化:给定初值,系统给定长度
//格式一
数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, 元素3...};
//格式二 语法糖(简化语法的格式)
数据类型[] 数组名 = {元素1, 元素2, 元素3, ...};

初始化数组不可同时给定长度和初值。
int[] arr = new int[3];
解释:

  • 数据类型:数组中存储元素的数据类型。如这里的int说明数组中只能存储int类型的数据。
  • []:表示是数组
  • 数组名:类似于变量名,要符合小驼峰
  • new:指创建数组对象

17.2 数组特点及基本用法

17.2.1 特点
  1. 数组中的元素编号(索引)从0开始。
  2. 数组中每个元素都有默认值。
    类型元素默认值
    int0
    double0.0
    booleanfalse
    Stringnull
17.2.2 基本用法
  1. 通过数组名[索引]的形式,可以快速获取数组中的指定元素。
  2. 通过数组名[索引]=值;的形式,可以修改数组中的指定元素值。
  3. 通过数组名.length的方式可以获取数组的长度。

17.3 数组的内存图

17.3.1 内存解释

内存是计算机中的重要元件,也是临时存储区域,作用是运行程序。我们编写的程序是存放在硬盘当中的,在硬盘中的程序是不会运行的,必须放入内存中才能运行,运行完毕后会清空内存。
即:Java虚拟机要运行程序,必须要对内存进行空间的分配和管理。为例提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
JVM的内存划分

  1. 栈:存储局部变量以及所有代码执行的。
    局部变量:定义在方法中,或者方法声明上的变量。
    特点:先进后出
  2. 堆:存储所有new出来的内容,即对象
    特点:堆中的内容会在不确定的时间被GC回收。
  3. 方法区:存储字节码文件。
    字节码文件:后缀为.class的文件。
  4. 本地方法区:和系统相关,了解即可。
  5. 寄存器:和CPU相关,了解即可。
    内存图解,示意图(并不严格)
public class ArrayDemo{
	public static void main (String[] args){
		int[] arr = new int[3];
		System.out.println(arr[0]);
		System.out.println(arr);//打印的是存储地址
	}
}

17.3.2 两个数组的内存图
public class StoragePic {
    public static void main(String[] args) {
        int[] arr = new int[3];
        arr[0] = 11;
        System.out.println(arr[0]);
        System.out.println(arr[1]);
        System.out.println(arr);
        int[] arr2 = {1, 2};
        arr2[1] = 22;
        System.out.println(arr2[1]);
        System.out.println(arr2);
    }
}

17.4 数组的两个小问题

17.4.1 数组索引越界异常

产生原因:访问了数组中不存在的索引
解决方案:访问数组中存在的索引即可

17.4.2 空指针异常

产生原因:访问了空对象
解决方案:对对象赋具体的值

17.5 遍历数组

int[] arr = {11, 22, 33, 44, 55};
for(int i : arr) System.out.println(i);

17.6 获取数组的最值

public class ArrayDemo02 {
    public static void main(String[] args) {
        int[] arr = {55, 22, 66,77, 33, 44, 55};
        int max = arr[0];
        for(int i : arr){
            if (i >= max) max = i;
        }
        System.out.println(max);
    }
}

17.7 反转数组

public class ReverseArray {
    public static void main(String[] args) {
        int[] arr = {11, 22, 33, 44, 55};
        int temp;
        for (int i = 0; i <= arr.length/2; i++){
            temp = arr[i];
            arr[i] = arr[arr.length-1-i];
            arr[arr.length-1-i] = temp;
        }
        for(int i : arr) System.out.println(i);
    }
}

18 方法

方法也叫函数,是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集。

18.1 定义格式

修饰符 返回值的数据类型 方法名(参数类型 参数名1, 参数类型 参数名2{//这里可以写多个参数
//方法体;
return 具体的返回值;
}
  • 修饰符:目前记住这里是固定格式public static
  • 返回值的数据类型:用于限定返回值数据类型,如果没有具体的返回值,数据类型用void修饰
  • 方法名:方便调用方法
  • 参数类型:限定调用方法时传入数据的数据类型
  • 参数名:用于接收调用方法时传入的数据的变量
  • 方法体:完成特定功能的代码
  • return 返回值:用来结束方法并把返回值返回给调用者。如果没有明确的返回着,return关键字可以不写

18.2 注意事项

  • 方法与方法之间时平级关系,不能嵌套定义
  • 方法必须先创建才可以使用
  • 方法自身不运行,需要调用
  • 方法的功能越单一越好
  • 定义方法的时候写在参数列表中的参数都是形参
    • 形参:形容调用方法的时候需要传入什么类型的参数
  • 调用方法的时候,传入的具体的值,是实参
    • 实参:调用方法时实际参与运算的数据

18.3 无参无返回值的方法

public static void 方法名(){
	//方法体;
}

图解

18.4 有参无返回值的方法

public static void printNum(int number){
    System.out.println("The number is "+ number);
}

18.5 无参有返回值的方法

public static String getSchool(){
    return "Huazhong University of Science and Technology";
}

18.6 有参有返回值的方法

public static int getAdd(int a, int b){
    return a+b;
}

18.7 方法重载

同一个类中,出现方法名相同,但是参数列表不同的两个或多个的方法时,称为方法重载,方法重载与方法的修饰符、返回值的数据类型无关
参数列表不同分为两种类型:

  • 参数的个数不同
  • 对应参数的数据类型不同

18.8 基本类型、引用类型作为形参的情况

形参如果是基本类型,形参的改变不影响实参。

public class demo01 {
    public static void main(String[] args) {
        int num = 100;
        change(num);
        System.out.println(num);//打印结果仍然是100
    }
    public static void change(int num){
        num = 200;
    }
}


引用类型作为参数时,形参的改变直接影响实参(String类型除外,String类型当作形参使用时,用法和基本类型一致,后续API详解)

public class demo02 {
    public static void main(String[] args) {
        int[] arr = {10, 20, 30};
        System.out.println(arr[1]);//打印结果为20
        change(arr);
        System.out.println(arr[1]);//打印结果为200
    }
    public static void change(int[] arr){
        arr[1] = 200;
    }
}

19 Debug调试

步骤:

  1. 加断点,哪里不会点哪里
  2. 运行加了断点的程序,选择debug
  3. 开始调试
    debugger:看代码执行到哪里了
    console:控制台,查看程序运行结果
    variable:查看变量的变化过程
  4. 进行下一步
    F7:逐过程调试
    F8:逐行调试
    F9:逐断点调试
  5. 删除断点
    方式一:一个一个删除
    方式二:批量删除,选择breakpoints(双红点),移除断点即可

20 面向过程与面向对象

20.1 面向过程

  1. 明确目的
  2. 分析过程
  3. 通过代码一步步实现
    以上每一个步骤我们都是参与者,需要面对具体的每一个步骤和过程,
    代表语言:C

20.2 面向对象

当需求单一且简单,一步一步操作没有问题效率也挺高。但是如果需求更改、增多,把这些步骤和功能进行封装。封装时根据不同的功能进行不同的封装,功能类似的用一个类封装在一起。使用的时候找到对应的类。
思想特点:

  1. 是一种符合我们思考习惯的思想
  2. 可以将复杂的事情简单化
  3. 让我们从执行者变成了指挥者
    小结
    面向对象是一种编程思想,它是基于面向过程的,强调的是以对象为基础完成各种操作。

面试题:什么是面向对象?
思路:概述,思想特点,举例,总结

21 类和对象

我们是如何表示现实世界的事物的呢?

  1. Java语言是用来描述现实世界事物的,最基本的单位是:类
  2. 类:是一个抽象的概念,看不见也摸不着,它是属性和行为的集合
  3. 对象:类(该事物)的具体体现,实现
  4. 属性(成员变量)
  • 属性指的就是事物的描述信息(名词)
  • 属性在Java中被称为成员变量
  1. 行为(成员方法)
  • 用来指事物能够做什么
  • 也叫成员方法,和以前定义方法类似,先不写static

举例
类:学生;大象
对象:张三,23;北京动物园叫图图的大象
属性(成员变量):年龄,性别,专业;年龄,性别,品种
行为(成员方法):学习、吃饭、睡觉;吃饭、睡觉、迁徙

21.1 类的定义格式

定义类其实就是定义类的成员(成员变量和成员方法)

  • 成员变量:
  1. 和以前定义变量是一样的,只不过位置发生了改变,写到类中,方法外
  2. 成员变量还可以不用赋值,因为它有默认值
  • 成员方法:
  1. 和以前定义方法是一样的,只不过把static关键字去掉
  2. 这点记忆即可,后面再讲解static关键字的用法
public class student {
    //属性(成员变量):姓名,年龄,性别
    String name;
    int age;
    String sex;

    //行为(成员方法):学习,吃饭,睡觉
    public void study(){
        System.out.println("学习");
    }
    public void eat(){
        System.out.println("吃饭");
    }
    public void sleep(){
        System.out.println("睡觉");
    }
}

21.2 类的使用

类的使用就是使用类中定义的成员(成员变量和成员方法)

格式
  1. 创建该类的对象
    类名 对象名 = new 类名();
  2. 通过对象名.的形式,调用类中的指定成员
    //成员变量
    对象名.成员变量
    //成员方法
    对象名.成员方法(参数列表中各数据类型对应的值)
示例
public class StudentTest {
    public static void main(String[] args) {
        Student s = new Student();
        System.out.println(s.name);//null(默认值)
        System.out.println(s.age); //0(默认值)
        System.out.println(s.sex); //null(默认值)
        s.name = "Nick";
        s.age = 22;
        s.sex = "Male";
        System.out.println(s.name);//Nick
        System.out.println(s.age); //22
        System.out.println(s.sex); //Male
    }
}

21.3 一个对象的内存图

21.4 两个对象的内存图

21.5 两个引用指向同一个对象的内存图

21.6 成员变量和局部变量的区别

  • 成员变量:定义在类中,方法外的变量。
  • 局部变量:定义在方法中或者方法声明上的变量。
    他们的区别如下:
  1. 定义位置不同
    • 成员变量定义在类中,方法外
    • 局部变量定义在方法中或者方法声明上
  2. 在内存中的存储位置不同
    • 成员变量:存储在堆内存
    • 局部变量:存储在栈内存
  3. 生命周期不同
    • 成员变量随着对象的创建而存在,随着对象的消失而消失
    • 局部变量随着方法的调用而存在,随着方法的调用完毕而消失
  4. 初始化值不同
    • 成员变量有默认值
    • 局部变量没有默认值,必须定义赋值才能使用

22 封装

上述的代码中,我们可以任意的设置属性的值,包括我们可以设置一些非法值,例如把年龄设置成负数,这样做程序就容易出问题,针对这种情况,我们可以通过private关键字来优化。

22.1 private关键字

private是一个关键字,也是访问权限修饰符的一种,它可以用来修饰类的成员(成员变量和成员方法)
被private修饰的内容只能在本类中直接使用。

应用场景
  1. 在实际开发中成员变量基本上都是用private关键字来修饰的
  2. 如果明确知道类中的某些内容不想被外部访问
public class Phone{
	private int age;
	public int getAge(){
		return age;
	}
	public void setAge(int a){
		age = a;
	} 
}

22.2 封装的概述

封装是面向对象编程思想的三大特征之一,所谓的封装就是隐藏对象的属性和细节,仅对外提供一个公共的访问方式。
面向对象的三大特征:封装、继承、多态
隐藏:private修饰符
公共访问方式:public成员方法
原则

  1. 把不需要对外提供的内容都隐藏起来
  2. 把属性隐藏,并提供公共方法对其访问
    解释:成员变量都用private修饰,并提供对应的公共方法,其他都用public修饰
    好处
  3. 提高代码的安全性:由private保证
  4. 提高代码的复用型:由方法保证

22.3 this关键字

this表示本类当前对象的引用,即谁调用,this就代表谁
用来解决局部变量和成员变量重名的问题
使用变量的原则:就近原则(局部位置有就使用,没有就去本类的成员位置找,有就使用,没有就报错)(不严谨,还会去父类找)

package cn.edu.hust.demo;

public class Student {
    int x = 1;

    public void method(){
        int x = 2;
        System.out.println(this.x);
        System.out.println(x);
    }
}
package cn.edu.hust.demo;

public class StudentTest {
    public static void main(String[] args) {
        Student s = new Student();
        s.method();//1,2   this.x等价于s.x
        s.x = 10;
        s.method();//10,2
    }
}

加入this关键字后标准额度JavaBean类的编写方法

public class Student {
    private String name;
    private int age;

    public void setName(String name){
        this.name = name;
    }
    public String getName(){
//        return this.name;//能不多写就不写
        return name;
    }
    public void setAge(int age){
        this.age = age;
    }
    public int getAge(){
        return age;
    }
    public void study(){
        System.out.println("好好学习,天天向上!");
    }
    public void sleep(){
        System.out.println("为了保证精力,请好好休息!");
    }
}
public class StudentTest {
    public static void main(String[] args) {
        Student s = new Student();
        s.setAge(22);
        s.setName("Nick");
        System.out.println(s.getAge());
        System.out.println(s.getName());
        s.study();
        s.sleep();
    }
}

22.4 构造方法

构造方法是用来创建对象的,可以给对象的各个成员变量赋值。
构造方法就是用来快速对对象的各个属性赋值的。
格式

  1. 构造方法名必须和类名完全一致
  2. 构造方法没有返回值类型,void也不用
  3. 构造方法没有具体的返回值,但是可以写return(实际开发中一般不写)
  4. 构造方法可以重载
public 类名(参数类型 参数名1,参数类型 参数名2){
	//给对象的各个属性复制
}

注意事项

  1. 如果我们没有给出构造方法,系统将给出一个默认的空参构造
  2. 如果我们给出了构造方法,系统不会给默认的构造方法
    给成员变量赋值有两种方式
  3. setXXX(),不会创建新对象
  4. 构造方法,会创建新对象
public class Student{
	private String name;
	private int name;
	public Student(String name, int age){
		this.name = name;
		this.age = age;
	}
}
public class StudentTest{
	String name = "Nick";
	int age = 22;
	Student s = new Student(name, age);
}

22.5 JavaBean

JavaBean也可以称为实体类,其对象可以用于在程序中封装数据。

标准JavaBean必须满足如下要求:

  • 成员变量全部用private修饰
  • 提供成员变量对应的getter和setter方法
  • 必须提供一个无参构造器,有参构造器可写可不写

23 继承

多个类中存在相同属性和行为时,将这些内容抽取到单独的一个类中,那么这个类就无需再定义这些属性和行为了,只要继承那个类即可。这个关系就叫继承。

有了继承以后,我们在定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义新的成员。
格式

public classA extendsB{ //A是子类,B是父类

}

好处:

  1. 提高了代码的复用型

  2. 提高了代码的可维护性

  3. 让类与类之间产生关系,是多态的前提

弊端:

  1. 让类与类之间产生关系,也就让类的耦合性增强了。开发原则:高内聚,低耦合。内聚指类自己独立完成某些事情的能力。耦合指类与类之间的关系。

23.1 继承的特点

  1. 在java中,类与类之间只能单继承,不能多继承。
  2. 在Java中,类与类之间可以多层继承。

23.2 继承关系中的成员变量的特点

使用变量遵循“就近原则”,局部位置有就使用,没有就去本类的成员位置查找,有就使用,没有就去父类的成员位置查找,有就使用,没有就报错。

23.3 super关键字

super的用法和this很像

  • this代表本类对象的引用
  • super代表当前对象的父类的内存空间标识
    解释:可以理解为父类对象引用
    用法
    |功能|本类|父类|
    |-|-|-|
    |访问成员变量|this.成员变量名|super.成员变量名|
    |访问构造方法|this(…)|super(…)|
    |访问成员方法|this.成员方法名(参数值…)|super.成员方法名(参数值…)|

23.4 继承中构造方法的特点

  1. 子类中所有的构造方法默认都会访问父类的空参构造
    问:为什么这样设计?
    答:用于子类对象访问父类数据前,对父类数据进行初始化
    即每一个构造方法的第一行都有一个:super()

  2. 如果父类没有空参构造怎么办?
    1)可以通过super(参数)的方式访问父类的带参构造
    2)可以this(参数)的方式访问本类的其他构造
    3)但是这样做比较麻烦,所以建议永远手动给出空参构造和带参构造。子类的空参构造访问父类的空参构造super();(可以省略不写,默认已有)。子类的带参构造访问父类的带参构造super(成员变量);

  3. 所有的类都间接继承自Object类,Object类是所有类的父类

public class Father {
    public Father(int age){
        System.out.println("Father带参构造");
    }
    public Father(){
        System.out.println("Father空参构造");
    }
}
public class Son extends Father {
    public Son(int age){
        super(age);
        System.out.println("Son带参构造");
    }
    public Son(){
        System.out.println("Son空参构造");
    }
}
public class FatherTest {
    public static void main(String[] args) {
        Son s = new Son(10);
        Son s2 = new Son();
    }
}

打印结果为:

Father带参构造
Son带参构造
Father空参构造
Son空参构造

23.5 继承中成员方法的特点

继承关系中,调用成员方法时,遵循“就近原则”,本类中有就直接使用,本类中没有就去父类查找。有就调用,没有就报错。

public class Father {
    public Father(){
        System.out.println("Father空参构造");
    }
    public Father(int age){
        System.out.println("Father带参构造");
    }
    public void show(){
        System.out.println("Father show");
    }
}
public class Son extends Father{
    public Son(){
        System.out.println("Son空参构造");
    }
    public Son(int age){
      	super(age);
        System.out.println("Son带参构造");
    }
    public void method(){
        System.out.println("Son method");
    }
}
public class FamilyTest {
    public static void main(String[] args) {
        Son s = new Son();
        s.method();
        s.show();
    }
}

打印结果为:

Father空参构造
Son空参构造
Son method
Father show

方法重写

子类中出现和父类一模一样的方法时,称为方法重写,要求返回值的数据类型也必须一样

应用场景
当子类需要使用父类的功能,而功能主题又有自己独有需求的时候,就可以考虑重写父类中的方法了,这样既沿袭了父类的功能,又定义了子类特有的内容

注意事项

  1. 子类重写父类方法时要用@overwrite注解来修饰
  2. 父类中私有的方法不能被子类重写
  3. 子类重写父类方法时,访问权限不能更低

private < 默认 <protected < public

public class Phone {
    public Phone(){}
    public Phone(String name){}
    public void call(String name){
        System.out.println("Calling "+name);
    }
}
public class NewPhone extends Phone{
    public NewPhone(){}
    public NewPhone(String name){
        super();
    }
    @Override
    public void call(String name){
        super.call(name);
        System.out.println("播放彩铃");
    }
}
public class PhoneTest {
    public static void main(String[] args) {
        Phone p = new Phone();
        NewPhone np = new NewPhone();
        p.call("Nick");
        np.call("Nick");
    }
}

打印结果:

Calling Nick
Calling Nick
播放彩铃

24 多态

多态指的是同一个事物(或者对象)在不同时刻表现出来的不同状态。

前提条件

  1. 要有继承关系
  2. 要有方法重写
  3. 要有父类引用指向子类对象

Person p = new Teacher();

24.1 多态中的成员访问特点

  1. 成员变量:编译看左边,运行看左边
    编译的时候看左边的数据类型有没有这个变量,有不报错,没有报错
    运行的时候具体运行的是左边的数据类型里边的:此变量
  2. 成员方法:编译看左边,运行看右边
    编译的时候看左边的数据类型有没有这个方法,有不报错,没有报错
    运行的时候具体运行的是左边的数据类型里边的:此方法

原因:方法有重写,而变量没有。

public class Person{
	int age = 50;
	public void eat(){
		System.out.println("Eat.")
	}
}
public class Student extends Person{//条件之一:要有继承
	int age = 20;
	@Override//条件之二:要有方法重写
	public void eat(){
		System.out.println("Eat hamburgers.")
	}
}

24.2 多态的好处和弊端

好处:提高了程序的拓展性
坏处:父类引用不能访问子类的特有功能
处理方法:向下转型

假设Student.class增加一个成员方法

public void study(){
	System.out.println("Study.")
}

那么主类需要这样写

public class PersonTest{
	public static void main(String[] args){
		Person p = new Student();
		//p.study() //会报错,因为p是Person类的引用,没有study()成员方法
		Student s = (Student)p;
		/*
			向下转型,类似于强制类型转换
			强制类型转换:int a = (int)10.3;
		*/
		s.study();
	}
}

24.3 向上转型和向下转型

向上转型:
Person p = new Student();
向下转型:
Student s = (Student)p;
bug:

Person p = new Student();
Student s = (Student)p;//正确
Teacher t = (Teacher)p;//报错

24.4 实际开发中多态的应用

实际开发中,方法的形参一般都是父类型,这样可以接受其任意子类对象,然后通过多态调用成员方法的规则调用指定子类对象的方法。

public class Animal {
    public void eat(){
        System.out.println("eat");
    }
}
public class Cat extends Animal{
    @Override
    public void eat(){
        System.out.println("cats eat fish");
    }
}
public class Dog extends Animal{
    @Override
    public void eat(){
        System.out.println("dogs eat meat");
    }
}
public class AnimalTest {
    public static void main(String[] args) {
        Animal a1 = new Cat();
        Animal a2 = new Dog();
        show(a1);
        show(a2);
    }
    public static void show(Animal a){
        a.eat();
    }
}

cats eat fish
dogs eat meat

24.5 instanceof关键字

格式
引用(对象) instanceof 数据类型
返回true或者false
作用
用来判断前边的引用(对象)是否是后边的数据类型
假设Cat类和Dog类分别增加成员方法:

public void catchMouse(){
	System.out.println("catch mouse")
}
public void guardHome(){
	System.out.println("guard home")
}

主类show方法改变为:

    public static void show(Animal a){
        a.eat();
        if(a instanceof Cat){
            Cat c = (Cat) a;
            c.catchMouse();
        }
        else if(a instanceof Dog){
            Dog d = (Dog) a;
            d.guardHome();
        }
    }

打印结果为:

cats eat fish
catch mouse
Dogs eat meat
guard home

24.6 final关键字

final是一个关键字,表示最终的意思,可以修饰类,成员变量,成员方法

  • 修饰的类:不能被继承,但是可以继承其他的类
  • 修饰的变量:是一个常量,只能被赋值一次
  • 修饰的方法:不能被子类重写

final常见面试题

final修饰的变量是一个常量,那如果修饰的是基本类型或者引用类型的数据,有区别吗?
如果final修饰的是基本类型的常量,数值不能发生变化
如果final修饰的是引用类型的常量,地址值不能发生变化,但是该对象的属性值可以发生变化

final, finally, finalize这三个关键字之间的区别是什么?

25 static关键字

static是一个关键字,表示静态的意思,可以修饰成员变量和成员方法。

static 修饰成员变量表示该成员变量只在内存中存储一份,可以共享和修改。

特点

  1. 随着类的加载而加载

  2. 优先于对象存在

  3. 被static修饰的内容,能被该类下所有的对象共享

    这也是我们判断是否用静态关键字的条件

  4. 可以通过**类名.**的形式调用

示例

public class Student {
    String name;
    static String school; //static修饰成员变量
    public void show(){
        System.out.println("Name:"+name+" School:"+school);
    }
}
public class Test {
    public static void main(String[] args) {
        Student s1 = new Student();
        Student s2 = new Student();
        s1.name = "Nick";
        Student.school = "HUST"; //通过“类名.”调用,所有对象共享
        s2.name = "Eva";
        s1.show();
        s2.show();
    }
}

Name:Nick School:HUST
Name:Eva School:HUST

访问特点及注意事项

  1. 静态方法只能访问静态的成员变量和静态的成员方法(静态只能访问静态)
  2. 在静态方法中没有this,super关键字
    因为静态的内容是随着类的加载而加载,而this和super是随着对象的创建而存在
    即先进内存的不能访问后进内存的

26 抽象类

回想前面我们的猫狗案例,提取出了一个动物类,这个时候我们可以通过Animal an = new Animal();来创建动物对象,但其实这是不对的。因为我说动物,你并不知道我说的是什么动物。只有看到了具体的动物,才知道是什么动物。所以说,动物本身不是一个具体的事物,而是一个抽象的事物。只有真正的猫、狗才是动物。同理,我们也可以对象,不同的动物吃的东西是不一样的,所以我们不应该在动物类中给出具体的体现,而是一个声明即可。

在Java中,一个没有方法体的方法定义为抽象方法(用abstract修饰),而类中如果有抽象方法,该类必须定义为抽象类(用abstract修饰)。

26.1抽象类的特点

  1. 抽象类和抽象方法法必须用abstract关键字修饰
  2. 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
  3. 抽象类不能是实例化,可以通过多态的方式,创建其子类对象,来完成抽象类的实例化,这也叫:抽象类多态
  4. 抽象类的子类
    • 如果是普通类,则必须重写父抽象类中的所有抽象方法
    • 如果是抽象类,则可以不用重写父抽象类中的抽象方法
public abstract class Animal {
    public abstract void eat();
    public void sleep(){
        System.out.println("Sleep");
    }
}
public class Cat extends Animal{
    @Override
    public void eat(){
        System.out.println("Eat");
    }
}
public class Test {
    public static void main(String[] args) {
        //Animal an = new Animal(); 抽象类不能实例化
        Animal an = new Cat();
        an.eat();
        an.sleep();
    }
}

26.2 抽象类的成员特点

抽象类中可以有变量、常量、构造方法、抽象方法和非抽象方法(比普通类多了抽象方法)
思考:既然抽象类不能实例化,那要构造方法有什么用?
答:用于子类对象访问父类数据前,对父类数据进行初始化

27 接口

继续回到我们的猫狗案例,我们想狗的一般行为就是看门,猫的一般行为是捉老鼠。但是有些狗猫可以训练出钻火圈、跳高、做算术等行为。这些行为并不是狗猫天生就具备的。所以这些额外的行为定义到动物类中就不合适,也不合适定义到猫类或者狗类中,因为只有部分猫和部分狗具备。

所以,为了体现事物功能的拓展性,Java就提供了接口来定义这些额外行为,并不给出具体实现,将来哪些猫狗需要被训练,只需要这部分猫狗把这些额外行为实现即可。

27.1 接口特点

  1. 接口用interface关键字修饰
  2. 类和接口之间是实现关系,用implements关键字表示
  3. 接口不能实例化。可以通过多态的方式,创建其子类对象,来完成接口的实例化。这也叫接口多态。
  4. 接口的子类
    • 如果是普通类,则必须重写父接口中所有的抽象方法
    • 如果是抽象类,则不用重写父接口中的抽象方法

27.2 接口成员特点

  1. 接口中有且只有常量或者抽象方法(适用JDK1.8以前),原因是:
    • 成员变量有默认修饰符:public static final
    • 成员方法有默认修饰符:public abstract
  2. 接口中是没有构造方法的,因为接口主要是扩展功能的,而没有具体存在。
  3. JDK1.8的时候,接口中加入了两个新的成员:静态方法、默认方法(必须用default修饰)。

27.3 类与接口之间的关系

  • 类与类:继承关系,只能单继承,不能多继承,可以多层继承
  • 类与接口:实现关系,可以单实现,可以多实现,可以在继承一个类的同时实现多个接口
  • 接口与接口:继承关系,可以单继承,可以多继承
public abstract class Animal {
    public abstract void eat();
}
public interface InterA{//父接口
    public abstract void methodA();
}
public interface InterB extends InterA{//子接口
    public abstract void methodB();
}
public class Cat extends Animal implements InterA, InterB{//由于InterB接口继承了InterA接口,所以这里只写InterB接口也可以
    @Override//父类抽象方法要重写
    public void eat(){
        System.out.println("Eat fish.");
    }
    @Override//接口抽象方法要重写
    public void methodA(){
        System.out.println("A");
    }
    @Override//接口抽象方法要重写
    public void methodB(){
        System.out.println("B");
    }
}
public class InterfaceTest {
    public static void main(String[] args) {
        //Animal an = new Animal();//**报错**。Animal是抽象类,不能实例化
        Animal an = new Cat();
        an.eat();//访问成员方法,编译看左(Animal类有eat方法),运行看右(Cat类有eat方法)
        //an.methodA(); //**报错**。编译看左(Animal类没有methodA方法)
        Cat c = (Cat) an;
        c.methodB();
        c.methodA();
    }
}

27.4 抽象类和接口的区别

  1. 成员区别
    抽象类可以写变量、常量、构造方法、抽象方法、非抽象方法
    接口可以写常量、抽象方法,JDK1.8引入了静态方法和默认方法
  2. 关系区别
    • 类与类:继承关系,只能单继承,不能多继承,可以多层继承
    • 类与接口:实现关系,可以单实现,可以多实现,可以在继承一个类的同时实现多个接口
    • 接口与接口:继承关系,可以单继承,可以多继承
  3. 设计理念的区别
    抽象类:类中定义的是整个继承体系的共性内容
    接口:定义的是整个继承体系的扩展内容

27.5 例题


28 包

包(package)就是文件夹,用来对类进行分类管理的,例如

  • 学生的增加,删除,修改,查询
  • 老师的增加,删除,修改,查询
  • 其他类的增删改查
  • 基本的划分:按照模块和功能划分
  • 高级的划分

28.1 格式

package 包名1.包名2.包名3
package语句必须是程序的第一条可执行代码
package在一个程序中只能有一个

28.2 package, import, class三者在一个程序中的顺序

Package必须放在java文件的第一行有效代码处,且一个.java文件只有一个package
import表示导包,可以写多个,必须写在package和class之间
class表示在定义类,写在import后,建议只写一个

28.3 常见分类

  • 按照功能分
    • edu.hust.add
      • AddStudent.java
      • AddTeacher.java
    • edu.hust.delete
      • DeleteStudent.java
      • DeleteTeacher.java
    • edu.hust.update
    • edu.hust.read
  • 按照模块分
    • edu.hust.student
      • AddStudent.java
      • DeleteStudent.java
    • edu.hust.teacher
      • AddTeacher.java
      • DeleteTeacher.java

28.4 导包

不同包下的类之间的访问,都需要加包的全路径。解决方法是导包。

28.5 格式

import 包名;

  1. import java.util.* 导入java.util包下所有类,这样效率低不推荐
  2. import java.util.Scanner 导入java.util.Scanner类,推荐使用
28.6 注意事项
  1. java.lang包下的类可以直接使用,无需导入,如果使用其他包下的类,则必须先导包
  2. 用public修饰的类叫公共类,也叫顶级类。在一个.java文件中只能有一个顶级类,必须和文件名一致
  3. 全类名=包名+类名
29 权限修饰符

权限修饰符是用来修饰类、成员变量、构造方法、成员方法的,不同的权限修饰符对应的功能不同

publicprotected默认private
同一个类中
同一个包中的子类或者其他类
不同包中的子类
不同包中的其他类(无关类)

30 集合

集合是用来存储多个同类型数据的容器,其长度可变。
长度固定用数组,长度可变用集合。

集合的类别

集合分为Collection和Map。
集合的顶层都是接口。其中Collection是单列集合的顶层接口,Map接口是双列集合的顶层接口。

学习思路:学顶层,用底层。
顶层:是整个继承体系的共性内容
底层:具体的体现和实现

Collection:单列集合的顶层接口

  • List:有序,可重复
    ArrayList:
    LinkedList:
    Vector
  • Set:无序,唯一
    HashSet:
    TreeSet
  • Map:双列集合的顶层接口
    HashMap:
    HashTable
    TreeMap

Collection集合

因为Collection是接口,不能用new关键字来创建。通过多态的方式创建其子类对象。

Collection<String> list = new ArrayList<String>();

泛型

<String>, <Integer>等形式
概述:指某种特定的数据类型
作用:泛型一般是结合集合来一起使用的,用来限定集合中存储什么类型的数据
注意事项:1.前后泛型必须保持一致。2.后边的泛型可以不写,这是jdk1.7的新特性,叫菱形泛型。
例如

List<String> list = new ArrayList<>();
public class Demo01 {
    public static void main(String[] args) {
        Collection<String> list = new ArrayList<String>();
        //或者Collection<String> list = new ArrayList();
        list.add("Hello");
        list.add("World");
        System.out.println(list);
    }
}

Collection集合的方法

public boolean add(E e)添加元素//E指泛型
public boolean remove(Object obj)从集合中移除指定的元素
public void clear()清空集合
public boolean contains(Object obj)判断集合中是否包含指定的元素
public boolean isEmpty()判断集合是否为空
public int size()获取集合的长度

范型的小技巧:范型一般用字母E,T,K,V表示。E:Element;T:Type;Key Value

Iterator遍历集合

Iterator 是依赖集合存在,集合遍历的方式

public Iterator<E> iterator()//根据集合对象,获取其对应的迭代器对象

因为Iterrator是接口,所以在这里返回的是Iterator接口的子类对象。
迭代器是依赖于集合而存在的。
Iterator迭代器中的方法

public boolean hasNext()//判断迭代器中是否有下个元素
public E next()//获取迭代器中的下一个元素
    public static void main(String[] args) {
        Collection<String> coll = new ArrayList<>();
        coll.add("Hello");
        coll.add("World");
        Iterator<String> it = coll.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
    }

打印结果

Hello
World

总结:
集合遍历的使用分为四大步三小步
1.创建集合对象
2.创建元素对象
3.把元素对象添加到集合对象中
4.遍历集合
1.根据集合对象获取其对应的爹太器
2.判断迭代器中是否有下一个
3.有则获取

List集合

有序集合(俗称序列),该界面的用户可以精准控制列表中每个元素的插入位置,且用户可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素。与Collection集合不同,列表通常允许重复的元素。
简单记忆:有序,可重复,元素有索引

List集合特有的成员方法

void add(int i, E element)//使index为i的位置插入element
E set(int i, E element) //修改指定索引处的元素指定的值,并返回修改前的元素
E remove(int i)//根据索引移除指定元素,并返回此元素
E get(int i)//根据索引,获得相应的元素

遍历List集合:

  • 增强for
  • 通过for循环+size()+get()的形式,遍历List集合
    快捷键:itli

列表迭代器 ListIterator

列表迭代器指的是ListIterator接口,它是List集合特有的迭代器
该迭代器继承了Iterator迭代器,所以我们可以直接使用

ListIterator<E> listIterator()
ListIterator<E> listIterator(int index)

成员方法:

boolean hasPrevious();
E previous();
int nextIndex();
int previousIndex();
List<String> list = new ArrayList<>();
list.add("Hello");
list.add("World");
list.add("Java");
//通过ListIterator正向遍历
ListIterator<String> it = list.listIterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
//逆向遍历
while(it.hasPrevious()){
String s = it.previous();
System.out.println(s);
}

并发修改异常

当使用普通迭代器(Iterator)遍历集合的同时,又往集合中添加了元素,就会报并发修改异常。

List<String> list = new ArrayList<>();
list.add("Hello");
list.add("World");
list.add("Java");
Iterator<String> it = list.iterator();
while(it.hasNext()){
	String s = it.next();
	if("World".equals(s)){
		it.add("JavaSE");//会报错并发修改异常
	}
}

产生原因:
迭代器是依赖于集合而存在,当判断成功后,集合中添加了新的元素,而迭代器不知道,所以报错了。(计数器会计算剩下的元素个数,所以add报错而remove不报错)本质是,迭代器遍历集合中的元素是,不能使用集合对象去修改集合中的元素。

解决方案:

  1. 通过列表迭代器(ListIterator)解决
List<String> list = new ArrayList<>();
list.add("Hello");
list.add("World");
list.add("Java");
ListIterator<String> it = list.listIterator();
while(it.hasNext()){
	String s = it.next();
	if("World".equals(s)){
		it.add("JavaSE");
	}
}
  1. 通过for循环+size()方法解决
List<String> list = new ArrayList<>();
list.add("Hello");
list.add("World");
list.add("Java");
for(int i=0; i<list.size(); i++){
	if("World".equals(list.get(i))){
		list.add(i+1, "JavaSE");
	}
}
for (int i = 0; i < list.size(); i++) {
	String s =  list.get(i);
	System.out.println(s);
}
  1. 通过CopyOnWriteArrayList集合解决(它的底层已经解决了这个问题)
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("Hello");
list.add("World");
list.add("Java");
Iterator<String> it = list.iterator();//普通迭代器
while(it.hasNext()){
	if("World".equals(it.next())){
		list.add("JavaSE");//并发
	}
}

面试题

什么是并发修改异常,怎么产生的,怎么解决
ConcurrentModificationException

增强for

增强for是JDK1.5的新特性,它是用来简化数组和Collection集合的遍历。

for(元素的数据类型 变量名:数组或Collection集合中的每一个元素)
for(int a: array)
for(Student l:list)

注意事项:数组或Collection集合不能为null;增强for的底层是迭代器

for(String elem : list){ }

常见的数据结构

数组:查询快,增删慢
链表:查询慢,增删快

List集合的子类(ArrayList和LinkedList)

List集合是一个接口,它的常用子类有两个ArrayListLinkedList
ArrayList的底层数据结构是数组,查询快,增删慢
LinkedList的底层数据结构是链表,查询慢,增删快
相同点:都是有序可重复的

LinkedList特有方法

void addFirst(E element)
void addLast(E element)
往链表的开头或末尾插入制定元素
E removeFirst()
E removeLast()
删除链表的开头或末尾元素,并返回这个元素
E getFirst()
E getLast()
返回链表的开头或末尾元素

Set集合

Set集合是Collection集合的子体系,它的元素特点是无序、唯一

  1. Set集合是一个接口,所以不能通过new的方式直接创建对象
  2. Set集合中没有带索引的方法,不能通过普通for进行遍历
  3. Set集合的常用子类有两个HashSet集合和TreeSet集合。
Set<String> set = new HashSet<>();//实际使用不用Set<String>,直接用HashSet<String>
set.add("Hello");
set.add("Java");
set.add("Hello");
for(String s : set){
	System.out.println(s);
}

Java
Hello

HashSet集合

  1. 底层数据结构是哈希表
  2. 对集合的迭代顺序不做保证
  3. 没有带索引的方法
  4. 不包含重复的元素
    总结:无序,唯一,元素无索引。底层数据结构是哈希表
HashSet<String> set = new HashSet<>();
set.add("Hello");
set.add("Java");
set.add("World");
for(String s : set){//遍历法1:增强for循环
	System.out.println(s);
}
Iterator<String> it = set.iterator();
while(it.hasNext()){//遍历法2:普通迭代器
	System.out.println(it.next());
}

LinkedHashSet集合

  1. 底层数据结构是哈希表+链表
  2. 保证元素有序
  3. 保证元素唯一
    总结:有序,唯一。

可变参数

可变参数又称参数个数可变,它用作方法的形参出现,那么方法参数个数就是可变的了。
格式

修饰符 返回值类型 方法名(数据类型... 变量名){}
  1. 可变参数的底层是一个数组
  2. 如果一个方法有多个参数,将可变参数放在形参列表的最后。
public static void main(String[] args) {
	System.out.println(getSum(1,2,3));
}
public static int getSum(int... nums){
	return Arrays.stream(nums).sum();//可变参数的底层是数组
}

Map集合

public interface Map<K,V>{}

特点:

  1. 键具有唯一性,值可以重复
  2. 双列集合的数据结构只针对于键有效
  3. Set集合底层依赖的是Map集合
    成员方法:
public V put (K key, V value)
第 一 章   Java概 述 § 1.1 Java语 言 出 现 的 背景 、 影 响 及 应 用 前 景 一 、 背 景 最 近 一 年 多 来 ,在 Internet上 出 现 的 特 别 吸 引 人 的 事 件 就是 Ja va语 言 和 用 Java编 写 的 浏 览 器 HotJava。 1991年 ,SUN MicroSystem 公 司 的 Jame Gosling、 Bill Joe等 人 , 为 在电视 、 控 制 烤 面 包箱 等 家 用 消 费 类 电 子 产 品 上 进 行 交 互 式操 作 而 开 发 了 一 个 名为 Oak的 软 件 (即一 种 橡 树 的 名 字 ), 但当 时 并 没 有 引 起 人 们 的 注 意 ,直 到 1994年下 半 年 ,Internet的 迅猛发 展 ,环 球 信 息 网 WWW的 快 速 增 长 ,促 进 了 Java 语 言 研 制 的 进展 ,使 得 它 逐 渐 成为 Int ernet上 受 欢 迎 的 开 发 与 编 程 语 言 ,一 些著 名 的 计 算 机 公司 纷 纷 购 买 了 Java 语言 的 使 用 权 , 如 Mi-croSoft、 IBM、 Netscape、 Novell、 Apple、 DEC、 SGI 等,因 此 ,Java 语言 被 美 国 的 著 名 杂 志 PC Magazine 评 为 1995年 十 大 优 秀科 技 产 品,(计 算 机 类 就 此 一项 入 选 ),随 之 大 量 出 现 了 用 Java编写 的 软 件 产 品 ,受 到 工 业 界的 重 视 与 好 评 ,认 为 "Java是八 十 年 代 以 来 计 算 机 界 的 一 件 大 事 ", 微 软 总 裁 比 尔 ·盖 茨 在 悄 悄 地 观 察了 一 段 时 间 后 ,不 无感 慨 地 说 :"Java是 长 时 间 以 来 最 卓 越 的 程序 设 计 语 言 ",并确 定 微软 整 个 软 件 开 发 的 战 略 从 PC 单 机 时 代 向 着 以 网 络为 心 的 计 算 时 代 转 移 ,而 购 买 Java则 是 他 的 重 大 战 略 决 策的实施 部 署 。因 此 ,Java的 诞 生 必 将 对 整 个 计 算 机 产 业 发 生 深远的 影 响,对 传 统 的 计 算 模型 提 出 了 新 的 挑 战 。 SUN MicroSystem 公 司 的 总 裁 Scott McNealy认 为 Java为 Internet和WWW开辟 了 一 个崭 新 的 时 代 . 环 球 信 息 网 WWW的 创 始 人 Berners-Lee说 : "计 算 机 事 业 发展 的下 一 个 浪 潮 就是 Java,并 且 将 很 快 会 发 生 的 "。看 来 ,使 用 Java已 成 大 势 所 趋 ! MicroSoft 和 IBM 两 大 公 司 都 计 划 在 Internet上 销 售 用 Java 编写的 软 件 。 Apple、 HP、 IBM、 MicroSoft、 Novell、 SGI、 SCO、 Tandem 等 公 司均计 划 将 Java并入 各 自 开 发 的 操 作系 统 ,而 负 责 开 发 并 推 广 Java技 术 的 SunSoft公司 (这 是 SUN下 属的 一 个 子 公 司 ), 将 通 过 颁发 许 可 证 的 办 法 来 允 许 各 家 公 司 把Java虚 拟 机 和 Java的Applets类库 嵌 入 他 们 开 发 的 操 作 系 统 ,这 样 各 类 开 发 人 员 就 能更 容易 地 选 择 多种 平 台 来 使 用 Java语 言 编 程 ,不 同 的 用 户 也 就 可以 脱 离 Web浏 览器 来 运 行 Java应 用程 序 ,这 无 疑 是 很 受 广 大 用户 欢 迎 的 ,也 为 Java语 言 的 应 用 开 拓了极为 广 阔 的 前景 。 (当然 ,各 类 JavaOS之 间 的 兼 容 性 必 须 得 到 重 视 ,好 在JavaSoft已 保证 将 监 督 这种 兼 容 性 )。 另 外 ,由 JavaSoft 推 出 的 完 全 用 Java编 写 的 Internet上 新 型 浏览器 HotJava,比 去 年alpha版 更 为 实 用 ,不 仅 能 编 制 动 态 的 应 用 软件 ,而 且 能 编 制 完整 的 成 套 桌 面 应 用软 件 ,将 来 还 会 提 供 更多 的 能 帮 助 编 制 动 态 应 用 软 件 的 模 块,显 然 ,这 也 是 为 J ava的应 用 提 供 了 有 力 的 例 证 。 今 年 6月 7日 ,由 SUN公 司 和 台 湾 经 济 事 务 部 信 息 发 展 局, 台湾信 息 技 术 研究 所 等 单 位 牵 头 ,成 立 了 一 个 "Java联 盟 ", 参 加 的 有 22个 在 台 湾相 当 著 名 的 计 算 机公 司 ,并 在 台 北 建 立一 个 "Java 开 发 心 ",在 新 竹 建 立 一 个 "Java语 言实 验 室 ", 以 掀起 台 湾 开 发 与 应 用 Java 语 言 的 热 潮 。 香 港 则 在 今 年 4月 就 举 行 了 全 岛 的 Java杯 比 赛 ,在 计 算 机界掀 起 了 学 习 Java的热 潮 (尤 其 是 在 大 学 生 们 ,出 现 了 一 批 Java迷 )。 有 人 预 言 :Java将 是 网 络 上 的 "世 界 语 ",今 后 所 有的 用 其 他语 言 编 写 的 软 件统 统 都 要 用 Java 语 言 来 改 写 。 二 、 Java 语 言 对 软 件 开 发 技 术 的 影 响 工 业 界 不 少 人 预 言 :"Java 语 言 的 出 现 ,将 会 引 起 一 场软 件革 命 ",这 是 因 为 传统 的 软 件 往 往 都 是 与 具 体 的 实现 环 境 有 关 ,换 了 一 个 环 境 就需 要 作 一 番 改 动 ,耗时 费 力 ,而 Java 语 言 能 在 执 行 码 (二 进 制 码 )上 兼 容 ,这 样 以 前 所开 发 的软 件 就 能 运行 在 不 同 的 机 器 上 ,只 要 所 用 的 机 器 能 提供 Java 语 言 解 释 器 即可 。 Java 语 言 将 对 未 来 软 件 的 开 发 产 生 影 响 , 可 从 如 下 几 个方面 考 虑 : 1 软 件 的 需 求 分 析 :可 将 用 户 的 需 求 进 行 动 态 的 、 可 视化描 述 ,以 提供设 计者 更 加 直 观 的 要 求 。 而 用 户 的 需 求 是 各色 各 样 的 ,不 受 地 区、 行 业 、 部 门 、 爱好 的 影 响 ,都 可 以 用 Java 语 言 描 述 清 楚 。 2 软 件 的 开 发 方 法 :由 于 Java 语 言 的 面 向 目 标 的 特 性 , 所以完 全 可 以 用 O-O的技 术 与 方 法 来 开 发 ,这 是 符 合 最 新 的 软件 开 发 规 范 要 求 的 。 3 Java 语 言 的 动 画 效 果 远 比 GUI技 术 更 加 逼 真 ,尤 其 是 利用WW W提 供 的 巨 大动 画 资 源 空 间 ,可 以 共 享 全 世 界 的 动 态 画面 的 资 源 。 4 软 件 最 终 产 品 :用 Java 语 言   开 发 的 软 件 可 以 具 有 可视化 、 可 听 化 、 可 操作 化 的 效 果 ,这 要 比 电 视 、 电 影 的 效果 更 为 理 想 ,因 为 它 可 以做 到 "即 时 、 交 互、 动 画 与 动作 ",要 它 停 就 停 ,要 它 继 续 就 继 续 ,而 这 是 在 电 影与 电视 播 放 过 程 难 以 做 到 的 。 5 其 它 :使 用 Java 语 言 对 开 发 效 益 、 开 发 价 值 都 有 比 较明显 的 影 响 。 三 、 工 业 界 对 Java 语 言 的 评 价 1996年 5月 29 ~ 31日 ,在 美 国 旧 金 山 召 开 了 一 个 全 世 界 Java语言 开 发 者 大 会,(JavaOne Developer Confer-ence),出 席 会 议 的 多 达 6500多 人 ,来 自 工 业界 的 超 过 一 半 ,有人 评 价 说 :"这 是 近年 来 计 算 机 界 最 光 辉 的 一 次 盛 会 ",一 些 工 业 界 的 老 总们 相 当看 好 Java 语 言 ,认 为 它 的 使 用 将 会 引 起 一 场 软 件 革命 。 从 软 件的 设 计 风 格 、 设计 方 法 、 设 计 目 标 到 设 计 过 程 ,都 会 产 生 彻 底 的 变 革 ,"甚 至 会改 变 此 星 球 的 生活 方 式 "。 在 这 次 会 上 ,Java的 创 始 人 之 一 James Gosling 说 :"Java 不仅 仅只 是 applets, 它 能 做任 何 事 情 ",Dta 咨 询 公 司 的 高 级软 件 工 程 师 Rich Kadel说 :"Java 不仅 仅 是 一 种 程 序 设计 语言 ,更 是 现 代 化 软 件 再 实 现 的 基 础 ;Java 还 是 未 来 新 型 OS的核 心 ;将 会 出 现Java 芯 片 ;将 构 成 各 种 应 用 软 件 的 开 发 平 台与 实 现 环 境 ,是 人们 必 不 可 少 的 开 发工 具 "。 由 于 各 界 都 看 好 它 ,因 此 ,各 大 公 司 都 纷 纷 表 示 支 持 Java,Inte l、 Xerox公 司 声 言将 把 Java嵌 入 到 他 们 的 产 品 去 。 就 连 华尔 街 金 融 界 也 在 投入 资 金 人 力 用 Java开 发 电 子 贸 易 、 金 融软 件 。 所 以 有 人 说 :"现 在 第 三 方 的 开 发 商 都 团 结 在 Java大旗 周 围了 !",纷 纷 推 出 用Java 开 发 的 各 种 软 件 产 品 ,以 期尽 快 地 占 领 市 场 。 四 、 Java 语 言 的 应 用 前 景 Java 语 言 有 着 广 泛 的 应 用 前 景 ,大 体 上 可 以 从 以 下 几 个方面 来 考 虑 其 应 用 : 1 所 有 面 向 对 象 的 应 用 开 发 ,包 括 面 向 对 象 的 事 件 描 述、处 理 、 综 合 等 ; 2 计 算 过 程 的 可 视 化 、 可 操 作 化 的 软 件 的 开 发 ; 3 动 态 画 面 的 设 计 ,包 括 图 形 图 像 的 调 用 ; 4 交 互 操 作 的 设 计 (选 择 交 互 、 定 向 交 互 、 控 制 流 程 等 ); 5 Internet的 系 统 管 理 功 能 模 块 的 设 计 ,包 括 Web页 面 的 动 态设计 、 管 理 和 交互 操 作 设 计 等 ; 6 Intranet(企 业 内 部 网 )上 的 软 件 开 发 (直 接 面 向 企 业 内 部用户 的 软 件 ); 7 与 各 类 数 据 库 连 接 查 询 的 SQL 语 句 实 现 ; 8 其 它 应 用 类 型 的 程 序 。 § 1.2 Java的 特 点 Java是 一 个 广 泛 使 用 的 网 络 编 程 语 言 ,它 是 一 种 新 的 计算概 念 。 首 先 ,作 为 一 种 程 序 设 计 语 言 ,它 简 单 、 面向对象 、 不依 赖于 机 器 的 结 构 、具 有 可 移 植 性 、 鲁 棒 性 、 安 全 性 、 并 且提 供 了 并 发 的 机 制 、具 有 很 高 的 性 能。 其 次 ,它 最 大 限 度 地 利 用 了 网 络 ,Java的小应用程序(applet) 可在网 络 上 传 输 而 不受 CPU和 环 境 的 限 制 。 另 外 ,Java还 提 供 了 丰富 的 类 库 ,使 程 序 设计 者 可 以 很 方 便地 建 立 自 己 的 系 统 。 下 面 我 们 分 别 从 这 三 个 方 面 来 讨 论 Java的 特 点 ,然 后通 过把 Java与 C,C++相 比进 一 步 指 出 它 所 具 有 的 优 点 。 一 、 Java语 言 Java语 言 有 下 面 一 些 特 点 :简 单 、 面 向 对 象 、 分 布 式 、解释 执 行 、 鲁 棒 、安 全 、 体 系 结 构 立 、 可 移 植 、 高 性 能、 多 线 程 以 及 动 态 性。 1.简 单 性 Java语 言 是 一 种 面 向 对 象 的 语 言 ,它 通 过 提 供 最 基 本 的方法 来 完 成 指 定 的任 务 ,只 需 理 解 一 些 基 本 的 概 念 ,就 可 以用 它 编 写 出 适 合 于 各种 情 况 的 应 用 程 序。 Java略 去了 运 算 符重 载 、 多 重 继 承 等 模 糊 的 概 念 ,并 且 通 过实 现 自 动 垃 圾 收集大 大 简 化 了 程 序 设 计 者 的 内 存 管 理 工 作 。 另 外 ,Java也 适合于 在 小 型 机 上 运行 ,它 的 基 本 解 释 器 及 类 的 支 持 只 有 40KB左右 ,加 上 标 准 类 库 和线 程 的 支 持 也 只 有 215KB左 右 。 库 和 线程 的 支 持 也 只 有 2 15KB左 右 。 2.面 向 对 象 Java语 言 的 设 计 集 于 对 象 及 其 接 口 ,它 提 供 了 简 单 的类机 制 以 及 动 态 的接 口 模 型 。 对 象 封 装 了 它 的 状 态 变 量以 及 相 应 的 方 法 ,实现 了 模 块 化 和 信 息隐 藏 ;而 类 则 提 供 了一 类 对 象 的 原 型 ,并 且 通 过 继 承 机 制 ,子 类可 以 使 用 父 类 所提供 的 方 法 , 实 现 了 代 码 的 复 用 。 3.分 布 性 Java是 面 向 网 络 的 语 言 。 通 过 它 提 供 的 类 库 可 以 处 理TCP/IP协议 ,用 户 可 以通 过 URL地 址 在 网 络 上 很 方 便 地 访 问 其 它 对 象。 4.鲁 棒 性 Java在 编 译 和 运 行 程 序 时 ,都 要 对 可 能 出 现 的 问 题 进 行检查 ,以 消 除 错 误 的产 生 。 它 提 供 自 动 垃 圾 收 集 来 进 行 内存 管 理 ,防 止 程 序 员 在管 理 内 存 时 容 易 产生 的 错 误 。 通 过集 成 的 面 向 对 象 的 例 外 处 理 机 制 ,在 编 译 时,Java提 示 出 可能 出现 但 未 被 处 理 的 例 外 ,帮 助 程 序 员 正 确 地 进 行 选 择 以防 止 系统 的 崩 溃 。 另 外,Java在 编 译 时 还 可 捕 获 类 型 声 明 的 许 多 常 见 错 误 ,防 止 动 态运 行 时 不 匹 配 问题 的 出 现 。 5.安 全 性 用 于 网 络 、 分 布 环 境 下 的 Java必 须 要 防 止 病 毒 的 入 侵 。Java 不 支 持 指 针 ,一切 对 内 存 的 访 问 都 必 须 通 过 对 象 的 实 例 变量 来 实 现 ,这 样 就防 止 程 序 员 使 用 "特洛 伊 " 木 马 等欺 骗 手 段 访 问 对 象 的 私 有 成 员 ,同 时 也 避 免 了指 针 操 作 容 易 产 生的 错 误 。 6.体 系 结 构 Java解 释 器 生 成 与 体 系 结 构 无 关 的 字 节 码 指 令 ,只 要 安装了 Java运 行 时 系 统,Java程 序 就 可 在 任 意 的 处 理 器 上 运 行 。这 些 字 节 码 指 令 对 应于 Java虚 拟 机 的表 示 ,Java 解 释 器 得到 字 节 码 后 ,对 它 进 行 转 换 ,使 之 能 够 在 不同 的 平 台 运 行 。 7.可 移 植 性 与 平 台 无 关 的 特 性 使 Java程 序 可 以 方 便 地 被 移 植 到 网 络上的 不 同 机 器 。同 时 ,Java的 类 库 也 实 现 了 与 不 同 平 台 的 接口 ,使 这 些 类 库 可以 移 植 。 另 外 ,Java编 译 器 是 由 Java语 言 实现 的 ,Java运 行 时 系 统 由 标 准 C实 现 ,这使 得 Java系 统 本 身 也具有 可 移 植 性 。 8.解 释 执 行 Java解 释 器 直 接 对 Java字 节 码 进 行 解 释 执 行 。 字 节 码 本身携 带 了 许 多 编 译时 信 息 ,使 得 连 接 过 程 更 加 简 单 。 9.高 性 能 和 其 它 解 释 执 行 的 语 言 如 BASIC、 TCL不 同 ,Java字 节 码 的 设计使 之 能 很 容 易地 直 接 转 换 成 对 应 于 特 定 CPU 的 机 器 码 ,从 而得 到 较 高 的 性 能。 10.多 线 程 多 线 程 机 制 使 应 用 程 序 能 够 并 行 执 行 ,而 且 同 步 机 制 保证了 对 共 享 数 据 的正 确 操 作 。 通 过 使 用 多 线 程 ,程 序 设 计 者可 以 分 别 用 不 同 的线 程 完 成 特 定 的 行为 ,而不 需 要 采 用 全 局的 事 件 循 环 机 制 ,这 样 就 很 容 易 地 实 现 网 络 上 的 实 时 交 互行为 。 11.动 态 性 Java的 设 计 使 它 适 合 于 一 个 不 断 发 展 的 环 境 。 在 类 库 可以 自 由 地 加 入新 的 方 法 和 实 例 变 量 而 不 会 影 响 用 户 程 序的 执 行 。 并 且Java通 过 接 口 来 支 持 多重 继 承 ,使 之 比 严 格 的类 继 承 具 有 更 灵 活 的 方 式 和 扩 展 性 。 二 、 Java Applet Java语 言 的 特 性 使 它 可 以 最 大 限 度 地 利 用 网 络 。 Applet是Jav a的 小 应 用 程序 ,它 是 动 态 、 安 全 、 跨 平 台 的 网 络 应 用 程 序。 Java Applet嵌 入HTML语 言 ,通 过 主页 发 布 到 Internet。 网 络 用 户访 问 服 务 器 的Applet时 ,这些Applet 从网 络 上 进 行 传 输 ,然 后 在支 持 Java 的 浏 览 器 运 行 。 由 于 Java语 言 的 安 全 机 制,用 户一 旦 载 入Applet,就 可 以 放 心 地 来 生 成 多 媒 体 的 用 户 界 面 或完 成 复 杂 的计 算 而 不 必 担 心 病毒 的 入 侵 。 虽 然 Applet可 以 和图 像 、 声 音 、 动 画 等 一 样 从 网 络上 下 载 ,但 它 并 不同 于 这些 多 媒 体 的 文 件 格 式 ,它 可 以 接 收 用 户 的 输 入 ,动 态 地进 行改 变 ,而 不 仅 仅是 动 画 的 显 示 和 声 音 的 播 放 。 三 、 丰 富 的 类 库 Java提 供 了 大 量 的 类 以 满 足 网 络 化 、 多 线 程 、 面 向 对 象系统 的 需 要 。 1.语 言 包 提 供 的 支 持 包 括 字 符 串 处 理 、 多 线 程 处 理 、例外 处 理 、 数 学 函数 处 理 等 ,可 以 用 它 简 单 地 实 现 Java 程 序的 运 行 平 台 。 2.实 用 程 序 包 提 供 的 支 持 包 括 哈 希 表 、 堆 栈 、 可 变 数组、 时 间 和 日 期 等。 3.输 入 输 出 包 用 统 一 的 "流 "模 型 来 实 现 所 有 格式 的 I/O,包括 文 件 系 统 、 网 络、 输 入 /出 设 备 等 。 4.低 级 网 络 包 用 于 实 现 Socket编 程 。 5.抽 象 图 形 用 户 接 口 包 实 现 了 不 同 平 台 的 计 算 机 的 图形用 户 接 口 部 件 ,包括 窗 口 、 菜 单 、 滚 动 条 、 对 话 框 等 ,使得 Java可 以 移 植 到 不 同平 台 的 机 器 。 6.网 络 包 支 持 Internet的 TCP/IP协 议 ,提 供 了 与 Internet的 接 口。它 支 持 URL连 接,WWW的 即 时 访 问 ,并 且 简 化 了 用 户 /服 务 器 模型 的 程 序 设 计 。 四 、 Java和 C、 C++ 对 于 变 量 声 明 、 参 数 传 递 、 操 作 符 、 流 控 制 等 ,Java 使用了 和 C、 C++相 同的 传 统 ,使 得 熟 悉 C、 C++的 程 序 员 能 很 方 便地 进 行 编 程 。 同 时,Java为 了 实 现 其简 单 、 鲁 棒 、 安 全 等 特性 ,也 摒 弃 了 C和 C++ 许 多 不 合 理 的 内容 。 1.全 局 变 量 Java程 序 ,不 能 在 所 有 类 之 外 定 义 全 局 变 量 ,只 能 通 过在一 个 类 定 义 公用 、 静 态 的 变 量 来 实 现 一 个 全 局 变 量 。例 如 : Class GlobalVar{ public static global_var; } 在 类 GlobalVar 定 义 变 量 global_var为 public stat-ic,使 得 其 它类可 以 访 问 和 修 改该 变 量 。 Java对 全 局 变 量 进 行 了 更 好 的 封 装 。 而 在 C和 C++ , 依 赖于不 加 封 装 的 全局 变 量 常 常 造 成 系 统 的 崩 溃 。 2.Goto Java不 支 持 C、 C++ 的 goto语 句 ,而 是 通 过 例 外 处 理 语 句 try,Ca tch, final等 来 代替 C、 C++ 用 goto来 处 理 遇 到 错 误 时 跳 转 的情 况 ,使 程 序 更 可 读且 更 结 构 化 。 3.指 针 指 针 是 C、 C++ 最 灵 活 ,也 是 最 容 易 产 生 错 误 的 数 据 类型。 由 指 针 所 进 行的 内 存 地 址 操 作 常 会 造 成 不 可 预 知 的 错误 ,同 时 通 过 指 针 对某 个 内 存 地 址 进 行显 式 类 型 转 换 后 ,可以 访 问 一 个 C++ 的 私 有 成 员 ,从 而 破 坏 安全 性 ,造 成 系 统 的崩 溃 。 而 Java 对 指 针 进 行 完 全 的 控 制 ,程 序 员 不 能 直 接进行 任 何 指 针 操 作 ,例 如把 整 数 转 化 为 指 针 ,或 者 通 过 指 针释放 某 一 内 存 地 址 等 。 同时 ,数 组 作 为 类 在Java 实 现 ,良 好 地解 决 了 数 组 访 问 越 界 这 一 C、 C++ 不 作 检 查的 错 误 。 4.内 存 管 理 在 C ,程 序 员 通 过 库 函 数 malloc()和 free()来 分 配 和 释 放 内存 , C++ 则 通 过 运算 符 new和 delete来 分 配 和 释 放 内 存 。 再 次 释放 已 释 放 的 内 存 块或 未 被 分 配 的 内存 块 ,会 造 成 系 统 的 崩溃 ;同 样 ,忘 记 释 放 不 再 使 用 的 内 存 块 也会 逐 渐 耗 尽 系 统资源 。 而 在 Java ,所 有 的 数 据 结 构 都 是 对 象 , 通 过 运 算 符 new为它们 分 配 内 存 堆。 通 过 new得 到 对 象 的 处 理 权 ,而 实 际 分 配 给对 象 的 内 存 可 能随 程 序 运 行 而 改变, Java对 此 自 动 地 进 行 管理 并 且 进 行 垃 圾 收 集 ,有 效 防 止 了 由 于程 序 员 的 误 操 作而导 致 的 错 误 ,并 且 更 好 地 利 用 了 系 统 资 源 。 5.数 据 类 型 的 支 持 在 C、 C++ ,对 于 不 同 的 平 台 ,编 译 器 对 于 简 单 数 据 类 型如in t,float等 分 别 分配 不 同 长 度 的 字 节 数 ,例 如 :int在 IBM PC为 16位 ,在 VAX-11 为32位 ,这 导 致 了 代 码的 不 可 移 植 性 ,但 在 Java ,对 于 这 些 数 据 类 型 总 是 分 配 固 定 长 度 的 位 数 ,如 对 int型 ,它 总 占 32位 ,这 就 保 证 了 Java的 平 台 无 关 性 。 6.类 型 转 换 在 C、 C++ ,可 以 通 过 指 针 进 行 任 意 的 类 型 转 换 ,常 常 带来不 安 全 性 ,而 Java ,运 行 时 系 统 对 对 象 的 处 理 要 进 行 类型 相 容 性 检 查 ,以 防 止不 安 全 的 转 换 。 7.头 文 件 C、 C++ 用 头 文 件 来 声 明 类 的 原 型 以 及 全 局 变 量 、 库 函数等 ,在 大 的 系 统 ,维 护 这 些 头 文 件 是 很 困 难 的 。 而 Java不支 持 头 文 件 ,类 成 员的 类 型 和 访 问 权限 都 封 装 在 一 个 类 ,运 行 时 系 统 对 访 问 进 行 控 制 ,防 止 对 私有 成 员 的 操 作 。 同时 ,Java 用 import语 句 来 与 其 它 类 进 行 通 讯 ,以 便 使 用它 们 的方法 。 8.结 构 和 联 合 C、 C++ 的 结 构 和 联 合 所 有 成 员 均 为 公 有 ,这 就 带 来了安 全 性 问 题 。Java 不 包 含 结 构 和 联 合 ,所 有 的 内 容 都 封装 在 类 。 9.预 处 理 C、 C++ 用 宏 定 义 来 实 现 的 代 码 给 程 序 的 可 读 性 带 来 了困难 。 在 Java ,不 支 持 宏 ,它 通 过 关 键 字 final 来 声 明 一 个 常量 ,以 实 现 宏 定 义 广 泛 使 用 的 常 量定 义 。 § 1.3 简 单 的 Java程 序 下 面 我 们 先 介 绍 两 个 简 单 的 Java程 序 ,并 对 其 进 行 分 析。 例 1.1. public class HelloWorldApp { //an application public static void main (String args[ ]){ System.out.println("Hello World!"); } } 本 程 序 的 作 用 是 输 出 下 面 一 行 信 息 : Hello World! 程 序 ,首 先 用 保 留 字 class来 声 明 一 个 新 的 类 ,其 类 名 为Hell oWorldApp,它 是 一 个公 共 类 (public)。 整 个 类 定 义 由 大 括 号 {}括起 来 。 在 该 类 定义 了 一 个 main ()方 法 ,其 public表 示 访 问权 限 ,指 明 所 有 的 类 都 可 以 使 用 这 一 方 法 ;static指 明 该 方法 是 一 个 类方 法 ,它 可 以 通 过 类 名 直 接 调 用 ;void则 指 明 main()方法 不 返 回 任何 值 。 对 于 一 个 应 用程 序 来 说 ,main()方 法 是 必需 的 ,而 且 必 须 按 照 如 上 的 格 式 来 定义 。 Jave解 释 器 在 没 有生成 任 何 实 例 的 情 况 下 ,以 main()作 为 入 口 来 执 行 程 序 。 Jave程序 可 以 定 义 多 个 类 , 每 个 类 可 以 定 义 多 个 方 法 ,但 是 最多 只 能 有 一 个 公 共 类,main()方 法 也 只 能 有 一 个 ,作 为 程 序 的入 口 。 main()方 法 定 义 ,括 号 () 的 String args[ ]是传 递 给 main()方法 的 参 数 ,参 数 名 为 args,它 是 类 String的 一 个 实 例 ,参 数 可 以为 0个 或 多 个,每 个 参 数 用 "类 名 参数 名 "来 指 定 , 多个 参 数 间 用 逗 号 分 隔 。 在 main()方 法 的 实 现(大 括 号 ),只有 一 条 语句 : System.out.println ("Hello World!"); 它 用 来 实 现 字 符串 的 输 出 ,这 条 语 句 实 现 与 C语 言 的printf 语 句 和 C++ cout<<语句 相 同 的 功 能 。 另 外 ,//后 的 内 容 为 注 释 。 现 在 我 们 可 以 运 行 该 程 序 。 首 先 把 它 放 到 一 个 名 为HelloWor ldApp.java的 文 件 ,这 里 ,文 件 名 应 和 类 名 相 同 ,因 为 Java解释 器 要 求 公 共 类 必 须 放在 与 其 同 名 的 文 件 。 然 后 对 它 进行 编 译 : C:\>javac HelloWorldApp.java 编 译 的 结 果 是 生 成 字 节 码 文 件 HelloWorldApp.class。最 后 用java 解 释 器 来 运 行 该字 节 码 文 件 : C:\>java HelloWorldApp 结 果 在 屏 幕 上 显 示 Hello World! 我 们 再 来 看 下 面 的 一 个 例 子 : 例 1.2 import java.awr.*; import java.applet.*; public class HelloWorldApplet extends Applet { //an applet public void paint(Graphics g){ g.drawString ("Hello World!",20,20); } } 这 是 一 个 简 单 的 Applet(小 应 用 程 序 )。 程 序 ,首 先 用 import语句 输 入 java.awr和java.applet下 所 有 的 包 ,使 得 该 程 序 可 能 使 用这 些 包 所 定 义 的类 , 它 类 似 于 C 的#include 语 句 。 然 后 声明 一 个 公 共 类 HelloWorldApplet,用 extends指明 它 是 Applet的 子 类。 在类 ,我 们 重 写 父 类 Ap-plet的 paint()方 法 ,其 参 数 g为 Graphics类,它表 明 当 前 作 画 的 上下 文 。 在 paint()方 法 ,调 用 g的 方 法 drawString(),在坐 标 (20,20)处输 出 字 符 串 ""Hello World!",其 坐 标是 用 象 素 点 来 表 示 的 。 这 个 程 序 没 有 实 现 main()方 法 ,这 是 Applet与 应 用 程序 Applica tion(如 例 1)的 区 别 之一 。 为 了 运 行 该 程 序 ,首 先 我们 也 要 把它 放 在 文 件HelloWorldAppl et.java ,然 后 对 它 进行 编 译 : C:\>javac HelloWorldApplet.java 得 到 字 节 码 文 件 HelloWorldApplet.class。 由 于 Applet 没 有main()方法 作 为 Java解 释 器的 入 口 ,我 们 必 须 编 写 HTML文 件 ,把 该 Applet嵌入 其 ,然 后 用 appletviewer来 运 行 ,或 在支 持 Java的 浏 览 器 上运 行 。 它 的 <HTML>文 件 如 下 : <HTML> <HEAD> <TITLE> An Applet </TITLE> </HEAD> <BODY> <applet code="HelloWorldApplet.class" width=200 height=40> </applet> </BODY> </HTML> 其 用 <applet>标 记 来 启 动 HelloWorldApplet,code指 明字 节 码所在 的 文 件 ,width和height指 明 applet所 占 的 大 小 ,我 们 把 这 个 HTML文件 存 入Example.html,然 后 运 行 : C:\>appleviewer Example.html 这 时 屏 幕 上 弹 出 一 个 窗 口 ,其 显 示 Hello World!,显 示 结果如 图 : 从 上 述 例 子 可 以 看 出 ,Java程 序 是 由 类 构 成 的 ,对 于 一个应 用 程 序 来 说 ,必 须有 一 个 类 定 义 main()方 法 ,而 对 applet来说 ,它 必 须 作 为 Applet的一 个 子 类 。 在 类 的 定 义 ,应 包 含 类变 量 的 声 明 和 类 方 法 的 实 现 。 Java在 基 本 数据 类 型 、 运算 符 、 表达 式 、 控 制 语 句 等 方 面 与 C、 C++基 本 上 是 相 同 的 ,但 它 同 时 也增 加 了 一 些 新 的 内 容 ,在 以 后 的 各 章 ,我 们会 详 细 介 绍 。 本 节 ,只 是 使 大 家 对Java程 序 有 一 个 初 步 的了解 。 第 二 章   数 据 类 型 § 2.1 数 据 类 型 数 据 类 型 指 明 了 变 量 或 表 达 式 的 状 态 和 行 为 。 Java 的数据 类 型 如 下 所 示 : Java不 支 持 C、 C++ 的 指 针 类 型 、 结 构 体 类 型 和 共 用 体类型 。 本 章 我 们 主 要 介 绍 简 单 类 型 。 § 2.2 常 量 与 变 量 一 、 常 量 Java 的 常 量 值 是 用 文 字 串 表 示 的 ,它 区 分 为 不 同的 类 型,如整 型 常 量 123,实 型常 量 1.23,字 符 常 量 ‘ a’ ,布 尔 常 量 true、 false以 及 字 符 串 常 量"This is a constant string."。 与 C、 C++不 同 ,Java 不 能 通 过 #define命 令 把 一 个 标 识 符 定义为 常 量 ,而 是 用 关键 字 final来 实 现 ,如 final double PI=3.14159( 有 关 final的 用 法 见[6.2.3])。 二 、 变 量 变 量 是 Java程 序 的 基 本 存 储 单 元 ,它 的 定 义 包 括 变 量名、 变 量 类 型 和 作 用 域几 个 部 分 。 ① 变 量 名 是 一 个 合 法 的 标 识 符 ,它 是 字 母 、 数 字 、 下 划线或 美 元 符 "$ "的 序 列,Java对 变 量 名 区 分 大 小 写 ,变量 名 不 能 以 数 字 开 头 ,而 且 不 能为 保 留 字 。 合 法 的 变 量 名如 :myName、 value-1、 dollar$ 等 。 非 法 的 变 量 名 如 : 2mail、room#、 class (保 留 字 )等 ,变量 名 应 具 有 一 定 的 含 义 ,以 增 加 程 序 的可 读 性 。 ② 变 量 类 型 可 以 为 上 面 所 说 的 任 意 一 种 数 据 类 型 。 ③ 变 量 的 作 用 域 指 明 可 访 问 该 变 量 的 一 段 代 码 。 声 明一个 变 量 的 同 时 也 就指 明 了 变 量 的 作 用 域 。 按 作 用 域 来 分 ,变 量 可 以 有 下 面 几 种:局 部 变 量 、 类 变 量 、方 法 参 数 、 例外 处 理 参 数 。 局 部 变 量 在 方 法 或 方 法 的 一 块 码 声 明 ,它 的 作 用域 为它 所 在 的 代 码 块 (整 个 方 法 或 方 法 的 某 块 代 码 )。 类 变 量 在 类 声 明 ,而 不 是 在 类 的 某 个 方 法 声 明 , 它的作 用 域 是 整 个 类 。 方 法 参 数 传 递 给 方 法 ,它 的 作 用 域 就 是 这 个 方 法 。 例 外 处 理 参 数 传 递 给 例 外 处 理 代 码 ,它 的 作 用 域 就 是 例外处 理 部 分 。 在 一 个 确 定 的 域 ,变 量 名 应 该 是 唯 一 的 。 通 常 , 一 个域用 大 括 号 {}来 划 定 。 ④ 变 量 的 声 明 格 式 为 : type identifier[=value][,identifier[=value]… ]; 例 如 : int a, b, c; double d1, d2=0.0; 其 ,多 个 变 量 间 用 逗 号 隔 开 ,d2=0.0对 实 型 变 量 d2赋 初 值0.0, 只 有 局 部 变 量 和 类变 量 是 可 以 这 样 赋 初 值 的 ,而 方 法 参 数和 例 外 处 理 参 数 的 变量 值 是 由 调 用 者 给 出的 。 § 2.3 整 型 数 据 一 、 整 型 常 量 : 与 C,C++相 同 ,Java的 整 常 数 有 三 种 形 式 : ① 十 进 制 整 数 ,如 123,-456,0 ② 八 进 制 整 数 ,以 0开 头 ,如 0123表 示 十 进 制 数 83,-011 表 示十进 制 数 -9。 ③ 十 六 进 制 整 数 ,以 0x或 0X开 头 ,如 0x123表 示 十 进 制 数291,-0X12 表 示 十 进 制 数 -18。 整 型 常 量 在 机 器 占 32位 ,具 有 int型 的 值 ,对 于 long 型 值 ,则要 在 数 字 后 加 L或 l,如123L表 示 一 个 长 整 数 ,它 在 机 器 占 64位 。 二 、 整 型 变 量 : 整 型 变 量 的 类 型 有 byte、 short、 int、 long四 种 。 下 表 列 出各类 型 所 在 内 存 的 位数 和 其 表 示 范 围 。 int类 型 是 最 常 使 用 的 一 种 整 数 类 型 。 它 所 表 示 的 数 据范围 足 够 大 ,而 且适 合 于 32位 、 64位 处 理 器 。 但 对 于 大 型 计算 ,常 会 遇 到 很 大 的整 数 ,超 出 int类型 所 表 示 的 范 围 ,这 时 要使 用 long类 型 。 由 于 不 同 的 机 器 对 于 多 字 节 数 据 的 存 储 方 式 不 同 ,可 能是从 低 字 节 向高 字 节 存 储 ,也 可 能 是 从 高 字 节 向 低 字 节 存 储 ,这 样 ,在 分 析 网络 协 议 或 文 件格 式 时 , 为 了 解 决 不 同 机 器上 的 字 节 存 储 顺 序 问 题 ,用 byte类 型来 表 示 数 据 是合 适 的 。而 通 常 情 况 下 ,由 于 其 表 示 的 数 据 范 围 很 小 ,容 易 造成 溢 出 ,应 避 免使 用 。 short类 型 则 很 少 使 用 ,它 限 制 数 据 的 存 储 为 先 高 字 节 ,后低字 节 ,这 样 在 某些 机 器 会 出 错 。 三 、 整 型 变 量 的 定 义 ,如 : byte b; //指定变量b为byte型 short s; //指定变量s为short型 int i; //指定变量i为int型 long l; //指定变量l为long型 § 2.4 浮 点 型 (实 型 )数 据 一 、 实 型 常 量 与 C,C++相 同 ,Java的 实 常 数 有 两 种 表 示 形 式 : ① 十 进 制 数 形 式 ,由 数 字 和 小 数 点 组 成 ,且 必 须 有 小 数点,如 0.123, .123,123.,123.0 ② 科 学 计 数 法 形 式 。 如 :123e3或 123E3,其 e或 E之 前 必 须有数 字 ,且 e或 E后面 的 指 数 必 须 为 整 数 。 实 常 数 在 机 器 占 64位 ,具 有 double型 的 值 。 对 于 float 型的值 ,则 要 在 数 字后 加 f或 F,如 12.3F,它 在 机 器 占 32位 , 且 表示 精 度 较 低 。 二 、 实 型 变 量 实 型 变 量 的 类 型 有 float和 double两 种 ,下 表 列 出 这 两 种 类型所 占 内 存 的 位数 和 其 表 示 范 围 。 数据类型 所占位数 数的范围 float 32 3.4e-038~3.4e+038 double 64 1.7e-308~1.7e+308 双 精 度 类 型 double比 单 精 度 类 型 float具 有 更 高 的 精 度 和更大 的 表 示 范 围 ,常 常 使 用 。 三 、 实 型 变 量 定 义 ,如 float f; //指 定 变 量 f为 float型 double d; //指 定 变 量 d为 double型 [注 ]与 C、 C++不 同 ,Java 没 有 无 符 号 型 整 数 ,而 且 明 确 规定了 整 型 和 浮点 型 数 据 所 占 的 内 存 字 节 数 ,这 样 就 保 证 了安 全 性 、 鲁 棒 性和 平 台 无 关 性。 § 2.5 字 符 型 数 据 一 、 字 符 常 量 字 符 常 量 是 用 单 引 号 括 起 来 的 一 个 字 符 ,如 ‘ a’ , ‘ A’。另 外 ,与 C、C++相 同 ,Java也 提 供 转 义 字 符 ,以 反 斜 杠 (\)开 头 ,将其 后 的 字 符转 变 为 另 外 的 含义 ,下 表 列 出 了 Java 的 转 义 字符 。 与 C、 C++不 同 ,Java 的 字 符 型 数 据 是 16位 无 符 号 型 数 据 ,它表 示 Unicode集,而 不 仅 仅 是 ASCII集 ,例 如 \u0061表 示 ISO拉 丁 码的 ‘ a’ 。 转义字符 描述 \ddd 1到3位8进制数据所表示的字符(ddd) \uxxxx 1到4位16进制数所表示的字符(xxxx) \' 单引号字符 \\ 反斜杠字符 \r 回车 \n 换行 \f 走纸换页 \t 横向跳格 \b 退格 二 、 字 符 型 变 量 字 符 型 变 量 的 类 型 为 char,它 在 机 器 占 16位 ,其 范 围 为 0~65 535。 字 符 型变 量 的 定 义 如 : char c='a'; //指 定 变 量 c为 char型 ,且 赋 初 值 为 'a' 与 C、 C++不 同 ,Java 的 字 符 型 数 据 不 能 用 作 整 数 , 因 为Java不提 供 无 符号 整 数 类 型 。 但 是 同 样 可 以 把 它 当 作 整 数 数 据来 操 作 。 例 如 : int three=3; char one='1'; char four=(char)(three+one);//four='4' 上 例 ,在 计 算 加 法 时 ,字 符 型 变 量 one被 转 化 为 整 数 , 进行相 加 ,最 后 把 结果 又 转 化 为 字 符 型 。 三 、 字 符 串 常 量 与 C、 C++相 同 ,Java的 字 符 串 常 量 是 用 双 引 号 ("")括起 来 的一 串 字 符 ,如"This is a string.\n"。 但 不 同 的 是 ,Java 的 字 符 串 常 量 是 作 为String类 的 一 个 对 象 来处 理 的 ,而不 是 一 个 数 据 。 有 关 类 String,我 们 将 在 第 七 章 讲 述。 § 2.6 布 尔 型 数 据 布 尔 型 数 据 只 有 两 个 值 ,true和 false,且 它 们 不 对 应 于 任何整 数 值 。 在 流 控制 常 用 到 它 。 布 尔 型 变 量 的 定 义 如 : boolean b=true; //定 义 b为 布 尔 型 变 量 ,且 初 值 为 true § 2.7 举 例 例 2.1.下 例 用 到 了 前 面 提 到 的 数 据 类 型 ,并 通 过 屏 幕显 示 它 们 的 值 。 public class SimpleTypes{ public static void main( String args[] ){ byte b=0x55; short s=0x55ff; int i=1000000; long l=0xfffL; char c='c'; float f=0.23F; double d=0.7E-3; boolean bool=true; System.out.println("b = "+b); System.out.println("s = "+s); System.out.println("i = "+i); System.out.println("c = "+c); System.out.println("f = "+f); System.out.println("d = "+d); System.out.println("bool = "+bool); } } 编译并运行该程序,输出结果为: C:\>java SimpleTypes b = 85 s = 22015 i = 1000000 l = 4095 c = c f = 0.23 d = 0.0007 bool = true § 2.8 各 类 数 值 型 数 据 间 的 混 合 运 算 一 、 自 动 类 型 转 换 整 型 、 实 型 、 字 符 型 数 据 可 以 混 合 运 算 。 运 算 , 不同类 型 的 数 据 先转 化 为 同 一 类 型 ,然 后 进 行 运 算 。 转 换 从低 级 到 高 级 ,如 下 图: 转 换 规 则 为 : ① (byte或 short) op int→ int ② (byte或 short或 int) op long→ long ③ (byte或 short或 int或 long) op float→ float ④ (byte或 short或 int或 long或 float) op double→ double ⑤ char op int→ int 其 ,箭 头 左 边 表 示 参 与 运 算 的 数 据 类 型 ,op为 运 算 符 (如加、 减 、 乘 、除 等 ),右 边 表 示 转 换 成 的 进 行 运 算 的 数 据 类 型。 例2.2 public class Promotion{ public static void main( String args[ ] ){ byte b=10; char c='a'; int i=90; long l=555L; float f=3.5f; double d=1.234; float f1=f*b; // float * byte -> float int i1=c+i;    // char + int -> int long l1=l+i1; // long + int ->ling double d1=f1/i1-d; // float / int ->float, float - double -> double} } 二 、 强 制 类 型 转 换 高 级 数 据 要 转 换 成 低 级 数 据 ,需 用 到 强 制 类 型 转 换 ,如 : int i; byte b=(byte)i; //把 int型 变 量 i强 制 转 换 为 byte型 这 种 使 用 可 能 会 导 致 溢 出 或 精 度 的 下 降 ,最 好 不 要 使 用。 第 三 章   运 算 符 和 表 达式 运 算 符 指 明 对 操 作 数 所 进 行 的 运 算 。 按 操 作 数 的 数 目来分 ,可 以 有 一元 运 算 符 (如 ++、--),二 元 运 算 符 (如 +、 >)和 三元 运 算 符 (如?:),它 们 分 别 对 应 于一 个 、 两 个 和 三 个 操 作 数。 对 于 一 元 运 算 符 来 说 ,可 以 有 前缀 表 达 式 (如 ++i )和 后 缀表 达 式 (如 i++),对 于 二 元 运 算 符 来 说 则 采 用 缀 表 达 式 (如 a+b)。 按 照运 算 符 功 能 来 分 ,基 本 的 运 算 符 有 下 面 几 类 : 1.算 术 运 算 符 (+,-,*,/,%,++,--) 2.关 系 运 算 符 (>,<,>=,<=,==,!=) 3.布 尔 逻 辑 运 算 符 (!,&&,||) 4.位 运 算 符 (>>,<<,>>>,&,|,^,~ ) 5.赋 值 运 算 符 (=,及 其 扩 展 赋 值 运 算 符 如 +=) 6.条 件 运 算 符 ( ?:) 7.其 它 (包 括 分 量 运 算 符 · ,下 标 运 算 符 [],实 例 运 算 符 instanc eof,内 存 分 配运 算 符 new,强 制 类 型 转 换 运 算 符 (类 型 ), 方 法调 用 运 算 符 () 等 ) 本 章 我 们 主 要 讲 述 前 6类 运 算 符 。 § 3.1 算 术 运 算 符 算 术 运 算 符 作 用 于 整 型 或 浮 点 型 数 据 ,完 成 算 术 运 算。 一 、 二 元 算 术 运 算 符 ,如 下 表 所 示 运算符 用法 描述 + op1+op2 加 - op1-op2 减 * op1*op2 乘 / op1/op2 除 % op1%op2 取模(求余) Java对 加 运 算 符 进 行 了 扩 展 ,使 它 能 够 进 行 字 符 串 的连 接,如 "abc"+"de",得到 串 "abcde"。 我 们 将 在第 七 章 讲 解 。 与 C、 C++不 同 ,对 取 模 运 算 符 %来 说 ,其 操 作 数 可 以为浮点 数 , 如37.2%10=7.2。 二 、 一 元 算 术 运 算 符 ,如 下 表 所 示 : 运算符 用法 描述 + +op 正值 - -op 负值 ++ ++op,op++ 加1 -- --op,op-- 减1 i++与 ++i的 区 别 i++在 使 用 i之 后 ,使 i的 值 加 1,因 此 执 行 完 i++后 ,整 个 表达式的 值 为 i,而 i的 值变 为 i+1。 ++i在 使 用 i之 前 ,使 i的 值 加 1,因 此 执 行 完 ++i后 ,整 个 表达式和 i的 值 均 为 i+1。 对 i--与 --i同 样 。 例 3.1.下 面 的 例 子 说 明 了 算 术 运 算 符 的 使 用 public class ArithmaticOp{ public static void main( String args[] ){ int a=5+4; //a=9 int b=a*2; //b=18 int c=b/4; //c=4 int d=b-c; //d=14 int e=-d; //e=-14 int f=e%4; //f=-2 double g=18.4; double h=g%4; //h=2.4 int i=3; int j=i++; //i=4,j=3 int k=++i; //i=5,k=5 System.out.println("a = "+a); System.out.println("b = "+b); System.out.println("c = "+c); System.out.println("d = "+d); System.out.println("e = "+e); System.out.println("f = "+f); System.out.println("g = "+g); System.out.println("h = "+h); System.out.println("i = "+i); System.out.println("j = "+j); System.out.println("k = "+k); } } 其结果为: C:\>java ArithmaticOp a = 9 b = 18 c = 4 d = 14 e = -14 f = -2 g = 18.4 h = 2.4 i = 5 j = 3 k = 5 § 3.2 关 系 运 算 符 关 系 运 算 符 用 来 比 较 两 个 值 ,返 回 布 尔 类 型 的值true或 false。关 系 运 算 符 都 是 二 元 运 算 符 ,如 下 表 所 示 : 运算符 用法 返回true的情况 > op1>op2 op1大于op2 >= op1>=op2 op1大于或等于op2 < op1<op2 op1小于op2 <= op1<=op2 op1小于或等于op2 == op1==op2 op1与op2相等 != op1!=op2 op1与op2不等 Java ,任 何 数 据 类 型 的 数 据 (包 括 基 本 类 型 和 组 合 类 型)都可 以 通 过 ==或!=来 比 较 是 否 相 等 (这 与 C、 C++不 同 )。 关 系 运 算 的 结 果 返 回 true或 false,而不是C、C++ 的 1或 0。 关 系 运 算 符 常 与 布 尔 逻 辑 运 算 符 一 起 使 用 ,作 为 流 控 制语句 的 判 断 条件 。 如 if( a>b && b==c) § 3.3 布 尔 逻 辑 运 算 符 布 尔 逻 辑 运 算 符 进 行 布 尔 逻 辑 运 算 ,如 下 表 所 示 : op1 op2 op1&&op2 op1||op2 !op1 false false false false true false true false true true true false false true false true true true true false } ·&&、‖ 为二元运算符,实现逻辑与、逻辑或。 ·! 为一元运算符,实现逻辑非。 ·对 于 布 尔 逻 辑 运 算 , 先 求 出 运 算 符 左 边 的 表 达 式 的 值 , 对 或 运 算 如 果 为 true, 则 整 个 表 达 式 的 结 果 为 true, 不 必对 运 算 符 右 边 的 表 达 式 再 进 行 运 算 ; 同 样 , 对 与 运 算 , 如果 左 边 表 达 式 的 值 为 false, 则 不 必 对 右 边的 表 达式 求 值 , 整个表 达 式 的 结果 为 false。 下面的例子说明了关系运算符和布尔逻辑运算符的使用。 public class RelationAndConditionOp{ public static void main( String args[] ){ int a=25,b=3; boolean d=a<b; //d=false System.out.println("a<b = "+d); int e=3; if(e!=0 && a/e>5) System.out.println("a/e = "+a/e); int f=0; if(f!=0 && a/f>5) System.out.println("a/f = "+a/f); else System.out.println("f = "+f); } } 其运行结果为: C:\>java RelationAndConditionOp a<b = false a/e = 8 f = 0 注 意 :上 例 ,第 二 个 if语 句 在 运 行 时 不 会 发 生 除 0溢 出的错 误 ,因 为 e!=0为false,所 以 就 不 需 要 对 a/e进 行 运 算 。 § 3.4 位 运 算 符 位 运 算 符 用 来 对 二 进 制 位 进 行 操 作 ,Java 提 供 了 如 下表所 示 的 位 运 算符 : 位 运 算 符 ,除   ~   以 外 ,其 余 均 为 二 元 运 算 符 。 操 作 数 只 能 为 整 型 和 字 符 型 数 据 。 3.4.1 补 码 Java使 用 补 码 来 表 示 二 进 制 数 ,在 补 码 表 示 ,最 高 位 为符号 位 ,正 数 的 符 号 位 为 0,负 数 为 1。 补 码 的 规 定 如 下 : 对 正 数 来 说 ,最 高 位 为 0,其 余 各 位 代 表 数 值 本 身 (以 二 进制表 示 ),如 +42的补 码 为 00101010。 对 负 数 而 言 ,把 该 数 绝 对 值 的 补 码 按 位 取 反 ,然 后 对 整个数 加 1,即 得 该 数的 补 码 。 如 -42的 补 码 为 11010110 (00101010 按位 取 反 11010101 +1=11010110 ) 用 补 码 来 表 示 数 ,0的 补 码 是 唯 一 的 ,都 为 00000000。 (而 在原码 ,反 码 表 示 ,+0和 -0的 表 示 是 不 唯 一 的 ,可 参 见 相 应 的书 籍 )。 而 且 可 以用 111111表 示 -1的 补 码 (这 也 是 补 码 与 原 码和 反 码 的 区 别 )。 3.4.2 按 位 取 反 运 算 符 ~ ~   是 一 元 运 算 法 ,对 数 据 的 每 个 二 进 制 位 取 反 ,即 把 1变为 0,把 0变 为 1。 例 如 : 0010101 ~ 1101010 注 意 ,~ 运 算 符 与 - 运 算 符 不 同 ,~ 21≠ -21。 3.4.3 按 位 与 运 算 符 & 参 与 运 算 的 两 个 值 ,如 果 两 个 相 应 位 都 为 1,则 该 位 的 结果为 1,否 则 为 0。即 : 0 & 0 = 0,0 &1 = 0,1 & 0 = 0,1 & 1 = 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值