1.Java学习过程笔记(传播智客毕向东)

来源:互联网 发布:python 中英文拆分 编辑:程序博客网 时间:2024/05/17 07:55

目录

1.Helloworld.1

Java.1

变量...2

关键字(所有字母为小写)...2

标识符...2

IF语句...3

99乘法表...3

99主函数带入参数...3

内存结构,5个内存空间...3

2.函数...4

函数的格式...4

3.重载(add(4,5),add(4,5,6)或者99乘法表88)...5

4数组...6

原理 int[] x = new int[3]6

示例...7

遍历,length.7

获取最大值,ArrayMax.8

排序...8

冒泡排序bub.8

数组的查找(折半查找)...9

8十进制转二进制...10

5面向对象...11

1.面向对象概述...11

3.类与对象的关系...11

4.类主函数,成员变量和局部变量...12

5.匿名对象...13

代码分析,主函数,内存...13

匿名对象作实际参数传输...14

6.封装Encapsulation.15

7.priavte.15

8.构造函数, 与类同名,可重载...16

9.构造代码块,{初始化}18

10this关键字...18

11this关键字的应用,该类...20

12this关键字在构造函数间调用,this(name),Person(name)20

6面向对象...21

1static关键字静态...21

方法区/共享区,类中的方法,类中的共享数据...21

2.main,主函数是静态的...24

静态的应用...25

帮助文档的使用...25

静态代码块...26

对象的初始化...26

单例设计模式...27

接口interface,特殊抽象类...29

接口举例...30

8面向对象...30

多态,事物存在的多种体现形态...30

8.Object类上帝类equals.30

9.toString()31

9面向对象...32

1.内部类(内置类、嵌套类)...32

1.为什么内部类可以访问外部类内容...33

4.匿名内部类...34

4.匿名内部类调用父类方法...35

4.匿名内部类的...36

5.Java的异常机制...38

6.异常处理机制...39

7.异常处理...40

继承...40

聚集...40

子父类...40

抽象对象,抽象类...41

模板方法TemplateDemo.42

构造函数,名称随类名走...42

final43

10面向对象...43

7.包Package.43

包名要全称...43

javac –d 目录...43

放在其它目录...44

8.包与包之间的访问...44

9. import导入...45

import pack.haha.hehe.heihei.*;46

import导入的是包中的类。...46

Eclipse.47

jar包...47

18其他对象...47

System..47

11多线程...48

1.多线程...49

2.创建线程-继承Thread类...49

3.run和start的特点,start才可以开启线程...50

4多线程练习...51

5.线程运行状态4:被创建,运行、冻结(临时状态/阻塞)、消亡    51

6.获取线程对象及名称...52

7.卖票例子...53

8.实现Runnable接口...54

8. 实现方式和继承方式有什么区别?...56

9.多线程的安全问题...57

冻结状态sleep,模拟这个卧倒...57

覆盖接口是不能抛异常的...58

解决,同步代码块...58

10同步代码块,同步锁,锁旗标,火车卫生间。。。...58

11.多线程,同步函数...59

12.同步函数的锁是this.60

13静态同步函数的锁是Class对象(getClass获取实例)...63

静态同步:类名.class.63

14单例设计模式-懒汉式...64

15.死锁...65

12多线程...66

1.线程通信,一堆煤,卡车进,卡车出,BUG..66

2.解决安全问题...68

3.等待唤醒机制...69

4.代码优化...69

5生产者和消费者,问题...71

5.生产者消费者,解决问题...72

6生产者消费者JDK5.0,lock.73

7.停止线程...77

8守护线程setDaemon.79

9多线程join方法...80

10优先级&yield.80

yield.81

10开发写线程...82

22GUI(图形用户界面)Graphical User Interface.83

布局...83

3图形化界面Frame.84

4事件监听机制...85

5.窗体事件...85

Action事件...87

鼠标事件(共性事件)...88

键盘事件,确定事件源,确定事件,确定要操作谁!...89

TextS简单界面...89

错误处理...91

菜单MyMenuDemo.92

窗口fileDialog.92

异常处理...93

不要打开dos命令行方式...93

打jar包...93

jar -cvfm my.jar 1.txt mymenu.94

双击安装版的jdk才能运行...94

自己配置...94

exe4j转换下...94

13String(应用程序接口API类)...94

1.String概述...95

2.String获取和判断...95

3.String转换...98

4.字符串替换...100

5.转换,去除空格,比较...100

6字符串练习...101

查找kk.102

10StringBuffer.102

13String(应用程序接口API类)...105

字符串替换...105

StringBuffer.106

14对象封装新特性...108

14集合框架...108

共性方法...109

4.迭代器...110

讲完Collection,讲List集合,主要是角标...111

5ListIterator.112

6.List集合对象特点...112

7.LinkedList112

10ArrayList练习...112

11ArrayList练习多态编译失败...115

12HashSet(hashCode和equals)...115

HashSet查找...117

13hashset判断和删除的依据...118

15集合框架TreeSet119

2TreeSet存储自定义对象...119

3二叉树...120

4.comparator方式排序...121

6泛型通过<>泛型由来...121

定义容器的时候,就定义了类型...122

泛型就加个<>.122

8.泛型类...123

9泛型定义在方法上...124

10静态方法泛型...125

11泛型定义在接口上...126

12泛型的高级应用,限定...126

13不用泛型太麻烦...127

16.Map.127

接口共性方法看完,看小弟...128

Hashtable.128

3.Map共性方法...128

4.Key-Set130

5.entrySet130

6.Map练习...131

8TreeMap练习...131

17Collections.131

18其他对象...132

System..132

14集合框架...132

迭代器...133

List集合,主要是角标...133

ArrayList134

HashSet137

HashSet查找...138

TreeSet140

泛型通过<>.140

泛型类...141

泛型定义在接口上...142

Map.143

17集合...143

16Arrays.143

17集合转成数组...144

18增强for循环...145

19可变参数。。。...145

20静态导入...145

18其他对象...146

System..146

2.Runtime对象...146

5其他对象Math-Random..147

18IO流(Input、Output)...147

FileWriterDemo新建写入文件...147

IO异常处理...148

原有数据上续写...149

IO流读取...149

IO流文本文件读取联系...150

拷贝文件...151

拷贝图片,媒体文件,字节流...151

拷贝MP3,字节流...152

properties,util包...152

打印流PrintWrite和PrintStream..153

序列流SequenceInputStream..153

管道流PipeInputStream和PipeOutputStream..153

RandomAccessFile.155

23网络编程...155

2301网络编程概述...155

24网络编程...156

Socket156

UDP传输,发送端和接收端...156

聊天对话...156

图形化聊天界面...157

TCP传输,客户端和服务端Socket和ServerSocket158

14TCP复制文件...160

2401TCP上传图片...160

2402客户端并发上传图片...161

代码解析...161

TCP变成客户端小写,返回大写...162

浏览器客户端...163

2405tomcat服务器...164

2406服务端的请求信息...164

自定义客户端...165

自己封装URL,否则切割split很麻烦...166

网络编程...169

域名解析...169

25正则表达式...169

网页爬虫,蜘蛛...169

 

1.Helloworld

Java代码都是通过类来执行的,注意编码Java要用笔记本打开,或者另存为ANSI格式

新建一个java文件,就是一个源文件,然后将它变成执行文件(就是翻译成计算机/虚拟机,可执行的文件)

javc和java,注意之前环境变量已配置,报错注意class是不是写错了。

(1)java要注意大小写

(2)如果想在其它地方运行该Demo,可以自己新定义一个环境变量

(3)所有函数都是从主函数开始执行的。

Java

注释//或/*注释*/

变量

Java是强类型语言,运算都是在内存中进行的,需要开辟空间

数据类型:基本数据类型、引用数据类型

byte是字节1个8位-128到127,-2的7次方

float占了4个8位,double占了8个8位

关键字(所有字母为小写)

标识符

Java严格区分大小写

1.数字不可以开头

2.不可以使用关键字

IF语句

99乘法表

99主函数带入参数

内存结构,5个内存空间

数组,同一种类型数据的集合,其实数组 一个容器。

数组的容器能够自动给数组中的元素编号,从0号开始,方便操作这些元素

(1)栈,数据使用完毕会自动释放。

针对int x=3,主函数在运行的时候,会在栈里面开辟一个空间,空间里就有一个变量x=3

如果调用了show函数,就会开辟一个show内存区域的空间

(2)堆,默认有值,根据字符类型,java会回收堆中的垃圾

int[] x=newint[3]

int[] x局部变量在栈里面

而new出来的东西都是实体,在堆里面,new int[]就在堆里面开辟一个空间,这个空间分了3个格子[0][1][2]。

内存里都是地址池,用地址标识数据存放的位置。

2.函数

函数:就是定义在类中具有特定功能的一段独立小程序

函数也称为方法。

相同的地方抽取出来,封装成独立的功能。

函数的格式

修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,….)

{

     执行语句;

     return 返回值;

}

返回值类型:函数运行后的结果的数据类型int、double。

参数类型:是形式参数的数据类型

形式参数:是一个变量,用于存储调用函数时传递给函数的实际参数

实际参数:传递给形式参数的具体数值。

return:用于结束函数。

返回值:该值返回给调用者。

(1)定义好一个功能

(2)函数只有被调用才能执行

(3)调用函数,返回值类型为int

定义函数可以将代码功能进行封装,便于该功能的复用

函数中只能调用函数,不能在函数内部定义函数

(4)void没有具体返回值,当函数返回值类型是void时,return可以不写,系统默认会加上

3.重载(add(4,5),add(4,5,6)或者99乘法表88)

在同一个类中,允许存在一个以上的同名函数,只要他们的参数个数或者参数类型不同即可

什么时候用重载:当定义功能相同,但参与运算的未知内容不同

那么就定义一个函数名称以表示起功能,方便阅读,而通过参数列表的不同来区分多个同名函数

4数组

数组:同一种类型数据的集合,其实数据就是个容器

好处:可以自动给数组中的元素从0开始编号,方便操作这些元素。

格式1:

元素类型[] 数组名 = new 元素类型[元素个数或数组长度]

示例:int[] arr = newint[5]

格式2:

元素类型[] 数组名 = new 元素类型[]{元素,元素,…..}

int[] arr = newint[]{3,4,5,6,2}

int[] arr ={3,4,5,7,1}

原理 int[] x = new int[3]

凡是局部变量,都在栈内存。(定义在方法中变量,定义方法参数中的变量,定义在for循环中的变量)

凡是new出来的实体都在堆里面(包括数组和对象)

(1)int[] x在栈内存中开辟一个空间

(2)new就在堆中产生一个空间int[3],产生三个格子,每个格子都有个编号:0角标位

(3)堆和栈中的x怎么联系?堆内存中每一个实体都有一个存放位置(地址,内存地址池),这个地址都有一个起始位置,这个数组在堆内存中的首地址,用它来表示堆内存中的地址,就赋给栈中x,x就指向了堆中的数组(或者引用了堆中的数组)

(4)堆中数组都有默认初始值,根据类型定(int0,double0.0)

(5)x取值变了只是指向变了,堆中数组没有变

示例

运行的时候,才会在内存产生空间。//ArrayIndexOutofBoundsException:3:操作数组时,访问到了数组中不存在的角标。

(2)NullPointerException:空指针异常

arr = null;

System.out.println(arr[1]);

遍历,length

(1)常见错误

@右边就是数组的存放地址,这是Hash值16进制的

获取最大值,ArrayMax

排序

0角标和其它排序,最小的放在0角标

然后是1角标和剩下的排序

冒泡排序bub

相邻的两个元素进行比较,如果符合条件换位

数组的查找(折半查找)

(1)一般查找方式

(2)折半查找

(2)第二种折半查找

8十进制转二进制

不想011

9查表法

5面向对象

(1)将执行者,转变为指挥者

(2)实际例子用,到哪就用什么,会议室:会议室封装了public开门,public开会,private首席,使用function会议室这个功能就ok了。

1.面向对象概述

(1)面向对象是相对面向过程而言的

面向对象和面向过程都是一种思想

(2)面向过程:强调的是功能行为

把大象放进冰箱:打开冰箱,放进大象,关闭冰箱

这个打开动作,关闭动作都是面向过程的。

(3)面向对象:将功能封装进对象,强调具备了功能的对象。比如冰箱具备:打开功能和关闭功能。

面向对象是基于面向过程的

结果就是:冰箱.打开、冰箱.存储、冰箱.关闭

3.类与对象的关系

(1)人开门:名词提炼法

 

{

     开门(门)

{

       门.开();//人是一个指挥者的角色

}

}

 

 

{

     谁最清楚门这个开的动作,用到了门里面的轴,把

     开(){操作门轴等};

}

2)面向对象的特征:封装、继承、多态

围绕特征:比如耳朵大,腿短,走路慢,慢慢的就会形成一个大象的概念

开发:其实就是找对象使用,没有对象就创建一个对象

找对象、建立对象,使用对象。维护对象的关系。        提高功能复用性

(3)类和对象的关系

类就是:对现实生活中事物的描述。

对象:就是这类事物,实实在在存在的个体。Java中通过new操作符产生的实体,这个实体在堆内存中。

 

映射到java中,描述就是class定义的类

具体对象就是对应java在堆内存中用new建立实体(凡是数据多了就用实体,对象也是用于存储数据的)

 

先有类还是先有对象?先有类,那是针对计算机语言而言的,有了类才能建立对象。但生活中万事万物皆对象。

 

现实生活中的对象:张三,李四

想要描述:提取对象中共性内容。对具体的抽象。

描述时:这些对象的共性有:姓名,年龄,性别,学习java功能。描述完并不具体,但是这个事务描述出来了

具体要落实到每个学员/对象上,每个学员都有自己的姓名,性别

4.类主函数,成员变量和局部变量

主函数就是入口:用于调用别人

主函数的功能是为了保证一个类的独立运行,当一个类不准备独立运行的时候,就可以不使用主函数

(1)成员变量:作用于整个类,在堆内存中,因为对象的存在,才在内存中存在。

(2)局部变量:作用于函数或者语句中,存在栈内存中

图纸创建新车永远是红色!!!

car中也可以写主函数!!!在本类中创建本类对象,这样就可以直接运行了

一般不写主函数,一个程序由N个类组成,但是一个类做入口就好了。

5.匿名对象

调用方法时有意义的

匿名对象使用方式一:当对对象的方法只调用一次时,可以用匿名对象来完成,这样写比较简化

如果对一个对象进行多个成员调用,必须给这个对象起个名字。

匿名对象使用方式二:可以将匿名对象作为实际参数进行传递。

代码分析,主函数,内存

(1)运行主函数就有Car这个类了,首先主函数加载进栈内存,栈底部加载main,main中有c

(2)然后右边创建对象newCar(),对象中有num=4;color=”红色”;

(3)先分配的空间0x0034,对应该对象的,然后将该地址0x0034赋给c,c便指向了对象

(4)执行到第二句话show(c)时,在栈内存上面又开辟了一个空间,show方法中的很多局部变量都放到栈中,show方法空间有个c,(第一个c是main的,第二个c是show的)

(5)show(c)中的c就是,Car c =new Car()中的c,而show(c)将c传给了show(Car c)这个函数

(6)这就代表着主函数中的c,赋值给了show方法中的c,也就是该c也指向了刚刚的对象,然后就是c.num进行了操作

内存中一直是一个对象

最后show方法结束后,show方法就结束了,堆中对象就没有了指向,就成为了垃圾了

q = null;可以指定下

匿名对象作实际参数传输

show(new Car());

6.封装Encapsulation

private

指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

好处:

将变化隔离

便于使用

提高重用性

提高安全性

封装原则:

(1)将不需要对外提供的内容都隐藏起来

(2)把属性都隐藏,提供公共方法对其访问

 

函数本身就是一个最小的封装体

类也是封装体

 

public权限超级大

类以外有包,包以外可以有框架,框架在做的时候有几千几百个类的

用框架不必要知道原理,学习才需要

7.priavte

一个属性往往会被私有化

(1)封装

封装不是私有,私有仅仅是封装的一种表现形式,只要权限在你访问之外,都叫封装。

(2)私有化不可访问

一个成员变量对应两个访问方式,一个叫设置,一个叫获取

但凡类里面有setget,它肯定是private的某个类

Eclipse:针对private有set和get方法

8.构造函数, 与类同名,可重载

函数名与类名相同,用于对象初始化,构造函数可以多个,即重载。

类中有多个构造函数,重载了,对应不同的对象初始化

描述人的时候,人对象一产生就必须有名或有姓,如果不存在Person()构造函数的话(必须传参)

特点:

(1)函数名与类名相同

(2)不用定义返回值类型(void是一种返回类型,代表没有具体结果返回!!!构造函数是根本不需要定义返回值类型,不可能出现return语句)

有了类后,想使用该类就要创建该类对象

没有写p.Person()啊!!!对象一建立就会调用其对应的构造函数

new一次调用一次

构造函数的作用:可以用于给对象进行初始化,比如人一出生就会哭。。。

构造函数细节:

当一个类没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数

默认空参数构造函数,方便对象初始化

当类中自定义构造函数时,系统就不建立空参构造函数了

构造函数在对象一建立就运行。给对象初始化。只运行一次

而一般方法是对象调用才执行,是给对象添加对象具备的功能。可以被该对象调用多次

方法必定被对象调用(学习静态之前)

李四孩子生下来,后来嫌弃名字难听,所以才setName方法

9.构造代码块,{初始化}

构造代码块最先执行,定义的是不同对象共性的初始化内容,优先于构造函数

10this关键字

this:就代表本类对象

this代表它所在函数所属对象的引用

this:看上去是区分局部变量和同名变量的

构造函数可以被私有,但不能所有构造函数都私有,那样就不能建立对象了

Person(String name)这样好一些,语义化。

对象却没有赋给堆内存中,局部变量名称和成员变量名称相同

局部有就在局部中找,所以上面两个name都是局部的name

是局部给局部复制

int x=3;x=x+1;当然可以

this的特点:

真正运行的是对象,用图纸造汽车,真正开上马路的是汽车,总不能图纸上路吧?

写不写就是阅读上的问题,只有一个方法

函数也是缺省this的

11this关键字的应用,该类

this的应用:当定义类中功能时,该函数内部要用到调用该函数的对象时,这时要用this来表示这个对象

12this关键字在构造函数间调用,this(name),Person(name)

this语句用于构造函数之间进行互相调用

this语句只能定义在构造函数的第一行。

因为初始化中可能会覆盖传入参数

6面向对象

1static关键字静态

static特点:随着类的加载而加载(生命周期最长);优于对象而存在,被对象所共享;可以直接被类名所调用

static用法:是一个修饰符,用于修饰成员(成员变量,成员函数),不能修饰局部!!!!!!

 

静态的使用注意事项:

1.静态可以修饰变量和方法

如public static voidshow()但是要注意直接使用Person.void的时候

静态方法只能访问静态成员,非静态方法既可以访问静态也可以访问非静态

 

2.静态方法中不可以定义this,super关键字

因为静态优先于对象的存在,所以静态方法中不可以出现this!!!(this肯定是有对象的)

 

 

不在堆内存中

多个对象当中存在共同数据,比如cn

对象建立越多,内存中country越多,那就单独提取出来,没必要每个对象都放一份

那么这个static Stringcountry=”cn”在哪呢??

它在共享区,也称为方法区,数据区,多了一片空间(除了堆和栈)

方法区/共享区,类中的方法,类中的共享数据

人有说话能力,但说的内容不一样

说是一种共性行为

姓名和内容才是在对象中的

new一个,就在堆内存中产生一个对象


 

当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被【类名.静态成员】调用

static特点:

1.随着类的加载而加载(class Person要被使用肯定要被加载,一旦该类加载,cn就进入内存了

     也就是说,静态随着类的消失而消失,说明它的生命周期最长。

2.优先于对象存在(比如Stringname是非静态变量,只有下方 Person P=new Person()创建才存在)

3.被所有对象所共享

4.可以直接被类名所调用

 

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

1.存放位置:类变量随着类的加载而存在于方法区中,实例变量随着对象的建立而存在于堆内存中

2.生命周期:类变量生命周期最长,随着类的消失而消失,实例变量随着对象的消失而消失。

区别:类一进入内存,可以产生很多对象、

 

静态的使用注意事项:

1.静态可以修饰变量和方法

如public static voidshow()但是要注意直接使用Person.void的时候

静态方法只能访问静态成员,非静态方法既可以访问静态也可以访问非静态

 

2.静态方法中不可以定义this,super关键字

因为静态优先于对象的存在,所以静态方法中不可以出现this!!!(this肯定是有对象的)

*/

class Person

{

     String name;//成员变量,实例变量

     static String country = "CN";//静态这个关键字,静态是共有的饮水机

     public void show()

     {

            System.out.println(name+"::"+country);

     }

}

 

class StaticDemo

{

     public static void main(String[] args)

     {

            //Person p = new Person();

            //p.name = "zhangsan";

            //p.show();

            //System.out.println(p.country);

            System.out.println(Person.country);

     }

}

2.main,主函数是静态的

public staticvoid main(String[] args)

主函数的定义:

public:代表着该函数访问权限是最大的。

static:代表随着类的加载就已经存在了

void:主函数没有具体返回值。(返回啥呢?返回的话,虚拟机是不是挺害怕的啊!!!就是一个入口调用其他类函数运行的。)

main:不是关键字,但是一个特殊的单词,可以被jvm识别。

String[] args:函数的参数,参数类型是一个数组,该数组中的元素是字符串。字符串类型的数组。

只有变量名可以,比如String[] x;

虚拟机只是先运行那个固定格式的先

args是个数组实体,可以args.length看看

静态static是最先被加载的

静态的应用

将功能封装在对象中,找到了对象就找到了功能。

帮助文档的使用

setclasspath=.;c:\myclass

class文件不知道有哪些功能,全被封装了,也打不开。

public的才可以!!!!

静态代码块

对象的初始化

Person p =newPerson(“zhangsan”,20);

(1)new的时候将Person.class文件从硬盘中通过java虚拟机加载进内存,并开辟堆内存空间,就有地址了比如p的地址为0x23。

主函数,栈中有main,p

(2)静态代码块执行

(3)堆中开辟空间,newPerson(),分配内存地址,

(4)在堆内存中建立对象的特有属性:name、age初始化

(5)构造代码块初始化

(6)构造函数初始化,将name赋值为张三。。。

单例设计模式

单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。

(1)先读主函数main,栈和堆就出来了,然后读Singless = Single.getInstance();

其中Single类一加载出来,方法区就有Single空间了,首先由静态变量s变量,然后是getInstance方法,然后是privateSingle(){},这个时候s变量就有值了。

s的值是newSingle();对象,对象在堆中有内存空间比如0x0045,s值就是指向对象的(引用对象)

然后给ss赋值,就是将0x0045赋给了ss

保证了一个类在对象的唯一性


 

接口interface,特殊抽象类

/*

接口:特殊的抽象类

 

接口定义时,格式特点:

1.接口中常见定义:常量、抽象方法

2.接口中的成员都有固定修饰符。

常量:public staticfinal

方法:public abstract

 

记住:接口中的成员都是public的

接口:是不可以创建对象的,因为有抽象方法

需要被子类实现,子类对接口中的抽象方法全部都覆盖后,子类才可以实例化。

否则子类是一个抽象类

 

接口可以被类多实现,一个类可以同时实现多个接口

*/

 

 

interface Inter

{

     public static final int NUM = 3;//全局静态最终常量

     //int NUM=3;也可以,因为interface都会默认加上的,声明了抽象

     public abstract void show();//抽象方法,不能创建对象

}

 

class Testimplements Inter//类与类是继承关系,子类不用辛苦直接拿来用;接口是实现,需要全部复写

{

     public void show(){}

}

 

classInterfaceDemo

{

     public static void main(String[] args)

     {

            Test t = new Test();

            System.out.println(t.NUM);

            System.out.println(Test.NUM);

            System.out.println(Inter.NUM);//注意NUM是常量,不能赋值

     }

}

接口举例

class zhangsanextends Student implements Smoking

张三在体系中扩展了功能

class Lisiextends Student

李四集成了学生,但是不抽烟

8面向对象

多态,事物存在的多种体现形态

8.Object类上帝类equals

(1)Java认为所有对象都具备比较性,这种所有就定义在Object类中

比如equals

对象只要一存在,就有方法。

(2)任意对象编程字符串,如toString()

下面d1和d3比较的其实是地址

 

建立自己的equals就直接覆写

9.toString()

类文件里面封装了构造函数、函数、成员变量

所有对象都是依赖于class文件创建的。

所有对象都有hash值,那么就在Object中

9面向对象

1.内部类(内置类、嵌套类)

(1)先定义的都是外部类

(2)内部类可以直接访问外部类中的成员,包括私有

外部类要访问内部类,必须建立内部类对象

(3)外部类访问,需要加类.类

内部类可以被私有修饰

 

1.为什么内部类可以访问外部类内容

之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的应用。格式:外部类名.this

静态的Inner

调用方法就进栈了

4.匿名内部类

匿名内部类其实就是内部类的简写格式

内部类,与匿名内部类

/*

匿名内部类:

1.匿名内部类其实就是内部类的简写格式,没名字的内部类

2.定义匿名内部类的前提:

     内部类必须是继承一个类或者实现接口。(想简化)

     (你想把if...else简化成三元运算符,没有结果不行)

3.匿名内部类的格式:new 父类或者接口()(定义子类内容)

4.其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象

 

*/

abstract classAbsDemo

{

     abstract void show();

     //给心脏提供一个抽象类,实现在内部实现

     //有抽象方法

}

 

class Outer

{

     int x = 3;

     /*

     class Inner extends AbsDemo//Inner有了自己的体系

     {

            void show()

            {

                   System.out.println("show:"+x);

            }

     }

     */

    

     public void function()

     {

            //new Inner().show();

            new AbsDemo()//抽象方法不能创建对象,所以不能分号,式AbsDemo的子类对象

            //现在是对象还带有内容!!!很胖的对象

            //我要覆盖抽象方法

            {

                   void show()

                   {

                          System.out.println("x==="+x);

                   }

                   void abc()

                   {

                          System.out.println("haha");

                   }

            }.abc();

     }

}

 

class InnerClassDemo

{

     public static void main(String[] args)

     {

            new Outer().function();

     }     

}

4.匿名内部类调用父类方法

一般写匿名方法不会超过三个,调用它比较方便

方法多了怎么办,直接搞个类继承下

4.匿名内部类的

(1)题目

function后面加了()就是代表函数

(2)分析

(3)正常方法实现

(4)匿名内部类实现

interface Inter

{

     void method();      

}

 

class Test

{

     //补足代码,通过匿名内部类

     static class Inner implements Inter//参数列表我知道,是空参数

     {

            public void method()

            {

                   System.out.println("methodrun");

            }

     }

    

     static Inter function()

     {

            return new Inner();//Inner是Inter的子类

     }

}

 

classInnerClassTest

{

     public static void main(String[] args)

     {

            Test.function().method();

            //调用一个函数,函数后面还有点,就是调用method方法

            //method方法时非静态的,因为它是抽象的

            //前面的东西运算完,还能调用method,所以返回的是对象,才能调用method()

            //什么对象可以调用method,必然是Inter的对象

     }

}

直接子类是可以的

5.Java的异常机制

就是不正常机制

异常:就是程序在运行是出现不正常情况。

     异常由来:问题也是现实生活中一个具体事物,也可以通过java的类形式进行描述。并封装成对象。

                   其实就是java对不正常情况进行描述后的对象体现。

     问题划分:严重、非严重

     严重的:java通过Error类进行描述

            对于Error一般不编写针对性的代码进行处理

     非严重:java通过Exception类进行描述 

            对于Exception可以使用针对性的处理方法进行处理

除数不能为0,计算机没办法帮你运算了。。。。程序异常了,虚拟机帮你把程序停止掉了

父类(超类)

重点看可以处理的

常见的已有的数学规则进行封装,万物皆对象,这个异常就是对违反了数学规则的进行了封装

6.异常处理机制

jvm虚拟机把它熟悉的规则封装了,只有出现该问题,就不管了

finally

不能单独一句,比如sop(x)必须和x一起

7.异常处理

函数有异常,程序就扔出了

继承

1.提高了代码的复用性

2.让类与类之间产生了关系,有了这个关系,才有了多态的特性。

Java只支持单继承,不支持多继承

但是保留了这种机制,并用另一种体现形式来表示,即多实现,比如interface

聚集

聚集:has a

聚合:

子父类

千万不要改源码!!!灾难

为了提高程序的扩展性,新出的手机和老手机有共性

(1)覆盖:子类覆盖父类,必须保证子类权限大于等于父类权限,才能覆盖,否则编译失败(子类不能单独private)

(2)静态只能覆盖静态(一般无用)

(3)重载只看同名函数的参数列表,重写子父类方法要一模一样。

(4)父类是intshow(){return -1},子类是void show(){},这样是不行的,无法覆盖

class NewTelextends Tel

{

     void show()

     {

            System.out.println(“number”);

            //super.show();

//来电显示父类已经有了,就没有必要显示了,不能直接show(),会有this

     System.out.println(“name”);

}

}

抽象对象,抽象类

class Student{}

classBaseStudent extends Student{}

class AdvStudentextends Student{}

实例

/*

需求:

1.员工建模,三个属性:姓名、工号、工资

2.经理也是员工,此外还有一个属性:奖金

用继承的的思想设计出员工类和经理类,要求类中提供必要的方法进行属性访问。

 

员工类:name、id、pay

工号比较特殊,不是单纯的int,比如技术部有JiSu01,测试部有Test01

经理类:bonus

 

*/

 

abstract classEmployee

{

     private String name;

     private String id;

     private double pay;

    

     Employee(String name,String id,double pay)//初始化

     {

            this.name = name;

            this.id = id;

            this.pay = pay;

     }     

    

     //public void work(){}//公司分普通员工和经理,但是工作不一样,那么就抽象

     public abstract void work();

}

 

class Managerextends Employee

{

     private int bonus;

     Manager(String name,String id,doublepay,int bonus)

     {

            super(name,id,pay);

            this.bonus = bonus;

     }

    

     public void work()

     {

            System.out.println("managerworker");

     }

}

 

class Proextends Employee

{

     Pro(String name,String id,double pay)

     {

            super(name,id,pay);

     }

    

     public void work()

     {

            System.out.println("Prowork");

     }

}

 

 

classAbstractTest

{

     public static void sop(Object obj)

     {

            System.out.println(obj);

     }

    

}

模板方法TemplateDemo

 

 

 

 

 

 

 

 

 

 

构造函数,名称随类名走

(1)子类一定要访问父类中的构造函数

父类定义完后,子类定义好

子类定义好会拿到父类的数据,子类拿数据之前会先看看父类是如何对数据初始化的

(2)Fu(int x)的话,没有空参数

super()就不能是隐式参数了,必须是如super(4);了

final

(1)可以修饰类、函数、变量

(2)被final修饰的类不可以被继承

10面向对象

7.包Package

定义类是class,定义接口是interface,定义包是Package放在代码第一行

编译后class可能会被覆盖,类重名也通过文件夹进行区分,也就是Java的包

对类文件进行分类管理

给类提供多层命名空间,不同文件夹下相同名字的东西

写在程序文件的第一行

类名的全称是 包名.类名

包也是一种封装形式

一般写项目肯定先先包,再写类!

包名要全称

结果还是不行,需要新建文件夹pack,然后才是java pack.PackageDemo

javac –d 目录

javac –d 点 PackageDemo.java

这组类什么功能,那组类什么功能

自动生文件夹

放在其它目录

不一定要写在当前地址,就是放在其它地址,这样的好处就是使得类文件也就是Java运行文件源文件相分离!!!class给别人喽~

setclasspath=c:\myclass

不用写pack,只要指向包的父目录即可。

(1)PackDemo调用packa包

(2)packa包不在当前目录下,需要设置classpath,告诉jvm去哪里找包

(3)找到包,提示不是公共的,设置为public class DemoA。(包中的类被访问,需要足够大的权限public)

(4)类公有后,被访问的成员也需要公有

包也是封装的一种,封装了10个类,9个类不是public,就相当于只有一个对外界访问。

8.包与包之间的访问

包与包之间可以使用的权限只有两种:public、protected

 

public

protected

default

private

同一类中

ok

ok

ok

ok

同一包中

ok

ok

ok

 

子类

ok

ok

 

 

不同包中

ok

 

 

 

同一个包中protected,一般用于覆盖

一个java文件,不允许两个或以上公有

可以放pack中有两个类,放在同一个包

真正运行的是目录下的class文件

先编译DemoA!

一个包中的类要被访问需要足够大的权限,被访问的类,需要public修饰,被访问的成员也要公有才可以访问

继承没有问题

包之间的继承,你认我为父,就可以拿到别人拿不到的权限,protected,保护权限

9. import导入

为了简化类名的书写!importpackb.*;导入的是该包下的所有类。

用*,导入许多不允许的类,很占内存的(建议不要写通配符*,需要用到包中的哪个类就导入哪个类)

建立对象太费劲

import pack.haha.hehe.heihei.*;

就是这个文件夹下的DemoC类、其它DemoN类都导入了

import导入的是包中的类。

出现重名时,必须加包名!!!

建议定义包名不要重名: 可以使用url来完成定义,url是唯一的

用域名(不重复的),上互联网哪有重名的,比如:

pcakagecn.itcast.demo

packagecn.itcast.test

Eclipse

Ctrl+shift+O自动导入包。

jar包

jar.exe来驱动

Java的压缩包:方便项目的携带;方便使用,只要在classpath设置jar路径即可;数据

清单文件:

meta-inf/

meta-inf/mainfest.mf

 

18其他对象

System

getProperties()

/*

组合成输出语句

System:类中的方法和属性都是静态的

out:标准输出,默认是控制台

in:标注输入,默认是键盘

*/

importjava.util.*;

 

11多线程

线程一般都是循环,如果不是循环,一个线程足以

进程:正在执行的程序,process

 

线程:

thunder:迅雷下载分5个数据!

进程和线程是系统创建的,虚拟机Java只是调用下该接口。

1.多线程

Java VM启动的时候会有一个进程java.exe

该进程中至少有一个线程负责java程序的执行,而这个线程运行的代码存在于main方法中,即主线程

扩展:其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收的机制的线程。

2.创建线程-继承Thread类

windows本身是一个多任务操作系统,其实CPU在某一时刻只能执行一个程序

是CPU执行完一个程序之后,比如先执行游戏,再执行视频,不断切换,很快以至于你感觉不到区别。

双核CPU懂了吧!

3.run和start的特点,start才可以开启线程

Thread类

创建线程第一种方式,继承Thread类:

步骤:

1.定义继承Thread

2.复写Thread类中的run方法

     目的:将自定义的代码存储在run方法中,让线程运行

3.调用线程的start的方法

     该方法两个作用:启动线程,调用run方法

start是调用底层,开启线程去运行的

run仅仅是封装线程要运行的代码

Thread类用于描述线程

 

该类就定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法。

 

也就是说Thread类中的run方法,用于存储线程要运行的代码。

 

主线程要运行的代码存在main方法中,虚拟机定义的,哥们要运行的代码都在main方法中,不在不运行!!

d.start();//开启线程并执行该线程的run方法

//d.run();//仅仅是对象调用方法。而线程创建了,并没有运行

4多线程练习

如果是t1.run();的话,就只能是一个线程了,挨个运行完

private Stringname;

Test(Stringname)

{

     SYstem.out.println(name+”….”);

}

 

主函数

Test t1 = newTest(“one”);

5.线程运行状态4:被创建,运行、冻结(临时状态/阻塞)、消亡

被创建:new一个Thread对象(或其子类对象),就是创建线程的

Thread类是依赖于windows创建的,是描述线程的一个类。

wait();

notify();//唤醒状态

 

stop();

run方法结束。

 

临时状态(阻塞),线程start不一定运行,因为你开启了3个线程,它可能在等待CPU的执行权,具备运行资格但没有执行权

临时状态(阻塞

6.获取线程对象及名称

this.getName()

Test(String name){    super(name);    }//继承父类方法,构造函数

也可以

t1在调用的时候,run就属于t1,所以Thread.currentThread()就属于t1

 

创建线程的方法

接口Runable

Runnable实现方式和继承方式有什么区别?

7.卖票例子

出现争执了

让4个对象共享100张票,用静态试试

但是一般不定义静态,它的生命周期太长

如果只是t1对象多开线程呢?不行

已经从创建状态到start方法了,就没有意义了,线程状态出问题了,已经运行的程序,不需要再次开启的

好比,发令枪碰!运动员跑了半圈,发令枪又蹦!!!

8.实现Runnable接口

创建线程的第二种方式:实现Runnable接口

 

步骤:

1.定义类实现Runnable接口

2.覆盖Runnable接口中的run方法

     将线程要运行的代码存在该run方法中

 

3.通过Thread类建立线程对象

4.将Runnable接口的子类对象作为实际参数,传递给Thread类的构造函数

     为什么要将Runnable接口的子类对象传递给Thread的构造函数

     因为:自定义的run方法所属的对象是Runnable接口的子类对象

     所以要让线程去指定对象的run方法。就必须明确该run方法所属对象

 

5.调用Thrad类的start方法开启线程,并调用Runnable接口子类的run方法

 

Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为run 的无参数方法

怎么写呢??

Thread类认识Runnable接口

new一个对象,用4个线程执行

8. 实现方式和继承方式有什么区别?

继承Thread:线程代码存在Thread子类run方法中。

实现Runnable:线程代码存在接口的子类的run方法中。

继承继承了Thread类后,就不能继承其它类了

(1)假设有一个类,这个类中有一部分代码需要多线程执行run()方法,怎么办?让它继承Thread类,并复写run方法。

(2)还是学生类,学生类和工人类,在不断向上处理过程中产生了一个Person()类,也就是学生类继承了Person类,那么学生类就不能继承Thread了

(3)Java工程师发现!你可以不是我的儿子,你的代码我还是可以给你执行,但是你得符合我的规则。。。。也就是接口Runnable,可运行的,定义好了规则run

功能性扩展:避免单继承的局限性

Thread类本身也实现了Runnable方法

9.多线程的安全问题

线程执行如上图,共用的是一个对象t,所以执行过程中可能会导致一个线程正在执行,另外一个线程也执行,导致比如卖票0,-1

冻结状态sleep,模拟这个卧倒

抛出异常了

只能try

覆盖接口是不能抛异常的

只能try

解决,同步代码块

为了解决该问题,采用了:同步代码块的方法。synchronize(对象){需要被同步的代码}

哪些代码需要同步?就看哪个数据是共享数据,上述是tick的运算

只有共享数据需要

synchronized(obj)本来是1,谁进去后就会置0,只有出来后,才会将obj置为1,它在里面怎么执行,外面的人都进不来(就算获取到cpu执行权都不可以进去)

锁旗标/监视器

随便一个对象都可以

10同步代码块,同步锁,锁旗标,火车卫生间。。。

synchronizeed(obj)

只要一存在就有0和1(默认)。

(1)0线程一过来,发现synchronizeed(obj)是1,开着的,进来后不是执行if而是将1变成了0

(2)然后执行if语句,执行到sleep的时候,执行权可能放出去了,卧倒了,这时候3抢到执行权了,判断synchronizeed(obj)是0,进不来。

(3)0线程醒了后,继续执行,出了同步后将标志位0又置为1

obj这个位置叫什么呢?专业术语叫锁旗标,就是锁/监视器。持有监视器,拿着锁才能进去

 

同步的前提:

1.必须是2个或以上线程;必须是多个线程使用同一个锁

虽然解决了问题,但是消耗了资源,每次都要查看锁(允许范围内的)

2.必须是多个线程使用同一个锁。

 

同步代码块或者同步函数

11.多线程,同步函数

执行过程中,下一个线程进来了

class Bank

{

     private int sum;

     Object obj = new Object();

     public void add(int n)//这是能抛的

     {

            synchronized(obj)

            {

                   sum = sum +n;             

                   try{Thread.sleep(10);}catch(Exceptione){}

                   System.out.println("sum="+sum);

            }            

     }

}

 

class Cusimplements Runnable

{

     private Bank b = new Bank();

     public void run()

     {

            for(int x=0;x<3;x++)

            {

                   b.add(100);

            }

     }

}

 

class BankDemo

{

     public static void main(String[] args)

     {

            Cus c = new Cus();

            Thread t1 = new Thread(c);

            Thread t2 = new Thread(c);

            t1.start();

            t2.start();

     }

    

}

直接同步函数

把同步作为修饰符

12.同步函数的锁是this

错误的问题

同步函数用的是this,同步代码块也用this

/*

需求:简单的卖票程序

同步函数用的是哪个锁?

函数需要被对象调用,那么函数都有一盒所属对象引用,就是this

所以同步函数使用的锁是this

 

通过改程序进行验证

 

一个线程在同步代码块

一个线程在同步函数中

都在执行卖票动作

 

 

*/

 

class Ticketimplements Runnable//extends Thread

{  

     private static int tick = 100;

     Object obj = new Object();

     boolean flag = true;

    

     public void run()

     {

            if(flag)

            {

                   while(true)

                   {

                          synchronized(this)

                          {

                                 if(tick>0)

                                 {

                                 try{Thread.sleep(10);}catch(Exceptione){}//不加sleep,有可能1万次不发现,但是就怕这个1万次01

                                        System.out.println(Thread.currentThread().getName()+"code:--------  "+tick--);

                                 }

                          }

                                                                   

                   }

            }

            else

                   while(true)

                          show();

                  

           

     }

    

     public static synchronized voidshow()//this

     {

            if(tick>0)

            {

            try{Thread.sleep(10);}catch(Exceptione){}

                   System.out.println(Thread.currentThread().getName()+"show:.............."+tick--);

            }

     }

}

 

classStaticMethodDemo

{

     public static void main(String[] args)

     {

            Ticket t = new Ticket();

            Thread t1 = new Thread(t);

            Thread t2 = new Thread(t);

            //Thread t3 = new Thread(t);//创建了一个线程            

            //Thread t4 = new Thread(t);//创建线程目的,运行我指定的代码,之前他们是没有关系的

           

           

            t1.start();//开启后处于临时状态

            try{Thread.sleep(10);}catch(Exceptione){}

            t.flag = false;          

            t2.start();//执行到这,主线程就结束了

            //t3.start();

            //t4.start();                          

     }

}

13静态同步函数的锁是Class对象(getClass获取实例)

如果同步函数被静态修饰后,使用的锁是什么呢

通过验证,发现不再是this。因为静态中也不可以定义this

 

静态进内存是,内存中没有对象,但是一定有该类对应的字节码文件对象

类名.class 该对象类型是Class

函数用静态可以修饰

为了编译通过,tick也加静态

tick不加静态,是堆内存中的共享数据,加静态是在方法区中共享数据

静态同步:类名.class

14单例设计模式-懒汉式

懒汉式特点:实例的延迟加载

懒汉式延迟加载有没有问题,有。如果多线程访问时会出现安全问题,可以加同步解决。

用同步代码块和静态同步函数可以解决,稍微低效

用双重判定可以解决效率问题,加同步使用锁是:该类所属的字节码流对象。

传统懒汉式,线程不安全

加锁可以,但是低效

A进来后,挂着,B判断s==null,继续在synchronized等着,A出来后,继续判断s!=null,就出来了

后来的C什么,一开始就判断if(s==null)了,双重判定,减少锁判定的开销

同步代码块

饿汉式

15.死锁

class Test implementsRunnable

{

     private boolean flag;

     Test(Boolean flag)

     {

            this.flag = flag;

     }

     public void run()

     {

            if(flag)

            {

                   synchronized(MyLock.locka)

                   {

                          System.out.println("iflocka");

                          synchronized(MyLock.lockb)

                          {

                                 System.out.println("iflockb");

                          }

                   }

            }

            else

            {

                   synchronized(MyLock.lockb)

                   {

                          System.out.println("elselockb");

                          synchronized(MyLock.locka)

                          {

                                 System.out.println("elselocka");

                          }

                   }

            }

     }

}

 

class MyLock

{

     static Object locka = new Object();//本来调用还要实例化,那么直接静态吧

     static Object lockb = new Object();//方便调用

}

 

classDeadLockTest

{

     public static void main(String[] args)

     {

            Thread t1 = new Thread(newTest(true));

            Thread t2 = new Thread(newTest(false));

           

            t1.start();

            //try{Thread.sleep(1);}catch(Exceptione){}

            t2.start();

     }

}

12多线程

1.线程通信,一堆煤,卡车进,卡车出,BUG

之前不管是卖票,还是银行存钱都是一个代码

动作不一致,需要两个run()方法,放置代码

String name;String sex

1个描述资源,2个run方法

/*

线程间通讯

其实就是多个线程在操作同一个资源

但是操作的动作不同

 

单例可以,静态不建议,不能清理,对象还可以清理

*/

 

class Res

{

     String name;

     String sex; 

}

 

class Inputimplements Runnable

{

     private Res r;//建立引用

     Input(Res r)

     {

            this.r = r;

     }

     public void run()//run方法操作资源

     {

            int x = 0;

            while(true)

            {

                   if(x==0)

                   {

                          r.name ="mike";

                          r.sex ="man";

                   }

                   else

                   {

                          r.name = "丽丽";

                          r.sex = "女女女女女";

                   }

                   x = (x+1)%2;//1模以2为1,然后2摸以2为0;

                  

            }

     }

}

 

class Outputimplements Runnable

{

     private Res r;

     Output(Res r)

     {

            this.r = r;

     }

     public void run()

     {

            while(true)

            {

                   System.out.println(r.name+"......"+r.sex);

            }

     }

}

 

classInputOutputDemo

{

     public static void main(String[] args)

     {

            Res r = new Res();

            Input in = new Input(r);//凡是实现Runnable接口的都要建立对象

            Output out = new Output(r);

           

            Thread t1 = new Thread(in);

            Thread t2 = new Thread(out);

           

            //有一堆煤,然后有一辆大卡车,一辆进的,一辆出的

            t1.start();

            t2.start();

           

     }

}

2.解决安全问题

加了同步后还不安全,前提是???

(1)两个线程

(2)用的是不是用一个锁

CPU机制造成的一大片一大片的

3.等待唤醒机制

等待的线程在哪呢?线程在运行的时候,内存中会建立线程池,等待线程都存在线程池中,没死但是不能动!notify会唤醒线程池中的所有线程,先唤醒第一个等待的。

为什么定义在Object,因为锁是任意对象的

4.代码优化

常见操作,private私有

/*

线程间通讯

其实就是多个线程在操作同一个资源

但是操作的动作不同

 

单例可以,静态不建议,不能清理,对象还可以清理

*/

 

class Res

{

     private String name;

     private String sex;

     boolean flag = false;

    

     public synchronized void set(Stringname,String sex)

     {

            if(flag)

                   try{this.wait();}catch(InterruptedExceptione){}

            this.name = name;

            //停在这里了!

            this.sex = sex;

            flag = true;

            this.notify();

     }

     public synchronized void out()

     {

            if(!flag)

                   try{this.wait();}catch(InterruptedExceptione){}

            System.out.println(name+".......:"+sex);

            flag = false;

            this.notify();

     }

}

 

class Inputimplements Runnable

{

     private Res r;//建立引用

    

     Input(Res r)

     {

            this.r = r;

     }

     public void run()//不能完全同步!会单线程的

     {

            int x = 0;

            while(true)

            {                                               

                   if(x==0)                          

                          r.set("mike","man");                

                   else

                          r.set("丽丽","女女女女女");                            

                   x = (x+1)%2;//1模以2为1,然后2摸以2为0;                                            

            }

     }

}

 

class Outputimplements Runnable

{

     private Res r;

    

     Output(Res r)

     {

            this.r = r;

     }

     public void run()

     {

           

            while(true)

            {

                   r.out();       

            }

     }

}

 

classInputOutputDemo

{

     public static void main(String[] args)

     {

            Res r = new Res();

           

            new Thread(new Input(r)).start();

            new Thread(new Output(r)).start();

           

     }

}

 

/*

wait;

notify();

notifyAll();

 

都使用在同步中,因为要对持有监视器(锁)的线程操作

所以要使用在同步中,因为只有同步才具有锁。

 

 

为什么这些操作线程的方法要定义Object类中呢?

因为这些方法操作同步线程时,都必须要标识它们所操线程作只有的锁

只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒

不可以对不同锁中的线程进行唤醒

 

也就是说,等待和唤醒必须是同一个锁

 

而所锁可以是任意对象,多以可以被任意对象调用的方法定义在Object类中

 

*/

5生产者和消费者,问题

(1)假设生产者先拿到执行权t1,t2,那么t1进来后flag=false;t1不需要等待,往里面赋了个值,值++一次。

出来的时候flag=true了

(2)执行完t1还有执行权,继续执行的时候,判断了flag为true了,就等着了

t2进来,也等着了。。。。

(3)只剩下t3、t4了,t3执行完,唤醒了t1,t1获取执行资格,但不一定执行

(4)t3第一次执行完后,活着t4和t1,但是t4很快挂着了

(5)t1执行完,先唤醒的是线程池中等待着的t2,将本方唤醒了。。。。t2不需要判断标记的,直接往下走了

原因是醒来的时候,没有判断标记

怎么判断多次,用while,会返回再读一次

只是notify会全部等待,全部冻结,挂起了

唤起对方线程!!!notifyAll();

(1)t1执行完,t1,t2都等着了

(2)t3执行了,t3执行完,t3,t4等着了唤醒了t1

(3)t1执行完唤醒notify了本方的t2,t2一判断。。。flag=true…就一起等着了,,,,

5.生产者消费者,解决问题

生产一个,消费一个

当出现多个生产者和消费者的时候,必须用while,notifyAll(),要把对方唤醒

6生产者消费者JDK5.0,lock

1.5版本开始的,1.5是里程碑式的升级叫JDK5.0!

1.4的程序员都在while,notifyAll

synchronized被lock替代了

finally

没有写catch,就抛出异常,throws InterruptedException

记得导包

condition

两对象搞定!!!

/*

生产者,消费者有什么替代方案呢?1.5版本后显示的锁机制,以及显示的锁对象上的的等待,唤醒操作机制

同时封装了,使得,一个锁可对应多个condition

再建锁,嵌套容易死锁。

JDK1.5中提供了多线程升级解决方案

 

将同步Synchronized替换成了lock操作

将Object中wait,notifynotifyAll 替换了Condition对象

该对象可以Lock锁 进行获取

 

只唤醒对象操作。

 

 

*/

 

importjava.util.concurrent.locks.*;

 

classProducerConsumerDemo

{

     public static void main(String[] args)

     {

            Resource r = new Resource();

            Producer pro = new Producer(r);

            Consumer con = new Consumer(r);

           

            Thread t1 = new Thread(pro);

            Thread t2 = new Thread(pro);

            Thread t3 = new Thread(con);

            Thread t4 = new Thread(con);

           

            t1.start();

            t2.start();

            t3.start();

            t4.start();

     }     

}

 

class Resource

{

     private String name;

     private int count = 1;

     private boolean flag = false;

    

     private Lock lock = new ReentrantLock();

    

     private Condition condition_pro =lock.newCondition();

     private Condition condition_con =lock.newCondition();

    

     public void set(String name) throwsInterruptedException

     {

            lock.lock();

            try

            {

                   while(flag)

                          condition_pro.await();//拿到锁,执行代码抛出异常,还没有执行到unlock,也就是我还拿着锁

                   this.name =name+"---"+count++;

                  

                   System.out.println(Thread.currentThread().getName()+"...生产者"+this.name);

                   flag = true;

                   condition_con.signal();

            }

            finally

            {

                   lock.unlock();//释放锁的动作一定要执行

            }            

     }

    

     //t3,t4

     public void out() throws  InterruptedException

     {

            lock.lock();

            try

            {

                   while(!flag)

                          condition_con.await();

                   System.out.println(Thread.currentThread().getName()+"...消费者.....>......."+this.name);

                   flag = false;

                   condition_pro.signal();

            }

            finally

            {

                   lock.unlock();

            }

           

     }

}

 

class Producerimplements Runnable

{

     private Resource res;

    

     Producer(Resource res)

     {

            this.res = res;

     }

     public void run()

     {

            while(true)

            {

                   try

                   {

                          res.set("+商品+");

                   }

                   catch(InterruptedException e)

                   {

                         

                   }                   

            }

     }

}

 

class Consumerimplements Runnable

{

     private Resource res;

    

     Consumer(Resource res)

     {

            this.res = res;

     }

     public void run()

     {

            while(true)

            {

                   try

                   {

                          res.out();

                   }

                   catch(InterruptedException e)

                   {

                         

                   }

            }

     }

}

 

7.停止线程

不能用stop方法(会显示过时了,没清楚,老程序还在用)了,只能用run方法结束

它有bug,强制停止了!甭管你线程在干嘛

flag标记下,changeFlag就结束了

/*

stop方法已经过时

如何停止线程?

只有一种!run方法结束。

开启多线程,运行代码通常是循环结构

只要控制住循环,就可以让run方法结束,也就是线程结束

*/

 

class StopThreadimplements Runnable

{  

     private boolean flag = true;

     public void run()

     {

            while(flag)

            {

                   sop(Thread.currentThread().getName()+"...run");

            }

     }

    

     public void changeFlag()

     {

            flag = false;

     }

    

     public static void sop(Object obj)

     {

            System.out.println(obj);

     }

}

 

classStopThreadDemo

{

     public static void main(String[] args)

     {

            StopThread st = new StopThread();

            Thread t1 = new Thread(st);

            Thread t2 = new Thread(st);

           

            t1.start();

            t2.start();

           

            int num = 0;

           

            while(true)

            {

                   if(num++ == 60)

                   {

                          st.changeFlag();

                          break;

                   }

                   System.out.println(Thread.currentThread().getName()+"......"+num);

            }

     }

}

直接扔砖头

8守护线程setDaemon

后台线程:开启后,共同和前台线抢CPU资源,只是结束不一致。当所有前台线程结束后,后台自动结束。

传入true就好了

9多线程join方法

10优先级&yield

线程组

任务管理器,设置高一点,CPU执行它的频率就高一点

优先级一共1到10,默认是5

5、6不明显,只有1、5、10明显max、min、norm

yield

10开发写线程

什么时候用多线程:当某些代码需要被同时执行时,就用单独线程进行封装

可以使封装3个类。。。

new Thread(){

public void run(){覆盖run方法}

}.start();//Thread的匿名内部类

这样一封装,独立运算,单独封装个线程出来

匿名内部类就好了

22GUI(图形用户界面)Graphical User Interface

图形化界面和dos命令行(dos、javac、java等命令)

Java为GUI提供的对象都存在java.Awt和javax.Swing两个包中

java.Awt:AbstractWindow ToolKit(抽象窗口工具包),需要调用本地系统方法实现功能。(依靠平台windows里面不一定和Linux一致)。属重量级控件。

java.Swing:在Awt的基础上,建立一套图形界面系统,其中提供了更多的组件,而完全由Java实现。增强了移植性,属轻量级控件。(基于此,建立N多组件)

//Eclipse是存Java编写的,但是它使用Swt编写的。

Container比较特殊,可以添加其他组件。

文本框是单行文本,TextArea文本区域时多行文本

比如:文件对话框,可以操作保存文件

布局

布局:容器中的组件的排放方式

常见的布局管理器:

FlowLayout(流式布局管理器),从左到右的顺序,Panel默认的布局管理器

BorderLayout边界布局,东南西北中,Frame默认的布局

GridLayout,网格布局,规则的矩阵,比如calc

CardLayout,卡片布局,选项卡

GridBagLayout,网格包布局,非规则的矩阵

Eclipse+插件(画布)

3图形化界面Frame

查看JDK

查看方法超多,但是有个Container

(1)输出HelloWorld稍微等待了一下

查看方法

(2)setVisible(true)

(3)按钮超级大需要setLayout

 

4事件监听机制

事件源(组件)、事件(Event)、监听器(Listener)、事件处理(引发事件后处理方式)

事件监听机制流程图

5.窗体事件

(1)创建类

(2)既然就一个方法,就用内部类

(1)窗体监听先找window

监听器中监听的都是动作

Action事件

importjava.awt.*;

importjava.awt.event.*;

 

class FrameDemo

{

     private Frame f;

     private Button but;

    

     FrameDemo()

     {

            init();

     }

    

     public void init()

     {

            f = new Frame("my Frame");

           

            f.setBounds(300,100,600,500);

            f.setLayout(new FlowLayout());

           

            but = new Button("mybutton");

            //将组件添加到Frame中

            f.add(but);

            //加载一下窗体上的事件

            myEvent();

            //显示窗体

            f.setVisible(true);

     }

    

     private void myEvent()

     {

            f.addWindowListener(newWindowAdapter()

            {

                   public voidwindowClosing(WindowEvent e)

                   {

                          System.exit(0);

                   }

            });

            //让按钮具备退出程序功能

            //按钮就是事件源,选者哪个监听器呢?

           

            but.addActionListener(newActionListener()

            {

                   public voidactionPerformed(ActionEvent e)

                   {

                          System.out.println("退出,按钮干的");

                          System.exit(0);

                   }

            });

           

           

     }

    

     public static void main(String[] args)

     {

            new FrameDemo();

     }

}

鼠标事件(共性事件)

importjava.awt.*;

importjava.awt.event.*;

 

classMouseAndKeyEvent

{

     private Frame f;

     private Button but;

    

     MouseAndKeyEvent()

     {

            init();

     }

    

     public void init()

     {

            f = new Frame("my Frame");

           

            f.setBounds(300,100,600,500);

            f.setLayout(new FlowLayout());

           

            but = new Button("mybutton");

            //将组件添加到Frame中

            f.add(but);

            //加载一下窗体上的事件

            myEvent();

            //显示窗体

            f.setVisible(true);

     }

    

     private void myEvent()

     {

            f.addWindowListener(newWindowAdapter()

            {

                   public voidwindowClosing(WindowEvent e)

                   {

                          System.exit(0);

                   }

            });

            //让按钮具备退出程序功能

            //按钮就是事件源,选者哪个监听器呢?

           

            but.addMouseListener(newMouseAdapter()

            {

                   private int count = 1;

                   private int clickcount = 1;

                   public voidmouseEntered(MouseEvent e)

                   {

                          System.out.println("鼠标进入到该组件"+count++);

                   }

                   /*

                   public void mouseClicked(MouseEvente)

                   {

                          System.out.println("点击动作"+clickcount++);

                   }

                   */

                  

                   public voidmouseClicked(MouseEvent e)

                   {

                          if(e.getClickCount()==2)

                                 System.out.println("双击动作"+clickcount++);

                   }

            });

           

           

     }

    

     public static void main(String[] args)

     {

            new MouseAndKeyEvent();

     }

}

键盘事件,确定事件源,确定事件,确定要操作谁!

注意使用该接口,所有已知实现类

TextS简单界面

(1)先把界面所涉及的组件定义出来

(2)先做出来界面,然后做功能

importjava.awt.*;

importjava.awt.event.*;

importjava.io.*;

 

class TextS

{

     private Frame f;

     private Panel p1;

    

     private TextField tf;

     private Button but;

     private TextArea ta;

    

     //来一个构造,并初始化init()

     TextS()

     {

            init();

     }

    

     public void init()

     {

            f = newFrame("CreateString");

            f.setBounds(300,100,600,500);

            f.setLayout(new FlowLayout());//流布局,默认边界布局

           

            tf = new TextField(60);

           

            but = new Button("转到");

           

            ta = new TextArea(25,70);

                  

            f.add(tf);

            f.add(but);

            f.add(ta);

           

            myEvent();//忘了吧!!!!

            f.setVisible(true);

     }

    

     private void myEvent()

     {

            but.addActionListener(newActionListener()

            {

                   //actionPerformed覆盖下

                   public voidactionPerformed(ActionEvent e)

                   {

                          //找get找不到,就找父类的方法

                          //String text =tf.getText();

                          //System.out.println(text);

                          //能打印出来就set,set会替换

                          //ta.setText(text);

                          String dirPath =tf.getText();

                          File dir = newFile(dirPath);

                          if(dir.exists()&&dir.isDirectory())

                          {

                                 //切换c盘、D盘要清空

                                 ta.setText("");

                                 String[] names= dir.list();

                                 for(Stringname:names)

                                 {

                                        ta.append(name+"\r\n");

                                 }

                          }

                          //tf.setText("");

                   }

            });

           

            f.addWindowListener(newWindowAdapter()

            {

                   public voidwindowClosing(WindowEvent e)

                   {

                          System.exit(0);

                   }

            });

     }

    

     public static void main(String[] args)

     {

            new TextS();

     }     

}

错误处理

不要else处理不该窗体初始化完就出现就别放里面,优化内存

菜单MyMenuDemo

窗口fileDialog

异常处理

打开后,不选择,直接关闭

不要打开dos命令行方式

打jar包

jar –cvf my.jarmymenu

这个jar包有很多类,jar包不知道找哪个才是主函数类

给jar包配置

jar -cvfm my.jar 1.txt mymenu

1.txt格式固定的,注意空格和回车

jar –cvfm my.jar 1.txt mymenu

双击安装版的jdk才能运行

自己配置

exe4j转换下

注意勾选64位

13String(应用程序接口API类)

1.String概述

字符串是一个特殊的对象

字符串一旦初始化就不可以被改变

String str = “abc”;

String str1 =new String(“abc”);

常量池

String s2 = newString(“abc”);//在内存中产生了两个对象

2.String获取和判断

方法区,静态区,常量池(固定不变的数据)

int indexOf(int ch)

1.获取

     1.1字符串中包含的字符数,也就是字符串的长度

            int length();(数组也有长度,但它是属性,没有括号)

     1.2根据位置获取位置上某个字符

            char charAt(int index)

     1.3根据字符获取该字符在字符串中的位置

            int indexOf(int ch):返回的是ch在字符串中第一次出现的位置

            int indexOf(int ch,int fromIndex):从fromIndex指定位置开始,获取ch在字符串出现的位置

           

            int indexOf(String str):返回的是str在字符串中第一次出现的位置

            int indexOf(String str,intfromIndex):从fromIndex指定位置开始,获取str在字符串出现的位置

角标越界异常

public staticvoid method_get()

     {

            String str = "abcdasdfed";

            //长度

            sop(str.length());

            //根据索引获取字符

            sop(str.charAt(40));//当访问到字符串中不存在的角标时,会发生StringIndexOutOfBoundsException

            //角标越界异常

            //根据字符获取索引

            sop(str.indexOf('a',3));

     }

 

判断

2.判断(判断开头结尾范围肯定是boolean型)

     2.1字符串中是否包含某一个字串

            boolean contains(str);

            特殊之处,indexOf(str):可以索引str第一次出现的位置,如果返回-1,表示该str不在字符串中。

                   所以,也可以用于对指定判断是否包含。

                   if(str.indexOf("aa")!=-1)

                          而且该方法既可以判断,又可以获取出现的位置。

     2.2字符串中是否有内容

            boolean isEmpty();原理就是判断长度是否为0,(""null有区别,前者是对象,后者是为空)

     2.3字符串是否是以指定内容开头

            boolean startsWith(str);

     2.4字符串是以指定内容结尾//没有这个功能就自己造呗

            boolean endsWith(str);

     2.5判断字符串内容是否相同,复写了Object类中的equals方法,复写Object中的equals方法

            boolean equals(str)

     2.6判断内容是否相同,并忽略大小写

            boolean equalsIgnoreCase();

sop(str.endsWith(".java"));//判断文件是否是.java的文件,这里注意haha.java.txt

区别于contains(str);

判断内容是否相同

3.String转换

3.1将字符数组转成字符串

            构造函数:String(char[])

                            String(char[],offset,count):将字符数组中的一部分转换成字符串

            静态方法:

                          static StringcopyValueOf(char[]);

                          static StringcopyValueof(char[] data,int offset, int count)

                         

                          static StringvalueOf(char[]);

     3.2将字符串转成字符数组

            查文档,首先肯定不是构造函数,有返回类型

                          char[] toCharArray();

                  

     3.3将【字节数组】转成字符串

                   String(byte[])

                   String(byte[],offset,count):将字节数组中的一部分转换成字符串            

     3.4将字符串转成字节数组

                   byte[] getBytes();

     3.5将基本数据类型转换成字符串

            static String valueOf(int)

            static String valueOf(double)

           

            3+"";//String.valueOf(3);返回的也是字符串

           

            特殊:字符串和字节数组在转换过程中,可以指定编码表的。

     3.6将字符串按照

构造函数

String(char[],offset,count):将字符数组中的一部分转换成字符串

静态方法

4.字符串替换

 

5.转换,去除空格,比较

根据ASCII码表作比较

1是49,a和a相同,1和a不相同后面就不比较了

实际使用只要大于0小于0就好了

忽略大小写的比较,先全部改成小写

6字符串练习

去除首尾空格

错了!!!!!

查找kk

10StringBuffer

字符串的组成原理就是通过该类实现的

String不能被改变,但是StringBuffer可以对字符串内容进行增删

StringBuffer是一个容器,很多方法和String相同

StringBuffer是可变长度的

插入

替换

/*

StringBuffer是字符缓冲区,是一个容器

1.增:存储

StringBufferappend():将制定数据作为参数添加到已有数据的结尾处

StringBufferinsert(insert,数据):可以将数据插入到指定index位置。

2.删

StringBufferdelete(start,end):删除缓冲区,包含start,不包含end,集合[);

StringBuffer

4.改,修改(替换)

3.查,获取

charcharAt(index);

intindexof(String str)

intlastIndexof(String str);

int length()

Stringsubstring(int start,int end)

5.反转StringBuffer reverse();

6.将缓冲区指定数据存储到制定字符数组中。

voidgetChars(int srcBegin,int SrcEnd,char[] dst,int dstBegin)

 

JDK1.5版本之后出现了StringBuilder

StringBuffer线程同步的

StringBuilder是线程不同步的(建议使用)

*/

 

classStringBufferDemo

{

     public static void main(String[] args)

     {

            method_del();

     }     

     public static void method_del()

     {

            StringBuffer sb = newStringBuffer("abcddd00");

            //sb.delete(0,3);

            //清空缓冲区

            //sb = new StringBuffer();//太败家了,在内存里重新开了一个缓冲区

            //sb.delete(0,sb.length());//清空缓冲区,包含start,不包含end    

            sb.replace(1,4,"java");//bcd替换掉

            sb.setCharAt(5,'k');//注意了''

            sop(sb.toString());

     }

     public static void method_add()

     {

            StringBuffer sb = newStringBuffer();

            sb.append("abc").append(true).append(34);

           

            //StringBuffer sb1 = sb.append(34);

            sb.insert(1,"qq");

            sop(sb.toString());

            //sop(sb1.toString());

            //sop("sb==sb1:"+(sb==sb1));

     }            

    

    

     public static void sop(Object obj)

     {

            System.out.println(obj);

     }

}

13String(应用程序接口API类)

字符串是一个特殊的对象

字符串一旦初始化就不可以被改变

String str = “abc”;

String str1 =new String(“abc”);

常量池

字符串替换

StringBuffer

字符串的组成原理就是通过该类实现的

String不能被改变,但是StringBuffer可以对字符串内容进行增删

StringBuffer是一个容器,很多方法和String相同

StringBUffer是可变长度的

插入

替换

/*

StringBuffer是字符缓冲区,是一个容器

1.增:存储

StringBufferappend():将制定数据作为参数添加到已有数据的结尾处

StringBufferinsert(insert,数据):可以将数据插入到指定index位置。

2.删

StringBufferdelete(start,end):删除缓冲区,包含start,不包含end,集合[);

StringBuffer

4.改,修改(替换)

3.查,获取

charcharAt(index);

intindexof(String str)

intlastIndexof(String str);

int length()

Stringsubstring(int start,int end)

5.反转StringBuffer reverse();

6.将缓冲区指定数据存储到制定字符数组中。

voidgetChars(int srcBegin,int SrcEnd,char[] dst,int dstBegin)

 

JDK1.5版本之后出现了StringBuilder

StringBuffer线程同步的

StringBuilder是线程不同步的(建议使用)

*/

 

classStringBufferDemo

{

     public static void main(String[] args)

     {

            method_del();

     }     

     public static void method_del()

     {

            StringBuffer sb = newStringBuffer("abcddd00");

            //sb.delete(0,3);

            //清空缓冲区

            //sb = new StringBuffer();//太败家了,在内存里重新开了一个缓冲区

            //sb.delete(0,sb.length());//清空缓冲区,包含start,不包含end    

            sb.replace(1,4,"java");//bcd替换掉

            sb.setCharAt(5,'k');//注意了''

            sop(sb.toString());

     }

     public static void method_add()

     {

            StringBuffer sb = newStringBuffer();

            sb.append("abc").append(true).append(34);

           

            //StringBuffer sb1 = sb.append(34);

            sb.insert(1,"qq");

            sop(sb.toString());

            //sop(sb1.toString());

            //sop("sb==sb1:"+(sb==sb1));

     }            

    

    

     public static void sop(Object obj)

     {

            System.out.println(obj);

     }

}

14对象封装新特性

14集合框架

集合框架:不断向上抽取出来的,在util包

数据多了用对象存储,对象多了用集合存储(或数组)

但是不能确定员工人数

数组是固定长度,集合不定

数组只能是同一类型对象比如new Demo(),集合是不定对象的,比如newDemo(),然后继续存储new Person();

importjava.util.*

两种存储:数组和集合。对象多了用集合存,数据多了用对象存。

集合类:面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。

Collection:收集、集合

他们之间有共性,向上抽取出来后,

容器分很多种,不断向上抽取就成为了一种体系

看体系先看顶层,顶层定义的是共性行为

看完顶层找具体的圈和框用

(1)不断向上抽取出来的东西可能不能创建对象的,如abstract

(2)创建此类对象,底层方法多些

Set:元素是无序(存入和去除的顺序不一定一致),元素不可以重复

HshSet:底层数据结构是Hash表,数据结构是哈希表,线程是非同步的

Treeset:

 

为什么会出现这么多容器呢?

每一个容器对数据的存储方式都有不同。这个存储方式称之为:数据结构。

数据结构:数据在内存中的构成情况

共性方法

增删改查

returnAll(Collection<?>c)

a1.returnAll(a2);a1只剩下交集

编译完有提示,1.5版本出现的,是泛型问题。

add方法的参数类型是Object

集合中存储的都是对象的引用,或地址

4.迭代器

定义了内部类,每个容器都有内部类,新容器也要。

有没有元素啊,有!然后取。(判断,取出)

抽取共性,形成接口

这些类都符合一个规则Iterator,如何获取集合的取出对象,通过一个对外的提供方法iterator();

但凡取出,就是要操作的,要么判断。。。

Iterator it =al.iterator();

这个方法返回的是,该接口的子类对象,接口型引用只能指向自己的子类对象,而这个对象不是new出来的,是通过集合中的方法获取出来的。

Iterator接口,就是夹子

老外用for这种内部变量,释放内存,下图是iterator源代码

因为前者是对象,后者是局部变量

讲完Collection,讲List集合,主要是角标

list特点,元素是有序的,元素可以重复,因为该集合体系有索引

set,元素是无序的,元素不可重复。

一般用ArrayList,查询多

/*

Collection

 

List:特有的方法,凡是可以操作角标的方法都是该体系特有的方法

     add(index,element);

     addAll(index,Collection);

     remove(index);

     set(index,element);

     get(index);

     subList(from,to);

     listIterator();

*/

 

importjava.util.*;

class ListDemo

{

     public static void sop(Object obj)

     {

            System.out.println(obj);

     }

    

     public static void main(String[] args)

     {

            ArrayList al = new ArrayList();

           

            al.add("java01");

            al.add("java02");

            al.add("java03");

            al.add("java04");

           

            sop("原集合是:"+al);

            //在指定位置添加元素

            al.add(1,"java09");

            //删除指定位置的元素

            al.remove(2);

            //修改元素

            al.set(2,"java007");

           

            //通过角标获取元素

            sop("get(1):"+al.get(1));

           

            sop("增集合是:"+al);

           

            //获取所有元素

            for(int x=0;x<al.size(); x++)

            {

                   System.out.println("al("+x+")="+al.get(x));

            }

           

            Iterator it = al.iterator();

            while(it.hasNext())

            {

                   sop("next:"+it.next());

            }

     }     

}

5ListIterator

容易发生并发异常

迭代器在使用前,已经知道固定的个数啥的了

不能这么搞!!!

只能判断,删除

那么,生了个儿子

6.List集合对象特点

ArrayList底层的数据结构使用的是数组结构。特点:有角标,查询速度很快(修改),但是增删很慢。线程不同步。

LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢

Vector底层是数据数据结构

Vector是同步的,容器增删同时容易出问题。无论增删都慢!被ArrayList替代了。

7.LinkedList

addFirst();

addLast();

 

getFirst();

getLast();

 

removeFirst();

removeLast();

10ArrayList练习

ArrayList去重,定义一个新容器,newAl.contains(obj);

 

/*

将自定义对象作为元素存到ArrayList集合中,并去除重复元素。

比如:存人对象,同姓名,同年龄视为同一个人,为重复元素

 

思路:

1.对人描述

2.定义容器,将人存入

3.取出

*/

importjava.util.*;

 

class Person

{

     private String name;

     private int age;

     Person(String name,int age)

     {

            this.name = name;

            this.age = age;

     }

     public boolean equals(Object obj)

     {

            if(!(obj instanceof Person))

                   return false;//或者直接抛异常

            Person p = (Person)obj;

           

            System.out.println(this.name+"...."+p.name);

            returnthis.name.equals(p.name)&&this.age == p.age;

     }

    

     public String getName()

     {

            return name;

     }

     public int getAge()

     {

            return age;

     }

}

 

 

classArrayListTest2

{

     public static void sop(Object obj)

     {

            System.out.println(obj);

     }

    

     public static void main(String[] args)

     {

            ArrayList al = new ArrayList();//他判断的是对象是否相同,equals方法

            al.add(newPerson("lisi01",30));//al.add(Object obj);//Object obj = newPerson("lisi",30);

            al.add(newPerson("lisi02",30));

            al.add(newPerson("lisi02",30));

            al.add(newPerson("lisi03",30));

           

           

            al = SingleElement(al);

            Iterator it = al.iterator();

           

            while(it.hasNext())

            {

                   Person p=(Person)it.next();//向下转型

                   sop(p.getName()+"::"+p.getAge());

            }            

     }

    

     public static ArrayListSingleElement(ArrayList al)

     {

            //定义一个临时容器

            ArrayList newAl = new ArrayList();

           

            Iterator it = al.iterator();

           

            while(it.hasNext())

            {

                   Object obj = it.next();

                   if(!newAl.contains(obj))

                          newAl.add(obj);

            }

            return newAl;

     }

}

11ArrayList练习多态编译失败

返回的Object,当然没有getName方法了

向下转型

12HashSet(hashCode和equals)

会调用equals

Set元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。(有序是怎么存就怎么取。)

主要看HashSet和TreeSet

哈希表里面,当哈希值重合时,需要再做一个判断,元素对象是否相同

(1)地址池一致,但是咱们不是同一个对象

(2)碰撞比较是否同一个对象,以哈希

(3)new出来的,有自己的hash值

(1)a1进来了

(2)a2进来了,算了自己的hash值,发现自己和a1不一样,就在3c地址之上顺延一个位置。

(3)a3进来了,又比,又顺延

(4)又来一个a2,先跟a3比,再跟a2比。。。a2就没有放进去

(1)自定义对象时,通常复写hashCode的equals(调用equals慢)

(2)有可能对象要存放到hashset中,不复写,有equals,但根据地址判断的(new出来的对象,hash值都是不一样的)

(3)而且hashCode是底层调用的,自己拿对象去比较的,封装好了

HashSet查找

先找到值

/*

HashSet:底层数据结构是哈希表,如何保证元素唯一性呢?

hashCode和equals来完成

如果元素的HashCode值相同,才会判断equals

如果元素的HashCode值不同,就不会调用

 

注意:对于判断元素是否存在,以及删除等操作,都依赖于元素的hashCode和equals方法。

都是先判断哈希值的!!!哈希表的特点

 

public inthashCode(){return 60;}以前的哈希值是windows底层算出来的。

Demo@3c,两个哈希值一样,即位置一样,咱两元素对象是否相同

会在3C下面顺延,都在同一个地址上

@c17164再进来,会先碰一下哈希值,不一样就找个位置放下了

HashSet就是哈希表结构

*/

 

importjava.util.*;

 

 

classHashSetDemo

{

     public static void sop(Object obj)

     {

            System.out.println(obj);

     }

     public static void main(String[] args)

     {

            HashSet hs = new HashSet();

           

            hs.add(newPerson("a1",11));

            hs.add(newPerson("a2",12));

            //hs.add(newPerson("a2",12));

            hs.add(newPerson("a3",13));

            //hs.add(newPerson("a4",14));

           

            sop("a1:"+hs.contains(newPerson("a1",11)));//它是先比较的哈希值

            hs.remove(newPerson("a3",13));

           

            Iterator it = hs.iterator();

            while(it.hasNext())

            {

                   Person p =(Person)it.next();

                   sop(p.getName()+"::"+p.getAge());

            }

     }

}

 

class Person

{

     private String name;

     private int age;

     Person(String name,int age)

     {

            this.name=name;

            this.age=age;

     }

     public int hashCode()//Object的,不需要复写

     {

            System.out.println(this.name+"....hashCode");

            return name.hashCode()+age;//age*39保证哈希值的唯一性,比如张三40,李四20算出来哈希值一个20+40,都是60

     }

     public boolean equals(Object obj)

     {

            if(!(obj instanceof Person))

                   return false;

            Person p = (Person)obj;

            System.out.println(this.name+"...."+p.name);

            returnthis.name.equals(p.name)&&this.age==p.age;

     }

    

     public String getName()

     {

            return name;

     }

     public int getAge()

     {

            return age;

     }

}

13hashset判断和删除的依据

先算hash值,然后对比equals

 

ArrayList判断是否存在,只判断equals(原因全在数据结构上)

hashset先依赖hashcode,然后依赖equals

 

15集合框架TreeSet

set无序,不可以重复

(1)HashSet:数据结构是哈希表,线程是非同步的

保证元素唯一性的原理:判断元素的hashCode值是否相同

如果相同,还会继续判断元素的equals方法,是否为true

2TreeSet存储自定义对象

问题:按age进行compareTo

返回是0,都是19岁就重复了??不行

当主要条件相同,就要比较次要条件

对Set集合中的元素进行排序

Set有一定顺序,按ASCII码表排序

3二叉树

存一个数据就要对比一下,所以TreeSet底层用了比较特殊的底层结构,二叉树

元素越多,如果都从22走,那也比较慢!!!

二叉树,元素比较多的时候,会自动折中走。

取的时候吗,从小到大,降序,改成-1。

保证元素唯一性的依旧:compareTo方法return 0;

4.comparator方式排序

构造一个空的TreeSet,它根据指定比较器进行排序

(1)自然顺序,按照年龄排序的

(2)现在想按姓名排序,但是不介意改代码

姓名一样,年纪一样,就重新比较下

(3)两种排序都有时,以比较器为主

comparator

 

6泛型通过<>泛型由来

升级3个机制:高效、简化书写、安全

泛型JDK1.5以后出现的新特性

类型编译异常

本来应该全存String的,存了int

定义容器的时候,就定义了类型

像数组一样,定义的时候就明确类型

泛型就加个<>

Collection<e>

ArrayList<e>   element

Comparator<T>  type

将java运行时期的问编译时期的问题。

连原来的未经检查的安全问题都没有了

后面就有add,具体的元素对象比如<String

8.泛型类

(1)泛型前做法

importjava.util.*;

 /*

 

 */

class Worker

{

    

}

 

class Student

{

    

}

 

class Tool

{

     privateObject obj;

     publicvoid setObject(Object obj)

     {

            this.obj= obj;

     }

     publicObject getObject()

     {

            returnobj;

     }

}

 

/*

class Tool

{

     private Worker w;

     public void setWorker(Worker w)

     {

            this.w = w;

     }

     public Worker getWorker()

     {

            return w;

     }

}

//对象是后进来的,抽取对象共享类型

 */

 

 

classGenericDemo3

{

     public static void main(String[] args)

     {

            Tool t = new Tool();

            t.setObject(new Worker());

            Worker w = (Worker)t.getObject();

     }

}

9泛型定义在方法上

(1)直接使用就可以了

泛型定义在方法上

10静态方法泛型

Demo<T>传入的,后面的public void show<T t>是泛型类

public void <Q> print(Q q);则无所谓(跟Q、T无关)

返回值类型前面,修饰符后面

函数是返回类型加函数名

11泛型定义在接口上

泛型类和泛型接口

 

 

12泛型的高级应用,限定

通配符<?>和<T>,T先定义下

<?>是不明确具体类型,只是个占位符

T是具体类型,可以接收并操作具体类型

用泛型<?>好处:是可以不明确类型

不好处:不能用类型特有方法,比如length();但是toString可以

13不用泛型太麻烦

泛型限定是用于泛型扩展用的

 

16.Map

collection叫单列集合,Map叫双列

给我一个key,返回一个v,就是value

接口共性方法看完,看小弟

Map集合:该集合存储键值对,一对一对往里存,而且要保证键的唯一性

1.添加

     put(K key,V value);

     putAll(Map<? extends K,? extends V>m);//类似addAll

2.删除

     clear()

     remove(Object key);//为什么根据键删,键唯一

3.判断

     containsKey(Object key);//返回类型boolean

     containsValue(Object value)

    

     isEmpty()

4.获取

     get(Object key)

     size();

     values();

    

     entrySet();

     keySet();

Hashtable

实现一个哈希表,该哈希表将键映射到相应的值。

任何非null对象都可以用作键或值

一看是JDK1.0开始的,元老级别的,那么就是线程同步的

3.Map共性方法

Collection<V>这个返回类型,V要具体带入!!!

/*

Map集合:该集合存储键值对,一对一对往里存,而且要保证键的唯一性

1.添加

     put(K key,V value);

     putAll(Map<? extends K,? extends V>m);//类似addAll

2.删除

     clear()

     remove(Object key);//为什么根据键删,键唯一

3.判断

     containsKey(Object key);//返回类型boolean

     containsValue(Object value)

    

     isEmpty()

4.获取

     get(Object key)

     size();

     values();

    

     entrySet();

     keySet();

    

    

Map:三个小弟,两个常见

     Hashtable:底层是哈希表数据结构,不可以存入null键null值,该集合线程同步,jdk1.0,效率低

     HashMap:底层哈希表数据结构,允许使用null值和null键,该集合是不同步的,jdk1.2,效率高

     TreeMap:底层是二叉树数据结构,线程不同步,可以用于给map集合中键进行排序

 

和set很像

其实Set底层就是使用了Map集合,你能存一对,我去掉一个就可

    

 */

importjava.util.*;

 

 class MapDemo

 {

      public static void main(String[] args)

      {

             Map<String,String> map = newHashMap<String,String>();

           

            //添加元素,出现添加相同键

            //后添加的值会覆盖原有键对应值

            //并put方法会返回被覆盖的值。

            map.put("01","zhangsan1");

            map.put("02","zhangsan2");

            map.put("03","zhangsan3");

            Demo.sop("......"+map.put("03","wangwu"));

           

           

            Demo.sop("contatinsKey:"+map.containsKey("022"));

            //Demo.sop("remove:"+map.remove("02"));

            Demo.sop("get:"+map.get("02"));

            //map.put(null,"haha");

            Demo.sop("get:"+map.get(null));

            //通过get判断键是否存在

           

            Collection<String> coll =map.values();

           

            Demo.sop(coll);

           

            Demo.sop(map);

           

      }

      

      

 }

 

 

class Demo

{

     public static void sop(Object obj)

      {

             System.out.println(obj);

      }

}  

4.Key-Set

Map集合中,通过Set集合的迭代器取出Set集合中的键

然后,通过map的get(key)方法获取键对应值

 

5.entrySet

(1)堆内存就有双列集合,集合中有很多键值关系

(2)有很多引用

(3)entrySet(),是将map集合中的映射关系取出,存放在Set集合中

(4)这个关系就是Map.Entry类型。(一个圈就代表一个Map.Entry对象,一个关系,可以理解为结婚证书)

(5)它既不是丈夫类型,也不是妻子类型,是个关系

(6)那么关系对象Map.Entry获取到后,就可以通过Map.Entry中getKey和getValue方法获取关系中的键和值

Map.Entry 其实Entry也是一个接口,它是Map中的一个内部接口(接口名.Entry得是静态的,而且对外公开)

只有有了map才有关系,那么entry就是内部接口,内部规则

能加static的接口都是内部接口,因为只有在成员位置 上才能加static

6.Map练习

类产生的对象很多,有可能存到二叉树中,那么让学生具备自然顺序

8TreeMap练习

(1)先取到a(作为键)

17Collections

专门对集合操作的工具类,N多静态

public static<T extends Comparable<? super T>> void (List<T> list)

//泛型限定

18其他对象

System

(1)out对应对象是打印流,打印流有许多打印方法

(2)in,获取键盘录入

(3)System.gc();垃圾回回收器

(4)getProperties();获取当前系统信息

系统启动的时候,设置系统级别的东西

14集合框架

importjava.util.*

两种存储:数组和集合。对象多了用集合存,数据多了用对象存。

集合类:面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。

Set:元素是无序(存入和去除的顺序不一定一致),元素不可以重复

HshSet:底层数据结构是Hash表,数据结构是哈希表,线程是非同步的

Treeset:

 

每一个容器对数据的存储方式都有不同。这个存储方式称之为:数据结构。

迭代器

Iterator接口,就是夹子

老外用for这种内部变量,释放内存,下图是iterator源代码

List集合,主要是角标

一般用ArrayList,查询多

/*

Collection

 

List:特有的方法,凡是可以操作角标的方法都是该体系特有的方法

     add(index,element);

     addAll(index,Collection);

     remove(index);

     set(index,element);

     get(index);

     subList(from,to);

     listIterator();

*/

 

importjava.util.*;

class ListDemo

{

     public static void sop(Object obj)

     {

            System.out.println(obj);

     }

    

     public static void main(String[] args)

     {

            ArrayList al = new ArrayList();

           

            al.add("java01");

            al.add("java02");

            al.add("java03");

            al.add("java04");

           

            sop("原集合是:"+al);

            //在指定位置添加元素

            al.add(1,"java09");

            //删除指定位置的元素

            al.remove(2);

            //修改元素

            al.set(2,"java007");

           

            //通过角标获取元素

            sop("get(1):"+al.get(1));

           

            sop("增集合是:"+al);

           

            //获取所有元素

            for(int x=0;x<al.size(); x++)

            {

                   System.out.println("al("+x+")="+al.get(x));

            }

           

            Iterator it = al.iterator();

            while(it.hasNext())

            {

                   sop("next:"+it.next());

            }

     }     

}

ArrayList

 

/*

将自定义对象作为元素存到ArrayList集合中,并去除重复元素。

比如:存人对象,同姓名,同年龄视为同一个人,为重复元素

 

思路:

1.对人描述

2.定义容器,将人存入

3.取出

*/

importjava.util.*;

 

class Person

{

     private String name;

     private int age;

     Person(String name,int age)

     {

            this.name = name;

            this.age = age;

     }

     public boolean equals(Object obj)

     {

            if(!(obj instanceof Person))

                   return false;//或者直接抛异常

            Person p = (Person)obj;

           

            System.out.println(this.name+"...."+p.name);

            returnthis.name.equals(p.name)&&this.age == p.age;

     }

    

     public String getName()

     {

            return name;

     }

     public int getAge()

     {

            return age;

     }

}

 

 

classArrayListTest2

{

     public static void sop(Object obj)

     {

            System.out.println(obj);

     }

    

     public static void main(String[] args)

     {

            ArrayList al = new ArrayList();//他判断的是对象是否相同,equals方法

            al.add(newPerson("lisi01",30));//al.add(Object obj);//Object obj = newPerson("lisi",30);

            al.add(newPerson("lisi02",30));

            al.add(newPerson("lisi02",30));

            al.add(newPerson("lisi03",30));

           

           

            al = SingleElement(al);

            Iterator it = al.iterator();

           

            while(it.hasNext())

            {

                   Person p=(Person)it.next();//向下转型

                   sop(p.getName()+"::"+p.getAge());

            }            

     }

    

     public static ArrayListSingleElement(ArrayList al)

     {

            //定义一个临时容器

            ArrayList newAl = new ArrayList();

           

            Iterator it = al.iterator();

           

            while(it.hasNext())

            {

                   Object obj = it.next();

                   if(!newAl.contains(obj))

                          newAl.add(obj);

            }

            return newAl;

     }

}

HashSet

哈希表里面,当哈希值重合时,需要再做一个判断,元素对象是否相同

无序的

HashSet查找

先找到值

/*

HashSet:底层数据结构是哈希表,如何保证元素唯一性呢?

hashCode和equals来完成

如果元素的HashCode值相同,才会判断equals

如果元素的HashCode值不同,就不会调用

 

注意:对于判断元素是否存在,以及删除等操作,都依赖于元素的hashCode和equals方法。

都是先判断哈希值的!!!哈希表的特点

 

public inthashCode(){return 60;}以前的哈希值是windows底层算出来的。

Demo@3c,两个哈希值一样,即位置一样,咱两元素对象是否相同

会在3C下面顺延,都在同一个地址上

@c17164再进来,会先碰一下哈希值,不一样就找个位置放下了

HashSet就是哈希表结构

*/

 

importjava.util.*;

 

 

classHashSetDemo

{

     public static void sop(Object obj)

     {

            System.out.println(obj);

     }

     public static void main(String[] args)

     {

            HashSet hs = new HashSet();

           

            hs.add(newPerson("a1",11));

            hs.add(newPerson("a2",12));

            //hs.add(newPerson("a2",12));

            hs.add(newPerson("a3",13));

            //hs.add(newPerson("a4",14));

           

            sop("a1:"+hs.contains(newPerson("a1",11)));//它是先比较的哈希值

            hs.remove(newPerson("a3",13));

           

            Iterator it = hs.iterator();

            while(it.hasNext())

            {

                   Person p =(Person)it.next();

                   sop(p.getName()+"::"+p.getAge());

            }

     }

}

 

class Person

{

     private String name;

     private int age;

     Person(String name,int age)

     {

            this.name=name;

            this.age=age;

     }

     public int hashCode()//Object的,不需要复写

     {

            System.out.println(this.name+"....hashCode");

            returnname.hashCode()+age;//age*39保证哈希值的唯一性,比如张三40,李四20算出来哈希值一个20+40,都是60

     }

     public boolean equals(Object obj)

     {

            if(!(obj instanceof Person))

                   return false;

            Person p = (Person)obj;

            System.out.println(this.name+"...."+p.name);

            return this.name.equals(p.name)&&this.age==p.age;

     }

    

     public String getName()

     {

            return name;

     }

     public int getAge()

     {

            return age;

     }

}

TreeSet

Set有一定顺序,按ASCII码表排序

存一个数据就要对比一下,所以TreeSet用了比较特殊的底层结构,二叉树

元素越多,如果都从22走,那也比较慢!!!

二叉树,元素比较多的时候,会自动折中走。

取的时候吗,从小到大,降序,改成-1。

保证元素唯一性的依旧:compareTo方法return 0;

泛型通过<>

通过<>

将java运行时期的问题转移到了javac编译时期的问题。

连原来的未经检查的安全问题都没有了

后面就有add,具体的元素对象比如<String

泛型类

importjava.util.*;

 /*

 

 */

class Worker

{

    

}

 

class Student

{

    

}

 

class Tool

{

     privateObject obj;

     publicvoid setObject(Object obj)

     {

            this.obj= obj;

     }

     publicObject getObject()

     {

            returnobj;

     }

}

 

/*

class Tool

{

     private Worker w;

     public void setWorker(Worker w)

     {

            this.w = w;

     }

     public Worker getWorker()

     {

            return w;

     }

}

//对象是后进来的,抽取对象共享类型

 */

 

 

classGenericDemo3

{

     public static void main(String[] args)

     {

            Tool t = new Tool();

            t.setObject(new Worker());

            Worker w = (Worker)t.getObject();

     }

}

泛型定义在接口上

 

 Map

collection叫单列集合,Map叫双列

17集合

16Arrays

/*

 

Arrays:用于操作数组的工具类

里面都是静态方法

 

asList:将数组变成list集合

 */

importjava.util.*;

 

 class ArraysDemo

 {

      public static void main(String[] args)

      {

             //int[] arr = {2,4,5};

             //System.out.println(Arrays.toString(arr));

            /* System.out.print("[");

             for(int x=0;x<arr.length;x++)

             {

                    if(x==arr.length-1)

                           sop(arr[x]+"]");

                    else

                          System.out.print(arr[x]+",");

             } */

             

             String[] arr ={"abc","ccc","kkkk"};

           

            //把数组变成list集合有什么好处

            /*

            可以使用集合的思想和方法操作数组中的元素

            否则要挨个遍历然后对比

           

            注意:将数组变成集合,不可以使用集合的增删方法

            因为数组的长度是固定的

            contains

            get

            indexof()

            sublist()

           

            如果增删,会发生UnsupportOperationException

            */

            List<String> list =Arrays.asList(arr);

           

            sop("contains:"+list.contains("ccc"));

            //list.add("qq");

            //sop(list);

           

            //int[] nums = {2,4,5};

            Integer[] nums = {2,4,5};

           

            List<Integer> li =Arrays.asList(nums);

           

           

            /*

            如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素

            如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在

            */

            sop(li);

                    

      }

      

      public static void sop(Object obj)

      {

             System.out.println(obj);

      }

 }

17集合转成数组

/*

集合变数组

Collection接口中的toArray方法

 

 */

 

importjava.util.*;

classCollectionToArray

{

     public static void main(String[] args)

     {

            ArrayList<String> al = newArrayList<String>();

           

            al.add("abc1");

            al.add("abc2");

            al.add("abc3");

           

            /*

            1.指定类型的数组到底要定义多长呢?

            当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组

            长度为集合的size

            当指定类型的数组长度大于了集合的size,就不会新创建了数组,而是使用传递进来的数组

            。。。。创建一个刚刚好的数组最优(短的,内存中就有两个了)

           

            2.为什么要将集合变数组?

            为了限定对元素的操作

            */

           

            String[] arr = al.toArray(newString[al.size()]);

            System.out.println(Arrays.toString(arr));

     }

}

18增强for循环

19可变参数。。。

20静态导入

没有写静态导的都是类,导入跟静态,导入的都是某一个类中的所有成员

 

18其他对象

System

getProperties()

/*

组合成输出语句

System:类中的方法和属性都是静态的

out:标准输出,默认是控制台

in:标注输入,默认是键盘

*/

importjava.util.*;

2.Runtime对象

系统的进程杀不了,已启动拿不到对象了

5其他对象Math-Random

math的重点方法,随机数random,返回大于等于0.0且小于1.0的一个伪随机数。

Collections不就有一个随机数排列么,就是它。

18IO流(Input、Output)

IO流用来处理设备之间的数据传输,处理数据的流,比如硬盘上的数据,内存上的数据等

Java对数据的操作是通过流的方式

Java用于操作流的对象都在IO包中

流按操作数据分为两种:字节流与字符流

备注:基于字节流(到底是GBK还是UTF-8表)避免问题产生了字符流的方法,字符流的对象融合了编码表。处理图片只能用字节流。通用的是字节流

流按流向分为:输入流,输出流

字节流的抽象基类:InputStream,OutputStream

字符流的抽象基类:Reader,Writer

由这个四个

FileWriterDemo新建写入文件

(1)后缀名是父类名,前缀名是该流对象的功能

new的时候就把对象给覆盖掉了

抛出异常,比如会存在k盘么??,另外new会被覆盖

(2)fw.write(“abcd”)不会写入,是因为写入是到缓冲区的

(3)也可以用close()

注意:java本身是

IO异常处理

凡是和设备发生交互的,都会有IO异常,读和写。try异常

/*

IO异常处理方式

*/

 

importjava.io.*;

 

classFileWriterDemo

{

     public static void main(String[] args)

     {

            try

            {

                   FileWriter fw = newFileWriter("demo.txt");

                   fw.write("abcd"+"\t");            

                   fw.close();

            }

            catch(IOException e)

            {

                   System.out.println(e.toString());

            }

            finally

            {

                   fw.close();

            }

     }

}

原有数据上续写

FileWriter(Stringfilename,boolean append)

父类可以写入字符数组或者一个个写

IO流读取

默认字符编码(系统中的编码)和默认字节缓冲区大小都是适当的

(1)read一次读一个字符,并自动往下读

那么采用while(true){}的方法

(2)数组的方式的话

注意指针末尾会变成-1,原先buf中的两个还在

(3)采用while

String(buf,开始,结束)

(4)缓冲区,读一个存一个,读满之后全打出去

之前是读一个打印一个

IO流文本文件读取联系

拷贝文件

char字符流

拷贝图片,媒体文件,字节流

importjava.io.*;

class CopyPic

{

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

     {

            FileOutputStream fos = null;

            FileInputStream fis = null;

           

                   fos = newFileOutputStream("c:\\2.bmp");

                   fis = newFileInputStream("c:\\1.bmp");

                  

                   byte[] buf = new byte[1024];

                   int len = 0;

                  

                   while((len=fis.read(buf))!=-1)

                   {

                          fos.write(buf,0,len);

                   }

                  

                   fis.close();

                   fos.close();

           

     }

    

}

拷贝MP3,字节流

BufferedInputStream

properties,util包

properties是hashtable的子类

也就是说它具备map集合的特点,而且它里面存储的键值对都是字符串

是集合中和IO技术集合的集合容器

该对象的特点:可以用于键值对形式的配置

就是很多的ini配置文件

需要指明是文本还是背景,成为键值对

importjava.io.*;

importjava.util.*;

classPropertiesDemo

{

     public static void main(String[] args)

     {

            setAndGet();

     }

    

     public static void setAndGet()

     {

            Properties prop = new Properties();

            prop.setProperty("zhangsan","30");

            prop.setProperty("lisi","39");

           

            //System.out.println(prop);

            String value = prop.getProperty("lisi");

            System.out.println(value);

           

            Set<String> names =prop.stringPropertyNames();

            for(String s:names)

            {

                   System.out.println(s);

            }

     }

}

打印流PrintWrite和PrintStream

可以直接操作输入流和文件

序列流SequenceInputStream

管道流PipeInputStream和PipeOutputStream

从这个管子写,可以对接到另外一个管道

输入输出可以直接进行连接,通过结合线程使用

importjava.io.*;

class Readimplements Runnable

{

     private PipedInputStream in;

     Read(PipedInputStream in)

     {

            this.in = in;

     }

     public void run()

     {

            try

            {                   

                   byte[] buf = new byte[1024];

                   System.out.println("读取前。。。没有数据阻塞");

                   int len = in.read(buf);

                   System.out.println("读到后。。。阻塞结束");

                  

                   String s = newString(buf,0,len);

                   System.out.println(s);

                   in.close();

            }

            catch(Exception e)

            {

                   throw newRuntimeException("管道读取失败");

            }

     }

}

 

class Writeimplements Runnable

{

     private PipedOutputStream out;

     Write(PipedOutputStream out)

     {

            this.out = out;

     }

     public void run()

     {

            try

            {

                   System.out.println("开始写入数据,等待6s后");

                   Thread.sleep(6000);

                   out.write("Piped laila".getBytes());

                   out.close();

            }

            catch(Exception e)

            {

                   throw newRuntimeException("管道输出失败");

            }

           

     }

}

classPipedStreamDemo

{

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

     {

            PipedInputStream in = newPipedInputStream();

            PipedOutputStream out = new PipedOutputStream();

            in.connect(out);

           

            Read r = new Read(in);

            Write w = new  Write(out);

            new Thread(r).start();

            new Thread(w).start();

     }     

}

RandomAccessFile

没有父类,直接继承object

该类不算是IO体系中的子类,而是直接继承自Object

但是它是IO包中成员,因为它具备读和写功能。

内部封装了一个数组,而且通过指针对数组的元素进行操作

可以通过getFilePointer获取指针位置

同时可以通过seek改变指针的位置

 

其实完成读写的原理就是内部封装了字节(一个大型的byte数组)输入流和输出流。

通过构造函数看出该类只能操作文件

23网络编程

2301网络编程概述

(1)IP、端口(是逻辑端口,是一种数字逻辑,不是网线这种物理端口)

(2)定义通信规则,这个通信规则称为协议,国际组织定义了通用协议TCP/IP

咱两的协议要一致

24网络编程

网络模型:OSI参考模型、TCP/IP参考模型

网络通讯要素:IP地址、端口号、传输协议

IP地址:本地环回地址127.0.0.1主机名localhost

端口号:用于标识进程的逻辑地址,不同进程的标识;有效端口0~65535,其中0~1024系统或保留端口

Socket

Socket就是为网络服务提供的一种机制

通信的两端都有Socket

网络通信其实就是Socket间的通信

数据在两个Socket间通过IO传输

UDP传输,发送端和接收端

DatagramSocket

聊天对话

importjava.net.*;

importjava.io.*;

 

class UdpSend2

{

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

     {            

            DatagramSocket ds = newDatagramSocket();

           

            BufferedReader bufr = newBufferedReader(new InputStreamReader(System.in));

            String line = null;

            while((line=bufr.readLine())!=null)

            {

                   if("886".equals(line))

                          break;

                   byte[] buf = line.getBytes();

                  

                   DatagramPacket dp = newDatagramPacket(buf,buf.length,InetAddress.getByName("172.10.20.31"),10001);

                   ds.send(dp);

            }

            ds.close();

    

     }     

}  

 

    

class UdpRece2

{

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

     {     

            DatagramSocket ds = newDatagramSocket(10001);

            while(true)

            {

                   byte[] buf = new byte[1024];

                   DatagramPacket dp = newDatagramPacket(buf,buf.length);

                   ds.receive(dp);

                  

                   String ip = dp.getAddress().getHostAddress();

                   String data = newString(dp.getData(),0,dp.getLength());

                   System.out.println(ip+"::"+data);

                  

            }

     }

 

    

}

图形化聊天界面

/*

编写一个聊天程序

收和发,两个线程

*/

importjava.io.*;

importjava.net.*;

 

class Sendimplements Runnable

{

     private DatagramSocket ds;

     public Send(DatagramSocket ds)

     {

            this.ds = ds;

     }

    

     public void run()

     {

            try

            {

                   BufferedReader bufr = newBufferedReader(new InputStreamReader(System.in));

                   String line = null;

                   while((line=bufr.readLine())!=null)

                   {

                          if("886".equals(line))

                                 break;

                          byte[] buf =line.getBytes();

                         

                          DatagramPacket dp =newDatagramPacket(buf,buf.length,InetAddress.getByName("172.10.20.32"),10002);

                         

                          ds.send(dp);

                   }

            }

            catch (Exception e)

            {

                   throw new RuntimeException("发送端失败");

            }

     }

    

}

 

 

class Receimplements Runnable

{

     private DatagramSocket ds;

     public Rece(DatagramSocket ds)

     {

            this.ds = ds;

     }

    

     public void run()

     {

            try

            {

                   while(true)

                   {

                          byte[] buf =  new byte[1024];

                          DatagramPacket dp = newDatagramPacket(buf,buf.length);

                         

                          ds.receive(dp);

                         

                          String ip =dp.getAddress().getHostAddress();

                          String data = newString(dp.getData(),0,dp.getLength());

                          System.out.println(ip+":"+data);

                   }

            }

            catch (Exception e)

            {

                   throw newRuntimeException("接收端失败");

            }

     }

}

 

class ChatDemo

{

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

     {

            DatagramSocket sendSocket = newDatagramSocket();

            DatagramSocket receSocket = newDatagramSocket(10002);

           

            new Thread(new Send(sendSocket)).start();

            new Thread(newRece(receSocket)).start();

           

     }

    

}

TCP传输,客户端和服务端Socket和ServerSocket

/*

客户端和服务端互访

*/

importjava.io.*;

importjava.net.*;

 

class TcpClient

{

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

     {

            Socket s = new Socket("172.10.20.31",10004);//一旦建立成功,就有流

            OutputStream out =  s.getOutputStream();

           

            out.write("服务端你好".getBytes());

           

            InputStream in = s.getInputStream();

           

            byte[] buf = new byte[1024];//建立缓冲区

            int len = in.read(buf);

           

            System.out.println(newString(buf,0,len));

           

            s.close();

     }

}

 

/*

 

 

*/

 

 

class  TcpServer

{

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

     {

            ServerSocket ss = newServerSocket(10004);

            Socket s =ss.accept();

           

            String ip =s.getInetAddress().getHostAddress();

            System.out.println(ip+".....connected");

           

            InputStream in =s.getInputStream();

           

            byte[] buf = new byte[1024];

            int len = in.read(buf);

            System.out.println(newString(buf,0,len));

           

            OutputStream out =s.getOutputStream();

             Thread.sleep(5000);

            out.write("哥们收到,你也好".getBytes());

           

            s.close();//关闭客户端

            ss.close();

     }

    

}

14TCP复制文件

2401TCP上传图片

/*

客户端

1.服务端点

2.读取客户端已有的图片数据

3.通过socket输出流将数据发给服务端

4.读取服务端反馈信息

5.关闭

一般玩net包肯定要玩io包

*/

importjava.io.*;

importjava.net.*;

 

class PicClient

{

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

     {

            Socket s = newSocket("172.10.20.31",10007);

            FileInputStream fis = newFileInputStream("1.bmp");

            OutputStream out =s.getOutputStream();

            byte[] buf = new byte[1024];

            int len = 0;

            while((len=fis.read(buf))!=-1)

            {

                   out.write(buf,0,len);

            }

            //告诉服务端,数据已写完!!!!!很重要,否则服务端不知道

            s.shutdownOutput();

            InputStream in = s.getInputStream();

            byte[] bufIn = new byte[1024];

           

            int num = in.read(bufIn);

            System.out.println(newString(bufIn,0,num));

            fis.close();

            s.close();

     }

}

 

/*

服务端

*/

 

class PicServer

{

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

     {

            ServerSocket ss = newServerSocket(10007);

            Socket s = ss.accept();

            InputStream in = s.getInputStream();

            FileOutputStream fos = newFileOutputStream("server.bmp");

            byte[] buf = new byte[1024];

            int len = 0;

            while((len=in.read(buf))!=-1)

            {

                   fos.write(buf,0,len);                 

            }

            OutputStream out =s.getOutputStream();

            out.write("上传成功".getBytes());

           

            fos.close();

            s.close();

            //服务一次就关掉,那么就ss.close()

            ss.close();

     }

}

2402客户端并发上传图片

(1)第一个客户端上传后,必须把数据读取完,然后才会执行while(true),只有到Socket s = ss.accept();才能开始执行线程

A连接上后,这时B客户端连接,只有等待,等待下次accpet

(2)为了可以让多个客户端同时并发访问服务端

那么服务端最好将每个客户端封装到一个单独的线程中,这样,就可以同时处理多个客户端请求

代码解析

(1)class PicServer下主函数main一开启,就开启主线程,建立ss服务,然后主线程进入等待,客户端上传后new了一个线程,就出现两个线程。

TCP变成客户端小写,返回大写

/*

需求:建立一个文本转换服务器。

客户端给服务端发送文本,服务端将文本转成大写返回客户端

当客户端输入over,转换结束

*/

importjava.io.*;

importjava.net.*;

 

classTransClient

{

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

     {

            Socket s = newSocket("172.10.20.31",10005);//一旦建立成功,就有流

            //定义读取键盘数据的流对象

            BufferedReader bufr = newBufferedReader(new InputStreamReader(System.in));

            //定义目的,将数据写入到socket输出流,发给服务端

            BufferedWriter bufOut = newBufferedWriter(new OutputStreamWriter(s.getOutputStream()));

            //定义一个socket读取流,读取服务端返回的大写信息

            BufferedReader bufIn = newBufferedReader(new InputStreamReader(s.getInputStream()));

            String line = null;

            while((line=bufr.readLine())!=null)

            {

                   if("over".equals(line))

                          break;                             

                   bufOut.write(line);

                   bufOut.newLine();

                   bufOut.flush();

                  

                   String str =bufIn.readLine();

                   System.out.println("server:"+str);

                  

            }

            bufr.close();

            s.close();

     }

}

 

/*

服务端:socket读取流

目的:socket输出流

 

*/

 

 

class  TransServer

{

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

     {

            ServerSocket ss = newServerSocket(10005);

            Socket s =ss.accept();

            String ip =s.getInetAddress().getHostAddress();

            System.out.println(ip+"....connected");

           

            //读取socket读取流中的数据

            BufferedReader bufIn = new BufferedReader(newInputStreamReader(s.getInputStream()));

            //目的:socket输出流,将大写数据写入到socket输出流并发送给客户端

            BufferedWriter bufOut = newBufferedWriter(new OutputStreamWriter(s.getOutputStream()));

           

            String line = null;

            while((line=bufIn.readLine())!=null)

            {

                   System.out.println(line);

                   bufOut.write(line.toUpperCase());

                   bufOut.newLine();//读键盘的时候没结束标记很重要

                   bufOut.flush();

            }

           

            s.close();//关闭客户端

            ss.close();

     }

    

}

浏览器客户端

(1)telenet方式

2405tomcat服务器

bin中startup起来

tomcat就是纯java编写的,里面封装了ServerSocket类的!!!!

2406服务端的请求信息

浏览器和tomcat等虽然都是不同厂商生产的,但是他们都遵从一些国际标准化协议规则

(1)底层传输不说了,都走tcp

(2)应用层,就走http协议

GET/myweb/index.html HTTP/1.0

Accept:application/x-ms-application, image/jpeg, application/xaml+xml, image/gi

f, image/pjpeg,application/x-ms-xbap, */*

Accept-Language:zh-CN

User-Agent:Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.

0; SLCC2; .NETCLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Cent

er PC 6.0;InfoPath.3; .NET4.0C; .NET4.0E)

Host:172.10.20.31:11000

Connection:Keep-Alive

【代码分析】

(1)http://172.10.20.31:11000/myweb/index.html

就是协议,ip,端口,路径,资源

(2)accept支持哪些。。。。

(2)Accept-Encoding:gzip,比如很多文件,按gzip压缩就能很快~

(3)Connection:连接,保活

比如浏览器修改支持

自定义客户端

(1)tomcat中webapps下面

(2)直接ie访问

(3)客户端访问

之前keepalive是还等着,现在这个直接close了,上面消息是应答消息

HTTP/1.1 然后200就是状态码OK,

浏览器强大就是挂了很多解析引擎

css解析引擎,js解析引擎等等

咱的是传输层的协议,获取到了服务器发送过来的所有数据,将符合应用层的消息进行了分析

自己封装URL,否则切割split很麻烦

uri比url大,书本的条形码也是唯一的,也属于uri

我们异常已经很多了, 出去面试的时候,给我列出15个异常,你得列得出来。。。

地址栏可能会带参数信息比如

http://172.10.20.31:8080/myweb/demo.html?name=haha&&age=30

用?进行分隔,用&&进行多信息连接,信息都是以键值对出现的

当地址没有输入端口的时候,getPort返回-1,这个时候就会用默认的80

得到地址会封装成以下对象

Socket对象走的是传输层

直接用InputStream

直接走了应用层了,这样!

网络编程

ServerSocket(intport,int backlog)

backlog,同时连接数

域名解析

 

25正则表达式

网页爬虫,蜘蛛

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0 0
原创粉丝点击