1、java语言

1.1、java起源

1)1990年 sun公司 启动 绿色计划

2)1992年 创建 oak语言 →java

3)1994年 sun公司副总gosling 参加硅谷大会 演示java功能,震惊世界

5)1995年 sun公司 正式发布java第一个版本

1.2、java语言的特点

1)java语言是简单的

2)java语言是面向对象的

3)java语言是跨平台(操作系统)的 【即一次编译,到处运行】

4)java是高性能的

1.3、jdk

1.3.1、工欲善其事,必先利其器

为了能够运行你的Hello.java,你需要安装和配置jdk。

1.3.2、jdk是什么

1)jdk全称Java Development Kit,中文是java开发工具包

2)jdk是sun公司开发的

3)jdk包括:

(1)jre(java runtime envirnment)中文是java运行环境

(2)一堆Java工具(最终的两个工具:java编译器:javac.exe;java解释器:java.exe)

(3)Java基础的类库(共有3600多个,其中常用的有150个类库)

1.3.3、安装jdk和jre

1)jdk是开发环境

2)jre是运行环境

直接默认安装即可。

注意:安装完毕之后,需要配置环境变量。

1.4、第一个java程序:打印Hello!

1.4.1、编写java程序

//作者:

//功能:在控制台显示"Hello!"

//日期:

//public:表示这个类是公共的,一个java文件中只能有一个public类

//class:表示这是一个类

//Hello:类名(公共类的类名必须和文件名一致)

public class Hello

{

//一个主函数,相当于是程序的入库

public static void main (String args[])

{

//执行语句

System.out.println("Hello!");

}

}

1.4.2、编译java程序

javac Hello.java

1.4.3、执行java程序

java Hello

1.5、java编译和java程序运行关系

2、变量、数据类型

2.1、引出变量

请编写一个程序,计算两个数的和。

java程序内容如下:

public class jisuan

{

//一个主函数,相当于是程序的入库

public static void main (String args[])

{

//执行语句

int a=10; //定义一个整形变量,变量名a,并赋初值10

int b=20; //定义一个整形变量,变量名b,并赋初值20

int result=a+b;

//输出结果

System.out.println("结果是"+result);

}

}

不论是使用哪种高级程序语言编写程序,变量都是其程序的基本组成单位。java中基本数据类型的定义与c/c++中大体一致。

2.2、java基本数据类型

2.2.1、整数类型

整数类型可以表示一个整数,常用的整数类型有:byte,short,int,long

主要区别是:数据大小范围。

byte 一个字节 -128到127

short 两个字节 -32768到32767

int 四个字节 -2147483648到2147483647

long 八字节 -?到?

注意:

1)最高为是符号位,0表示正数,1表示负数。

2)int将负0定义为-128,其它类型也是这样。

3)负数最小值:-2^(字节数*8-1);正数最大值:2^(字节数*8-1)-1。

2.2.2、小数(浮点)类型

小数类型可以表示一个小数,常用的小数(浮点)类型有:float,double

主要区别是:数据大小范围。

2.2.3、布尔类型

布尔类型可以表示真或者假,类型是:boolean

例如:boolean spBool=true;

2.2.4、字符类型

字符类型可以表示单个字符,字符类型是char。

char是两个字节(可以存放汉字)。

多个字符我们称为字符串,在java中使用String数据类型表示。但是Sting不是基本数据类型,而是类,类是复合数据类型。

注意:在java中,对char进行运算的时候,直接当做ascii码对应的整数对待。

2.3、基本数据类型转换

2.3.1、自动转换

数据类型可以自动的从低精度→高精度。

byte<short<int<long<float<double

在java中的小数,默认是double。在小数后面加f,就是float类型。

2.3.2、强制转换

int a=(int)1.2;

int b=(int)1.9;

System.out.println(a);

System.out.println(b);

上述结果是:

1

1

注意:java中并不是四舍五入取整的,而是向下取整。

2.3.3、计算过程中的转换

int a=3;

int b=a+3.4;

System.out.println(b);

编译报错。错误:不兼容的类型:从double转换到int可能会有损失。

注意:当一个整数和一个double运算的时候,运算结果会向高精度转换。

3、运算符

3.1、算术运算符

1)+ 加

2)- 减

3)* 乘

4)/ 除

5)% 取模

6)++ 自加

7)-- 自减

8)+= 左加

9)-= 左减

10)/= 左除

11)%= 左取模

3.2、关系运算符

1)== 等于

2)> 大于

3)< 小于

4)>= 大于等于

5)<= 小于等于

6)!= 不等于

请编写一个程序,该程序可以接收两个数(可以是整数,也可以是小数),并判断两个数是大于?小于?还是等于?

java程序内容如下:

import java.io.*;

public class Demo

{

public static void main (String args[])

{

try{

//输入流,从键盘接收数

InputStreamReader isr= new InputStreamReader(http://System.in);

BufferedReader br=new BufferedReader(isr);

//给出输入提示

System.out.println("请输入第一个数");

//从控制台读取一行数据

String a1=br.readLine();

//给出输入提示

System.out.println("请输入第二个数");

//从控制台读取二行数据

String a2=br.readLine();

//把String转换成float

float num1=Float.parseFloat(a1);

float num2=Float.parseFloat(a2);

if(num1>num2)

{

System.out.println("第一个数大");

}

if(num1==num2)

{

System.out.println("相等");

}

if(num1<num2)

{

System.out.println("第二个数大");

}

}catch(Exception e)

{

e.printStackTrace();

}

}

}

3.3、逻辑运算符

用于判断逻辑关系的运算符。

1)&& 与

2)|| 或

3)! 非

3.4、数字运算

1)floor

floor 返回不大于的最大整数

2)round

round 则是4舍5入的计算,入的时候是到大于它的整数

round方法,它表示“四舍五入”,算法为Math.floor(x+0.5),即将原来的数字加上0.5后再向下取整,所以,Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11。

3)ceil

ceil 则是不小于他的最小整数

4、三大流程控制

4.1、顺序控制

听其名而知其意,让程序可以顺序的执行。

如果没有遇到特殊情况,java程序是按照从上到下,从左到右,顺序执行。

4.2、分支控制

让程序有选择的执行,分支控制有三种:

1)单分支

2)双分支

3)多分支

4.2.1、单分支

基本语法:

if(条件表达式){

语句;

}

4.2.2、双分支

基本语法:

if(条件表达式){

语句;

}else{

语句;

}

4.2.3、多分支

4.2.3.1、if多分支

基本语法:

if(条件表达式){

语句;

}else if(条件表达式){

语句;

}else if(条件表达式){

语句;

}else{

语句;

}

注意:多分支程序只执行第一个匹配成功的条件语句,后面的条件语句不会执行。

4.2.3.2、switch多分支

基本语法:

switch(条件表达式){

case 常量1:

语句1;

break;

case 常量2:

语句2;

break;

......

case 常量n:

语句n;

break;

default:

语句;

break;

}

注意:

1)条件表达式的数据类型,应和常量的数据类型一致。

2)switch中条件表达式的可用数据类型主要是:byte、short、int、char、enum。

4.3、循环控制

听其名而知其意,就是让你的代码可以循环的执行。

4.3.1、for循环

基本语法:

fro(循环初值;循环条件;不长){

语句; //循环体

}

请编写一个程序,可以打印10句“你好,我是刘德华同志!”

java程序内容如下:

for(int i=0;i<10;i++)

{

System.out.println("你好,我是刘德华同志!");

}

4.3.2、while循环

基本语法:

while(循环条件){

语句; //循环体

}

注意:while循环是先判断再执行语句。

java程序内容如下:

int i=0;

while(i<10)

{

System.out.println("你好,我是刘德华同志!");

i++;

}

4.3.3、do while循环

基本语法:

do{

语句; //循环体

}while(循环条件);

注意:do while循环是先执行语句,再判断。

java程序内容如下:

int i=0;

do{

System.out.println("你好,我是刘德华同志!");

i++;

}while(i<10);

4.3.4、打印金字塔

请编写一个程序,可以接收一个整数,表示层数,打印出金字塔。

java程序内容如下:

import java.io.*;

public class Demo

{

public static void main (String args[]) throws Exception

{

//给出输入提示

System.out.println("请输入金字塔层数");

//输入流,从键盘接收数

BufferedReader br=new BufferedReader(new InputStreamReader(http://System.in));

//从控制台读取一行数据

String str1=br.readLine();

//把String转换成int

int lay=Integer.parseInt(str1);

System.out.println("\r\n"+"开始打印"+lay+"层金字塔"); //\r表示回车,\n表示换行

for(int i=1;i<=lay;i++){

//打印空格

for(int k=1;k<=lay-i;k++){

System.out.print(" ");

}

//打印*

for(int j=1;j<=2*i-1;j++){

System.out.print("*");

}

System.out.println();

}

System.out.println("\r\n"+"开始打印"+lay+"层空心金字塔");

for(int i=1;i<=lay;i++){

//打印空格

for(int k=1;k<=lay-i;k++){

System.out.print(" ");

}

//打印*

for(int j=1;j<=2*i-1;j++){

//判断该层是否属于顶层或者底层

if(j==1||i==lay){

System.out.print("*");

}else{

//如果是第一个*

if(j==1||j==2*i-1){

System.out.print("*");

}else{

System.out.print(" ");

}

}

}

System.out.println();

}

}

}

5、类与对象

5.1、java语言是面向对象的

计算机语言的发展向接近人的思维方式演变。

汇编语言 【面向机器】

c语言 【面向过程】

java语言 【面向对象】

java最大的特点就是面向对象。

对象总是存在内存中。

5.2、类和对象的关系

请编写一个程序,张老太养了两只猫猫:一只名字叫小白,今年3岁,白色。还有一只叫小花,今年100岁,花色。

java程序内容如下:

public class Demo

{

public static void main (String args[])

{

//创建第一只猫对象

Cat cat1=new Cat();

cat1.age=3;

cat1.name="小白";

cat1.color="白色";

//创建第二只猫对象

Cat cat2=new Cat();

cat2.age=100;

cat2.name="小花";

cat2.color="花色";

}

}

//java中定义一个猫类【类名的首字母是大写的】

class Cat

{

int age; //如果不给赋初值,则默认等于0

String name;

String color;

}

注意:从猫类到对象,目前有几种说法:

1)创建一个对象

2)实例化一个对象

3)把类实例化

5.3、类和对象的区别和联系

1)类是抽象的、概念的,代表一类事物,比如人类、猫类……

2)对象是具体的、实际的,代表一个具体事物。

3)类是对象的模板,对象是类的一个个体、实例。

5.4、类的定义

一个全面的类定义比较复杂,如下:

package 包名;

class 类名 extends 父类 implements 接口名{

成员变量;

构造方法;

成员方法;

}

5.5、成员变量

成员变量是类的一个组成部分,一般是基本数据类型,也可是引用类型(引用类型理解为:指向另外一个类),比如我们前面定义猫类的int age;就是成员变量。

5.5.1、如何创建对象

1)先声明再创建

①对象声明:类名 对象名;

②对象创建:对象名=new 类名();

2)一步到位法

类名 对象名=new 类名();

5.5.2、如何访问(使用)对象的成员变量

对象名.变量名

5.6、成员方法

5.6.1、成员方法的语法

成员方法也叫成员函数。

基本语法:

public 返回数据类型 方法名 (参数列表)

{

语句; //方法(函数)主体

}

1)参数列表:表示成员方法的输入

2)数据类型(返回类型):表示成员方法的输出

3)方法主体:表示为了实现某一功能代码块

注意:

1)方法名的首字母是小写的。

2)返回类型和返回结果的类型要一致。

3)方法的参数列表可以是多个的,并且参数列表的数据类型可以是任意类型int、float、double、char……

4)在调用某个成员方法的时候,给出具体数据的个数和类型要与参数列表相互匹配。

5)方法可以没有返回值

5.6.2、成员方法的声明

基本语法:

public 返回数据类型 方法名 (参数列表);

例如:public int test(int a); /*方法声明*/

5.7、构造方法

5.7.1、构造方法

构造方法是类的一种特殊的方法,它的主要作用是完成对新对象的初始化。

构造方法有几个特点:

1)构造方法名和类名相同

2)构造方法没有返回值

3)主要作用是完成对新对象的初始化

4)在创建新对象时,系统自动的调用该类的构造方法

5)一个类可以有多个构造方法

6)每个类都有一个默认的构造方法

5.7.2、默认构造方法(函数)

如果程序员没有定义的构造方法,系统会自动生成一个默认构造方法。

例如:Person类

Person(){

};

那么,当创建一个Person对象时,Person p1=new Person();

默认的构造方法就会被自动的调用。

如果程序员定了新的构造方法,那么默认构造方法将被覆盖。

5.8、this

java虚拟机会给每个对象分配this,代表当前对象。

this不能在类定义的外部使用,只能在类定义的方法中使用。

5.9、类变量、类方法

5.9.1、类变量

类变量是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量。

基本语法:

访问修饰符 static 数据类型 变量名;

如何访问类变量:

类名.类变量名 或者 对象名.类变量名

类变量与实例变量的区别:

1)加上static称为类变量或静态变量,否则称为实例变量

2)类变量是与类相关的,公共的属性

3)实例变量属于每个对象个体的属性

4)类变量可以通过类名.变量名直接访问

5.9.2、类方法

类方法是属于所有对象实例的。

基本语法:

访问修饰符 static 数据返回类型 方法名() {}

注意:类方法中不能访问非静态变量(类变量)。

如何访问类方法:

类名.类方法名 或者 对象名.类方法名

类方法与实例方法的区别:

1)类方法属于与类相关的、公共的方法

2)实例方法属于每个对象个体的方法

3)类方法可以通过类名.类方法名直接访问

请编写一个程序,统计学生的学费总和。

java程序内容如下:

public class Demo

{

public static void main (String args[])

{

Student stu1=new Student(29,"aa",340);

Student stu2=new Student(39,"bb",240);

System.out.println(Student.getTotalFee());

}

}

//定义学生类

class Student

{

int age;

String name;

int fee=0;

static int totalFee=0;

public Student(int age,String name,int fee)

{

this.age=age;

this.name=name;

totalFee+=fee;

}

//返回总学费[这是一个类方法(静态方法)]

//java规则:类变量原则上用类方法去访问。

public static int getTotalFee()

{

return totalFee;

}

}

5.10、四大特征

5.10.1、抽象

我们在前面去定义一个类的时候,实际上就是把一类事物共有的属性和行为提取出来,行程一个屋里模型(模板)。这种研究问题的方法称为抽象。

5.10.2、封装

5.10.2.1、封装的定义

封装就是把抽象出的数据和对数据的操作封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(成员方法),才能对数据进行操作。

5.10.2.2、访问控制修饰符

java提供四种访问控制修饰符号,控制方法和变量的访问权限:

1)公开级别:用public修饰,对外公开

2)受保护级别:用protected修饰,对子类和同一个包中的类公开

3)默认级别:没有修饰符号,向同一个包的类公开

4)私有级别:用private修饰,只有类本身可以访问,不对外公开

5.10.2.3、包

1)包的三大作用

①区分相同名字的类

②当类很多时,可以很好的管理类

③控制访问范围

2)打包命令

package com.zhangmeng;

3)命名规范

小写字母

例如:com.dimpt.zhangmeng

4)常用的包

一个包下,包含很多的类,java中常用的包有:

java.lang.* Object类位于java.lang包中,java.lang包包含着Java最基础和核心的类,在编译时会自动导入

java.util.* 工具包

java.net.* 网络开发包

java.awt.* 窗口工具包

5)如何引入包

基本语法:import 包名;

例如:import java.awt.*;

我们引入一个包的主要目的是:使用该包下的类。

5.10.3、继承

继承可以解决代码复用,让我们的编程更加靠近人类思维。当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends语句来声明继承父类。

class 子类 extends 父类

这样,子类就会自动拥有父类定义的某些属性和方法。

不是父类的所有属性、方法都可以被子类继承的。

1)父类的public修饰符的属性和方法,protected修饰符的属性和方法,默认修饰符的属性和方法被子类继承了。

2)父类的private修饰符的属性和方法不能被子类继承。

注意:

1)子类最多只能继承一个父类(指直接继承)

2)java所有类都是Object类的子类

3)JDK6中有202个包 3777个类、接口、异常、枚举、注释和错误

4)在做开发的时候,强烈建议大家多查jdk帮助文档

5)在使用类时,实在不知道怎么办,多上网百度

5.10.4、多态

5.10.4.1、方法重载(overload)

请编写一个程序,可以接收两个整数,返回两个数中较大的数。如果接收数的类型变了,怎么办?

java程序内容如下:

public class Demo{

public static void main (String args[]){

Abc abc1=new Abc();

System.out.println(abc1.getMax(12,34));

System.out.println(abc1.getMax(12.3f,4.5f));

System.out.println(abc1.getMax(12.3f,45.6));

}

}

class Abc{

//返回较大的整数

public int getMax(int i,int j){

if(i>j){

return i;

}else{

return j;

}

}

public float getMax(float i,float j){

if(i>j){

return i;

}else{

return j;

}

}

public double getMax(float i,double j){

if(i>j){

return i;

}else{

return j;

}

}

}

简单的说:方法重载就是类的同一种功能的多种实现方式,到底采用哪种方式,取决于调用者给出的参数。

注意:

1)方法名相同

2)方法的参数类型、个数、顺序,至少有一项不同

3)只是返回类型不一样,不能构成重载

5.10.4.2、方法覆盖/方法重写(override)

请编写一个程序,有猫和狗两种动物,我们知道它们都是动物,动物必然存在相同的特点。根据类的抽象特征,我们可以把它们的相同点提取出来,形成一个父类Animal,然后继承。

简单的说:方法覆盖就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的那个方法。比如上个案例的Cat类中的cry方法就覆盖了Animal类的cry方法。

注意:

1)子类方法的返回类型、参数、方法名称,要和父类方法完全一样

2)子类方法不能缩小父类方法的访问权限,但可以扩大父类方法的访问权限

5.10.4.3、多态

所谓多态,就是指一个引用(类型)在不同情况下的多种状态。

也可以这样理解:多态就是指通过指向父类的指针,来调用在不同子类中实现的方法。

注意:

1)java允许父类的引用变量引用它的子类的实例(对象)

例如:Animal an=new Cat();

这种转换是自动完成的。

2)关于类型转换还有一些具体的细节要求,我们在后面还要学习。

比如子类能不能转成父类,有什么要求等等……

5.11、抽象类

当父类的一些方法不能确定时,可以用abstract关键字来修饰该方法【抽象方法】,用abstract来修饰该类【抽象方法】。

抽象类是java中一个比较重要的类:

1)用abstract关键字来修饰一个类时,这个类就叫抽象类。

2)用abstract关键字来修饰一个方法时,这个方法就叫抽象方法。

3)抽象方法在编程中用的不是很多,但是在公司笔试时,却是考官比较爱问的知识点。

注意:

1)抽象类不能被实例化

2)抽象类中可以有实例化的方法,也可以有抽象方法

3)抽象类不一定要包含abstract方法。也就是说,抽象类可以没有abstract方法

4)一旦类包含了abstract方法,则这个类必须声明为abstract

5)抽象方法不能有方法主体。即不能有{ }

5.12、接口

接口就是给出一些没有内容的方法,封装到一起,到某个类要使用的时候,再根据具体情况把这些方法写出来。

接口是更加抽象的抽象类,抽象类里的方法可以含有方法体,接口里的所有方法都没有方法体。接口体现了程序设计的多态和高内聚低耦合的设计思想。

基本语法:

class 类名 implement 接口{

方法;

变量;

}

注意:

1)接口不能被实例化

2)接口中所有的方法都不能有主体。即不能有{ }

3)一个类可以实现多个接口

4)接口中可以有变量,但变量不能用private和protected修饰

①接口中的变量,本质上都是static的,而且是final类型,不管你加不加static修饰

②在java开发中,我们经常把常用的变量,定义在接口中,作为全局变量使用。访问形式为:接口名.变量名

5)一个接口不能继承其它的类,但是可以继承别的接口

5.13、实现接口VS继承类

java的继承是单继承,也就是一个类最多只能有一个父类,这种单继承的机制可以保证类的纯洁性,比c++中的多继承机制简洁。但是不可否认,对子类功能的扩展有一定影响。所以我们认为:实现接口可以看做是对继承的一种补充。

还有一点:继承是层级式的,不太灵活。比如修改某个类时,就会打破这种层级式的继承平衡。而接口就没有这样的麻烦,因为接口只针对实现接口的类才起作用,所以:实现接口可以在不打破继承关系的前提下,对某个类的功能扩展,非常灵活。

5.14、final

final 可以修饰变量或者方法。

final应用场景:

1)当不希望父类的某个方法被子类覆盖(override)时,可以用final关键字修饰。

2)当不希望类的某个变量的值被修改,可以用final修饰。比如圆周率3.1415926

3)当不希望类被继承时,可以用final修饰。

注意:

1)final修饰的变量又叫常量,一般用xx.xx.xx来命名

2)final修饰的变量在定义时,必须赋初值,并且以后不能再赋值

6、数组、排序、查找

6.1、数组

6.1.1、数组的用法

6.1.1.1、程序员用法

基本语法:数组类型 数组名[]=new 数据类型[大小]

例如:int a[]=new int[5];

如何使用数组:

数组名[下标]

例如:你要使用a数组的第3个数,那么使用a[2]

6.1.1.2、分步法

1)先声明数组

基本语法:数据类型 数据名[]; 也可以:数组类型[] 数组名

例如:int a[]; 或者int[] a;

2)创建数组

基本语法:数组名=new 数据类型[大小];

例如:a=new int[5];

3)数组的引用(使用)

基本语法:数组名[下标]

例如:引用a数组的第8个元素,那么使用a[7]

6.1.1.3、古板用法

1)初始化数组

基本语法:数据类型 数组名[]={元素值1,元素值2,元素值3……}

例如:int a[]={2,5,6,7,8,89,90,34,56}

也可以:int b[]=new int[]{2,5,6,7,8,89,90,34,56}

2)数组的引用(使用)

基本语法:数组名[下标]

注意:这种用法需要事先知道数组的大小和元素值。

6.1.2、对象数组

既然int、float、double等都可以有数组,那么可以有对象数组。

注意:如何知道数组的大小,数组名.length

6.1.3、数组-小结

1)数组可以存放同一类型数据

2)简单数据类型(int、float、double)的数组,可以直接赋值

3)对象数组在定义后,赋值时需要再次为每个对象分配空间【即:new 对象】

4)数组缺点:数组大小必须事先指定

5)数组名可以理解为指向数组首地址的引用

6)数组的下标是从0开始编号的

6.2、排序

排序是将一群数据,依据指定的顺序进行排列的过程。

排序(Sort)是数据处理中一种很重要的运算,同时也是很常用的运算,一般数据处理工作25%的时间都在进行排序。简单地说,排序就是把一组记录(元素)按照某个域的值的递增(即由小到大)或递减(即由大到小)的次序重新排列的过程。

6.2.1、排序的分类

1)内部排序法:

指将需要处理的所有数据都加载到内存中进行排序。

包括(交换式排序法、选择式排序法、插入式排序法)。

2)外部排序法

数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。

包括(合并排序法和直接合并排序法)。

6.2.2、交换式排序法

交换式排序属于内部排序法,是运用数据值比较后,依据判断规则对数据位置进行交换,以达到排序的目的。

交换式排序法又分为两种:

1)冒泡排序法(Bubble Sort)

2)快速排序法(Quick Sort)

6.2.3、交换式排序法——冒泡排序法

冒泡排序法(Bubble Sort)的基本思想是:通过对待排序序列从后向前(从下标较大的元素开始),依次比较相邻元素的排序码,若发现逆序则交换,使排序码较小的元素逐渐从后部移向前部(从下标较大的单元移向下标较小的单元),就像水底下的气泡一样逐渐向上冒。

因为排序的过程中,各元素不断接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序。因此要在排序过程中设置一个标志flag判断元素是否进行过交换,从而减少不必要的比较。

请编写一个程序(冒泡排序法):

java程序内容如下:

public class Demo1 {

public static void main(String[] args) throws Exception{

int arr1[]={1,6,0,-1,9};

Bubble bubble=new Bubble();

bubble.sort(arr1);

//输出结果

for(int i=0;i<arr1.length;i++) {

System.out.print(arr1[i]+" ");

}

}

}

//冒泡排序法

class Bubble{

public void sort(int arr[]) {

int temp=0;

//外层循环,它决定一共走几趟

for(int i=0;i<arr.length-1;i++) {

//内层循环,开始逐个比较,如果发现前一个数比后一个数大,则交换

for(int j=0;j<arr.length-1-i;j++) {

if(arr[j]>arr[j+1]) {

temp=arr[j];

arr[j]=arr[j+1];

arr[j+1]=temp;

}

}

}

}

}

上述结果是:-1 0 1 6 9

6.2.4、选择式排序法

选择式排序法也属于内部排序法,是从欲排序的数据中,按指定的规则选出某一元素,经过和其他元素重整,再依据原则交换位置后达到排序的目的。

选择式排序法又分为两种:

1)选择排序法(Selection Sort)

2)堆排序法(Heap Sort)

6.2.5、选择式排序法——选择排序法

选择排序法(Selection Sort)也是一种简单的排序方法。它的基本思想是:第一次从R[0]至R[n-1]中选取最小值,与R[0]交换;第二次从R[1]至R[n-1]中选取最小值,与R[1]交换;第三次从R[2]至R[n-1]中选取最小值,与R[2]交换;……第i次从R[i-1]至R[n-1]中选取最小值,与R[i]交换;……第n-1次从R[n-2]至R[n-1]中选取最小值,与R[n-2]交换。总共通过n-1次,得到一个按排序码从小到大排列的有序序列。

请编写一个程序(选择排序法):

java程序内容如下:

public class Demo1 {

public static void main(String[] args) throws Exception{

int arr1[]={1,6,0,-1,9};

//创建一个Select类

Select select=new Select();

select.sort(arr1);

//输出结果

for(int i=0;i<arr1.length;i++) {

System.out.print(arr1[i]+" ");

}

}

}

//选择排序法

class Select{

public void sort(int arr[]) {

int temp=0;

for(int i=0;i<arr.length-1;i++) {

//认为第一个数就是最小

temp=arr[i];

int k=i;

for(int j=i+1;j<arr.length;j++) {

if(arr[i]>arr[j]) {

//修改最小数

arr[i]=arr[j];

k=j;

}

}

//交换位置

arr[i]=arr[k];

arr[k]=temp;

}

}

}

上述结果是:-1 0 1 6 9

6.2.6、插入式排序法

插入式排序法属于内部排序法,是对于欲排序的元素以插入的方式找寻该元素的适当位置,以达到排序的目的。

插入式排序法又分为三种:

1)插入排序法(Insertion Sort)

2)希尔排序法(Shell Sort)

3)二叉树排序法(Binary-tree Sort)

6.2.7、插入式排序法——插入排序法

插入排序法(Insertion Sort)的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。

请编写一个程序(插入排序法):

java程序内容如下:

public class Demo1 {

public static void main(String[] args) throws Exception{

int arr1[]={1,6,0,-1,9};

//创建一个Insert类

Insert insert=new Insert();

insert.sort(arr1);

//输出结果

for(int i=0;i<arr1.length;i++) {

System.out.print(arr1[i]+" ");

}

}

}

//插入排序法

class Insert{

public void sort(int arr[]) {

int temp,j;

for(int i=1;i<arr.length;i++) {

temp=arr[i];

for(j=i;j>0&&temp<arr[j-1];j--) {

arr[j]=arr[j-1];

}

arr[j]=temp;

}

}

}

上述结果是:-1 0 1 6 9

6.2.8、交换式排序法——快速排序法

快速排序法(Quick Sort)是对冒泡排序的一种改进,由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以达到整个数据编程有序序列。

请编写一个程序(快速排序法):

java程序内容如下:

import java.util.*;

public class Demo1 {

public static void main(String[] args) throws Exception{

int len=8000000;

int arr1[]=new int[len];

for(int i=0;i<arr1.length;i++) {

//Math.random()会产生一个0~1的小数

arr1[i]=(int)(Math.random()*10000);

}

//打印系统时间

Calendar cal=Calendar.getInstance();

System.out.println("排序前:"+cal.getTime());

//创建一个QuickSort类

QuickSort quicksort=new QuickSort();

quicksort.sort(0, arr1.length-1, arr1);

//重新得到实例

cal=Calendar.getInstance();

System.out.println("排序后:"+cal.getTime());

}

}

//快速排序法

class QuickSort{

public void sort(int left,int right,int arr[]) {

int l=left;

int r=right;

int pivot=arr[(left+right)/2];

int temp=0;

while(l<r) {

while(arr[l]<pivot) l++;

while(arr[r]>pivot) r--;

if(l>=r) break;

temp=arr[l];

arr[l]=arr[r];

arr[r]=temp;

if(arr[l]==pivot) --r;

if(arr[r]==pivot) ++l;

}

if(l==r) {

l++;

r--;

}

if(left<r) sort(left,r,arr);

if(right>l) sort(l,right,arr);

}

}

6.2.9、外部排序法——合并排序法

合并排序法(Merge Sort)是外部排序最常使用的排序方法。若数据量太大无法一次完全加载内存,可使用外部辅助内存来处理排序数据,主要应用在文件排序。它的基本思想是:将欲排序的数据分别存在数个文件大小可加载内存的文件中,再针对各个文件分别使用“内部排序法”将文件中的数据排序好写回文件。再对所有已排序好的文件两两合并,直到所有文件合并成一个文件后,则数据排序完成。

6.3、查找

6.3.1、顺序查找

用for循环顺序查找即可。

6.3.2、二分法查找

请编写一个程序(二分法查找):

java程序内容如下:

public class Demo1 {

public static void main(String[] args) throws Exception{

int arr1[]={2,5,7,12,25,33};

BinaryFind bf1=new BinaryFind();

bf1.find(0,arr1.length-1,12,arr1);

}

}

//二分查找

class BinaryFind{

public void find(int leftIndex,int rightIndex,int val,int arr[]) {

//首先找到中间的数

int midIndex=(rightIndex+leftIndex)/2;

int midVal=arr[midIndex];

if(rightIndex>=leftIndex) {

//如果要找的数比midVal大

if(midVal>val) {

//在arr的左边数中查找

find(leftIndex,midIndex-1,val,arr);

}else if(midVal<val) {

//在arr右边数中查找

find(midIndex+1,rightIndex,val,arr);

}else if(midVal==val) {

System.out.println("找到下标"+midIndex);

}

}

}

}

6.4、多维数组

多维数组,我们只介绍二维数组。

基本语法:类型 数组名[][]=new 类型[大小][大小];

比如:int a[][]=new int[3][3];

也可以:int a[][]= {{1,3,5},{2,4,6},{7,8,9}};

7、二进制、位运算符、移位运算符

7.1、二进制(原码、反码、补码)

二进制是逢2进位的进位制,0、1是基本算符。

对于有符号的而言:

1)二进制的最高位是符号位:0表示正数,1表示负数

2)正数的原码、反码、补码都一样

3)负数的反码=它的原码符号位不变,其它位取反(0→1,1→0)

4)负数的补码=它的反码+1

5)0的反码、补码都是0

6)java没有无符号数,换而言之,Java中的数都是有符号的

7)在计算机运算的时候,都是以补码的方式来运算的

7.2、位运算符

java中有4个位运算,分别是按位与&、按位或|、按位异或^,按位取反

它们的运算规则是:

按位与& :两位全为1,结果为1

按位或| :两位有一个为1,结果为1

按位异或^ :两位一个为0,一个为1,结果为1

按位取反~ :0→1,1→0

例如:

~2=-3

2&3=2

2|3=3

2^3=1

7.3、移位运算符

java中有3个移位运算符,它们的运算规则是:

>>算数右移 :低位溢出,符号位不变,并用符号位补溢出的高位

<<算数左移 :符号位不变,低位补0

>>>逻辑右移 :低位溢出,高位补0

例如:

1>>2=0

-1>>2=-1

1<<2=4

-1<<2=-4

3>>>2=0

8、集合类、泛型、异常处理

8.1、集合类

如果有这样一种数组,它可以动态的改变就好了,java的设计者为我们提供了一系列的集合类。

从上图可以看出java集合类主要有以下几种:

1)List结构的集合类

ArrayList类、LinkedList类、Vector类、Stack类

2)Map结构的集合类

HashMap类、Hashtable类

3)Set结构的集合类

HashSet类、TreeSet类

4)Queue结构的集合

Queue接口

选择集合的经验

1)如果要求线程安全,使用Vector、Hashtable

2)如果不要求线程安全,应使用ArrayList、LinkedList、HashMap

3)如果要求键值对,则使用HashMap、Hashtable

4)如果数据量很大,又要线程安全考虑Vector

8.2、泛型

8.2.1、泛型的基本概念

泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

Java语言引入泛型的好处是安全简单。

在Java SE 1.5之前,没有泛型的情况下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器不提示错误,在运行的时候才出现异常,这是一个安全隐患。

泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。

注意:泛型就是<>尖括号中的内容。

8.2.2、泛型的优点

1)类型安全

2)向后兼容

3)层次清晰

4)性能较高,用GJ(就是泛型java)编写的代码可以为java编译器和虚拟机带来更多的类型信息,这些信息对java程序做进一步优化提供条件。

8.3、异常处理

8.3.1、基本概念

当出现程序无法控制的外部环境问题时(用户提供的文件不存在;文件内容损坏;网络不可用……),Java就会用异常对象来描述。

java中用2种方法处理异常:

1)在发生异常的地方直接处理(即try…catch…);

2)将异常抛给调用者,让调用者处理(即throws Exception)。

8.3.2、异常分类

1)检查性异常:java.lang.Exception

2)运行期异常:java.lang.RuntimeException

3)错误:java.lang.Error

顶层是java.lang.Throwable类,检查性异常、运行期异常、错误都是这个类的子孙类。java.lang.Exception和java.lang.Error继承自java.lang.Throwable;而java.lang.RuntimeException继承自java.lang.Exception。

8.3.2.1、检查性异常

程序正确,但因为外在的环境条件不满足而引发。例如:用户错误即I/O问题;程序试图打开一个并不存在的远程Socket端口;或者是打开不存在的文件时。这不是程序本身的逻辑错误,而很可能是远程机器名字错误(用户拼写错误)。对商用软件系统,程序开发者必须考虑并处理这个问题。Java编译器强制要求处理这类异常,如果不捕获这类异常,程序将不能被编译。

8.3.2.2、运行期异常

这意味着程序存在bug,如数组越界;0被除;入参不满足规范……这类异常需要更改程序来避免,Java编译器强制要求处理这类异常。

8.3.2.3、错误

一般很少见,也很难通过程序解决。它可能源于程序的bug,但一般更可能源于环境问题,如内存耗尽。错误在程序中无需处理,而由运行环境处理。

8.3.3、异常处理

8.3.2.1、try…catch…

程序运行产生异常时,将从异常发生点中断程序并向外抛出异常信息。

java程序内容如下:

import java.io.*;

public class Demo1 {

public static void main(String[] args) throws Exception{

//检查异常——打开不存在的文件

try {

FileReader fr=new FileReader("d:\\aa.text");

//在出现异常的地方,就终止执行代码

//然后进入到catch语句

//如果你有多个catch语句,则进入匹配异常的那个catch语句

System.out.println("Go on!");

} catch (Exception e) {

//输出异常的信息,利于debug

e.printStackTrace();

}

}

}

8.3.2.2、finally

如果把finally块放置在try…catch…语句之后,finally块一般都会得到执行,它相当于一个万能的保险,即使前面的try块发生异常,而又没有对应异常的catch块,finally块将马上执行。

以下情形,finally块将不会被执行:

1)finally块中发生了异常;

2)程序所在线程死亡;

3)在前面的代码中用了System.exit();

4)关闭CPU。

java程序内容如下:

import java.io.*;

public class Demo1 {

public static void main(String[] args) throws Exception{

//检查异常——打开不存在的文件

FileReader fr=null;

try {

fr=new FileReader("D:\\aa.txt");

//在出现异常的地方,就终止执行代码

//然后进入到catch语句

//如果你有多个catch语句,则进入匹配异常的那个catch语句

} catch (Exception e) {

//输出异常的信息,利于debug

e.printStackTrace();

}finally {

//这个语句块,不管有没有异常,都会执行

//一般写入,需要关闭的资源【文件、连接、内存...】

if(fr!=null) {

try {

fr.close();

} catch (Exception e2) {

e2.printStackTrace();

}

}

}

}

}

注意:

1)try…catch…finally…一般它们是在一起使用;

2)try…finally…也可以使用;

3)只有finally…是不可以的。

8.3.2.3、抛出异常throws Exception

java程序内容如下:

import java.io.*;

public class Demo1 {

public static void main(String[] args) throws Exception{

Father father=new Father();

father.test1();

}

}

class Father{

private Son son=null;

public Father() {

son=new Son();

}

public void test1() {

try {

son.test2();

} catch (Exception e) {

System.out.println("父亲在处理异常");

e.printStackTrace();

}

}

}

class Son{

//抛出异常

public void test2() throws Exception{

FileReader fr=null;

fr=new FileReader("d:\\abc.txt");

}

}

自己也可以定义并抛出异常,方法是2步:创建异常、抛出异常(首先实例化一个异常对象,然后用throw抛出)合在一起就是——throw new IOException("异常说明信息")。将创建异常、抛出异常合在一起的好处是:创建异常时,会包含异常创建处的行信息。异常被捕获时可以通过堆栈迹(Stack Trace)的形式报告这些信息。如果在同一行代码创建和抛出异常,对于程序的调试将非常有用。所以,throw new XXX()已经成为一个标准的异常抛出范式。在定义一个方法时,方法块中调用的方法可能会抛出异常,可用上面的throw new XXX()处理,如果不处理,那么必须在方法定义时,用throws声明这个方法会抛出的异常。

对异常的处理,有一条行之有效的默认规则:向上抛出——被调用类在运行过程中对遇到的异常一概不作处理,而是直接向上抛出,一直到最上层的调用类,调用类根据应用系统的需求和特定的异常处理规则进行处理。如向控制台输出异常堆栈信息,打印在日志文件中。用一句形象的话来说:就是谁使用,谁处理。

8.3.2.4、多个异常的处理规则

定义多个catch可精确地定位异常。如果为子类的异常定义了特殊的catch块,而父类的异常则放在另外一个catch块中,此时必须满足以下规则:子类异常的处理块必须在父类异常处理块的前面,否则会发生编译错误。所以越特殊的异常越是在前面处理,越普通的异常越是在后面处理。这类似于制订防火墙的规则次序:教特殊的规则在前,较普通的规则在后。

9、图形用户界面(GUI)

9.1、介绍

图形用户界面(Graphics User Interface,GUI)是用户与程序交互的窗口,比命令行的界面更加直观并且更好操作。

9.1.1、什么是awt、swing、swt、JFace

1)Sun已经提供了一个跨平台GUI开发工具包AWT抽象窗口工具箱(Abstract Window Toolkit)

2)Sun又创建了一个新的gui框架swing,解决了awt存在的lcd(即本地化)问题,保证在Windows和Linux系统上运行的界面是一样的。

3)IBM认为swing比较消耗内存,创建了一个新的GUI库,这就是SWT

4)IBM为了方便开发SWT程序,在SWT基础上又创建了一个更易用、且功能强大的图形包“JFace”。

9.1.2、eclipse工具

1)eclipse最早是IBM附属公司oti开发的,一共投入了4000万美金,后来捐献给开源社区。

2)eclipse是一个开源的、可扩展的集成开发环境,已经成为目前最流行的java开发工具。

3)eclipse安装后就可以开发java se的项目了,但不能开发java ee项目,需要安装web开发插件(lomboz或是myeclipse…)。

9.1.3、IDE

集成开发环境(IDE,Integrated Development Environment )是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面等工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务套。

所有具备这一特性的软件或者软件套(组)都可以叫集成开发环境。如微软的Visual Studio系列,Borland的C++ Builder、Delphi系列等。该程序可以独立运行,也可以和其它程序并用。

IDE多被用于开发HTML应用软件。例如,许多人在设计网站时使用IDE(如HomeSite、DreamWeaver等),因为很多项任务会自动生成。

9.2、swing介绍

9.2.1、swing组件一览图

9.2.2、swing--窗体组件JFrame

在图形用户界面编程中,我们必须要用到窗体,也就是大家看到的那个窗口,这是最基本的。

下图就是swing的窗体组件JFrame做的。

注意:

1)JFrame是Frame的子类

2)属于容器类组件,是顶层容器

3)JFrame有一些常用的方法,如下所示

java程序内容如下:

import java.awt.*;

import javax.swing.*;

public class Demo1 {

public static void main(String[] args) {

//JFrame是一个顶层容器类(可以添加其它swing组件的类)

JFrame jf=new JFrame();

//给窗体设置标题

jf.setTitle("hello,world!");

//设置窗体大小(单位是像素)

jf.setSize(300, 200);

//设置窗体初始位置

jf.setLocation(100, 200);

//设置关闭窗口时,保证jvm也退出

jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//显示窗体

jf.setVisible(true);

}

}

9.2.3、swing--按钮组件JButton

注意:

1)JButton是AbstractButton的子类

2)属于容器类组件,可以加入别的组件

3)Swing包的按钮组件不只有JButton,还有单选按钮(JRadioButton)、箭头按钮(BasicArrowButton)、触发器按钮(JToggleButton)......

9.3、布局管理器

9.3.1、布局管理器

9.3.1.1、概念

组件在容器(比如JFrame)中的位置和大小是由布局管理器来决定的。所有的容器都会使用一个布局管理器,通过它来自动进行组件的布局管理。

9.3.1.2、分类

java共提供了五种布局管理器:流式布局管理器(FlowLayout)、边界布局管理器(BorderLayout)、网格布局管理器(GridLayout)、卡片布局管理器(CardLayout)、网格包布局管理器(GridBagLayout)。其中前三种是最常见的布局管理器。

9.3.2、边界布局管理器(BorderLayout)

边界布局管理器(BorderLayout)将容器简单的划分为东南西北中5个区域,中间区域最大。

注意:

1)不是5个区域都必须添加;

2)中部组件会自动的调节大小;

3)JFrame窗体、JDialog对话框组件的默认布局管理器就是BorderLayout边界布局。

9.3.3、流式布局管理器(FlowLayout)

FlowLayout布局,按照组件的添加次序将按钮组件(当然也可以是别的组件)从左到右放置在容器中。当到达容器的边界时,组件将放置在下一行中。FlowLayout可以以左对齐、居中对齐、以右对齐等不同的方式排列组件。

注意:

1)不限制它所管理的组件大小,允许它们有最佳大小;

2)当容器被缩放时,组件的位置可能变化,但组件的大小不变;

3)FlowLayout默认是居中对齐,可以通过FlowLayout(int align)函数来指定对齐方式。

9.3.4、网格布局管理器(GridLayout)

GridLayout布局,听其名而知其意,它将容器分割成多行多列,组件被填充到每个网格中,添加到容器中的组件首先放置在左上角的网格中,然后从左到右放置其它的组件,当占满该行的所有网格后,接着继续在下一行从左到右放置组件。

注意:

1)组件的相对位置不随容器的缩放而变化,但大小会变化;

2)所有组件的大小相同;

3)可以通过GridLayout(int rows,int cols,int hgap,int vgap)来指定网格的行、列、水平间隙、垂直间隙。

9.3.5、开发GUI程序步骤

1)继承JFrame;引入2个包java.awt.*、javax.swing.*

2)定义需要的组件

3)创建组件(构造函数)

4)设置布局管理器

5)添加组件

6)设置窗体;显示窗体

7)创建对象(主函数)

9.4、swing组件

9.4.1、面板组件(JPanel)

在图形用户界面编程中,如果只是普通的组件布局,我们用前面讲的三种布局管理器就可以解决,但是在比较复杂的布局要求时,就需要使用布局管理器的组合使用。

JPanel:面板组件,非顶层容器,一个界面只可以有一个JFrame窗体组件,但可以有多个JPanel面板组件,而JPanel上也可使用FlowLayout、BorderLayout、GridLayout等各种布局管理器,这样可以组合使用达到较为复杂的布局效果。

注意:

1)JPanel是JComponent的子类;

2)JPanel属于容器类组件,可以加入别的组件;

3)JPanel默认布局管理器是FlowLayout流式布局。

9.4.2、文本框、密码框、标签组件

在图形用户界面编程中,我们常常会提供用户登录界面,比如登录到会员管理系统、登录到工资管理系统、仓库管理系统等,这个时候我们就会用到:

1)文本框(JTextField)

2)密码框(JPasswordField)

3)标签(JLabel)

9.4.3、复选框、单选框组件

在图形用户界面编程中,我们常常会提供用户注册界面,这个时候我们就会用到:

1)复选框组件(JCheckBox)

2)单选框组件(JRadioButton)

特别说明:同一组单选按钮必须先创建ButtonGroup,然后把单选框组件放入到ButtonGroup中。

9.4.4、下拉框、列表框、滚动窗格组件

在图形用户界面编程中,我们常常会提供用户调查界面,这个时候我们就会用到:

1)下拉框组件(JcomboBox)

2)列表框组件(JList)

3)滚动窗格组件(JScrollPane)

特别说明:一般来说,列表框组件+滚动窗格组件是结合使用的,目的是让列表框中的选项可以有滚动条支持。

9.6、java绘图技术

9.6.1、java绘图坐标体系

下图说明了java坐标系,坐标原点位于左上角,以像素为单位,像素是计算机屏幕上最小的显示单位。在java坐标系中,第一个x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。

9.6.2、坐标系--像素

计算机在屏幕上显示的内容都是由屏幕上的每个像素组成的。例如,计算机显示器的分辨率是800*600,表示计算机屏幕上的每一行由800个点组成,共有600行,整个计算机屏幕共有48000个像素。

因此,像素是一个密度单位,而厘米是长度单位,两者无法比较。

9.6.3、绘图原理

Component类提供了两个绘图相关的重要方法:

1)paint(Graphics g)绘制组件的外观

2)repaint()刷新组件的外观

当组件第一次在屏幕显示的时候,程序会自动的调用paint()方法来绘制组件。

在一下情况paint()将会被调用:

1)窗口最小化,再最大化;

2)窗口大小发生变化;

3)repaint函数被调用。

9.6.4、Graphics类

Graphics类,你可以理解就是画笔,为我们提供了各种绘制图形的方法:【强烈建议参考jdk帮助文档】

1)画直线 drawLine(int x1, int y1, int x2, int y2)

2)画矩形边框 drawRect(int x, int y, int width, int height)

3)画椭圆边框 drawOval(int x, int y, int width, int height)

4)填充矩形 fillRect(int x, int y, int width, int height)

5)填充椭圆 fillOval(int x, int y, int width, int height)

6)画图片 drawImage(Image img, int x, int y, …)

7)画字符串 drawString(String str, int x, int y)

8)设置画笔的字体 setFont(Font font)

9)设置画笔的颜色 setColor(Color c)

9.7、java事件处理机制

9.7.1、java事件处理基本原理

java事件处理是采取“委派事件模型”。所谓“委派事件模型”是指当事件发生时,产生事件的对象(即事件源),会把此“消息”传递给“事件的监听者”处理的一种方式,而这里所说的“消息”实际上就是java.awt.event事件类库里某个类所创建的对象,我们暂时把它称为“事件的对象”。示意图如下:

9.7.2、几个重要概念

9.7.2.1、事件源

事件源是一个产生(或触发)时间的对象,比如前面的JButton的一个对象jb1。当这个事件源对象的某些状态以某种方式发生变化时,就会产生某种类型的时间(一个事件源可能会生成多个不同类型的事件)。如果某个组件(对象)希望得到事件源产生的事件,就需要在这个事件源上注册。

9.7.2.2、事件

事件就是承载事件源状态改变时的信息对象。或者说,事件是事件源向事件监听器传输事件源状态信息的载体。在用户与GUI组件进行交互时就会生成事件,比如当鼠标在面板中移动时,就会产生一个鼠标移动事件的对象,而这个对象保存着当前鼠标在面板中位置信息。java.awt.event包和javax.swing.event包中定义了各种事件类型,常见的事件类有:

9.7.2.3、事件监听器接口

我们前面讲到,事件源产生一个事件,可以传递给事件监听者处理,那么怎样才能编写一个事件监听者呢?

事件监听者实际上就是一个类,该类实现了某个事件监听器接口。比如前面我们案例中的MyPanel就是一个类,它实现了KeyListener接口,它就可以作为一个事件监听者,对接收到的事件进行处理。

事件监听器接口有多种,不同的事件监听器接口可以监听不同的事件,一个类可以实现一个事件监听接口,也可以实现多个监听接口。

9.7.3、事件处理编程步骤

1)编写事件处理类(事件监听者)

2)根据需求给事件处理类实现监听器接口

3)在事件处理类中重写(实现)其事件处理的函数

4)在事件源类中指定该事件的监听器(响应者)是谁,即注册监听。

9.7.4、总结

1)java采用委托机制处理事件

2)java中的事件是分类的,比如对窗体事件、鼠标事件、按键事件、操作事件[按按钮]

3)java中一个类要监听某个事件,则必须实现相应的事件监听接口

4)事件监听接口有多种,程序员应当针对不同的情况,实现不同的监听接口,不如监听鼠标事件就应当事件MouseListener;要监听键盘事件,就应当实现KeyListener

5)在实现监听接口的类(事件监听类/者)中,需要重写处理函数,比如实现了ActionListener接口,就应当重写actionPerformed(ActionEvent e),就可以参考前面的事件监听器接口表格

6)在事件源中需要注册事件监听类,否则事件监听类接收不到事件源发生的事件。

10、线程

10.1、进程的概念

进程是指运行中的应用程序,每个进程都有自己独立的地址空间(内存空间),比如用户点击桌面的IE浏览器,就启动了一个进程,操作系统就会为该进程分配独立的地址空间。当用户再次点击桌面的IE浏览器,又启动启动了一个进程,操作系统将为新的进程分配新的独立的地址空间。目前操作系统都支持多进程。

当然,用户既然可以启动IE浏览器,也可以启动别的程序,比如用户可以启动IE浏览器上网,同时也可以启动暴风影音看电影。

只要记住一点:用户每启动一个进程,操作系统就会为该进程分配一个独立的内存空间。

10.2、线程的概念

线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同一进程中的多个线程之间可以并发执行。线程有就绪、阻塞和运行三种基本状态。

简单理解线程:

1)线程是轻量级的进程

2)线程没有独立的地址空间(内存空间)

3)线程是由进程创建的(寄生在进程)

4)一个进程可以拥有多个线程

5)线程有几种状态:

①新建状态(new)

②就绪状态(Runnable)

③运行状态(Running)

④阻塞状态(Blocked)

⑤死亡状态(Dead)

注意:不管是通过继承Thread,还是通过实现Runnable接口,创建线程,它们的一个对象只能启动(即start())一次,否则就会有异常抛出。

10.3、extends Thread与implements Runnable的区别

从java的设计来看,通过继承Thread或者实现Runnable接口来创建线程本质上没有区别,从jdk帮助文档我们可以看到Thread类本身就实现了Runnable接口。如果一定要说它们有什么区别我这里总结几点:

1)尽可能使用实现Runnable接口的方式来创建线程

2)在使用Thread的时候只需要new一个实例出来,调用start()方法即可启动一个线程。如:

Thread test=new Thread();

test.start();

3)在使用Runnable的时候需要先new一个实现Runnable的实例,之后用Thread调用。如:

Test implements Runnable

Test t=new Test();

Thread th=new Thread(t);

th.start();

10.4、多线程同步机制

java任意类型的对象都有一个标志位,该标志位具有0、1两种状态,其开始默认状态为1,当某个线程执行了synchronized(Object)语句后,Object对象的标志位变为0的状态,直到执行完整个synchronized语句中的代码块后,该对象的标志位又回到1状态。

当一个进程执行到synchronized(Object)语句的时候,先检查Object对象的标志位,如果为0状态,表明已经有另外的线程正在执行synchronized包括的代码,那么这个线程将暂时阻塞,让出CPU资源,直到另外的线程执行完相关的同步代码,并将Object对象的标志位变为1状态,这个线程的阻塞就被取消,线程能继续运行,该线程又将Objec的标志位变为0状态,防止其它的线程再进入相关的同步代码块中。

如果有多个线程因等待同一个对象的标志位而处于阻塞状态时,当该对象的标志位恢复到1状态时,只会有一个线程能够进入同步代码块执行,其它的线程仍然处于阻塞的状态。

特别说明:

1)我们上面说的对象的标志位用术语讲就是:对象锁、文件锁

2)synchronized(Object),这个Object可以是任意类型对象

11、文件I/O操作

11.1、文件

文件是数据源的一种(保存数据的地方)。比如大家经常使用的word文档、txt文件、excel文件…...都是文件。文件最主要的作用就是保存数据,它既可以保存一张图片,也可以保持视频、声音……

11.2、文件流

文件在程序中是以流的形式来操作的。

流:数据在数据源(文件)和程序(内存)之间经历的路径。

输入流:数据从数据源(文件)到程序(内存)的路径。

输出流:数据从程序(内存)到数据源(文件)的路径。

如何判断是输入流,还是输出流?

以内存为参照,如果数据是向内存流动,则是输入流;反之是输出流。

11.3、文件流分类

java流分为两种流。

1)字节流:可以用于读写二进制文件及任何类型文件。

2)字符流:可以用于读写文本文件,不能操作二进制文件。

java io流类一览表

11.4、图片拷贝的基本用法

java程序内容如下:

import java.io.*;

public class Demo1 {

public static void main(String[] args) {

//思路:先把图片读入到内存,然后写入到某个文件

//因为图片是二进制文件,因此只能用字节流完成

FileInputStream fis=null;

FileOutputStream fos=null;

try {

//输入流

fis=new FileInputStream("d:\\caocao.jpg");

//输出流

fos=new FileOutputStream("e:\\caocao.jpg");

byte bytes[]=new byte[1024];

int n=0; //记录实际读取到的字节数

//循环读取

while((n=fis.read(bytes))!=-1) {

fos.write(bytes);

}

} catch (Exception e) {

e.printStackTrace();

}finally {

try {

fis.close();

fos.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

11.5、实现记事本读写文件功能

java程序内容如下:

import java.io.*;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class Demo1 extends JFrame implements ActionListener{

//定义组件

JTextArea jta=null;

JMenuBar jmb=null;

JMenu jm1=null;

JMenuItem jmi1=null;

JMenuItem jmi2=null;

public static void main(String[] args) {

Demo1 demo1=new Demo1();

}

//构造函数

public Demo1() {

//创建组件

jta=new JTextArea();

jmb=new JMenuBar();

jm1=new JMenu("文件(F)");

//设置助记符

jm1.setMnemonic(F);

jmi1=new JMenuItem("打开",new ImageIcon("src\\open.jpg"));

jmi2=new JMenuItem("另存为");

//添加组件

this.add(jta);

this.setJMenuBar(jmb);

jmb.add(jm1);

jm1.add(jmi1);

jm1.add(jmi2);

//注册监听

jmi1.addActionListener(this);

jmi1.setActionCommand("open");

jmi2.addActionListener(this);

jmi2.setActionCommand("save");

//设置窗体

this.setTitle("记事本");

this.setSize(400, 300);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//显示窗体

this.setVisible(true);

}

public void actionPerformed(ActionEvent e) {

if(e.getActionCommand().equals("open")) {

//文件选择组件JFileChooser

JFileChooser jfc1=new JFileChooser();

jfc1.setDialogTitle("请选择打开的文件");

//按默认方式显示

jfc1.showOpenDialog(null);

//显示

jfc1.setVisible(true);

//得到用户选择打开文件的绝对路径

String filename1=jfc1.getSelectedFile().getAbsolutePath();

FileReader fr=null;

BufferedReader br=null;

try {

fr=new FileReader(filename1);

br=new BufferedReader(fr);

//从文件中读取信息,并显示到JTextArea中

String s="";

String allContent="";

while((s=br.readLine())!=null) {

allContent+=s+"\r\n";

}

jta.setText(allContent);

} catch (Exception e2) {

e2.printStackTrace();

}finally {

try {

br.close();

fr.close();

} catch (Exception e3) {

e3.printStackTrace();

}

}

}else if(e.getActionCommand().equals("save")) {

//显示保存对话框

JFileChooser jfc2=new JFileChooser();

jfc2.setDialogTitle("另存为...");

//按默认方式显示

jfc2.showSaveDialog(null);

//显示

jfc2.setVisible(true);

//得到用户希望保存文件的绝对路径

String filename2=jfc2.getSelectedFile().getAbsolutePath();

FileWriter fw=null;

BufferedWriter bw=null;

try {

fw=new FileWriter(filename2);

bw=new BufferedWriter(fw);

//自己优化,如果是大文件可以循环输出

bw.write(this.jta.getText());

} catch (Exception e4) {

e4.printStackTrace();

}finally {

try {

bw.close();

fw.close();

} catch (Exception e5) {

e5.printStackTrace();

}

}

}

}

}

11.6、读取本地音频文件并播放

java程序内容如下:

import java.io.*;

import javax.sound.sampled.*;

public class Demo {

public static void main(String[] args) {

AePlayWave apw=new AePlayWave("d:\\tankGameMusic.wav");

apw.start();

}

}

//播放声音的类

class AePlayWave extends Thread {

private String filename;

AudioInputStream audioInputStream=null;

File soundFile;

SourceDataLine auline=null;

public AePlayWave(String wavfile) {

this.filename=wavfile;

}

public void run() {

soundFile=new File(filename);

try {

audioInputStream=AudioSystem.getAudioInputStream(soundFile);

} catch (Exception e) {

e.printStackTrace();

return;

}

AudioFormat format=audioInputStream.getFormat();

http://DataLine.Info info=new http://DataLine.Info(SourceDataLine.class, format);

try {

auline=(SourceDataLine)AudioSystem.getLine(info);

auline.open(format);

} catch (Exception e) {

e.printStackTrace();

return;

}

auline.start();

int nBytesRead=0;

byte[] abData=new byte[512];

try {

while(nBytesRead!=-1) {

nBytesRead=audioInputStream.read(abData, 0, abData.length);

if(nBytesRead>=0) {

auline.write(abData, 0, nBytesRead);

}

}

} catch (Exception e) {

e.printStackTrace();

}finally {

auline.drain();

auline.close();

}

}

}

分类: 教程分享 标签: 暂无标签

评论

暂无评论数据

暂无评论数据

目录

目录