首页 > 代码库 > JavaSE基础笔记513

JavaSE基础笔记513

JavaSE笔记整理

java概述

1. 人机交互

人机交互:是指人与计算机之间使用某种对话语言,以一定的交互方式,为完成确定任务的人与计算机之间的信息交换过程。

交互方式

图形化界面:这种方式简单直观,使用者易于接受,容易上手操作。

 

命令行方式:需要有一个控制台,输入特定的指令,让计算机完成一些操作。较为麻烦,需要记住一些命令。

2. 键盘功能键介绍

这些按键要求的不是认识:而是常用。

′ Tab *** 缩格

′ 空格 Enter ******

′ Window

′ Shift *** (CapsLock:大写) 选中

′ 上下左右

′ Home End

3. 键盘快捷键介绍

Ctrl + A:全选

Ctrl + C:复制

Ctrl + V:粘贴

Ctrl + X:剪切

Ctrl + Z:撤销

Ctrl + Y:恢复键入

Ctrl + S:保存 需要切记

4. 常用DOS命令

1、 打开DOS控制台的方式

a) Shift+桌面右键 -> 单击“在此处打开命令窗口” 命令窗口会进入当前路径

 

b) window+r -> cmd 进入“DOS窗口

2、 常用DOS命令

a) 盘符切换输入盘符+ “:” 回车即可

 

b) 列出当前目录的文件子目录:dir

 

c) 创建目录md :md+文件

 

d) 创建普通文本文件:edit

 

e) 删除目录:rd 目录名称

 

 

f) cd改变目录:cd 目录名称

 

g) 返回上一级目录 cd ..

 

h) 进入当前目录的根目录:cd \

 

i) del 删除文件

 

j) 清屏命令

 

k) 退出:exit 输入到命令行即可

5java语言平台版本

Java SE 标准版

用于开发普通桌面和商务应用程序

该技术体系是其他两者的基础,可以完成一些桌面应用程序的开发

Java ME 小型版

为电子消费产品和嵌入式设备提供的解决方案 例:手机软件开发

Java EE 企业版

为开发企业环境下的应用程序提供的一套解决方案

该技术体系中包含的技术有 ServletJSP等,主要针对于Web应用程序开发

6跨平台

通过Java语言编写的应用程序在不同的系统平台上都可以运行。

原理:只要在需要运行Java应用程序的操作系统上,安装一个Java虚拟机(JVM)即可。由JVM来负责Java程序在系统中运行。

Java语言是跨平台的

JVM不是跨平台的

7JREJDK

JRE Java Runtime Environment Java运行环境)

包括Java虚拟机(JVM)Java程序所需核心类库等,如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。

 

JDKJava Development Kit Java开发工具包)

JDK是提供了Java开发人员使用的,其中包含了Java的开发工具,也包括了JRE。所以安装了JDK,就不用再单独安装JRE了。

 

使用JDK开发,JRE运行,JVM保证跨平台

8JDK-JRE安装

9HelloWorld

1、编写HelloWorld.java

class HelloWorld {

public static void main(String[] args) {

System.out.println("HelloWorld");

}

}

2、编译javac HelloWorld.java -- > 生成class文件

3、运行:java HelloWorld --> 运行class文件

4、类名与文件名不一致会出现什么情况?

编译后的字节码文件名与类名一致,与java文件名无关。

Java基础一

1、关键字

定义被程序开发语言赋予特定含义的单词

关键字的特点:组成关键字的字母全部小写

关键字注意事项:

goto const 为保留字存在,目前并不使用

高级记事本,如Notepad++、Ultraedit、editplus,针对关键字有特殊的颜色标记,非常直观。

哪些是关键字:class, HelloWorld, public, static, void, main, String, System

 

 

2、标识符

定义:给类、接口、方法、变量等名字时,使用的字符序列

组成规则:英文大小写字母,数字字符,$_Unicode码

注意事项:不能以数字开头,不是java关键字,区分大小写

合法标识符? : HelloWorld, DataClass, _983, $bS5_c7, class, DataClass#, 98.3, Hell World

3标识符的命名规则

:单和多级:lyt; com.fangkuangjieke.lyt // 单词与单词之间“.”间隔

或者接口:一个单词和多个单词:StudentHelloWorld // 标识符首字母大写,每个单词首字母大写。大驼峰

方法和变量:一个单词和多个单词:name, mainstudentName // 首字母小写, 每个单词首字母大写。小驼峰

常量:一个单词和多个单词:MAXSTUDENT_MAX_AGE // 所有字母大写,单词与单词之间用下划线。

4注释

定义:用于解释说明程序的文字而且注释的内容不会编译,运行。

Java中注释分类格式:

单行注释: // 注释文字

行注释: /* 注释文字 */

文档注释: /** 注释文字 */

注释是一个程序员必须要具有的良好编程习惯。

初学者编写程序可以养成习惯:先写注释再写代码。

 

将自己的思想通过注释先整理出来,在用代码去体现。

因为代码仅仅是思想的一种体现形式而已。

 

重要的是防止自己遗忘。便于自己快速了解代码结构

5、常量

概念:在程序执行过程中其值不可以发生改变

java中常量的分类

字面值常量

自定义常量面向对象讲述)

常量

字符串常量 用双引号括起来的内容 “内容”

整数常量 所有整数 1 234

小数常量 所有小数 1.1 1.21.34

字符常量单引号括起来的内容 ‘a’, ‘1’, ‘d’

布尔常量 比较特殊只有 true, false

常量 null (数组部分中讲述)

6、进制

Java针对整数常量提供了4表现形式

进制 八进制, 十进制 十六进制

进制概述

进制:就是进制位,是人们规定的一种进位方法。对于任何一种进制---X进制就是表示某一位置上的数运算时是逢X一位二进制就是逢二进一,八进制是逢八进一,十进制是逢十进一,十六进制是逢十六进一。

不同进制的组成

二进制

0,1 组成。以0b开头

八进制

0,1,2,3,4,5,6,7。以0开头

十进制

0,12,3,4,5,6,7,8,9默认是十进制

十六进制

0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f 0X开头

理论上最大是多少进制?计算机进制数?

理论上任何进制都可能存在,但是在计算机中最大三十六进制0-9,a-z

进制转换

其他进制到10进制

通过进制推出结论:位数值*进制数^(位数-1)

0b100,0100,0x100转换成十进制

10进制到其他进制

通过十进制推出结论10进制的数字除以进制除商到0为止,余数反转

52分别表示成二进制,八进制,十六进制

快速转换:

8421

十进制到二进制:将该十进制数分解成8421二的整数次方之和的形式。每一个数代表一个,从左往右书写。

二进制十进制:将该二进制每一位分别对应8421每一位非0相加,得到和为十进制。

进制到八进制,到十六进制

二转八:三位一组,分别转8进制从左往右组合。

十六:四位一组,分别转16进制从左往右组合。

八进制到二进制,十六进制到二进制

八转二将八进制数每一位转换为三位二进制,从左往右组合。

十六转二:将十六进制数每一位转换位四位二进制,从左往右组合

学习原因

负数表示方式原码,反码,补码

正数表示方式:原码,反码,补码(全部一样

所有数据的运算都是采用补码进行的。(这里只有加法运算)

原码:

就是将数,用二进进行表示,最高位为符号0正,1负。

反码

正数的反码与原码相同,负数的反码,是将原码的除符号位按位取反。

补码

正数的补码与原码相同,负数的补码,是反码的末尾加1

总结补码存在原因:计算机中没有减法,通过加法,实现减法。

7变量

变量概述:在程序执行过程中,在某个范围内其值可以发生变量化的量。

相当于数学中的X未知数,其值不确定,可能是任何

变量定义格式:

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

// 注意:格式是固定,记住格式,以不变应万变。

8数据类型

Java语言是强类型语言,对于每一种数据都定义了明确的具体数据类型,在内存中分配了不同大小的内存空间

 

数据类型占用空间,以及表示范围

char 2字节

 

数据类型转换

boolean类型不能转换为其他的数据类型

默认转换

byte,short,char—int—long—float—double

byte,short,char相互之间不转换,他们参与运算首先转换为int类型

强制转换

目标类型 变量名=(目标类型)(被转换的数据);

Java基础

1、运算符

运算:对常量和变量进行操作的过程称为运算。

运算符:对常量和变量进行操作的符号称为运算符

操作数:参与运算的数据称为操作数

运算符把常量或者变量连接起来,符合java语法的式子称为表达式。

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

int a = 3 + 4;

 

这是做了一个加法运算

+就是运算符,是算术运算符,我们还有其他很多的运算符

34就是参与运算的操作数据

3 + 4整体其实就是一个算数表达式

1、算术运算符

+ - * / 都是比较简单的操作

+ 的几种作用:加法、正数、字符串连接符

除法的时候需要注意一个问题:

整数相除只能得到整数的到小数,可以*1.0

/, % 区别: /取;%取余

++, --用法:i++ è i+=1 è i = i + 1;

前自增自增:单独运算效果相同都将结果进行+1

参与运算使用,在操作数的前后效果不同

2、赋值运算符

= += -= *= /= %=

=基本的赋值运算符,其他为扩展赋值运算符

s+=1等价于s=(s的数据类型)(s+1);

3、关系运算符

 

注意1、关系运算符结果为true,或者false

  2、比较运算符“==” 不要误写成“=”

4、逻辑运算符

 

&:有false则false

|:有true则true

^:相同false,不同true

帮助理解:情侣必须是男女或者女男

!:非false则true,非true则false

&&,||和&以及|的区别

结果相同,但是有短路运算,一般建议使用&&,||

5、位运算:<<, >>, >>>, &,|,^,~

 

位运算是直接对二进制进行运算。

6、单目运算符:一个操作数  ! true

双目运算符:两个操作数 a > b

三目运算符三个操作数

三目运算符:关系表达式 ? 表达式1 : 表达式2;

如果关系表达式结果为true,运算后结果为表达式1.

如果关系表达式结果为false,运算结果为表达式2.

:获取两个数中最大数。

int x=3, y=4, z;

z = x > y ? x : y;

2流程控制语句

在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的。也就是说程序的流程对运行结果有直接的影响。所以,我们必须清楚每条语句的执行流程。而且,很多时候我们要通过控制语句的执行顺序来实现我们要完成的功能。

流程控制语句分类:

顺序结构

选择结构

循环结构

3、顺序结构

是程序中最简单最基本的流程控制,没有特定的语法结构,按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。

总的来说:写在前面的先执行,写在后面的后执行

代码执行顺序为:从上到,从左到右。

4选择结构

选择结构,又称分支结构:选择结构有特定的语法规则,代码要执行具体的逻辑运算进行判断,逻辑运算的结果有两个,所以产生选择,按照不同的选择执行不同的代码。

java语言提供了两种选择结构语句

if;

switch;

选择结构(if语句

if语句有三种格式

第一种格式:

if(关系表达式) {

语句;

}

 

执行流程:首先判断关系表达式看其结果是true还是false;如果是true就执行语句体;如果是false就不执行语句体

 

第二种格式:

if(关系表达式){

语句1;

}else{

语句体2;

}

 

执行流程:首先判断关系表达式看其结果是true还是false;如果是true就执行语句体1;如果是false就执行语句体2

 

第三种格式:

if(关系表达式1) {

语句1

}else if(关系表达式2) {

语句2

}else if(关系表达式3) {

语句3

}。。

else {

语句n+1

}

 

执行流程:先判断关系表达式1如果结果为true,执行语句1结束语句如果false执行表达式2如果结果为true,执行语句2结束语句如果为false执行表达式3如果结果为true,执行语句3结束语句如果为false。。。。。。如果都不满足,执行else,结束语句。

键盘录入

// 导包

import java.util.Scanner;

// 创建对象

Scanner sc = new Scanner(System.in);

这里可以添加提示语

// 获取输入内容

int n = sc.nextInt();

Java基础

1选择结构

选择结构,又称分支结构:选择结构有特定的语法规则,代码要执行具体的逻辑运算进行判断,逻辑运算的结果有两个,所以产生选择,按照不同的选择执行不同的代码。

java语言提供了两种选择结构语句

if;

switch;

选择结构(if语句

if语句有三种格式

第一种格式:

if(关系表达式) {

语句;

}

 

执行流程:首先判断关系表达式看其结果是true还是false;如果是true就执行语句体;如果是false就不执行语句体

 

第二种格式:

if(关系表达式){

语句1;

}else{

语句体2;

}

 

执行流程:首先判断关系表达式看其结果是true还是false;如果是true就执行语句体1;如果是false就执行语句体2

 

第三种格式:

if(关系表达式1) {

语句1

}else if(关系表达式2) {

语句2

}else if(关系表达式3) {

语句3

}。。

else {

语句n+1

}

 

执行流程:先判断关系表达式1如果结果为true,执行语句1结束语句。如果false执行表达式2如果结果为true,执行语句2结束语句如果为false执行表达式3如果结果为true,执行语句3结束语句如果为false。。。。。。如果都不满足,执行else,结束语句。

键盘录入

// 导包

import java.util.Scanner;

// 创建对象

Scanner sc = new Scanner(System.in);

这里可以添加提示语

// 获取输入内容

int n = sc.nextInt();

 

选择结构(switch语句:可以break;中断

switch(表达式){

case 1:

语句体1;

case 2:

语句体2;

….

default:

语句体n+1;

}

根据表达式结果,匹配,值1如果相同,执行语句体1语句体2… 语句体n+1;直到结束如果2相同,执行语句体2,语句体…,语句体n+1,直到结束。如果都不匹配,执行default:语句n+1结束。

switch(表达式){

case 1:

语句体1;

break;

case 2:

语句体2;
break;

….

default:

语句体n+1;

}

如果匹配值1执行语句体1语句体2…直到遇到break,结束语句,如果匹配到值2执行语句体2遇到break,结束语句,如果都不匹配,执行default,语句体n+1,结束语句。

2、循环结构

循环语句可以在满足循环条件的情况下,反复执行某一段代码,这段被重复执行的代码被称为循环体语句,当反复执行这个循环体时,需要在合适的时候把循环判断条件修改为false,从而结束循环,否则循环将一直执行下去,形成死循环。

比如:在控制台输出10次”HelloWorld”。

循环语句的组成

初始化语句:

一条或者多条语句,这些语句完成一些初始化操作。

判断条件语句:

这是一个boolean 表达式,这个表达式能决定是否执行循环体。

循环体语句:

这个部分是循环体语句,也就是我们要多次做的事情。

控制条件语句:

这个部分在一次循环体结束后,行。通过用于控制循环条件中的变量,使得循环在合适的时候结束。下一次循环判断条件执行前执。

3、循环结构

for循环语句

for(初始化语句; 判断条件语句; 控制条件语句) {

循环体语句;

}

执行流程:

A:执行初始化语句

B执行判断条件语句,看其结果true还是false

如果false,循环结束

如果true继续执行

C:执行循环体语句

D:执行控制条件语句

E:回到B继续

 

while 循环语句

基本格式

while(判断条件语句) {

循环体;

}

执行流程A:判断条件语句是否为true

如果为true,执行循环体,转而执行A

如果false,终止循环

扩展格式

初始化语句;

while(判断条件语句) {

循环体;

控制条件语句;

}

 

for与while对比

forwhile可以做等价转换的。

使用区别:控制条件语句所控制的那个变量,在for循环结束后,就不能再被访问到了,而while循环结束还可以继续使用,如果你想继续使用,就用while,否则推荐使用for。原因是for循环结束,该变量就从内存中消失,能够提高内存的使用效率。

场景区别:

for循环适合针对一个范围判断进行操作

while循环适合判断次数不明确操作

 

do…while 循环语句

基本格式:

do{

循环体;

}while(判断条件语句) ;

扩展格式

初始化语句;

do{

循环体;

控制条件语句

}while(循环条件语句);

执行流程:

先执行循环体;在执行判断条件,如果条件true执行循环体,否则结束循环

 

 

Java基础

1、跳转控制语句

break中断

break的使用场景

在选择结构switch中;

循环语句中;

离开使用场景的存在是没有意义的。

break的作用:

跳出单层循环

跳出多层循环:带标签的break

 

continue 继续

使用场景:

循环体语句中;

离开使用场景的存在是没有意义的。

作用

单层continue

 

多层continue

 

return 返回

return关键字不是为了跳转出循环体,更常用的功能是结束一个方法,也就是退出一个方法。跳转到上层调用的方法。这个在方法的使用那里会在详细的讲解。

 

java 方法

1、为什么要有方法:

代码中有很多事情都是相同的,那么代码就没有必要重复填写。而这些相同代码就可以被程序中定义为一个方法。这样的话每次开枪只需调用方法,不需要再粘贴大量代码。

2、方法说明:

在很多语言里面都有函数的定义

函数在Java中被称为方法

3、格式

修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2) {

方法体;

return 返回值;

     }

方法格式解释:

修饰符:修饰方法的状态目前只需要用public static

返回值类型:用于限定返回值类byte short int long·····

方法一个名字,为了方法调用方法。

参数列表:

参数类型:限定调用方法,传入数据的类型

参数名:是一个变量,接收调用方法时传入的参数。

方法

完成功能的代码

return:结束方法以及返回方法指定的值

返回值:程序被return带回的结果,返回给调用者。

 

4、注意事项

方法不调用,不执行

方法与方法之间是平级关系,不能嵌套定义。

方法定义的时候参数之间用逗号间隔。

方法调用的时候不用传递数据类型

如果方法明确的返回值,一定要有return 带回一个值。

5、没有返回值的方法定义

修饰符 void 方法名(参数类型 参数名1,参数类型 参数名2) {

方法体;

// 如果return,后面直接“;”,如果不写,也是可以的。

// return ;

    }

 

6重载

概述在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。

重载的特点:

与返回值类型无关,只看方法名和参数列表

在调用时,虚拟机通过参数列表的不同来区分同名方法

例如:求和

 

java 数组

1、概述

数组是存储同一种数据类型多个元素的集合。也可以看成是一个容器。

数组既可以存储基本数据类型,也可以存储引用数据类型。

2、数组的定义格式

格式1、数据类型[] 数组名;

格式2数据类型 数组[];

注意:这两种定义做完了,数组中是没有元素值的。

3、数组元素初始化

数组初始化概述:

Java中的数组必须先初始化,然后才能使用。

所谓初始化:就是为数组中的数组元素分配内存空间,并为每个数组元素赋值。

数组初始化的方式:

静态初始化:初始化时指定每个数组元素的初始值,由系统决定数组长度。

动态初始化:初始化时只指定数组长度,由系统为数组分配初始值。

动态初始化

初始化时只指定数组长度,由系统为数组分配初始值。

格式

数据类型[] 数组 = new 数据类型[数组长度];

数组长度其实就是数组中的元素个数

举例

int[] array = new int[3];

解释:定义了一个int类型的数组,这个数组可以存放3int类型的数据。

 

4、内存分配:

Java 程序在运行时,需要在内存中的分配空间。为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。

存储局部变量

存储new出来的东西

方法区 (面向对象部分讲)

  寄存器 (CPU使用)

 

局部变量:在方法定义中或方法声明上的变量都称为局部变量

每一个new出来的东西都有地址值

每一个变量都有默认值

byte,short,int,long,0

float,double, 0.0

char ‘\u0000’

Boolean false

引用类型 null

使用完毕就变成垃圾,但是并没有立即回收,会在垃圾回收器空闲的时候回收。

5、数组静态初始:初始化时指定每个数组元素的初始值,由系统决定数组长度。

格式:数据类型[] 数组 = new 数据类型[]{元素1、元素2元素…};

举例

int[] arr = new int[]{1, 2, 3};

解释:定义了一个int类型的数组,这个数组中可以存放3int‘类型的值,并赋值为1,2,3,

其实这种写法还有一种简化写法

int[] arr = {1, 2, 3};

 

6数组的属性

数组length 数组的长度,属于数组对象

7数组中可能遇见异常

ArrayIndexOutOfBoundsException 数组下标越界

NullPointerException 空指针异常

二维数组

1二维数组概述

其实二维数组其实就是每一个数组元素为一维数组的数组

2、定义格式一

数据类型[][] 变量 = new 数据类型[m][n]

m代表这个二维数组有多少个一维数组

n 代表每一个一维数组元素个数。

 

举例

int[][] array = new int[3][2];

定义了一个二维数组array

3这个二维数组有3个一维数组,名称是array[0]、array[1]、array[2]

2 每一个一维数组有2元素,可以通过array[m][n]来获取array[0][1]

表示获取第m+1个一维数组n+1个元素。

3、定义格式二

数据类型[][] 变量名 = new 数据类型[m][];

m表示这个二维数组有多少个一维数组

这一次没有直接给出一维数组的元素个数。可以动态给出

 

举例

int[][] array = new int[3][];

array[0] = new int[2];

array[1] = new int[5];

array[2] = new int[4];

4、定义格式三 

静态初始化

数据[][] 变量名称 = new 数据类型[][] {

{元素1, 元素2,….},

{元素…},

{元素..}

};

简化格式

数据[][] 变量名称 = {

{元素1, 元素2,….},

{元素…},

{元素..}

};

 

举例

int[][] arr = {

{1, 2, 3},

{3, 6},

{123, 345, 678}

};

排序

http://blog.csdn.net/hguisu/article/details/7776068(八种排序方式自行学习)

冒泡排序

基本概述:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。至此第一趟结束,将最大的数放到了最后。在第二趟:仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。如此下去,重复以上过程,直至最终完成排序。

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

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

if(array[j] < array[j + 1]) {

int temp = array[j];

array[j] = array[j + 1];

array[j + 1] = temp;

}

}

}

插入排序:

每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。

public static void insertsort(int arr[]){                

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

//注意[0,i-1]都是有序的。如果待插入元素比arr[i-1]还大则无需再与[i-1]前面的元素进行比较了,反之则进入if语句

            if(arr[i-1] > arr[i]){

                int temp = arr[i];

                int j;

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

                        arr[j+1] = arr[j];//把比temp大或相等的元素全部往后移动一个位置            

                }

                arr[j+1] = temp;//把待排序的元素temp插入腾出位置的(j+1)

            }            

        }

        

    }

插入和冒泡排序的区别:

例如45 12     342   2

对于插入排序来说,进行一趟排序之后就有:   12   45   342 2

而对于冒泡排序,进行一趟排序之后有:       12    45    2  342   

 

杨辉三角:

 

int triangle[][]=new int[20][];// 创建二维数组

// 遍历二维数组的第一层

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

    triangle[i]=new int[i+1];// 初始化第二层数组的大小

    // 遍历第二层数组

    for(int j=0;j<=i;j++){

        // 将两侧的数组元素赋值为1

        if(i==0||j==0||j==i){

            triangle[i][j]=1;

        }else{// 其他数值通过公式计算

            triangle[i][j]=triangle[i-1][j]+triangle[i-1][j-1];

        }

        System.out.print(triangle[i][j]+"\t");         // 输出数组元素

    }

    System.out.println();               //换行

}

 

阶乘!n == n*!(n-1);

public static int jc (int n) {

if(n ==1 ){

return 1;

}else{

return n * jc(n-1);

}

}

 

 

斐波那契数列:F[n]=F[n-1]+F[n-2] (n>=2,F[1]=1,F[2]=1)

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233377610987159725844181676510946177112865746368

 

public static int fibonacci(int n){

    if(n<=1)

return 1;

   return fibonacci(n-1)+fibonacci(n-2);

    }

 

排序

http://blog.csdn.net/hguisu/article/details/7776068(八种排序方式自行学习)

冒泡排序

基本概述:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。至此第一趟结束,将最大的数放到了最后。在第二趟:仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。如此下去,重复以上过程,直至最终完成排序。

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

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

if(array[j] < array[j + 1]) {

int temp = array[j];

array[j] = array[j + 1];

array[j + 1] = temp;

}

}

}

插入排序:

每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。

public static void insertsort(int arr[]){                

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

//注意[0,i-1]都是有序的。如果待插入元素比arr[i-1]还大则无需再与[i-1]前面的元素进行比较了,反之则进入if语句

            if(arr[i-1] > arr[i]){

                int temp = arr[i];

                int j;

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

                        arr[j+1] = arr[j];//把比temp大或相等的元素全部往后移动一个位置            

                }

                arr[j+1] = temp;//把待排序的元素temp插入腾出位置的(j+1)

            }            

        }

        

    }

插入和冒泡排序的区别:

例如45 12     342   2

对于插入排序来说,进行一趟排序之后就有:   12   45   342 2

而对于冒泡排序,进行一趟排序之后有:       12    45    2  342   

 

杨辉三角:

 

int triangle[][]=new int[20][];// 创建二维数组

// 遍历二维数组的第一层

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

    triangle[i]=new int[i+1];// 初始化第二层数组的大小

    // 遍历第二层数组

    for(int j=0;j<=i;j++){

        // 将两侧的数组元素赋值为1

        if(i==0||j==0||j==i){

            triangle[i][j]=1;

        }else{// 其他数值通过公式计算

            triangle[i][j]=triangle[i-1][j]+triangle[i-1][j-1];

        }

        System.out.print(triangle[i][j]+"\t");         // 输出数组元素

    }

    System.out.println();               //换行

}

 

阶乘!n == n*!(n-1);

public static int jc (int n) {

if(n ==1 ){

return 1;

}else{

return n * jc(n-1);

}

}

 

 

斐波那契数列:F[n]=F[n-1]+F[n-2] (n>=2,F[1]=1,F[2]=1)

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233377610987159725844181676510946177112865746368

 

public static int fibonacci(int n){

    if(n<=1)

return 1;

   return fibonacci(n-1)+fibonacci(n-2);

    }

 

java面向对象一

1面向对象思想引入

前面我们讲过数组,当有多个数组都需要遍历时,我们可以将遍历的代码封装到方法中,需要遍历时,就调用相应的方法即可,提高代码的复用性。在对数组遍历的基础上继续增加需求,比如获取最值,数值逆序等,同样需要将这些功能封装到相应的方法中。这样继续封装会发现方法越来越多,于是就想能不能将这些方法继续进行封装呢?

通过前面的讲解我们知道类是可以存放方法的,所以,我们就考虑使用类封装来这多个方法,将来再做数组的操作时,不用去找具体的方法,先找到这个类,然后使用这个类中的方法。这就是面向对象思想的编程方式。

2、面向过程思想概述

当需求单一,或者简单时,我们一步一步去操作没问题,并且效率也挺高。可随着需求的更改,功能的增多,发现需要面对每一个步骤很麻烦了,这时就开始思索,能不能把这些步骤和功能在进行封装,封装时根据不同的功能,进行不同的封装,功能类似的封装在一起。这样结构就清晰了很多。用的时候,找到对应的类就可以了。这就是面向对象的思想。

面向对象思想概述

面向对象是基于面向过程的编程思想

面向对象思想特点

是一种更符合我们思想习惯的思想

可以将复杂的事情简单化

将我们从执行者变成指挥者

角色转变

“面向过程”(Procedure Oriented)是一种以过程为中心的编程思想。

“面向对象”(Object Oriented,简称OO)是一种以事物为中心的编程思想。

3、面向对象思想举例

买电脑:

面向过程:我的了解电脑--了解我自己的需求--找对应的参数信息--去中赛格电脑--讨价还价--买回电脑

面向对象:我知道我要买电脑 -- 班长去给我买 -- 班长就买回来了

洗衣服:

面向过程:把衣服脱下--找一个盆--放点洗衣粉--加点水--把衣服扔进去--搓一搓--清洗衣服--拧干--晾起来

面向对象:把衣服脱下--打开全自动洗衣机--扔进去--一键即可--晾起来

吃饭:

面向过程:去超市买菜--摘菜--洗菜--切菜--炒菜--盛起来--吃

面向对象:上饭店吃饭,你--服务员(点菜)--厨师(做菜)--服务员(端菜)--吃

 

家常事物,买洗衣机和去饭店太不划算了,所以,找个对象。

但是,你不跟我好好学习,你将来4000,你对象8000。

4、面向对象开发,设计,特征

面向对象开发

就是不断的创建对象,使用对象,指挥对象做事情。

面向对象设计

其实就是在管理和维护对象之间的关系。

面向对象特征

封装(encapsulation)

继承(inheritance)

多态(polymorphism)

5、类与对象关系

属性 就是该事物的描述信息

行为 就是该事物能够做什么

类: 是一组相关的属性和行为的集合

对象: 是该类事物的具体体现

举例:

类:学生

对象:班长就是一个对象

类:可以理解为构筑对象的一个蓝图或者模板,是抽象的概念。

对象:是以类为模型创建的具体实例,是对类的一种具体化。

6、类定义

现实世界的事物

属性 人的身高,体重等

行为 人可以学习,吃饭等

Java中用class描述事物也是如此

成员变量 就是事物的属性

成员方法 就是事物的行为

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

1、成员变量 和以前定义变量是一样的,只不过位置发了变化。 在类中,方法外。

2、成员方法 和以前定义方法是一样的,只不过把static去掉,后面再详细讲解static的作用。

7、类与对象案例

学生类

如何定义

按照事物到类的过程一步一步分析

如何使用

创建对象

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

对象名.成员变量

对象名.成员方法

定义人类:

 

使用人类

 

8内存图

对象变量保存的不是真实的对象内容,而是对象内存所在堆地址,通过该地址位置,可以找到堆中的对象内。可以进行赋值,取值,操作。

 

9、形式参数问题:(形参问题)

基本类型作为参数 long

会将实际参数值进行赋值给形式参数。

引用类型作为参数 String

会将实际参数值(引用赋值形式参数(引用

因为引用类型参数方式堆地址的能力,引用地址进行赋值,作用是相同的,也可以访问堆地址

 

10、匿名对象

匿名对象:就是没有名字的对象

是对象的一种简化表示形式

匿名对象的两种使用情况

对象调用方法仅仅一次的时候

作为实际传递

 

11封装概念

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

好处:

隐藏实现细节,提供公共的访问方式

提高了代码的复用性

提高安全性

封装原则

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

把属性隐藏起来,提供公共方法对其访问。

private关键字

是一个权限修饰符。

可以修饰成员(成员变量和成员方法)

private修饰的成员只在本类中才能访问。

private最常见的应用:

把成员变量用private修饰

提供对应的getXxx()/setXxx()方法

一个标准的案例的使用

private仅仅是封装的一种体现,类和方法其实也是封装体

 

12this

this:代表所在类的对象引用

什么时候使用this?

局部变量隐藏成员变量

其他用法后面和super一起讲解

13、构造方法

作用:给对象的数据进行初始化的。

构造方法格式

方法相同

没有返回值类型,连void都没有。

没有具体的返回值。

注意事项

如果你不提供构造方法,系统会给出默认构造方法。

如果你提供了构造方法,系统将不再提供。

构造方法也是可以重载的。

虽然构造方法没有返回值,但是也是可以使用return的,在最后写return; 这种做法在任何返回值为void类型的方法最后都是没有问题的。

14、类的成员方法

成员方法就是之前讲过普通方法。

方法具体划分:

根据返回值:有返回值的方法和返回值void类型的方法

根据形式参数:带参方法和无参方法。

15、一个基本类的标准写法:

带参构造:带有参数的构造方法

多参构造:一个以上参数的构造方法

不带参构造:无参构造方法。

私有构造:该类不予许创造对象。或者不需要别的类创造构造方法而自己可以创造构造方法。

公有构造:任何人都可以new这个类,得到该类的对象。

必写无参构造:如果不无参构造,而写了有参构造,系统给默认的无参构造。这就不能使用无参构造方法创建对象。

给成员变量赋值的方式

无参构造方法+setXxx()

带参构造方法

16、类实例化为对象的过程。

Student s = new Student(“张三”, 18);

1加载Student.class

2、s开辟内存

3、在堆内存中为Student类的对象开辟内存。(默认值为null 0.0false\u0000)

4、调用构造方法,为对象属性赋初始值

5、将开辟的内存地址(引用)赋值s变量

17static 关键字

可以修饰成员变量和成员方法

static关键字的特点

随着类的加载而加载

优先于对象存在

类的所有静态资源共享

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

可以通过类名调用,当然可以通过对象名调用

static关键字的注意事项

在静态方法中是没有this关键字的。

静态方法只能访问(调用,使用静态成员变量和静态成员方法。

18、静态变量和非静态成员变量的区别

所属不同:

静态变量属于类,所以也称为类变量

非静态成员变量属于对象,所有也称为实例变量(对象变量)

内存中位置不同:

静态变量存储于方法区的静态区

成员变量存储于堆内存

内存出现时间不同

静态变量随着类的加载而加载,随着类的消失而消失

成员变量随着对象的创建而存在,随着对象的消失而消失。

调用不同

静态变量可以通过类名调用,可以通过对象调用

成员变量只能通过对象名调用。

非静态方法可以调用静态方法,静态方法可以调用非静态。

19、main方法是静态的

public static void main(String[] args) {}

public 公共的,访问权限最大,由于main虚拟机调用所以权限大。

static 静态的,不需要实例化该方法所在为了方法jvm调用。

void 方法的返回值,main是由JVM调用 返回内存给JVM没有意义。

main 方法名不是关键字,但是JVM就是只认它。

String[] args:是一个参数,该参数为一个字符串数组,它可以接收在运行时传入的参数。

面向对象

1、继承

继承概述:多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。原因。

用法:class 子类名 extends 父类{}

单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。

继承的好处

提高代码的复用性多个类的相同成员可以放到同一个类中。

提高了代码的维护性,如果功能更改只需修改一处

让类与类之间产生了关系,是多态的前提:弊端,类的耦合性增强。

代码设计原则:高内聚低耦合

简单的理解:

内聚就是自己完成某件事情的能力。

耦合就是类与类之间的关系。

我们在设计的时候原则是:自己能完成的就不麻烦别人,这样将来别人产生了修改,就对我的影响较小。

由此可见:在开发中使用继承其实是在使用一把双刃剑。今天我们还是以继承的好处来使用,因为继承还有很多其他的特性。

继承特点:

java只支持单继承,不支持多继承。

一个只能有一个父类,不可以有多个父类。

// class SubDemo extends Demo{} // 是可以的。

// class SubDemo extends Demo1, Demo2{} // 不可以多个

java支持多层继承(继承体系)

class A{}
class B extends A {}

class C extends B {}

注意事项

子类只能继承父类所有非私有的成员(成员方法和成员变量),可以继承父类的静态非私有属性。

其实这也体现了继承的另一个弊端:打破了封装性

子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。

不要为了部分功能而去继承。

继承中成员变量的关系

父类中同名和不同的成员变量

子类中访问一个变量

首先在子类局部范围

然后在子类的成员范围

最后在父类成员范围找(肯定不能访问到父类局部范围)

如果还是没有找到报错

2super关键

super的用法和this

this代表对象的引用

super代表父类存储空间的标识可以理解为父类对象的引用)

用法thissuper均可如下使用)

访问成员变量:

this.成员变量 super.成员变量

访问构造方法(子父类的构造问题讲

this(…) super(…)

成员方法(父类的成员方法问题讲)

this.成员方法() super.成员方法()

3、继承中构造方法的关系

子类中所有的构造方法默认都会访问父类的无参构造方法

因为子类会继承父类中的数据,可以还会使用父类的数据所有子类初始化之,一定要先完成父类数据初始化。

每一个构造方法第一条语句默认都是:super();

如果自行显示调用,就不会默认调用super();

 

子类通过super去显示调用父类其他的带参的构造方法

子类通过this去调用本类的其他构造方法

本类其他构造也必须首先访问了父类构造

一定要注意:

super()或者this(.)必须出现在第一条语句

否则报错。

4、代码块

什么是代码块?

可以执行的代码段,简称代码块,{}

三种:普通代码块,构造代码块,静态代码块。

普通代码块:在方法或语句中出现的{}就称为普通代码块。普通代码块和一般的语句执行顺序由他们在代码中出现的次序决定--“先出现先执行”代码块中定义变量只在代码块中有效。

构造代码块:直接在类中定义且没有加static关键字的代码块称为{}构造代码块。构造代码块在创建对象时被调用,每次创建对象都会被调用,并且构造代码块的执行次序优先于类构造函数。

静态代码块:在java中使用static关键字声明的代码块。静态块用于初始化类,为类的属性初始化。每个静态代码块只会执行一次。由于JVM在加载类时会执行静态代码块,所以静态代码块先于主方法执行。 //如果类中包含多个静态代码块,那么将按照"先定义的代码先执行,后定义的代码后执行"。

注意:静态代码块,不可能存在于任何方法体内

静态代码块,不能直接访问实例变量和实例方法。需要通过实例对象来访问。

5继承中的成员方法:

通过子类对象去访问一个方法

首先在子类中找

然后在父类中找

如果还是没有就报错。(不考虑父类的父类)

方法重写概述

子类中出现了和父类中一模一样的方法声明(定义),也被称为方法覆盖,方法复写。

使用特点:

如果方法名不同,就调用对应的方法。

如果方法名相同,最终使用子类自己的。

方法重写的应用:

当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容。

注意事项

父类中的私有方法不能被重写

子类重写父类方法时,访问权限不能更低。

// 报错正在尝试分配更低的访问权限; 以前为public-》子类重写后方为权限小于父类方法权限

父类静态方法,子类也必须通过静态方法进行重写。(其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解)

6final关键字

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

修饰类,不能被继承

修饰方法,方法不能被重写

修饰变量,变量就变成了常量,只能被赋值一次普通变量被修饰成为局部常量。成员变量被修饰,成员常量。成员常量只能在构造方法构造方法之前进行初始化。否则不允许初始化。

修饰成员变量

基本类型,是值不能被改变

引用类型,是地址值不能被改变

final修饰成员变量初始化的时机

在对象构造完毕前即可 (必须只赋值一次,不能重复赋值)

面向对象三(多态,抽象类)

1、多态

某一事物,在不同时刻表现出的不同状态。

举例

可以是猫的类型。猫 m = new ();

同时猫也是动物的一种,也可以把猫成为动物

动物 d = new ();

水在不同时刻的状态

多态前体和体现

继承关系

有方法重写

有父类有引用指向子类对象

多态案例以及成员访问特点

按照前提写一个多态案例

成员访问特点:

成员方法

编译看左边(语法)运行看右边(执行代码

成员变量

编译看左边(语法),运行看左边执行父类变量)

静态方法:

编译看左边(语法),运行看左边(执行父类静态方法)

多态好处与弊端:

多态的好处:

提高了程序的维护性(由继承保证)

提高了程序的扩展性(由多态保证)

多态的弊端:

不能访问子类特有功能

如果能够访问子类的特有功能呢?

多态中的转型

2多态转型:

向上转型

子类对象赋值给父类变量,将子类交给父类;父类引用执行子类对象

动物 d = new ();

向下转型:

父类对象赋值给子类变量父类交给了子类父类引用转为子类对象;

m = (猫)父类对象;

子类转父类,默认转换

父类子类强制类型转换,前提,这个,本质就是子类在可以转换。如果本质就是父,编译不会报错,执行时报运行时异常。java.lang.ClassCastException

3制作帮助文档

我想要对数组进行操作

如何制作一个说明书呢?

A:写一个工具类

B:对这个类加入文档注释

怎么加呢?

加些什么东西呢?

@author

@version V.10

@param 这是要被遍历的数组

@return 返回数组中的最大值

D:格式

javadoc -d 目录 ArrayTool.java

目录:就可以写一个文件夹的路径

制作帮助文档出错:

找不到可以文档化的公共或受保护的类:告诉我们类的权限不够

4、抽象

在java中,一个没有方法体的方法应该定义为抽象方法,类中如果有抽象方法,该类必须定义为抽象

如果一个类中包含了一个或者多个抽象方法,类就必须定义为abstract抽象。“抽象方法”属于不完成的方法,只包含一个声明,没有方法主体

抽象类的特点:

抽象类和抽象方法必须用abstract关键字修饰

格式

abstract class 类名{

}

public abstract void eat();

抽象类不一定有抽象方法,抽象方法的类,一定是抽象类。

抽象类不能实例化

那么,抽象类如何实例?

按照多态的方式,具体的抽象类子类实例

抽象类的子类

么事抽象类,要么实现抽象类中的所有抽象方法。

抽象类的成员特点

成员变量:可以是变量,也可以是常量

构造方法:有构造方法,但是不能实例,那么构造方法的作用是什么?用于父类数据初始化,在子类new或者主动调用父类构造时。

成员方法可以有抽象方法,作用是限定子类必须完成某些动作。

可以非抽象方法,提供代码复用性。

抽象类的几个小问题:

一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?

abstract不能和哪些关键字共存

private 冲突

final 冲突

static 无意义

面向对象四(接口,包,内部类)

1、接口

Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征(声明)没有方法的实现(体),因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。

接口就是提供一种统一的”协议”,而接口中的属性也属于“协议”中的成员。

接口特点

接口用关键字interface表示

格式interface 接口名{}

类实现接口用implements表示

格式class 类 implements 接口{}

接口不能实例化:

那么接口如何实例化?按照多态的方式,具体的子类实例化其实这也是多态的一种,接口多态。

接口的子类:

要么是抽象类

要么重写接口中所有抽象方法类。

接口的子:

接口,接口之间可以继承。extends

接口成员特点:

成员变量:

只能是常量,默认修饰符为public static final

构造方法

没有,因为接口注意是扩展功能的,没有具体存在。

成员方法

只能是抽象方法

默认修饰符为 public abstract

2、类与类,类与接口,接口与接口的关系

类与类extends继承关系,只能是单继承,但可以多层继承。

与接口Implements实现关系可以单实现,也可以多实现一个类中可以同时实现多个接口)还可以在继承一个类的同时实现多个接口

接口接口extends继承关系可以单继承,也可以多继承

3抽象类和接口的区别

成员区别:

抽象类:变量,常量有抽象方法,非抽象方法

接口:常量,抽象方法

关系区别:

类与类,继承,单继承多层继承

与接口实现,实现,多实现

接口接口,继承,单继承,多继承

设计理念区别

抽象类,被继承体现的是:“is a”的关系共性功能。

接口,被实现体的是:“like a”的关系,扩展功能。

总结区别

1、抽象类,单继承接口,多实现

2、抽象类,可以有变量,常量,抽象方法,非抽象方法接口只有常量,抽象方法。

3abstract class表示的是"is-a"关系,interface表示的是"like-a"关系

4、抽象类中可以有非抽象方法。接口中则不能有实现方法。

5、接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。

6、抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以重新赋值。

7、接口中的方法默认都是 public,abstract 类型的。

4参数返回值问题

抽象类和接口类型作为形式参数

:需要的是该类的对象。

抽象类:需要抽象类的子类的对象。

接口:需要接口的实现类的对象。

、抽象类和接口类型作为返回值

:其实返回的是该类的对象

抽象类:其实返回的是该抽象类子类的对象(自行完成

接口:其实返回的是该接口实现类的对象(自行完成

链式编程是将多个操作(多行代码)通过点号“.”链接在一起成为一句代码。

例如s.setAge(18).setName("张三").show();

5

的概述:其实就是文件,用来对进分类管理。

的定义以及注意事项:

package 包名;

多级用”.”分开即可

注意事项

package 语句必须是程序的第一条执行代码;

package 语句java文件中只能有一个

如果没有package,默认表示包名。

带包编译,运行:

手动式

ajavac 编译当前java文件

b、手动创建包对应的文件

c把a步骤得到的class文件,放到b得到的最后一个文件夹中。

d、通过java命令执行。注意是:需要带包名称执行。

java com.tx.lyt.HelloWorld

自动式

ajavac编译的时候带上参数 –d 即可

javac –d 目录 文件.java

javac –d . HelloWorld.java

这里的目录:当编译完成后,包的class存放的位置。

b:通过java命令执行手动式一样的。

不同包下类之间的访问

定义两个Demo Test

Demo 求和方法

Test 测试main方法

 

1、错误:找不到Demo 必须带包名

2、com.tx.Demo 不存在 没有编译Demo

3com.tx.Demo 不是公共的 Demo不是public

6导包

导包概述:不同包下的类之间的访问,我们发现,每次使用不同包下的类的时候,都需要加包的全路径。比较麻烦。这时候,java提供了导包的功能。

导包格式:

import 包名;

注意

这种方式导入类的名称。

虽然可以最后写*,但是不建议。

7、类及其组成可以用的修饰符

可以public final abstract

自己定义:public居多

成员变量:

四种权限修饰符均可,final static

自己定义:private居多

构造方法:

四种权限修饰均可,其他不可

自己定义:public居多

成员方法:

四种权限修饰均可,finalstaticabstract

自己定义:public居多

面向对象四(内部类)

1、内部类概述:

把类定义在其他类的内部,这个类就被称为内部类。

举例:在类A中定义了一个类B,类B就是内部类。

内部类的访问特点:

内部类可以直接访问外部类的成员,包括私有。

外部类要访问内部类的成员,必须创建对象。

内部类的位置:

按照内部类在类中定义的位置不同,可以分为如下两种格式:

成员位置(成员内部类)

局部位置(局部内部类)

2成员内部类

外界如何创建对象

外部类.内部类 对象 = 外部类对象.new 内部类();

内部类拿出了使用。在实际开发中是不会这样使用的。因为一般内部类就是不让外界直接访问的。例如:电脑和cpu

成员内部类的常见修饰符

private 为保证数据的安全性

static 为了让数据访问更加方便

内部类被静态修饰后方法都为静态方法

3局部内部类:

可以直接访问外部类成员

可以创建内部类对象,通过对象调用内部类方法,用局部内部类功能

 

4、匿名内部类

就是内部类的简化写法

前提:存在一个类或者接口。

格式

new 类名或者接口名(){

实现未实现的方法

};

本质:是一个继承了类或者实现了接口的子匿名对象。

匿名内部类在开发中的使用

首先回顾我们曾经讲过的方法的形式参数是引用类型的情况,重点是接口的情况,我们知道这里需要一个子类对象。而匿名内部类就是一个子类匿名对象,所以,可以使用匿名内部类改进以前的做法。

java常用类

1API概述

API(Application Programming Interface):应用程序编程接口

编写一个机器人程序去控制机器人踢足球,程序就需要向机器人发出向前跑、向后跑、射门、抢球等各种命令,没有编过程序的人很难想象这样的程序如何编写。但是对于有经验的开发人员来说,知道机器人厂商一定会提供一些用于控制机器人的Java类,这些类中定义好了操作机器人各种动作的方法。其实,这些Java类就是机器人厂商提供给应用程序编程的接口,大家把这些类称为Xxx Robot API。本章涉及的Java API指的就是JDK中提供的各种功能的Java类。

Java API就是Java提供给我们使用的类,这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用。

我们可以通过查帮助文档来了解Java提供的API如何使用

2Object

Object是所有的父类,都直接或间接的继承了该类

构造方法:

public Object(); 只有这一种构造方法

子类的构造方法默认访问的是父类的无参构造方法

Object 类的成员方法

public int hashCode() // 返回对象的地址值。

返回该对象的哈希码值。默认情况下,该方法会根据对象的地址来计算。

不同对象的,hashCode()一般来说不会相同,但是,同一个对象的hashCode()值肯定相同

不是对象的实际地址值,可以理解为逻辑地址值

public final Class getClass() // 表示此对象运行时类的 Class 对象

可以通过Class类中的一个方法,获取对象的真实类的全名称

public String toString() // 该对象的字符串表示

以字符串形式显示该对象:getClass().getName() + ‘@‘ + Integer.toHexString(hashCode())

默认情况下:toString()没有意义,需要子类重写该方法。

// 输出该对象,会调用toString方法,然后进行输出。

public boolean equals(Object obj) // 指示其他某个对象是否与此对象相等

指示其他某个对象是否与此对象“相等”

默认情况下比较的是对象的引用是否相同

由于比较对象的引用没有意义,一般建议重写该方法

protected void finalize() //当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。

垃圾回收器不会马上回收垃圾,但是我们可以建议它尽快回收垃圾。(System.gc()方法)

主要针对堆内存

protected Object clone() // 此实例的一个副本。

创建并返回此对象的一个副本,这种克隆机制十分高效,而且二者之间完全隔离。

克隆和两个引用指向同一个对象的区别,克隆是将一个对象复制了一份,所有堆内存中有两个对象。引用:两个变量指向同一个对象地址。

Object类clone()方法虽然简单,易用,但仅仅是一种”浅克隆”,它只克隆该对象所有的Field值,不会。对引用类型的Field所引用的对象进行克隆。开发中,我们也可以实现对象的”深度克隆”。

 

3Scanner类概述及其构造方法

Scanner类概述:JDK5以后用于获取用户的键盘输入。

构造方法

public Scanner(InputStream source);

成员方法:

基本格式:hasNextXxx()判断下一个输入项是否为Xxx类型的数据,如果返回true,不是为false例外String类型,省掉Xxx或者说HasNext就是判断String类型的)

nextXxx()  获取下一个输入项。Xxx的含义和上个方法中的Xxx相同

默认情况下,Scanner使用空格,回车等作为分隔符

常用方法:

public int nextInt(); // 接收一个Int类型的数据

public String nextLine(); // 接收一行数据。用字符串进行返回。

问题

先nextInt()然后nextLine()的问题。

原因nextInt只接受整型值,而回车被nextLine接收了,解决办法,就是都以字符串进行接收。

4String

字符串是由多个字符组成的一串数据(字符序列)

字符串可以看成是字符数组

构造方法

public String()

public String(byte[] bytes)

public String(byte[] bytes,int offset,int length)

public String(char[] value)

public String(char[] value,int offset,int count)

public String(String original)

在实际开发中,字符串的操作是最常见的操作,没有之一。

Java没有内置的字符串类型,所以,就在Java类库中提供了一个类String 供我们来使用。

String 类代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。

注意:

String s = “helloworld”;

s也是一个对象。

String类的特点及面试题

字符串是常量,它的值在创建之后不能更改(字符串常量池:方法区)

String s = “hello”; s+=”world”, s的结构?

字符串直接复制的方式是先到字符串常量池中去找,如果有就直接返回,没有就创建并返回。

面试题

String s = new String(hello)String s = hello;的区别?

前者两个对象,后者一个对象。

String类的判断功能

  boolean equals(Object obj) // 比较字符串内容

boolean equalsIgnoreCase(String str)// 忽略写,比较字符串内容

boolean contains(String str) // 查找子串

boolean startsWith(String str) // 是不是以参数开头的字符串

boolean endsWith(String str) // 是不是以参数结尾的字符串

boolean isEmpty() // 是不是空字符串; 当且仅当 length() 0 时返回 true

int length() // 获取长度

char charAt(int index) // 将对于下的字符进行返回。

int indexOf(int ch) // 找字符表所对应的字符,找到返回下,找不到返回-1

int indexOf(String str) //找字符串对应的下标,找不到-1

int indexOf(int ch,int fromIndex) // 找什么,从什么地方开始找。

int indexOf(String str,int fromIndex) // 找什么字符串,从什么地方开始找。

String substring(int start) // 从哪里开始截取

String substring(int start,int end) // 从哪里开始,到哪里结束。截取

byte[] getBytes() //String转换为byte[]

char[] toCharArray() //String转换为char[]

static String valueOf(char[] chs) //char[]转换为String

static String valueOf(int i) //int转为为String

String toLowerCase() //将字符串转为为小写

String toUpperCase() //将字符串转为为大写。

String concat(String str) //字符串拼接

String replace(char old,char new) //替换字符串中的字符

String replace(String old,String new) // 替换字符串中的字符串

String trim() // 去除前后空格

int compareTo(String str) // 比较字符串大

int compareToIgnoreCase(String str) // 忽略小写,比较字符串大

 

java 常用ii

1StringBuffer概述

我们如果对字符串进行拼接操作,每次拼接,都会构建一个新的String对象,既耗时,又浪费空间。而StringBuffer就可以解决这个问题

线程安全的可变字符串序列

StringStringBuffer的区别?

String长度不可变,存在于方法区中的常量池中。

StringBuffer:线程安全可变字符序列。

构造方法:

  public StringBuffer()

public StringBuffer(int capacity)

public StringBuffer(String str)

// 设置容量

// 设置负数,默认什么都不干。

// 设置正数,小于等于原来容量,容量不变

// 设置正数,大于原来容量,小于等于原来容量2倍加2,设置为原来容量2倍加2

// 设置正数,大于等于原来容量2倍加2,设置为该正数

public void ensureCapacity(int minimumCapacity)

// 根据长度,设置容量。尝试减少用于字符序列的存储空间。

public synchronized void trimToSize()

2StringBuffer类的成员方法

添加功能:

public StringBuffer append(String str)

字符串表示形式追加到序列

public StringBuffer insert(int offset,String str)

指定位置,字符串表示形式插入到序列

删除功能

public StringBuffer deleteCharAt(int index)

移除此序列指定位置的 char。此序列将缩短一个 char长度,容量不

public StringBuffer delete(int start,int end)

移除此序列的子字符串中的字符。该子字符串从指定的 start 处开始,一直到索引 end - 1 处的字符,如果不存在这种字符,则一直到序列尾部。如果 start 等于 end,则不发生任何更改。

替换功能:

public StringBuffer replace(int start,int end,String str)

从start开始,到end-1结束的字符串被str替换。

反转功能:

public StringBuffer reverse()

字符串进行反转,改变原串

// 截取 将StringBuffer中指定位置,进行截取,并且以String类型进行返回。原StringBuffer没有发生变化

public String substring(int start)

public String substring(int start,int end)

3Arrays类概述

针对数组进行操作的工具类。

提供了排序,查找等功能

成员方法

public static String toString(int[] a) // 数组字符串形式返回。要求懂源代码

public static void sort(int[] a) // 排序采用快速排序

public static int binarySearch(int[] a,int key) // 查找采用二分查找。要求懂源代码

4基本类型包装类概述:

将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据。

常用的操作之一:用于基本数据类型与字符串之间的转换。

基本类型和包装类的对应

Byte, byte

Short short

Integer int

Long long

Float float

Double double

Character char

Boolean Boolean

Integer类概述及其构造方法

Integer 类在对象中包装了一个基本类型 int 的值

该类提供了多个方法,能在 int 类型和 String 类型之间互相转换,还提供了处理 int 类型时非常有用的其他一些常量和方法

构造方法

public Integer(int value)

public Integer(String s)

成员方法

int类型和String类型的相互转换

int – String

String – int

public int intValue() // integer对象转换为int

public static int parseInt(String s) // 将字符串转换为int

public static String toString(int i) // 将int转换为String

public static Integer valueOf(int i) // int转为Integer

public static Integer valueOf(String s) // 将String转换为integer

常用的基本进制转换

public static String toBinaryString(int i) // int类型的数字,转为二进制的数

public static String toOctalString(int i) // int类型的数字,转为八进制

public static String toHexString(int i) // int类中的数字,转换为十六进制

十进制到其他进制

public static String toString(int i,int radix) // 将十进制转到其他进制。第二个参数指定进制。基数。

其他进制到十进制

public static int parseInt(String s,int radix) // 将其他进制转换为十进制。第二个参数表示基数。

JDK5的新特性:

Integer x = new Integer(4); // 可以直接写成

Integer x = 4; // 自动装箱。

x  =  x + 5; //自动拆箱。通过intValue方法。

需要注意:

使用时,Integer x = null; 上面代码会报错。NullPointerException

Integer i = 1;

i += 1;

做了哪些事情:将1变为Integer类型,赋值给ii+=1相等于i=i+1,将Integeri转换为int1,做加法,然后将在转换为Integer类型。

Integer.valueOf() // -128-+127之间,直接反回integer对象。否则,new一个新的Integer对象。

Character类概述及其构造方法

Character类概述

Character 类在对象中包装一个基本类型 char 的值

此外,该类提供了几种方法,以确定字符的类别(小写字母,数字,等等),并将字符从大写转换成小写,反之亦然

构造方法

public Character(char value)

  成员方法

public static boolean isUpperCase(char ch) // 是不是大写

public static boolean isLowerCase(char ch) // 是不是小写

public static boolean isDigit(char ch) // 是不是数字

public static char toUpperCase(char ch) // 转换为大写

public static char toLowerCase(char ch) // 转换为小写

常用类(三)

1、正则表达式

正则表达式:是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。其实就是一种规则。有自己特殊的应用。

举例:校验qq号码

15-15数字

2、0不能

正则表达式的组成规则

常见组成规则

字符

字符类

预定义字符类

边界匹配器

数量词

Pattern 规则字符在java.util.regex Pattern类中

正则表达式的应用

判断功能

public boolean matches(String regex)

分割功能

public String[] split(String regex)

替换功能

public String replaceAll(String regex,String replacement)

获取功能

PatternMatcher类的使用

2Math

Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。

成员方法

public static int abs(int a) // 取绝对值

public static double ceil(double a) // 向上取整

public static double floor(double a) // 向下取整

public static int max(int a,int b) min自学 // 取最大值/最小

public static double pow(double a,double b) // a^b

public static double random() // 获取[0,1)

public static int round(float a) 参数为double的自学 // 四舍五入

public static double sqrt(double a) // 平方根

3Random

Random类概述

此类用于产生随机数

如果用相同的种子创建两个 Random 实例,则对每个实例进行相同的方法调用序列,它们将生成并返回相同的数字序列。

构造方法

public Random()

public Random(long seed)

成员方法:

public int nextInt() 生成int范围内的随机数

public int nextInt(int n) 生成0参数之间的随机数

4System

System类概述

System 类包含一些有用的类字段和方法。它不能被实例化。

成员方法

public static void gc() //  运行垃圾回收器

public static void exit(int status) // 终止虚拟机

public static long currentTimeMillis() //当前时间与协调世界时 1970 1 1 日午夜之间的时间差(以毫秒为单位测量)。

public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length) //复制数组

1、原数组

2、原数组开始

3、目标数组(接收数据的数组

4、从目标数组哪开始

5、复制几个

复制的数量必须小于原数组长度-开始位置(复制的数量小于可以复制的数量

5BigInteger

BigInteger类概述

可以让超过Integer范围内的数据进行运算

BigInteger 理论上没有位数限制,受限于程序可用的内存。

构造方法:

public BigInteger(String val) // 获取大整型对象

成员方法:

public BigInteger add(BigInteger val) // +

public BigInteger subtract(BigInteger val) // -

public BigInteger multiply(BigInteger val) // *

public BigInteger divide(BigInteger val) // /

public BigInteger[] divideAndRemainder(BigInteger val) // / %

6BigDecimal

由于在运算的时候,float类型和double很容易丢失精度,演示案例。所以,为了能精确的表示、计算浮点数,Java提供了BigDecimal

BigDecimal类概述

不可变的、任意精度的有符号十进制数。

构造方法

public BigDecimal(String val)

成员方法:

public BigDecimal add(BigDecimal augend)

public BigDecimal subtract(BigDecimal subtrahend)

public BigDecimal multiply(BigDecimal multiplicand)

public BigDecimal divide(BigDecimal divisor)

除数 保留位数 舍入方式

public BigDecimal divide(BigDecimal divisor,int scale,int roundingMode)

7Date

Date类概述:类 Date 表示特定的瞬间,精确到毫秒。

构造方法

public Date()

public Date(long date)

成员方法

public long getTime()

public void setTime(long time)

8DateFormat抽象

DateFormat类概述

DateFormat 是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间。是抽象类,所以使用其子类SimpleDateFormat

SimpleDateFormat :格式处理日期

构造方法:

public SimpleDateFormat() // 获取SimpleDateFormat对象不设置日期格式

public SimpleDateFormat(String pattern) // 设置日期格式。

成员方法

public final String format(Date date) // 将日期对象,转换为日期字符串

public Date parse(String source) // 将日期字符串,转换为日期对象

9Runtime

每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。 应用程序不能创建自己的 Runtime 类实例

Process exec(String command)  // 执行dos命令

 

集合一

1、集合概述

为什么出现集合

集合存在是为了完善数组的功能

数组和集合类同是容器,有何不同?

数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储同一数据类型,集合只能存在引用对象。

集合类的特点:

集合只用于存储对象,集合长度可变集合可以存储不同类型的对象

2Collection接口概述

collection概述

Collection 层次结构中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。

collection接口成员方法

boolean add(E e) // 添加元素,成功返回true失败返回false

boolean remove(Object o) // remove移除指定元素,成功返回true否则false

void clear() // 清除所有元素

boolean contains(Object o) // 是否包含元素包含true,否则为false

boolean isEmpty() // 是否为空,为空返回true,否则false

int size() // 返回集合长度。

boolean addAll(Collection c) // 添加所有元素

boolean removeAll(Collection c) // 移除所有元素

boolean containsAll(Collection c) // 判断参数集合是否被包含

boolean retainAll(Collection c) // 将参数以外集合的元素移除

Object[] toArray()

把集合转成数组,可以实现集合的遍历

Iterator iterator()

迭代器,集合的专用遍历方式

3Iterator接口

Iterator接口概述

collection 进行迭代的迭代器

依赖于集合而存在

成员方法:

boolean hasNext() // 判断是否存在下一个元素

E next() // 返回下一个元素

4List接口概述

List接口概述:

有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

set 不同,list列表通常允许重复的元素。

List案例

存储字符串并遍历

存储自定义对象并遍历

List接口成员方法

void add(int index,E element) // 给指定的位置加入元素

E remove(int index) // 删除指定元素

E get(int index) // 获取指定下标的元素

E set(int index,E element) // 设置指定下标的元素

ListIterator listIterator() // 获取迭代器进行遍历

5ListIterator接口的成员方法

boolean hasPrevious()

E previous()

6常见数据结构

栈 先入后出,后入先出

队列 先入先出,后入后出

数组 方便查找,不方便增删

链表 方便增删,不方便查找

哈希表

7ArrayList类概述及使用

ArrayList类概述

底层数据结构是数组,查询快,增删慢

线程不安全,效率高

ArrayList案例

存储字符串并遍历

存储自定义对象并遍历

 

8Vector类概述及使用

Vector类概述

底层数据结构是数组,查询快,增删慢

线程安全,效率低

Vector类特有功能

public void addElement(E obj) 添加元素

public E elementAt(int index) 获取指定元素

public Enumeration elements() 遍历

Vector案例

存储字符串并遍历

存储自定义对象并遍历

9LinkedList类概述及使用

LinkedList类概述

底层数据结构是链表,查询慢,增删快

线程不安全,效率高

LinkedList类特有功能

public void addFirst(E e)addLast(E e)

public E getFirst()getLast()

public E removeFirst()public E removeLast()

练习重点collectionlistArrayListvectorLinkedList,遍历有三种方式,迭代器,for,增强for

10、泛型

为什么会有泛型呢?

早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。也就存在这隐患,所以Java提供了泛型来解决这个安全问题。

 

泛型应用:

泛型的作用位置类,接口,方法

泛型类:

泛型定义到上的类称为泛型

格式public class 类名<泛型类型, 泛型类型, … 泛型类型>

注意:泛型类必须是引用类型

泛型接口:

泛型定义到接口

格式public interface 接口<泛型, 泛型>

泛型方法

把泛型定义到方法

格式:public <泛型类型>  返回值类型 方法名称(泛型类型) {}

泛型最重要的作用,规定参数以及返回值类型。

 

泛型高级(通配符

泛型通配符<?>

任意类型,如果没有明确,那么就是Object以及任意的Java类了

? extends E

向下限定,E及其子类

? super E

向上限定,E及其父类

集合

1增强for概述及使用

增强for概述

简化数组和Collection集合的遍历

格式

for(元素数据类型 变量 : 数组或者collection集合) {

使用变量即可,该变量就是元素;

}

好处:简化遍历。缺点是没有索引。

注意事项增强for的目标必须不会null

前面的集合遍历用增强for改进。

2、静态导入概述及使用

静态导入概述

格式:import static 包名….类名.方法名;

可以直接导入到方法的级别

注意事项

方法必须是静态的

如果有多个同名的静态方法,不知道使用谁?这个时候要使用,必须加前缀。由此可见,意义不大,所以一般不用,但是要能看懂。

3、可变参数方法概述及使用

可变参数概述

定义方法的时候不知道该定义多少个参数

格式:

修饰符 返回值类型 方法名(数据类型变量名) {}

注意:这里的变量其实是一个数组;如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个。

4Set接口概述

一个不包含重复元素的集合collection

存储字符串并遍历

存储自定义对象并遍历

5HashSet类概述

hashset类概述:

不保证set的迭代顺序

特别是它不保证该顺序恒久不变

加入的顺序与输出的顺序无关

HashSet如果保证元素唯一性:

底层数据结构是哈希表(元素是链表的数组)

哈希表依赖于哈希值存储

添加功能底层依赖两个方法:

int hashCode()

boolean equals(Object obj)

6LinkedHashSet类概述:

LinkedHashSet类概述

元素有序唯一

由链表保证元素有序

由哈希表保证元素唯一

 

集合

1Map概述:

Map接口概述:将键映射到值的对象。一个映射不能包含重复的键,每一个键最只能映射到一个值

Map接口和collection接口的不同:Map是双列的,collection是单列的;Map的键唯一,collection的子体系set也是唯一的;Map集合的数据结构针对键有效,跟值无关

Map接口成员方法:

V put(K key,V value) // 添加数据

V remove(Object key) // 删除数据

void clear() // 清除所有数据

boolean containsKey(Object key) // 集合中是否包含这个键

boolean containsValue(Object value) // 集合中是否包含这个

boolean isEmpty() // 是否为空

int size() // 键值对的对数。

V get(Object key) // 获取value通过key

Set<K> keySet() // 返回所有键组成set集合

Collection<V> values() // 返回所有值组成collection集合

Set<Map.Entry<K,V>> entrySet() // 键值对组成set集合。

遍历map

两种方式:

获取的键,遍历键,通过键获取值

获取键值对对象Set,通过遍历键值对对象Set,获取每一个键值对对象,键值对对象获取键和值。

2HashMap类概述

键是哈希表结构,可以保证键的唯一性。key是无序的。

HashMap案例

HashMap<String,String>

HashMap<Integer,String>

HashMap<String,Student>

HashMap<Student,String>

3LinkedHashMap类概述

Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。有序

4TreeMap类概述

TreeMap类概述

键是红黑树结构,可以保证键的排序和唯一性

 

5collections概述和成员方法

针对集合操作的工具类

Collections成员方法

public static <T> void sort(List<T> list) // 排序

public static <T> int binarySearch(List<?> list,T key) // 二分查找

public static <T> T max(Collection<?> coll) // 获取最大值

public static void reverse(List<?> list) // 逆序

public static void shuffle(List<?> list) // 打乱集合内容

ExceptionFile

1、异常概述:

异常:异常就是java程序在运行过程中出现的错误。

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

我们见过的异常,角标越界异常,空指针异常

2、异常分类

 

ThrowableThrowable 类是 Java 语言中所有错误或异常的超类。只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。

ErrorError Throwable 的子类,用于指示合理的应用程序不应该试图捕获的严重问题。Error(错误)表示系统级的错误和程序不必处理的异常,是java运行环境中的内部错误或者硬件问题,比如,内存资源不足等,对于这种错误,程序基本无能为力,除了退出运行外别无选择。

Exception 类及其子类是 Throwable 的一种形式,它指出了合理的应用程序想要捕获的条件。

RuntimeException 是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。

 

程序的异常:Throwable

严重问题:Error

问题:Exception

编译器问题:不是RuntimeException的异常

运行期问题:RuntimeException

3异常处理

JVM默认处理方案:把异常的名称,错误原因及异常出现的位置等信息输出在了控制台

程序停止执行

自行处理方案:两种

方案:try…catch…finally

方案二:throws

try…catch处理方式:

一个异常处理方案:

try{

可能发生的异常代码

}catch(异常名 异常对象) {

捕捉到的异常对象

}finally {

无论异常如何处理,这里的代码必须执行。

}

A:try里面的代码越少越好,try中出现异常,异常代码后的代码,不会执行。

B:catch里面必须有内容,哪怕要给简单的提示

多个异常情况

平级情况

存在上下级的情况

JDK7的新特性及注意事项

try{

}catch(){

}catch(){

}

C:能明确的尽量明确,不要用大的来处理

D:平级关系的异常,谁先誰后没有关系,如果出现父子级关系,先子后父

Try{

}catch(异常名|异常名|异常名  变量){

}

缺点处理方式一致;异常之间必须是平级关系

编译时异常和运行时异常的区别:

Java中的异常被分为两大类:编译时异常和运行时异常。所有的RuntimeException类及其子类的实例被称为运行时异常,其他的异常就是编译时异常
编译时异常

Java程序必须显示处理,否则程序就会发生错误,无法通过编译

运行时异常

无需显示处理,也可以和编译时异常一样处理

4Throwable中的方法:

getMessage()

获取异常信息,返回字符串。

toString()

获取异常类名和异常信息,返回字符串。

printStackTrace()

获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void

printStackTrace(PrintStream s)

通常用该方法将异常内容保存在日志文件中,以便查阅。

5throws

定义功能方法时,需要把出现的问题暴露出来让调用者去处理。那么就通过throws在方法上标识。

如果本方法不需要解决此错误,就抛出异常

6throw

在功能方法内部出现某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出。

7throwsthrow的区别

throws

用在方法声明后面,跟的是异常类名

可以跟多个异常类名,用逗号隔开

表示抛出异常,由该方法的调用者来处理

throws表示出现异常的一种可能性,并不一定会发生这些异常

throw

用在方法体内,跟的是异常对象名

只能抛出一个异常对象名

表示抛出异常,由方法体内的语句处理

throw则是抛出了异常,执行throw则一定抛出了某种异常 

8、我们到底该如何处理异常呢

原则:如果该功能内部可以将问题处理,try,如果处理不了,交由调用者处理,这是用throws

区别:

后续程序需要继续运行就try

后续程序不需要继续运行就throws

举例:

感冒了就自己吃点药就好了,try

吃了好几天药都没好结果得了H7N9,那就的得throw到医院

如果医院没有特效药就变成Error

9finally的特点作用及面试题

finally的特点

finally控制的语句体一定会执行

特殊情况:在执行到finally之前jvm退出了(比如System.exit(0))

finally的作用

用于释放资源,在IO流操作和数据库操作中会见到

finally相关的面试题

final,finallyfinalize的区别

如果catch里面有return语句,请问finally的代码还会执行吗?如果会,请问是在return前还是return后。

finally必然在return 之前执行。

10、自定义异常

自定义异常

继承自Exception

继承自RuntimeException

异常注意事项:

子类覆盖父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)

如果父类抛出了多个异常,子类覆盖父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常

如果被覆盖的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws

11File

File概述:文件和目录路径名的抽象表示形式。

构造方法:

public File(String pathname)

public File(String parent,String child)

public File(File parent,String child)

成员方法:

创建功能:

public boolean createNewFile() // 根据file路径进行创建文件

public boolean mkdir() // 创建文件夹

public boolean mkdirs() // 创建多个子文件夹

删除功能:

public boolean delete() // 删除文件,或者目录。(只能删除最后一次,多级不能删除)

重命名

public boolean renameTo(File dest)

判断功能

public boolean isDirectory() // 判断是不是目录

public boolean isFile() // 判断是不是文件

public boolean exists() // 判断是不是存在

public boolean canRead() // 判断是否能读

public boolean canWrite() // 判断是否能修改,写操作

public boolean isHidden() // 是否为隐藏文件

基本获取功能

public String getAbsolutePath() // 文件绝对路径

public String getPath() // 文件路径

public String getName() // 文件名称

public long length() // 文件长度

public long lastModified() // 文件修改时间

高级获取功能

public String[] list() // 返回该目录下多有的文件,目录,名称字符串

public File[] listFiles() // 回该目录下多有的文件,目录,file对象

 

 

1IO流概述

IO流用来处理设备之间的数据传输

上传文件和下载文件

Java对数据的操作是通过流的方式

Java用于操作流的对象都在IO包中

IO流分类:

按照数据流向

输入流、读入数据 (针对于内存而言

输出写出数据

按照数据类型:

字节流

字符流

什么情况下使用哪种流

如果数据所在的文件通过windows自带的记事本打开并能读懂里面的内容,就用字符流。其他用字节流。如果不知道是什么文件,默认使用字节流。

IO常用基类

字节流的抽象基类:InputStreamOutputStream,

字符流的抽象基类:ReaderWriter

注意由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀

InputStream的子类FileInputStream

Reader的子类FileReader

2字节流写入数据

写入数据将数据从内存写入到硬盘。OutputStream

FileOutputStream

一个文本文件中写入一句话:“HelloWorld”

构造方法:

FileOutputStream(File file)

FileOutputStream(String name)

成员方法:

public void write(int b) // 写入一个int类型的数据

public void write(byte[] b) // 写入一个byte[] 类型的数据

public void write(byte[] b,int off,int len) // 写入一个byte[]类型数据,这里指定开始位置,和长度。

数据写成功后,为什么要close()? 释放资源

如何实现数据的换行?

Windows:\r\n

Linux:\n

Mac:\r

如何实现数据的追加写入?

构造方法:FileOutputStream(String name, boolean append) // 参数二,为true追加到末尾

3、字节流读取数据

其他位置的数据读入到内存。InputStream

FileInputStream 读入文件

刚才写的数据读显示到控制

FileInputStream构造方法

FileInputStream(File file)

FileInputStream(String name)

成员方法:

public int read()

public int read(byte[] b)

4字节缓冲

BufferedOutputStream // 需要OutputStream

BufferedInputStream // 需要 InputStream

IO

1转换流(OutputStreamWriterInputStreamReader

为什么是转换字符流由字节流转换而来所以outputStreamWriter称为转换流。

字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。所以字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性比较好!如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好点。

OutputStreamWriter

构造方法:

public OutputStreamWriter(OutputStream out) // 需要输出字节流

public OutputStreamWriter(OutputStream out,String charsetName) // 需要输出字节流编码方式

成员方法:

public void write(int c)

public void write(char[] cbuf)

public void write(char[] cbuf,int off,int len)

public void write(String str)

public void write(String str,int off,int len)

字符流操作注意问题:

flush()的作用

flush()close()的区别

缓冲区中的数据保存直到缓冲区满后才写出,也可以使用flush方法将缓冲区中的数据强制写出或使用close()方法关闭流,关闭流之前,缓冲输出流将缓冲区数据一次性写出。flush ()和close()都使数据强制写出,所以两种结果是一样的,如果都不写的话,会发现不能成功写出。

InputStreamReader

构造方法:

public InputStreamReader(InputStream in) // 需要输出字节流

public InputStreamReader(InputStream in,String charsetName) // 需要输出字节流编码方式

成员方法:

public int read()

public int read(char[] cbuf)

 

字节流与字符流的区别

字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候是使用到缓冲区的,一个操作字符,一个操作字节

字节流在操作文件时,即使不关闭资源(close方法),文件也能输出,但是如果字符流不使用close方法的话,则不会输出任何内容,说明字符流用的是缓冲区,并且可以使用flush方法强制进行刷新缓冲区(即强制输出缓冲区内容),这时才能在不close的情况下输出内容

二者使用:如果有字符操作,用字符流,否则用字节流。

2、字符流

转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化我们的书写,转换流提供了对应的子类。

FileWriter 写出

FileReader 读入

FileWriter

构造方法

FileWriter(File file)
          根据给定的 File 对象构造一个 FileWriter 对象。

FileWriter(File file, boolean append)
          根据给定的 File 对象构造一个 FileWriter 对象。

FileWriter(FileDescriptor fd)
          构造与某个文件描述符相关联的 FileWriter 对象。

FileWriter(String fileName)
          根据给定的文件名构造一个 FileWriter 对象。

FileWriter(String fileName, boolean append)

成员方法与OutputStreamWriter相同

FileReader

构造方法:

FileReader(File file)
          在给定从中读取数据的 File 的情况下创建一个新 FileReader。

FileReader(FileDescriptor fd)
          在给定从中读取数据的 FileDescriptor 的情况下创建一个新 FileReader。

FileReader(String fileName)
          在给定从中读取数据的文件名的情况下创建一个新 FileReader。

成员方法与OutputStreamReader相同

3、字符缓冲流

BufferedWriter

BufferedReader

特殊功能

BufferedWriter

void newLine() // 写出一个换行符

BufferedReader

String readLine() // 读入一行数据

BufferedWriter

构造方法:

BufferedWriter(Writer out)
          创建一个使用默认大小输出缓冲区的缓冲字符输出流。

BufferedWriter(Writer out, int sz)
          创建一个使用给定大小输出缓冲区的新缓冲字符输出流。

成员方法:

void newLine() // 写出一个换行符

BufferedReader

构造方法:

BufferedReader(Reader in)
          创建一个使用默认大小输入缓冲区的缓冲字符输入流。

BufferedReader(Reader in, int sz)
          创建一个使用指定大小输入缓冲区的缓冲字符输入流。

成员方法:

String readLine() // 读入一行数据

4、小结

字节流

字节输入流  InputStream

FileInputStream

BufferedInputStream

字节输出流  OutputStream

FileOutputStream

BufferedOutputStream

字符流

字符输入流  Reader

InputStreamReaderFileReader

BufferedReader

字符输出流  Writer

OutputStreamWriterFileWriter

BufferedWriter

5、对象序列化

概念

序列化:把Java对象转换为字节序列的过程。

反序列化:把字节序列恢复为Java对象的过程。

对象的序列化主要有两种用途:

1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;

2) 在网络上传送对象的字节序列。

ObjectOutputStream

代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。只有实现了SerializableExternalizable接口的类的对象才能被序列化。

概述ObjectOutputStream Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。

代码样例

FileOutputStream fos = new FileOutputStream("t.tmp");

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeInt(12345);

oos.writeObject("Today");

oos.writeObject(new Date());

oos.close();

ObjectInputStream

代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。

ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。

代码样例:

FileInputStream fis = new FileInputStream("t.tmp");

ObjectInputStream ois = new ObjectInputStream(fis);

int i = ois.readInt();

String today = (String) ois.readObject();

Date date = (Date) ois.readObject();

ois.close();

多线程

1、多线程概述

进程正在运行的程序,是系统进行资源分配和调用的独立单位;每一个进程都有它自己的内存空间和系统资源。

线程:是进程中的单个顺序控制流,是一条执行路径;一个进程如果只有一条执行路径,则称为单线程程序;一个进程如果有多条执行路径,则称为多线程程序。

线程是依赖于进程存在的。

多线程的作用不是提高执行速度,而是为了提高应用程序的使用率。而多线程却给了我们一个错觉:让我们认为多个线程是并发执行的。其实不是。

大家注意两个词汇的区别:并行和并发。

前者是逻辑上同时发生,指在某一个时间内同时运行多个程序。

后者是物理上同时发生,指在某一个时间点同时运行多个程序。

那么,我们能不能实现真正意义上的并发呢,是可以的,多个CPU就可以实现,不过你得知道如何调度和控制它们。

2java程序运行原理

java 命令会启动 java 虚拟机,启动 JVM,等于启动了一个应用程序,也就是启动了一个进程。该进程会自动启动一个 “主线程” ,然后主线程去调用某个类的 main 方法。所以 main方法运行在主线程中。在此之前的所有程序都是单线程的。

jvm虚拟机的启动是单线程的还是多线程的?

JVM启动至少启动了垃圾回收线程和主线程,所以是多线程的。

3多线程实现方式一

线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。

构造方法:选用无参构造

成员方法:

run() // 多线程执行内容

start() // 启动多线程,由虚拟机调用run()方法

为什么重写run方法

因为不是类中所有代码都需要被线程执行。所有Thread 类中run方法中的内容是需要被多线程执行的。

线程能不能多次启动:

多次启动会出现IllegalThreadStateException - 如果线程已经启动。

run()方法单独调用为什么是单线程的:

因为run()方法直接调用其实就相当于普通的方法调用,所以就是单线程的

run()start()方法的区别:

run(): 仅仅是封装被线程执行的方法,直接调用是普通方法

start(): 首先启动了线程,然后在由JVM去调用该线程的run()方法

成员方法:

public final String getName() // 获取线程名称

public final void setName(String name) // 设置线程名称

通过构造方法,设置线程名称

public static Thread currentThread() // 获取当前线程的引用

4、线程调度

假如我们的计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,线程只有得到 CPU时间片,也就是使用权,才可以执行指令。那么Java是如何对线程进行调用的呢?

线程有两种调度模型:

分时调度模型   所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片

抢占式调度模型   优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些。

 

Java使用的是抢占式调度模型

演示如何设置和获取线程优先级

public final int getPriority()

public final void setPriority(int newPriority)

优先级设置1-10值越小,优先级越小

Thread.MAX_PRIORITY

Thread.NORM_PRIORITY
Thread.MIN_PRIORITY

5线程控制

我们已经知道了线程的调度,接下来我们就可以使用如下方法对象线程进行控制

成员方法

线程休眠:public static void sleep(long millis)

线程加入,等待该线程终止:public final void join(),谁等待,当前线程!

线程礼让:public static void yield()

后台线程 守护线程:public final void setDaemon(booleanon)

守护线程:如果创建的线程没有显示调用此方法,这默认为用户线程。

线程划分为用户线程和后台(daemon)进程,setDaemon将线程设置为后台进程

setDaemon

需要在start方法调用之前使用

如果jvm中都是后台进程,当前jvm将exit。(随之而来的,所有的一切烟消云散,包括后台线程啦)

主线程结束后,用户线程将会继续运行;如果没有用户线程,都是后台进程的话,那么jvm结束

http://blog.csdn.net/m13666368773/article/details/7245570

中断线程:

public final void stop()

让线程停止,过时了,但是还可以使用。写程序运行十秒后停止,如果不停止强制停止

public void interrupt()

让线程停止,过时了,但是还可以使用。写程序运行十秒后停止,如果不停止强制停止

6、线程生命周期

 

新建 -- 就绪 -- 运行 -- 死亡

新建 -- 就绪 -- 运行 -- 阻塞 -- 就绪 -- 运行 -- 死亡

7、多线程实现方式

1、用类实现Runnable接口

2、将实现类的对象传入Thread的构造方法

实现接口方式的好处:

可以避免由于Java单继承带来的局限性。

适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码,数据有效分离,较好的体现了面向对象的设计思想。

8、练习电影院问题

1继承实现

某电影院目前正在上映贺岁大片,共有100张票,而它有3个售票窗口售票,请设计一个程序模拟该电影院售票。

继承Thread

继承Runnable类

出现负票原因:随机性和延迟导致的。线程安全问题在理想状态下,不容易出现,但一旦出现对软件的影响是非常大的。

2、解决线程安全问题的基本思想:

问题出现原因:

是否是多线程环境

是否有共享数据

是否有多条语句操作共享数据

如何解决多线程安全问题呢?

基本思想:让程序的环境没有安全问题

怎么实现呢?

把多个语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可。

同步代码块:

synchronized(对象){需要同步的代码;}

同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能。

访问同一个资源,多个代码使用同一把锁,有效多个程序使用多把锁,锁不住

方法的锁对象是当前对象(this

静态锁方法的锁对象是该当前类的class对象

多线程2

面试题:

1:多线程有几种实现方案,分别是哪几种?

两种。

 

继承Thread

实现Runnable接口

 

2:启动一个线程是run()还是start()?它们的区别?

start();

 

run():封装了被线程执行的代码,直接调用仅仅是普通方法的调用

start():启动线程,并由JVM自动调用run()方法

 

3:sleep()wait()方法的区别

sleep():必须指时间;不释放锁。

wait():可以不指定时间,也可以指定时间;释放锁。

http://www.cnblogs.com/hongten/p/hongten_java_sleep_wait.html

 

4:为什么wait(),notify(),notifyAll()等方法都定义在Object类中

因为这些方法的调用是依赖于锁对象的,而同步代码块的锁对象是任意锁。

Object代码任意的对象,所以,定义在这里面。

 

5:线程的生命周期图

新建 -- 就绪 -- 运行 -- 死亡

新建 -- 就绪 -- 运行 -- 阻塞 -- 就绪 -- 运行 -- 死亡

课件:

多线程引入

把备注部分的代码通过画图解释一下调用流程。这个程序只有一个执行流程,所以这样的程序就是单线程程序。

假如一个程序有多条执行流程,那么,该程序就是多线程程序。

接下来我们来看看到底什么是多线程

多线程概述

进程:

正在运行的程序,是系统进行资源分配和调用的独立单位。

每一个进程都有它自己的内存空间和系统资源。

线程:

是进程中的单个顺序控制流,是一条执行路径

一个进程如果只有一条执行路径,则称为单线程程序。

一个进程如果有多条执行路径,则称为多线程程序。

举例

扫雷游戏,迅雷下载等

1:要想说线程,首先必须得聊聊进程,因为线程是依赖于进程存在的。

2:那么,什么是进程呢?通过任务管理器我们就可以看到进程的存在。

给出一个概念:进程就是正在运行的程序,是系统进行资源分配和调用的独立单位。每一个进程都有它自己的内存空间和系统资源。

3:多进程有什么意义呢?

单进程计算机只能做一件事情。而我们现在的计算机都可以一边玩游戏(游戏进程),一边听音乐(音乐进程),所以我们常见的操作系统都是多进程操作系统。比如:WindowsMacLinux等,能在同一个时间段内执行多个任务。

对于单核计算机来讲,游戏进程和音乐进程是同时运行的吗?不是。

因为CPU在某个时间点上只能做一件事情,计算机是在游戏进程和音乐进程间做着频繁切换,且切换速度很快,所以,我们感觉游戏和音乐在同时进行,其实并不是同时执行的。

多进程的作用不是提高执行速度,而是提高CPU的使用率。

 

4:那么什么又是线程呢?

在一个进程内部又可以执行多个任务,而这每一个任务我们就可以看成是一个线程。线程是程序中单个顺序的控制流,是程序使用CPU的基本单位。

 

5:多线程有什么意义呢?

多线程的作用不是提高执行速度,而是为了提高应用程序的使用率。

而多线程却给了我们一个错觉:让我们认为多个线程是并发执行的。其实不是。

因为多个线程共享同一个进程的资源(堆内存和方法区),但是栈内存是独立的,一个线程一个栈。所以他们仍然是在抢CPU的资源执行。一个时间点上只有能有一个线程执行。而且谁抢到,这个不一定,所以,造成了线程运行的随机性。

 

6:那么什么又是并发呢?

大家注意两个词汇的区别:并行和并发。

前者是逻辑上同时发生,指在某一个时间内同时运行多个程序。

后者是物理上同时发生,指在某一个时间点同时运行多个程序。

那么,我们能不能实现真正意义上的并发呢,是可以的,多个CPU就可以实现,不过你得知道如何调度和控制它们。

7:那么,我们来举例说说什么是进程,什么是线程。

扫雷游戏,迅雷下载等。

 

 

Java程序运行原理

java 命令会启动 java 虚拟机,启动 JVM,等于启动了一个应用程序,也就是启动了一个进程。该进程会自动启动一个 “主线程” ,然后主线程去调用某个类的 main 方法。所以 main方法运行在主线程中。在此之前的所有程序都是单线程的。

思考:

jvm虚拟机的启动是单线程的还是多线程的?

1JVM启动至少启动了垃圾回收线程和主线程,所以是多线程的。

多线程的实现方案1

 

通过查看API来学习多线程程序的实现

参考Thread

继承Thread

步骤及代码演示

几个小问题

为什么要重写run()方法

启动线程使用的是那个方法

线程能不能多次启动

run()start()方法的区别

1、为什么要重写run方法,因为不是类中所有代码都需要被线程执行。所有Thread 类中run方法中的内容是需要被多线程执行的。

2run()方法为什么是单线程的呢?

    因为run()方法直接调用其实就相当于普通的方法调用,所以就是单线程的

 

3run():仅仅是封装被线程执行的方法,直接调用是普通方法

     strat():首先启动了线程,然后在由JVM去调用该线程的run()方法

 

如何获取和设置线程名称

Thread类的基本获取和设置方法

public final String getName()

public final void setName(String name)

其实通过构造方法也可以给线程起名字

思考:

如何获取main方法所在的线程名称呢?

public static Thread currentThread()

这样就可以获取任意方法所在的线程名称

线程调度:

假如我们的计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,线程只有得到 CPU时间片,也就是使用权,才可以执行指令。那么Java是如何对线程进行调用的呢?

线程有两种调度模型:

分时调度模型   所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片

抢占式调度模型   优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些。

Java使用的是抢占式调度模型。

演示如何设置和获取线程优先级

public final int getPriority()

public final void setPriority(int newPriority)

线程控制:

我们已经知道了线程的调度,接下来我们就可以使用如下方法对象线程进行控制

线程休眠

public static void sleep(long millis)

线程加入,等待该线程终止

public final void join()

线程礼让

public static void yield()

后台线程 守护线程

public final void setDaemon(booleanon)

中断线程

public final void stop()

public void interrupt()

备注:

1sleep() 休眠单位毫秒

2join()线程加入A.join,在API中的解释是,堵塞当前线程B,直到A执行完毕并死掉,再执行B

3yield()礼让A.yieldA让出位置,给B执行,B执行结束A再执行。跟join意思正好相反!

4setDaemon(boolean) 守护线程、后台进程

如果创建的线程没有显示调用此方法,这默认为用户线程。

setDaemon需要在start方法调用之前使用

线程划分为用户线程和后台(daemon)进程,setDaemon将线程设置为后台进程

如果jvm中都是后台进程,当前jvmexit。(随之而来的,所有的一切烟消云散,包括后台线程啦)

主线程结束后,用户线程将会继续运行;如果没有用户线程,都是后台进程的话,那么jvm结束

http://blog.csdn.net/m13666368773/article/details/7245570

5stop()让线程停止,过时了,但是还可以使用。写程序运行十秒后停止,如果不停止强制停止

     interrupt()中断线程。 把线程的状态终止,并抛出一个InterruptedException

 

线程运行周期图:

 

 

备注

    新建 -- 就绪 -- 运行 -- 死亡

新建 -- 就绪 -- 运行 -- 阻塞 -- 就绪 -- 运行 -- 死亡

多线程的实现方案2

 

实现Runnable接口

如何获取线程名称

如何给线程设置名称

实现接口方式的好处

可以避免由于Java单继承带来的局限性。

适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码,数据有效分离,较好的体现了面向对象的设计思想。

 

线程练习:电影院买票

需求:

某电影院目前正在上映贺岁大片,共有100张票,而它有3个售票窗口售票,请设计一个程序模拟该电影院售票。

继承Thread

备注:、1票数定义到方法内

2、票数定义到成员变量

3、票数定义到静态成员变量

关于电影院卖票程序的思考

我们前面讲解过电影院售票程序,从表面上看不出什么问题,但是在真实生活中,售票时网络是不能实时传输的,总是存在延迟的情况,所以,在出售一张票以后,需要一点时间的延迟

改实现接口方式的卖票程序

每次卖票延迟100毫秒

改进后的电影院售票出现问题

 

问题

相同的票出现多次

CPU的一次操作必须是原子性的(这里的原子操作指那些内容?)

还出现了负数的票

随机性和延迟导致的

 

注意

线程安全问题在理想状态下,不容易出现,但一旦出现对软件的影响是非常大的。

 

解决线程安全问题的基本思想

 

首先想为什么出现问题?(也是我们判断是否有问题的标准)

是否是多线程环境

是否有共享数据

是否有多条语句操作共享数据

如何解决多线程安全问题呢?

基本思想:让程序没有安全问题的环境。

怎么实现呢?

把多个语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可。

 

解决线程安全问题实现

 

同步代码块

格式:

synchronized(对象){需要同步的代码;}

同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能。

同步代码块的对象可以是哪些呢?

 

备注:同步代码块的锁对象是谁呢?

任意对象。

同步方法的格式及锁对象问题?

把同步关键字加在方法上。

同步方法是谁呢?

 this

 C:静态方法及锁对象问题?

 静态方法的锁对象是谁呢?

 类的字节码文件对象。(反射会讲)

同步的特点

同步的前提

多个线程

多个线程使用的是同一个锁对象

同步的好处

同步的出现解决了多线程的安全问题。

同步的弊端

当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。

 

 

 

死锁问题

同步弊端

效率低

如果出现了同步嵌套,就容易产生死锁问题

死锁问题及其代码

是指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待现象

车辆问题:

1、第一辆车南、北各位同一把锁。

将南加锁,走南,

将北加锁,走北

2、第二辆车

将北加锁,走北

将南加锁,走南,

线程间通信

针对同一个资源的操作有不同种类的线程

举例:包子,一边做,一边吃。

 

通过设置线程(生产者)和获取线程(消费者)针对同一个吃包子事件阐述

 

 

1、准备第一个类笼,里面用来存放包子,需要两个成员属性,包子名字,以及有没有包子

2、做包子类:

死循环(true// 往死了做

先判断有没有包子?

如果没有包子,加锁。做包子

3、吃包子类:

死循环(true// 往死了吃

先判断有没有包子?

如果有包子,加锁,吃包子。

4、测试类:

定义一个笼对象

一个做包子的,

一个吃包子的

同时启动,

一定时间后,同时停止

 

线程的状态转换图

 

 

网络编程

1、网络编程概述

计算机网络:是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。

网络编程:就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。

2网络模型

计算机网络之间以何种规则进行通信,就是网络模型研究问题。

网络模型一般是指

OSIOpen System Interconnection开放系统互连)参考模型(七层模型)

TCP/IP参考模型

 

3网络通信三个要素

IP地址:InetAddress

网络中设备的标识,不易记忆,可用主机名

端口号:

用于标识进程的逻辑地址,不同进程的标识

传输协议:通讯的规则常见协议:TCPUDP

4IP地址

要想让网络中的计算机能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接受数据的计算机和识别发送的计算机,在TCP/IP协议中,这个标识号就是IP地址。

那么,我们如果获取和操作IP地址呢?为了方便我们对IP地址的获取和操作,java提供了一个类InetAddress供我们使用。

5InetAddress的使用

没有构造方法,那么如何使类提供的功能呢?

InetAddress.getByName("PC201511270151");

InetAddress.getByAddress(bytes);

InetAddress.getLocalHost();

可以通过类的静态方法进行调用

成员方法:

getHostAddress() // 获取IP地址

getHostName() // 获取主机名称 可能不成功

java.net.InetAddress类的getHostName方法用来获取某一IP地址的主机名。返回结果:此IP地址的主机名;如果安全检查不允许操作,则返回IP地址的文本表示形式。 

6端口号

物理端口 网卡口

逻辑端口 我们指的就是逻辑端口

每个网络程序都会至少有一个逻辑端口

用于标识进程的逻辑地址,不同进程的标识

有效端口:0~65535,其中0~1024系统使用或保留端口。

通过360可以查看端口号-工具-流量防火墙-网络连接

7协议UDPTCP

UDP将数据源和目的封装成数据包中,不需要建立连接;每个数据报的大小在限制在64k;因无连接,是不可靠协议;不需要建立连接,速度快.

TCP: 建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手完成连接,是可靠协议;必须建立连接,效率会稍低.

udp:

面向无连接。

不可靠。

速度快。

将数据封包传输,数据包最大64k。

举例:

聊天留言,在线视频,视频会议,发短信,邮局包裹。

tcp:

面向连接。

安全可靠

效率稍低。

通过三次握手确保连接的建立。

举例:

下载,打电话,QQ聊天(你在线吗,在线,就回应下,就开始聊天了)

8Socket套接字TCP

Socket套接字:网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。

Socket原理机制:

通信的两端都有Socket

网络通信其实就是Socket间的通信。

数据在两个Socket间通过IO传输。

9UDP传输

DatagramSocketDatagramPacket

建立发送端,接收端

建立数据包

调用Socket的发送接收方法方法

关闭Socket

发送端与接收端是两个独立的运行程序

1UDP传输——发送端:

1:建立udpsocket服务

2:将要发送的数据封装成数据包

3:通过udpsocket服务,将数据包发送出

4:关闭资源

 

2UDP传输——接收端

建立udpsocket服务.

通过receive方法接收数据

将收到的数据存储到数据包对象中

通过数据包对象的完成对接收到数据进行解析.功能来

可以对资源进行关闭

 

10TCP传输

SocketServerSocket

建立客户端和服务器端

建立连接后,通过Socket中的IO流进行数据的传输

关闭socket

同样,客户端与服务器端是两个独立的应用程序。

 

1TCP传输——客户端

1:建立客户端的Socket服务,并明确要连接的服务器。

2:如果连接建立成功,就表明,已经建立了数据传输的通道.就可以在该通道通过IO进行数据的读取和写入.该通道称为Socket,Socket流中既有读取流,也有写入流.

3:通过Socket对象的方法,可以获取这两个流

4:通过流的对象可以对数据进行传输

5:如果传输数据完毕,关闭资源

 

2TCP传输——服务器

1:建立服务器端的socket服务,需要一个端口

2:服务端没有直接流的操作,而是通过accept方法获取客户端对象,在通过获取到的客户端对象的流和客户端进行通信

3:通过客户端的获取流对象的方法,读取数据或者写入数据

4:如果服务完成,需要关闭客户端,然后关闭服务器,但是,一般会关闭客户端,不会关闭服务器,因为服务端是一直提供服务的

 

GUI

1GUI图像用户界面

GUI

Graphical User Interface(图形用户接口)

用图形的方式,来显示计算机操作的界面,这样更方便更直观。

JavaGUI提供的对象都存在java.Awtjavax.Swing两个包中。

CLI

Command line User Interface (命令行用户接口)

就是常见的Dos命令行操作。

需要记忆一些常用的命令,操作不直观。

举例创建文件夹,或删除文件夹。

2awtswing包的概述

java.awt:Abstract Window ToolKit (抽象窗口工具包),需要调用本地系统方法实现功能。属重量级控件。

javax.swing:在AWT的基础上,建立的一套图形界面系统,其中提供了更多的组件,而且完全由Java实现。增强了移植性,属轻量级控件。

3、继承体系图

 

Container:为容器,是一个特殊的组件,该组件中可以通过add方法添加其他组件进来。

4GUI第一个案例

Frame

Frame  f = new Frame(“my window”);

f.setLayout(new FlowLayout()); // 设置布局样式

f.setSize(300,400);//设置窗体大小

f.setLocation(300,200);//设置窗体出现在屏幕的位置

f.setVisible(true);

 

Frame.addWindowListener 关闭窗口 监听这个接口

f.dispose(); 调用关闭窗口

5、事件监听机制

事件监听机制流程

 

事件源:事件发生控件发生事件的地方。

事件:发生了什么事情。

事件处理:发生了事件应该怎么处理

事件监听器:用来监听事件的。

 

如何添加事件监听

1:确定事件源(容器或组件)

2:通过事件源对象的addXXXListener()方法将侦听器注册到该事件源上。

3:该方法中接收XXXListener的子类对象,或者XXXListener的子类XXXAdapter的子类对象。

4:一般用匿名内部类来表示。

在覆盖方法的时候,方法的参数一般是XXXEvent类型的变量接收。

5:事件触发后会把事件打包成对象传递给该变量。(其中包括事件源对象。通过getSource()或者,getComponent()获取。)

6JFrame

JFrame是Frame的子类,轻量级。

构造方法

public JFrame(String title);

public JFrame()

成员方法

setBounds 设置位置,大小

setLayout 设置布局

getContentPane 获取存储控件的容器

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) // 关闭

Container 容器

用于存放各种控件

 

JLabel

JTextField

 

JOptionPane 该对象用于弹框操作

7、菜单组件

MenuBar:菜单

Menu:菜单

MenuItem:选项

反射机制

1、反射概述:

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

获取Class对象的三种方式:

1、 Person p = new Person();

  Class c = p.getClass();

2、 Class c2 = Person.class; // 任意数据类型都具备一个class静态属性,看上去要比第一种方式简单.

3、 Class c3 = Class.forName("Person"); // 这里的字符串必须是类的全路径

// 将类名作为字符串传递给Class类中的静态方法forName即可

分析第三种和前两种的区别:
前两种你必须明确Person类型.

后者只需要知道类字符串形式,扩展性更强。按照配置文件加载就可以了。

2通过反射获取构造方法并使用

第一种方式获取对象:

Class——newInstance(); // 创建此 Class 对象所表示的类的一个新实例,该对象是通过无参构造new出来的。具有局限性,不能使用多构造。

第二种方式获取对象:(可以通过有参构造进行new

Constructor ——public T newInstance(Object ... initargs) // 创建带参构造所对应对象

public Constructor<?>[] getConstructors() // 获取所有公共构造方法

public Constructor<?>[] getDeclaredConstructors() // 获取所有构造方法

public Constructor<T> getConstructor(Class<?>... parameterTypes) // 获取指定构造方法

参数为,构造方法的参数类型的class

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) // 获取指定构造方法,(可以是任意权限的构造方法)

public void setAccessible(boolean flag) // 设置忽略权限拿构造不需要忽略权限,但是使用构造需要忽略权限

3通过反射获取属性并使用

获取属性:

public Field[] getFields() // 获取所有公共属性(字段,成员变量)

public Field[] getDeclaredFields() // 获取所有的属性

public Field getField(String name) // 获取指定公共属性

public Field getDeclaredField(String name) // 获取指定属性名称的属性对象

使用属性:

Field ——public void set(Object obj, Object value) // 给对象设置值

第一个参数:对象,第二个参数是

4通过反射获取方法使用

获取方法:

getMethods 获取所有公共方法 包含继承的方法

getDeclaredMethods 获取所有方法 不包含继承的方法

getMethod 获取指定公共方法

getDeclaredMethod 获取指定方法

强制访问,私有方法method.setAccessible(true);

使用方法:

invoke(Object obj, Object... args)

 

 

 

 

 

 

 

 

JavaSE基础笔记513