javaSE 笔记全!

2019年12月06日 阅读数:117
这篇文章主要向大家介绍javaSE 笔记全!,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

Java基础html


基本操做java

dos(Disk Operating System)命令行的简单操做mysql

dir(directory):列出当前目录下的文件及文件夹git

md(make directory):建立目录程序员

rd(remove directory):删除目录web

cd(Change directory):进入指定目录正则表达式

cd.. :退回到上一级目录算法

cd\ :退回到根目录sql

del(delete):删除文件编程

exit:退出dos命令行

echo: 建立文件 eg.  echo abc > 1.java 在当前目录下建立包含abc内容的1.java

edit:编辑文件


java 语言概述


SUN(Stanford University Network,斯坦福大学网络公司)1995年推出的一门高级编          

程语言。

是一种面向Internet的编程语言。

随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。

是简单易学,彻底面向对象,安全可靠,与平台无关的编程语言。


Java语言的三种技术架构

J2EE(Java 2 Platform Enterprise Edition)企业版

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

该技术体系中包含的技术如Servlet Jsp等,主要针对于Web应用程序开发。

J2SEJava 2 Platform Standard Edition)标准版

是为开发普通桌面和商务应用程序提供的解决方案。

该技术体系是其余二者的基础,能够完成一些桌面应用程序的开发。

好比Java版的扫雷。

J2ME(Java 2 Platform Micro Edition)小型版

是为开发电子消费产品和嵌入式设备提供的解决方案。

该技术体系主要应用于小型电子消费类产品,如手机中的应用程序等。

Java5.0版本后,改名为JAVAEE JAVASE JAVAME


Java语言的特色:跨平台性


什么是跨平台性?

经过Java语言编写的应用程序在不一样的系统平台上均可以运行。

原理是什么?

只要在须要运行java应用程序的操做系统上,先安装一Java虚拟机(JVM Java Virtual Machine)便可。

JVM来负责Java程序在该系统中的运行。


Java语言的特色:跨平台性(图解)


由于有了JVM,因此同一个Java程序在三个不一样的操做系统中均可以执行。这样就实现了Java程序的跨平台性。也称为Java具备良好的可移植性。

什么是JRE,JDK?

JRE(Java Runtime Environment Java运行环境)

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

JDK(Java Development Kit Java开发工具包)

JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包括了JRE。因此安装了JDK,就不用在单独安装JRE了。

其中的开发工具:编译工具(javac.exe) 打包工具(jar.exe)

简单而言:使用JDK开发完成的java程序,交给JRE去运行。


Java6.0 Platform


安装JDK


傻瓜式安装,下一步便可。

建议:安装路径不要有中文或者特殊符号 如空格等。

当提示安装JRE时,能够选择不安装。


配置环境变量path

path(1)


dos命令行中敲入javac,出现错误提示。



错误原理:当前执行的程序在当前目录下若是不存在,windows系统会在系统中已有的一个名为path的环境变量指定的目录中查找。若是尚未找到,就出现以上的错误提示。

因此进入到 jdk安装路径\bin目录下,执行javac。看到javac参数提示信息。


path(2)


每次执行java的工具都要进入到bin目录下, 是很是麻烦的。


可不能够在任何目录下均可以执行java的工具呢?

根据windows系统在查找可执行程序的原理, 能够java工具所在路径定义到path环境变量中,让系统帮咱们去找运行执行的程序。


path(3)


个人电脑--属性--高级--环境变量

编辑path环境变量,在变量值开始处加上java工具所在目录,后面用;和其余值分隔开便可。

从新打开DOS命令行,任意目录下敲入javac

若是出现javac 的参数信息,配置成功。

这种配置方式,一劳永逸。


path(4)


临时配置方式:经过dos命令中set命令完成 :用于查看本机的全部环境变量的信息。

set 变量名:查看具体一个环境变量的值。

set 变量名=:清空一个环境变量的值。

set 变量名=具体值:给指定变量定义具体值。


想要在原有环境变量值基础上添加新值呢?

首先,经过%变量名%操做符获取到原有环境变量的值。

而后加上新值后在定义给该变量名便可

举例:给path环境变量加入新值set path=新值;%path%


注意:这种配置方式只在当前dos窗口有效。窗口关闭,配置消失


配置技巧


为了避免由于jdk的目录或者目录名称的改变,而不断更改path的值,而致使对path变量值的误操做,能够经过如下技巧完成。新建立一个环境变量JAVA_HOME 记录住jdk的目录。


path中经过%%动态的获取JAVA_HOME的值便可。

JAVA_HOME=F:\jdk1.6.0_01

path=%JAVA_HOME%\bin;%path%

%path%:动态获取path环境变量的值。

%JAVA_HOME%:动态获取名称为JAVA_HOME环境变量的值。


java程序开发体验

Hello World

Java代码编写到扩展名为.java的文件中。

经过javac命令对该java文件进行编译

经过java命令对生成的class文件进行运行



步骤


步骤一:编写选择最简单的编辑器记事本。

敲入代码

class Demo

{}

将文件保存成Demo.java,这个文件是存放java代码的文件,称为源文件


编译


步骤二:编译有了java源文件,将其编译成JVM能够识别的文件

在该源文件目录下,经过javac编译工具对Demo.java文件进行编译。

若是程序没有错误,没有任何提示,但在当前目录下会出现一个Demo.class文件,该文件称为字节码文件,也是能够执行的java的程序。


运行


步骤三:运行

有了可执行的java程序(Demo.class字节码文件)

经过运行工具java.exe对字节码文件进行执行。

出现提示:缺乏一个名称为main的方法。


由于一个程序的执行须要一个起始点或者入口,因此在Demo类中的加入public static void main(String[] args){}

对修改后的Demo.java源文件须要从新编译,生成新的class文件后,在进行执行。

发现没有编译失败,但也没有任何效果,由于并无告诉JVM要帮咱们作什么事情,也就是没有能够具体执行的语句。

想要和JVM来个互动,只要在main方法中加入一句

System.out.println("hello java");在从新编译,运行便可.


配置classpath

classpath1


既然class文件(字节码文件)java的运行文件,可不能够实现, 在任意目录下均可以执行某一目录下的class文件呢?

根据path环境变量的原理,能够定义一个名为classpath环境变量,将要运行的class文件所在目录定义在该变量中。

例:set classpath=c:\

classpath变量值是java类文件的目录

path变量是windows程序文件的目录


classpath(2)


JVM查找类文件的顺序:

若是没有配置classpath环境变量,JVM只在当前目录下查找要运行的类文件。

若是配置了classpath环境,JVM先在classpath环境变量值的目录中查找要运行的类文件。

值的结尾处若是加上分号,那么JVMclasspath目录下没有找到要指定的类文件,会在当前目录下在查找一次。

值的结尾出若是没有分号,那么JVMclasspath目录下没有找到要指定的类文件,不会在当前目录下查找,即便当前目 录下有,也不会运行。


建议:配置classpath环境变量时,值的结尾处不要加分号,若是须要访问当前目录能够“.”表示


复习建议


JDK,JRE,JVM的特色。

环境变量的配置pathclasspath以及做用。

Java程序的编写,编译,运行步骤。

在配置,编写,编译,运行各个步骤中常 见的错误以及解决方法。


做业


简述JDK,JRE的区别。

简述pathclasspath环境变量的做用。

独立编写Hello World程序。

class的做用

main函数的做用

输出语句的做用


总结:



Java语言基础

Java关键字

关键字的定义和特色

定义:被Java语言赋予了特殊含义的单词

特色:关键字中全部字母都为小写

用于定义数据类型的关键字

class

interface

byte

short

int

long 

float

double

char

boolean

void





用于定义数据类型值的关键字

true

false

null



用于定义流程控制的关键字

if

else

switch

case

default

while

do

for

break

continue

return






用于定义访问权限修饰符的关键字

private

protected

public



用于定义类,函数,变量修饰符的关键字

abstract

final

static

synchronized


用于定义类与类之间关系的关键字

extends

implements




用于定义创建实例及引用实例,判断实例的关键字

new

this

super

instanceof


用于异常处理的关键字

try

catch

finally

throw

throws

用于的关键字

package

import




其余修饰符关键字

native

strictfp

transient

volatile

assert


Java标识符


在程序中自定义的一些名称。

26个英文字母大小写,数字:0-9 符号_ $ 组成

定义合法标识符规则:

数字不能够开头。

不能够使用关键字

Java中严格区分大小写

注意:在起名字的时,为了提升阅读性,要尽可能有意义。


Java中的名称规范

包名:多单词组成时全部字母都小写xxxyyyzzz

类名接口名:多单词组成时,全部单词的首字母大写XxxYyyZzz

变量名和函数名:多单词组成时,第一个单词首字母小写,第二个单词开始每一个单词首字母大写xxxYyyZzz

常量名:全部字母都大写。多单词时每一个单词用下划线链接。XXX_YYY_ZZZ


注释


用于注解说明解释程序的文字就是注释。

提升了代码的阅读性。

Java中的注释格式:

单行注释格式://注释文字

多行注释格式:/* 注释文字*/

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


对于单行和多行注释,被注释的文字,不会被JVM java虚拟机)解释执行

对于文档注释,是java特有的注释,其中注释内容能够JDK提供的工具javadoc 所解析,生成一套以网页文件形式体现的该程序的说明文档。

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

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

将本身的思想经过注释先整理出来,再用代码去体现

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


常量与变量

常量

常量表示不能改变的数值。

Java中常量的分类:


整型

整数,4个字节

长整型

整数8个字节。以L结尾。

单精度浮点数

小数,4个字节。以F结尾。

双精度浮点数

小数,8个字节

布尔

只有两个值,真(true)或假(false),1个字节。

字符

单个字符,2个字节。例如:'a', '', '5', '\u0026' , '\u0027'


在字符常量中,反斜杠(\是一个特殊的字符,它的做用是用来转义后面一个字符,这些字符一般是不可见的或者有特殊意义的。

'\r' 回车,回到一行的开始

'\n' 换行,换到下一行

'\t' 制表符,键盘上的Tab

'\b' 相似退格,键盘上的Backspace

以上字符都不可见,没法直接表示,因此用斜杠加上另一个字符来表示。


'\'' 单引号,Java代码中单引号表示字符的开始和结束,若是直接写程序会认为前两个是一对,报错。

'\"' 双引号,Java代码中双引号表示字符串的开始和结尾,若是要写一个包含双引号的字符串那么这个双引号也须要转义。

'\\' 斜杠,Java代码中的斜杠是转义字符,用来和后面一个字符配合使用,在真正须要用斜杠的时候那么就要用另外一个斜杠来转义。

以上字符都有特殊意义,没法直接表示,因此用斜杠加上另一个字符来表示。

字符串

由若干个字符组成的一串。能够是一个字符、多个字符、或者一个都没有。字符串没有固定大小。

null只有这一个值,用来表示一个引用为空。



进制转换

对于整数:java有三种表现形式。

十进制:0-9 ,满101.

八进制:0-7 ,满81. 0开头表示

十六进制:0-9A-F,满161. 0x开头表示


进制的基本转换十进制二进制互转十进制转成二进制除以2取余数

二进制转成十进制乘以2的幂数


十进制八进制互转

十进制十六进制互转


负数的二进制表现形式对应的正数二进制取反加1





变量


变量的概念

内存中的一个存储区域

该区域有本身的名称(变量名)和类型(数据类型)

该区域的数据能够在同一类型范围内不断变化

为何要定义变量:

用来不断的存放同一类型的常量,并能够重复使用

使用变量注意:

变量的做用范围(一对{}之间有效)

初始化值

定义变量的格式

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

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

理解:变量就如同数学中的未知数。


基本数据类型

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


整数默认:int 小数默认:double

a.基本数据类型: 8

整数

byte 1个字节,最小值:-128,最大值:127

short 2个字节,最小值:-32768,最大值:32767

int 4个字节,最小值:-2147483648,最大值:2147483647

long 8个字节,最小值:- 9223372036854775808,最大值:9223372036854775807

浮点数:

float 4个字节,最小值:1.4E-45最大值:3.4028235E38

double 8个字节,最小值:4.9E-324,最大值:1.7976931348623157E308

字符:

char 2个字节,最小值:0,最大值:65535

布尔:

boolean 1个字节,truefalse


b引用数据类型

类、接口、数组都是引用数据类型,除了8种基本数据类型,其余全部类型都是引用数据类型。



类型转换


自动类型转换(也叫隐式类型转换)

强制类型转换(也叫显式类型转换)

类型转换的原理

何时要用强制类型转换?

表达式的数据类型自动提高

全部的byte型、short型和char的值将被提高到int型。

若是一个操做数是long型,计算结果就是long型;

若是一个操做数是float型,计算结果就是float型;

若是一个操做数是double型,计算结果就是double型。

分析

System.out.println(‘a’)System.out.println(’a’+1) 的区别。


自动类型提高

byte b = 3;

int x = 4;

x = x + b;//b会自动提高为int类型进行运算。

强制类型转换

byte b = 3;

b = b + 4;//报错

b = (byte)b+4;//强制类型转换,强制将b+4的结果转换为byte类型,再赋值给b

思考:

byte b1=3,b2=4,b;

b=b1+b2;//报错

b=3+4;//编译经过,

b = 3 + 127//编译失败,130 大于byte类型的最大值

哪句是编译失败的呢?为何呢?

2.类型转换?

/**

类型转换

*/

class VarDemo 

{

public static void main(String[] args) 

{

char c = 'a';

//c = 'a' + 'b';//编译经过,结果:?

//c = c + 'b'; //编译失败,c int类型损失精度

c += 'b';//编译经过,结果:?

System.out.println(c);

}

}


运算符

算术运算符



算术运算符的注意问题

若是对负数取模,能够把模数负号忽略不记,如:5%-2=1。但被模数是负数就另当别论。(取模运算符号看被模数,即左边

对于除号“/”,它的整数除和小数除是有区别的:整数之间作除法时,只保留整数部分而舍弃小数部分。

例如:int x=3510;x=x/1000*1000; x的结果是?3000

“+”除字符串相加功能外,还能把非字符串转换成字符串,

例如:System.out.println("5+5="+5+5);//打印结果是?5+5 = 55


习题:

aSystem.out.println(3500 / 1000 * 1000); 3000

b.某个培训中心要为新到的学员安排房间,假设共有x个学员,每一个房间能够住6人,让你用一个公式来计算他们要住的房间数?


 赋值运算符

 SHAPE  \* MERGEFORMAT 


示例:

int a,b,c; a=b=c =3;

int a = 3; a+=5;等同运算a=a+5;


思考:

short s = 3; 

s=s+2;//编译报错

s+=2;//编译经过

有什么区别?


 比较运算符



比较运算符运行结束以后返回的都是boolean

注意运算符= =不要写成=


逻辑运算符

 SHAPE  \* MERGEFORMAT 


逻辑运算符用于链接布尔型表达式,在Java中不能够写成3<x<6,应该写成x>3 & x<6

“&”“&&”的区别:

&,左边不管真假,右边都进行运算

&,若是左边为真,右边参与运算,若是左边为假,那么右边不参与运算。

“|”“||”的区别同理,双或时,左边为真,右边不参与运算。

异或( ^ )与或( | )的不一样之处是:当左右都为true时, 结果为false


位运算符


位运算符

运算符

运算

范例

<<

左移

3 << 2 = 12 ‐‐> 3*2*2=12

>>

右移

3 >> 1 = 1 ‐‐> 3/2=1

>>>

无符号右移

3 >>> 1 = 1 ‐‐> 3/2=1

&

与运算

6 & 3 = 2

|

或运算

6 | 3 = 7

^

异或运算

6 ^ 3 = 5

~

反码

~6 = ‐7


位运算符的细节

<<

空位补0,被移除的高位丢弃,空缺位补0

>>

被移位的二进制最高位是0,右移后,空缺位补0

最高位是1,空缺位补1

>>>

被移位二进制最高位不管是0或者是1,空缺位都用0补。

&

二进制位进行&运算,只有1&1时结果是1,不然是0;

|

二进制位进行| 运算,只有0 | 0时结果是0,不然是1;

^

任何相同二进制位进行^ 运算,结果是01^1=0 , 0^0=0

不相同二进制位^ 运算结果是11^0=1 , 0^1=1


咱们能够对数据按二进制位进行移位操做,java的移位运算符有三种


<< 左移 将二进制的每一位向左移,低位补0。左移几位就至关于乘以2的几回方。

>> 右移 将二进制的每一位向右移,原来高位是0就补0,原来高位是1就补1。右移几位就至关于除以2的几回方。

>>> 无无符号右移 将二进制的每一位向右移,高位补0正数移动没区别,负数移动后变为正数。


练习:

&>>来作十进制转十六进制

有两个int型变量ab,在不使用第三个变量的状况下交换两个变量中的值

/**

不借用第三方完成变量值互换

*/

class SwapTest 

{

public static void main(String[] args) 

{

int a,b;

a = 3;

b = 4;

System.out.println("交换前:a="+a+"b="+b);

swapNum(a,b);

}


/**

不借用第三方完成变量值互换

@param a 带交换数字

@param b 带交换数字

*/

public static void swapNum(int a, int b)

{

a = a^b;

b = a^b;

a = a^b;

System.out.println("交换后:a="+a+"b="+b);

}


}

最有效率的方式算出2乘以8等于几?2<<3;

/**

高效完成2*8的运算

*/

class OperationTest 

{

public static void main(String[] args) 

{

System.out.println(2<<3);

}

}


运算符优先级

 SHAPE  \* MERGEFORMAT 

程序流程控制

 程序顺序结构

顾名思义,就是程序从上到下一行一行执行的结构,中间没有判断和跳转,直到程序结束。

 选择结构

程序具有多个分支,经过条件判断决定程序选择那一条分支执行


if语句:

经过if...else if...else决定程序流程。

若是if中的条件知足则执行其中语句,if未知足则继续判断else if,若是知足则执行,不知足继续判断下一个else if,若是全部都不知足,则执行else

练习:

if else语句判断一个数是奇数仍是偶数。

用户输入一个字符,用程序判断是否为小写字母,若是是,请输出您输入的字符是小写字母 


switch语句:

经过switch...case...default语句控制程序流程。

根据switch后括号中的值判断运行哪个case,这个值能够是byteshortcharint

注:java1.5 增长 enum 

Java 7 增长 String

default语句是可选的,若是全部case都不知足,则会执行default。(若是default语句放在结构最开始,注意加break

一旦匹配到一个case,程序就会从这个case向下执行,执行完一个case以后不会跳过其余的case,如需跳过请使用break


三元运算符

语法:表达式 ? 结果1 : 结果

若是表达式结尾为true取结果1,为false则取结果2

注意三元运算符也是有短路的效果,根据表达式的结果,只运行冒号一边的,另一边的不参与运行。


注:

Ifswitch语句很像,如何选择使用呢?

若是判断具体数值很少,并且符合byte,short ,char,int 这四种类型

虽然两种语句均可以使用,可是建议使用switch语句效率高

其余状况:对区间判断,对结果类型为boolean进行判断,使用if,if更广。

练习

定义一个函数,接收两个int参数,返回较大的一个。

循环结构

经过循环语句让同一段代码反复执行屡次,执行完毕程序才会继续日后运行


while

先判断while中的表达式结果是否为truetrue则执行循环体,执行结束以后再次判断,若是表达式结果为false则跳出循环。

练习:

打印出0-9

打印出a-z


do...while

先执行一次循环体,而后判断while中的表达式,若是是true继续执行,若是是false则跳出循环。

练习:

编写一个程序,这个程序不断地读取键盘上输入的字符,直到读到字符’q’时,程序结束。


for

for循环的括号中有三条语句,都是可选项。

语句1:这条语句会在整个循环开始以前执行,且仅运行一次,不参与循环。

语句2:必须是一个返回boolean值的表达式,若是写了这个语句那么每次循环开始以前会判断,true则执行循环,false则不执行。没写则直接执行。

语句3:这条语句在每次循环体运行结束以后执行。


注:

变量有本身的做用域,对于for来说,若是将用于控制循环的增量定义在for语句中,那么该变量只在for语句内有效,for语句执行完毕,该变量在内存中被释放。

forwhile能够进行互换,若是须要定义循环增量,用for 更为合适。

for里面的连个表达式运行的顺序,初始化表达式只读一次,判断循环条件, 为真就执行循环体,而后再执行循环后的操做表达式,接着继续判断循环条件, 重复找个过程,直到条件不知足为止。

最简单无限循环格式:while(true) , for(;;),无限循环存在的缘由是并不知道循环多少次,而是根据某些条件,来控制循环。


总结:

何时使用循环结构?

当要对某些语句执行不少次时,就使用循环结构。


练习:

使用星号打印以下图案


*****

*****

*****

*****

*****


i *

* 0 1

** 1 2

*** 2 3

**** 3 4

***** 4 5


i 空格 *

    * 0 4 1

   *** 1 3 3

  ***** 2 2 5

******* 3 1 7

********* 4 0 9


continuebreakreturn

continue:跳过一次循环,继续执行下一次

break:结束循环

return结束方法

注:

a,这两个语句离开应用范围,存在是没有意义的。

b,这个两个语句单独存在下面都不能够有语句,由于执行不到。

c,continue语句是结束本次循环继续下次循环。

d,标号的出现,可让这两个语句做用于指定的范围

语句练习


语句的嵌套应用

累加求和,计数器

循环嵌套

函数

 函数的定义

什么是函数?

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

函数也称为方法。

函数的格式:

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

{

执行语句;

return 返回值;

}

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

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

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

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

return:用于结束函数。

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

 函数的特色


定义函数能够将功能代码进行封装

便于对该功能进行复用

函数只有被调用才会被执行

函数的出现提升了代码的复用性

对于函数没有具体返回值的状况,返回值类型用关键字void表示,那么该函数中的return语句若是在最后一行能够省略不写。

注意:

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

定义函数时,函数的结果应该返回给调用者,交由调用者处理。

函数的应用


两个明确

明确要定义的功能最后的结果是什么?

明确在定义该功能的过程当中,是否须要未知内容参与运算

示例:

需求:定义一个功能,能够实现两个整数的加法运算。

分析:

该功能的运算结果是什么?两个数的和,也是一个整数(int)

在实现该功能的过程当中是否有未知内容参与运算?加数和被加数是不肯定的。(两个参数intint)

代码:

int getSum(int x,int y)

{

return x+y;

}

函数的重载(overload

重载的概念

在同一个类中,容许存在一个以上的同名函数,只要它们的参数个数或者参数类型不一样便可。

重载的特色:

与返回值类型无关,只看参数列表。

重载的好处:

方便于阅读,优化了程序设计。

重载示例:

//返回两个整数的和

int add(int x,int y){return x+y;}

//返回三个整数的和

int add(int x,int y,int z){return x+y+z;}

//返回两个小数的和

double add(double x,double y){return x+y;}


数组

数组的定义

概念

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

数组的好处

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

格式1

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

示例:int[] arr = new int[5];

格式2

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

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

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

数组的内存结构


内存结构

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

栈内存

用于存储局部变量,当数据使用完,所占空间会自动释放。

堆内存

数组和对象,经过new创建的实例都存放在堆内存中。

每个实体都有内存地址值

实体中的变量都有默认初始化值

实体再也不被使用,会在不肯定的时间内被垃圾回收器回收

方法区,本地方法区,寄存器

数组常见问题

数组脚标越界异常(ArrayIndexOutOfBoundsException)

int[] arr = new int[2];

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

访问到了数组中的不存在的脚标时发生。

空指针异常(NullPointerException)

int[] arr = null;

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

arr引用没有指向实体,却在操做实体中的元素时。

数组常见操做


获取最值(最大值,最小值)

排序(选择排序,冒泡排序)

折半查找(二分查找)


数组中的数组

二维数组[][]

格式1int[][] arr = new int[3][2];

定义了名称为arr的二维数组

二维数组中有3个一维数组

每个一维数组中有2个元素

一维数组的名称分别为arr[0], arr[1], arr[2]

给第一个一维数组1脚标位赋值为78写法是:arr[0][1] = 78;

格式2int[][] arr = new int[3][];

二维数组中有3个一维数组

每一个一维数组都是默认初始化值null

能够对这个三个一维数组分别进行初始化

arr[0] = new int[3];

arr[1] = new int[1];

arr[2] = new int[2];

格式3int[][] arr = {{3,8,2},{2,7},{9,0,1,6}};

定义一个名称为arr的二维数组

二维数组中的有三个一维数组

每个一维数组中具体元素也都已初始化

第一个一维数组arr[0] = {3,8,2};

第二个一维数组arr[1] = {2,7};

第三个一维数组arr[2] = {9,0,1,6};

第三个一维数组的长度表示方式:arr[2].length;

练习:获取arr数组中全部元素的和。使用for的嵌套循环便可。

注意特殊写法状况:int[] x,y[]; x是一维数组,y是二维数组。

练习


基础练习题

进制转换

幸运儿

定义一个函数,将数组中全部元素打印。要求打印成一行,每一个元素之间以逗号分隔。

定义一个函数,交换数组中的两个元素。

定义一个函数,找出数组中的最大数。

定义一个函数,将数组中全部元素反转。例如:{1, 2, 3} 反转后为 {3, 2, 1}

定义一个函数,对数组进行排序。

编写一个程序,程序接收键盘上输入的三个数,并输出这三个数的最大数。

编写一个程序,它先将键盘上输入的一个字符串转换成十进制整数,而后打印出这个十进制整数对应的二进制形式。 

使用移位方式将一个十进制数转换为十六进制。三种方式:

0-9之间的数值直接加上字符'0'9以上的数值减去10之后再加上字符'A'
定义一个数组,其中包含0-F这些字符,而后用要计算的数值做为数组的索引号,便可得到其对应的十六进制数据。
Character.forDigit
静态方法能够将一个十六进制的数字转变成其对应的字符表示形式,例如,根据数值15返回字符'F'

 

面向对象

面向对象的概念

什么是面向对象 

面向对象(Object Oriented)是一种思想,90年代之后软件开发的主流思想。

因为现实社会是由各类各样的事物所组成的,而咱们编程又是在模拟现实社会,那么在程序中也要用一些东西来表示现实社会中的事物,这些东西就是程序中的对象。咱们在程序中使用这些对象,对其特征和行为进行操做进行编程,这就是面向对象编程。

在使用面向对象编程思想以前,咱们一般用面向过程的思想编程,先分析出解决问题的步骤,而后按照步骤一步一步实现。


理解面向对象


面向对象是相对面向过程而言

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

面向过程

强调的是功能行为

面向对象

将功能封装进对象,强调具有了功能的对象。

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


面向对象的特色


是一种符合人们思考习惯的思想

能够将复杂的事情简单化

将程序员从执行者转换成了指挥者

完成需求时:

先要去找具备所需的功能的对象来用。

若是该对象不存在,那么建立一个具备所需功能的对象。

这样简化开发并提升复用。

向对象开发设计,设计,特征


开发的过程:其实就是不断的建立对象,使用对象, 指挥对象作事情。

设计的过程:其实就是在管理和维护对象之间的关系。

面向对象的特征:

封装(encapsulation)

继承(inheritance)

多态(polymorphism)

面向对象编程的优势

提升代码复用性。

使用者无需关心具体细节。  

转变程序员角色,更加符合人的思惟习惯。


类与对象

什么是类

类是用来描述对象的。因为对象是虚拟出来的东西,是看不见摸不着的,咱们须要在程序中使用对象,就须要用一种方式来描述对象,而后根据这个描述来建立对象。


使用计算机语言就是不断的在描述现实生活中的事物。

java中描述事物经过类的形式体现,类是具体事物的抽象,概念上的定义。

对象便是该类事物实实在在存在的个体。

类与对象的关系

对象是类的实例,类是对象的抽象。


类与对象的关系如图


能够理解为: 

类就是图纸 

汽车就是堆内存中的对象

类的定义


生活中描述事物无非就是描述事物的属性和行为。

如:人有身高,体重等属性,有说话,打球等行为。

Java中用class来描述事物

属性:对应类中的成员变量。

行为:对应类中的成员函数。

定义类其实在定义类中的成员(成员变量和成员函数)

class Person {

String name;

int age;

void speak(){

System.out.println("My name is " + name);

System.out.println("I am " + age + " years of age");

}

}

成员变量与局部变量的区别


成员变量

成员变量定义在类中,在整个类中均可以被访问。

成员变量随着对象的创建而创建,存在于对象所在的堆内存中。

成员变量有默认初始化值。

局部变量:

局部变量只定义在局部范围内,如:函数内,语句内等。

局部变量存在于栈内存中。

做用的范围结束,变量空间会自动释放。

局部变量没有默认初始化值。

成员变量初始化

当一个对象被建立时,会对其中各类类型的成员变量自动进行初始化赋值。基本数据类型初始化值为0,引用数据类型初始化值为null

 SHAPE  \* MERGEFORMAT 

建立对象,使用对象

class Car// 对这类事物进行描述Car

{

String color = "red";

int num = 4;

void show() 

{

  System.out.println("color="+color+"..num="+num); 

}

}

class CarDemo 

public static void main(String[] args) 

Car c = new Car();//创建对象 

c.color = "black";//对对象的属性进行修改 

  c.show();// 使用对象的功能。 

}

}

对象内存结构

对象的产生

Person p = new Person();

这句话先在堆内存中建立了一个对象,而后栈内存中建立一个变量引用了对象的地址。

Car c1 = new Car();c1.color="blue";

Car c2 = new Car();


对象的生命周期

对象的生命周期从new关键字建立时开始,到没有任何引用到达对象时结束(成为垃圾)


匿名对象

咱们能够不定义变量引用对象,使用new关键字建立对象后直接使用,这样的对象没有名字,因此叫匿名对象。

匿名对象由于没有任何引用到达,在使用一次以后即成为垃圾。

匿名对象是对象的简化形式

匿名对象两种使用状况

当对对象方法仅进行一次调用的时

匿名对象能够做为实际参数进行传递

封装(Encapsulation


封装:

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

好处:

将变化隔离。

便于使用。

提升重用性。

提升安全性。

封装原则:

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

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

private(私有)关键字


private关键字:

是一个权限修饰符。

用于修饰成员(成员变量和成员函数)

被私有化的成员只在本类中有效。

经常使用之一

将成员变量私有化,对外提供对应的set get 方法对其进行访问。

提升对数据访问的安全性。


private :私有,权限修饰符:用于修饰类中的成员(成员变量,成员函数)

私有只在本类中有效。

age私有化之后,类之外即便创建了对象也不能直接访问。

可是人应该有年龄,就须要在Person类中提供对应访问age的方式。

注意:私有仅仅是封装的一种表现形式。

之因此对外提供访问方式,就由于能够在访问方式中加入逻辑判断等语句

对访问的数据进行操做。提升代码健壮性

构造函数

什么是构造函数

构造函数(Constructor)是一个特殊的函数。


函数名和类名相同。

没有返回值类型。注意:没有返回值类型不等同于voidvoid也是一种返回值类型。不能使用return关键字返回任何值。

在使用new关键字建立对象以后自动调用。

构造函数的重载

构造函数的重载和普通函数相同,函数名相同,参数列表不一样便可

构造函数的调用

构造函数在new关键字建立对象时调用。

构造函数能够在该类其余构造函数的第一个语句使用this关键字调用。

构造函数的访问权限

在定义构造函数时,如无特殊须要,应使用public关键字修饰构造函数。

在一些特定状况下,咱们不想让别人建立该类对象,那么能够使用private修饰构造函数,例如单态设计模式。


特色:

函数名与类名相同

不用定义返回值类型

不能够写return语句

做用

给对象进行初始化。

注意:

默认构造函数的特色。

多个构造函数是以重载的形式存在的。

对象一创建就会调用与之对应的构造函数

构造函数的做用:能够用于给对象进行初始化。

构造函数的小细节

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

当在类中自定义了构造函数后,默认的构造函数就没有了。

构造函数和通常函数在写法上有不一样。

在运行上也有不一样。

构造函数是在对象一创建就运行。给对象初始化。

而通常方法是对象调用才执行,给是对象添加对象具有的功能。

一个对象创建,构造函数只运行一次

而通常方法能够被该对象调用屡次。

何时定义构造函数呢?

当分析事物时,该事物存在具有一些特性或者行为,那么将这些内容定义在构造函数中。

构造代码块{ 。。。}

做用:给对象进行初始化。

对象一创建就运行,并且优先于构造函数执行。

和构造函数的区别

构造代码块是给全部对象进行统一初始化,

而构造函数是给对应的对象初始化。

构造代码快中定义的是不一样对象共性的初始化内容。

this关键字

特色:

this表明其所在函数所属对象的引用。

换言之

this代本类对象的引用。

何时使用this关键字呢

当在函数内须要用到调用该函数的对象时,就用this

例如:

this:看上去,是用于区分局部变量和成员变量同名状况。

this为何能够解决这个问题?

this到底表明的是什么呢?

this:就表明本类的对象,到底表明哪个呢?

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

简单说:哪一个对象在调用this所在的函数,this就表明哪一个对象。

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

但凡本类功能内部使用了了本类对象,都用this表示

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

this语句只能定义在构造函数的第一行。由于初始化要先执行

函数的参数传递

基本数据类型的变量做为实参传入函数以后,在函数中将形参改变,调用处的实参不变。

由于基本数据类型的值是直接存在变量中,传入函数以后函数中的形参也一样存了一个值,这两个值是没有联系的,因此函数中将形参改变时修改的只是函数中的变量的值,和调用处的实参无关。

 

引用数据类型的变量做为实参传入函数以后,在函数中将形参改变,调用处的实参改变。

由于引用数据类型变量中存储的是地址,传入函数以后函数中的形参存储的也是一样一个地址,函数中将这个形参改变时改变的都是同一个地址上的对象,因此一边改变两边都变。

static 关键字

static 概述

static关键字用来修饰类的成员,被这个关键字修饰的成员都和类加载有关。

JVM运行时不会将全部类加载到内存,由于没法肯定程序中要使用哪些。类在第一次使用时加载,只加载一次。

静态变量

static修饰的变量就是静态变量。


静态变量在类加载后就初始化。

静态变量被类的全部实例所共享

静态变量能够使用 类名.变量名 形式访问。


若是在定义一个类的时候,发现一个成员变量须要被全部实例所共享,那么这个成员变量就须要定义为static的。

静态方法

static修饰的方法就是静态方法。


静态方法在类加载后就能够使用

静态方法能够使用 类名.方法名 形式访问。

静态方法不能直接访问外部非静态成员。

由于外部非静态成员必须在类建立对象以后才能使用,而静态方法能够在没建立对象时就使用。

若是要在静态方法内部访问外部非静态成员,须要先建立该类对象,经过对象访问。

静态方法中不能使用this关键字

由于this是个引用,哪一个对象调用方法就引用哪一个对象。 而静态方法有可能不是被对象调用的,this无从引用。


若是一个方法不用访问对象的非静态成员,那么就能够定义为静态的,这样使用者就不须要建立对象,直接用类名调用。

静态方法一般是做为工具方法或者一个能够产生对象的方法被声明,目的是为了让调用者更方便的使用,没必要建立对象。

static特色:

1,随着类的加载而加载。

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

2优先于的对象存在

明确一点:静态是先存在。对象是后存在的。

3,被全部对象所共享

4,能够直接被类名所调用

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

1存放位置。

类变量随着类的加载而存在于方法区中

实例变量随着对象的创建而存在于堆内存中

2生命周期:

类变量生命周期最长,随着类的消失而消失。

实例变量生命周期随着对象的消失而消失

静态使用注意事项:

1静态方法只能访问静态成员。

非静态方法既能够访问静态也能够访问非静态。

2静态方法中不能够定义thissuper关键字。

由于静态优先于对象存在。因此静态方法中不能够出现this

3,主函数是静态的。

静态有利有弊

利处:对对象的共享数据进行单独空间的存储,节省空间。没有必要每个对象中都存储一份。

能够直接被类名调用。

弊端:生命周期过长。

  访问出现局限性。(静态虽好,只能访问静态。)

java main函数

public static void main(String[] args) 

主函数:是一个特殊的函数。做为程序的入口,能够被jvm调用。

主函数的定义:

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

static:表明主函数随着类的加载就已经存在了。

void:主函数没有具体的返回值。

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

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

主函数是固定格式的:jvm识别。

jvm在调用主函数时,传入的是new String[0];

static 用的时机

什么时候定义静态变量(类变量)呢?

当对象中出现共享数据时,该数据被静态所修饰。

对象中的特有数据要定义成非静态存在于堆内存中。

什么时候定义静态函数呢?

当功能内部没有访问到非静态数据(对象的特有数据),那么该功能能够定义成静态的。

静态的应用

每个应用程序中都有共性的功能,

能够将这些功能进行抽取,独立封装。

以便复用。

javadoc 文档制做

javadoc -d myhelp -author -version ArrayTool.java


一个类中默认会有一个空参数的构造函数,

这个默认的构造函数的权限和所属类一致。

若是类被public修饰,那么默认的构造函数也带public修饰符。

若是类没有被public修饰,那么默认的构造函数,也没有public修饰。


默认构造构造函数的权限是随着的类的变化而变化的。


静态代码块

static修饰的代码块就是静态代码块。

静态代码块在类加载后执行。

静态代码块和静态方法相同,不能使用外部非静态成员。

静态代码块执行和静态变量的初始化顺序由代码从上到下顺序决定。


静态代码块。

格式:

static

{

静态代码块中的执行语句。

}


特色:随着类的加载而执行,只执行一次,并优先于主函数。

用于给类进行初始化的。


对象初始化过程

Person p = new Person("zhangsan",20);

该句话都作了什么事情?

1,由于new用到了Person.class.因此会先找到Person.class文件并加载到内存中。

2,执行该类中的static代码块,若是有的话,给Person.class类进行初始化。

3,在堆内存中开辟空间,分配内存地址。

4,在堆内存中创建对象的特有属性。并进行默认初始化。

5,对属性进行显示初始化。

6,对对象进行构造代码块初始化。

7,对对象进行对应的构造函数初始化。

8,将内存地址付给栈内存中的p变量。


对象调用方法过程?


静态内部类

static修饰的内部类就是静态内部类。

静态内部类在类加载后就能够建立对象,无需建立外部类对象。


垃圾回收

对象在没有任何引用能够到达时,生命周期结束,成为垃圾。


全部对象在被回收以前都会自动调用finalize()方法。


一个对象在成为垃圾以后不会被立刻回收,JVM会检测内存中的垃圾堆积到必定程度时才会回收,若是咱们不想等到这个时候才回收,能够使用System.gc()方法来通知虚拟机回收垃圾。调用该方法以后JVM会开启新线程作处理垃圾的工做,这须要必定时间。


单例设计模式(SingletonPattern

什么是设计模式

在编程过程当中咱们常常会遇到一些典型的问题或须要完成某种特定需求,而这些问题和需求前人也曾经遇到过,他们通过大量理论总结和实践验证以后优选出的代码结构、编程风格、以及解决问题的思考方式,这就是设计模式(Design pattern)。设计模式就像是经典的棋谱,不一样的棋局,咱们用不一样的棋谱,省得咱们本身再去思考和摸索。

单态(单例)设计模式

单态设计模式(Singleton pattern)就是要保证在整个程序中某个类只能存在一个对象,这个类不能再建立第二个对象。


想要保证对象惟一。

1,为了不其余程序过多创建该类对象。先禁止其余程序创建该类对象

2,还为了让其余程序能够访问到该类对象,只好在本类中,自定义一个对象。

3,为了方便其余程序对自定义对象的访问,能够对外提供一些访问方式。

这三部怎么用代码体现呢

1,将构造函数私有化。

2,在类中建立一个本类对象。

3,提供一个方法能够获取到该对象。

对于事物该怎么描述,还怎么描述。

当须要将该事物的对象保证在内存中惟一时,就将以上的三步加上便可。

/*

这个是先初始化对象。

称为:饿汉式。


Single类一进内存,就已经建立好了对象。

class Single

{

private static Single s = new Single();

private Single(){}

public static Single getInstance()

{

return s;

}

}

*/


//对象是方法被调用时,才初始化,也叫作对象的延时加载。成为:懒汉式。

//Single类进内存,对象尚未存在,只有调用了getInstance方法时,才创建对象。

class Single

{

private static Single s = null;

private Single(){}

public static Single getInstance()

{

if(s==null)

{

synchronized(Single.class)

{

if(s==null)

s = new Single();

}

}

return s;

}

}


//记录原则:定义单例,建议使用饿汉式。


继承(inherit

 继承概述

什么是继承

在程序中,能够使用extends关键字可让一个类继承另一个类。

继承的类为子类(派生类),被继承的类为父类(超类, 基类)

子类会自动继承父类全部的方法和属性。

为何要使用继承 

当咱们发现一个类的功能不行,方法不够用时,就能够派生子类,增长方法。

当咱们须要定义一个能实现某项特殊功能的类时,就能够使用继承。

最终仍是为了一个目的,实现代码的复用性。


当咱们定义一个类时,发现另外一个类的功能这个类都须要,而这个类又要增长一些新功能时,就能够使用extends关键字继承那个类,这样那个被继承类的功能就都有了,没必要重写编写代码。这时只要在新的类中编写新的功能便可,原有代码就被复用了。

继承的特色

子类中能够使用super调用父类成员

super用法和this相似,this是谁调用该方法就引用谁,super是调用该方法的对象的父类对象。


继承

1,提升了代码的复用性。

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

注意:千万不要为了获取其余类的功能,简化代码而继承。

必须是类与类之间有所属关系才能够继承。所属关系 is a


Java语言中:java只支持单继承,不支持多继承


由于多继承容易带来安全隐患:当多个父类中定义了相同功能,

当功能内容不一样时,子类对象不肯定要运行哪个。

可是java保留这种机制。并用另外一种体现形式来完成表示。多实现。


java支持多层继承。也就是一个继承体系


如何使用一个继承体系中的功能呢?


想要使用体系,先查阅体系父类的描述,由于父类中定义的是该体系中共性功能。

经过了解共性功能,就能够知道该体系的基本功能。

那么这个体系已经能够基本使用了。

那么在具体调用时,要建立最子类的对象为何呢?

一是由于有可能父类不能建立对象

二是建立子类对象能够使用更多的功能,包括基本的也包括特有的。


简单一句话:查阅父类功能,建立子类对象使用功能。


汇集has a


聚合:队员与球队的关系


组合:身体与心脏的关系


组合设计模式(CompositePattern)

何时用组合

组合是一种实现代码复用的方式,当咱们在定义一个类的时候须要用到另一个类的方法时,就能够用组合。

怎么用组合

定义一个所须要的类类型的成员变量

经过构造函数进行装配,接收一个该类类型的对象,用成员变量引用

在须要使用另外一个类的方法时经过成员变量访问

组合的优势

若是两个类没有父子关系,不合适用继承。

Java只支持单继承,组合不占用继承位置。


 super 关键字

子父类出现后,类成员的特色:


类中成员:

1,变量。

2,函数。

3,构造函数。


1,变量

若是子类中出现非私有的同名成员变量时,

子类要访问本类中的变量,用this

子类要访问父类中的同名变量,用super


super的使用和this的使用几乎一致。

this表明的是本类对象的引用。

super表明的是父类对象的引用。


 函数覆盖(override

2,子父类中的函数


当子类出现和父类如出一辙的函数时,

当子类对象调用该函数,会运行子类函数的内容。

如同父类的函数被覆盖同样。


这种状况是函数的另外一个特性:重写(覆盖)


当子类继承父类,沿袭了父类的功能,到子类中,

可是子类虽具有该功能,可是功能的内容却和父类不一致,

这时,没有必要定义新功能,而是使用覆盖特殊,保留父类的功能定义,并重写功能内容。


覆盖:

1,子类覆盖父类,必须保证子类权限(方法的修饰符)大于等于父类权限,才能够覆盖,不然编译失败。

2静态只能覆盖静态


记住你们:

重载:只看同名函数的参数列表。

重写:子父类方法要如出一辙。


3,子父类中的构造函数。


在对子类对象进行初始化时,父类的构造函数也会运行,

那是由于子类的构造函数默认第一行有一条隐式的语句 super();

super():会访问父类中空参数的构造函数。并且子类中全部的构造函数默认第一行都是super();


为何子类必定要访问父类中的构造函?


由于父类中的数据子类能够直接获取。因此子类对象在创建时,须要先查看父类是如何对这些数据进行初始化的。

因此子类在对象初始化时,要先访问一下父类中的构造函数。

若是要访问父类中指定的构造函数,能够经过手动定义super语句的方式来指定。


注意:super语句必定定义在子类构造函数的第一行。


 子类实例化过程

子类的实例化过程。


结论:

子类的全部的构造函数,默认都会访问父类中空参数的构造函数

由于子类每个构造函数内的第一行都有一句隐式super();


当父类中没有空参数的构造函数时,子类必须手动经过super语句形式来指定要访问父类中的构造函数。


固然:子类的构造函数第一行也能够手动指定this语句来访问本类中的构造函数。

子类中至少会有一个构造函数会访问父类中的构造函数。


 final 关键字

final : 最终。做为一个修饰符,

1,能够修饰类,函数,变量

2,被final修饰的类不能够被继承。为了不被继承,被子类复写功能。

3,被final修饰的方法不能够被复写

4,被final修饰的变量是一个常量只能赋值一次既能够修饰成员变量,有又能够修饰局部变量。

当在描述事物时,一些数据的出现值是固定的,那么这时为了加强阅读性,都给这些值起个名字。方便于阅读。

而这个值不须要改变,因此加上final修饰。做为常量:常量的书写规范全部字母都大写,若是由多个单词组成。

单词间经过_链接。

5,内部类定义在类中的局部位置上是,只能访问该局部被final修饰的局部变量。


 抽象类

抽象类:

Java中能够定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象                 方法,包含抽象方法的类就是抽象类。

抽象方法的由来

多个对象都具有相同的功能,可是功能具体内容有所不一样,那么在抽取过程当中,只抽取  了功能定义,并未抽取功能主体,那么只有功 能声明,没有功能主体的方法称为抽象方法。

例如:狼和狗都有吼叫的方法,但是吼叫内容是不同的。因此抽象出来的犬科虽然有吼叫功能,可是并不明确吼叫的细节。


当多个类中出现相同功能,可是功能主体不一样,

这是能够进行向上抽取。这时,只抽取功能定义,而不抽取功能主体。


抽象:看不懂。

抽象类的特色

1抽象方法必定在抽象类中

2,抽象方法和抽象类都必须被abstract关键字修饰。

3,抽象类不能够用new建立对象。由于调用抽象方法没意义。

4,抽象类中的抽象方法要被使用,必须由子类复写全部的抽象方法后,创建子类对象调用。

若是子类只覆盖了部分抽象方法,那么该子类仍是一个抽象类。


抽象类和通常类没有太大的不一样。

该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂的东西。

这些不肯定的部分,也是该事物的功能,须要明确出现。可是没法定义主体。

经过抽象方法来表示。


抽象类比通常类多个了抽象函数。就是在类中能够定义抽象方法。

抽象类不能够实例化。


特殊:抽象类中能够不定义抽象方法,这样作仅仅是不让该类创建对象


练习:


abstract 关键字,和哪些关键字不能共存。

final:被final修饰的类不能有子类。而被abstract修饰的类必定是一个父类。

private: 抽象类中的私有的抽象方法,不被子类所知,就没法被复写。

而抽象方法出现的就是须要被复写。

static:若是static能够修饰抽象方法,那么连对象都省了,直接类名调用就能够了。

但是抽象方法运行没意义。


抽象类中是否有构造函数?

有,抽象类是一个父类,要给子类提供实例的初始化。


模板设计模式(TemplatePattern)

为何要使用模板方法设计模式

在解决一些问题或者设计一个软件的时候,须要先定义一个模板,就至关于一种事先定义好的协议。

之后要作这系列的事情都按照这个模板来作。这样就实现统一化管理。

如何实现模板方法设计模式

定义一个抽象的父类作为模板,定义全部须要的方法

在父类中实现供外界调用的主方法,将方法声明为final

根据不一样业务需求定义子类实现父类的抽象方法


 接口(interface

什么是接口

接口是一种特殊的抽象类,接口中声明的全部方法都是抽象的

使用interface关键字修饰一个接口

接口的用法

咱们能够定义一个类来实现接口,使用implements关键字

实现一个接口须要实现接口中全部的方法,抽象类除外

一般使用匿名内部类来实现一个接口

接口能够继承接口(多继承),使用extends关键字。 接口不能继承抽象类,由于抽象类中可能有不抽象的方法。

一个类能够实现多个接口,为了实现多态

接口中的方法和变量

接口中定义的方法默认是公有的抽象的,被public abstract修饰

接口中定义的变量默认为全局常量,使用public static final修饰

abstract classinterface的区别

抽象类中能够有抽象的方法,接口中全是抽象的方法

抽象类用extends继承,接口用implements实现

抽象类中的变量和方法没有默认修饰符,接口中的变量默认为public static final的,接口中的方法默认为public abstract

一个类只能继承一个抽象类,一个类能够实现多个接口

何时用抽象类,何时用接口

若是能用接口,就不用抽象类,由于别人实现接口能够不占用继承的位置。

若是定义一个抽象的父类,其中全部方法都是抽象的,那么就定义为接口。

若是定义一个抽象的父类的时候,须要有不抽象的方法,那么只能定义为抽象类。


多态(Polymorphism

 多态概述

什么是多态

多态字面上的意思就是多种形态。在面向对象语言中,咱们能够将函数的形参定义为一个父类类型,而在真正调用该函数时这个父类类型的全部子类对象均可以传入,根据传入的子类对象不一样函数能够运行处多种形态。

多态的特色

应用程序没必要为每个派生类(子类)编写功能调用,只须要对抽象基类进行处理便可。这一招叫以不变应万变,能够大大提升程序的可复用性。

派生类的功能能够被基类的引用变量引用,这叫向后兼容,能够提升程序的可扩充性和可维护性。如今写的程序能够调用未来写的程序不足为奇


多态:能够理解为事物存在的多种体现形态。

Eg.

人:男人,女人

动物:猫,狗。

x = new ();

动物 x = new ();


一。表现:

父类或者接口的引用指向了或者接收了本身的子类对象。

二。前提:

1,类与类之间要有关系。继承,实现。

2,一般都会有覆盖。

三。好处:

预先定义的程序能够运行后期程序的内容。

加强了程序的扩展性。

四。弊端:

虽然能够预先使用,可是只能访问父类中已有的功能,运行的是后期子类的功能内容。

不能预先使用子类中定义的特有功能。

五。多态的注意事项

在代码中。

对于成员函数:Fu f = new Zi(); f.method();

编译时期:看左边。

运行时期:看右边。

由于成员函数有一个覆盖操做。

毕姥爷和毕老师的故事。

对于非私有的实例变量,

静态变量,静态方法。


编译和运行都看左边。

六。转型。

子类对象被父类引用:子类对象在向上转型。

将指向子类对象的父类应用转换成子类类型引用:向下转型。


毕姥爷和毕老师的故事。

class 毕姥爷

{}


class 毕老师 extends 毕姥爷

{}

毕姥爷 ly = new 毕老师();//毕老师向上转型为了毕姥爷。向上转型

毕老师 ls = (毕老师)ly; //将表明毕老师对象的父类引用ly强制转换成了毕老师类型。向下转型。

七。应用

电脑使用。主板运行。

 类型转换

向上转型

把一个子类当作父类来用是能够的,由于父类有的子类都有

把一个父类当作子类来用就不能够了,由于子类有的父类不必定有

能够定义一个父类类型的变量来记住子类对象,这在程序中称之为向上转型

强制类型转换

把一个子类当作父类来用的时候,不能调用子类特有方法。

由于编译时编译器会作语法检查,看到变量是父类类型那么就会到父类中查找是否有该方法,没有则报错。

这种状况下,就须要强制类型转换,将父类类型强转成子类类型。

(子类名)变量名形式进行强制类型转换

强制类型转换时,不管类型是否匹配编译都不会报错,但若是类型不匹配运行会报错,咱们能够使用instanceof进行判断,编译时预知错误。


在子类当作父类来用时,不能调用特有方法,若是必定要调用,就须要强制类型转换回子类。在作转换时最好instanceof判断一下类型是否匹配。


//Animal a = new Cat();//类型提高。 向上转型。

//a.eat();


//若是想要调用猫的特有方法时,如何操做?

//强制将父类的引用。转成子类类型。向下转型。

///Cat c = (Cat)a;

//c.catchMouse();

//千万不要出现这样的操做,就是将父类对象转成子类类型。

//咱们能转换的是父类应用指向了本身的子类对象时,该应用能够被提高,也能够被强制转换。

//多态自始至终都是子类对象在作着变化。

instanceof : 用于判断对象的类型。 对象 intanceof 类型(类类型 接口类型)  


 多态中成员的使用特色

在多态中成员函数的特色:

在编译时期:参阅引用型变量所属的类中是否有调用的方法。若是有,编译经过,若是没有编译失败。

在运行时期:参阅对象所属的类中是否有调用的方法。

简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。


在多态中,成员变量的特色:

不管编译和运行,都参考左边(引用型变量所属的类)


在多态中,静态成员函数的特色

不管编译和运行,都参考作左边。


Object

object:是全部对象的直接后者间接父类,传说中的上帝。

该类中定义的确定是全部对象都具有的功能。


Object类中已经提供了对对象是否相同的比较方法。


若是自定义类中也有比较相同的功能,没有必要从新定义。

只要沿袭父类中的功能,创建本身特有比较内容便可。这就是覆盖。

Object:java中全部对象的直接或者间接的父类。

它里面的方法都全部对象都具有的。

常见方法:

boolean equals(Object obj):用于比较两个对象是否相同。

String toString(): 获取对象的字符串表现形式 类名@哈希值  

getClass().getName()+"@"+Integer.toHexString(hashCode());

Class getClass():获取正在运行的对象所属的字节码文件的对象。也就是说若是Demo d = new Demo();

d.getClass():获取的就是d执行的对象所属的字节码文件Demo.class对象。

一般在自定义对象时,由于对象中都有本身特有的描述,

因此都会创建对象自身的特有比较方法,或者字符串表现形式。

也就是说,会覆盖Object中的方法。


内部类(InnerClass

内部类的访问规则

1,内部类能够直接访问外部类中的成员,包括私有。

之因此能够直接访问外部类中的成员,是由于内部类中持有了一个外部类的引用,格式 外部类名.this

2,外部类要访问内部类,必须创建内部类对象。


访问格式:

1,当内部类定义在外部类的成员位置上,并且非私有,能够在外部其余类中。

能够直接创建内部类对象。

格式

部类名.内部类名  变量名 = 外部类对象.内部类对象;

Outer.Inner in = new Outer().new Inner();


2,当内部类在成员位置上,就能够被成员修饰符所修饰。

好比,private:将内部类在外部类中进行封装。

static:内部类就具有static的特性。

当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。


外部其余类中,如何直接访问static内部类的非静态成员呢?

new Outer.Inner().function();


在外部其余类中,如何直接访问static内部类的静态成员呢?

Outer.Inner.function();


注意:当内部类中定义了静态成员,该内部类必须是static的。

  当外部类中的静态方法访问内部类时,内部类也必须是static的。


当描述事物时,事物的内部还有事物,该事物用内部类来描述。

由于内部事务在使用外部事物的内容。


内部类定义在局部时

1,不能够被成员修饰符修饰

2,能够直接访问外部类中的成员,由于还持有外部类中的引用。

可是不能够访问它所在的局部中的变量。只能访问被final修饰的局部变量。


匿名内部类:

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

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

内部类必须是继承一个类或者实现接口。

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

4,其实匿名内部类就是一个匿名子类对象。并且这个对象有点胖。 能够理解为带内容的对象。

5,匿名内部类中定义的方法最好不要超过3个。


异常(Exception

什么是异常

异常就是Java程序在运行过程当中出现的错误。如程序要打开一个不存的文件、网络链接中断、操做数组越界、装载一个不存在的类等。

Throwable

Throwable表示Java中可被抛出的对象,它是全部错误和异常的父类

Throwable有两个子类:ErrorException

Error表示错误

Exception表示异常

RuntimeException表示运行时异常,是Exception的子类


 SHAPE  \* MERGEFORMAT 

异常的分类

Error(错误)

Java虚拟机生成并抛出,包括动态连接失败、虚拟机错误等,程序对其不进行处理

Exception(异常

全部异常类的父类,子类定义了各类各样可能出现的异常事件,通常须要用户显式地声明向外抛出或捕获。

Runtime Exception(运行时异常)

一类特殊的异常,如被0除、数组角标越界等。产生比较频繁,处理麻烦,若是每次都处理,会对程序可读性和运行效率影响比较大,所以由系统检测并将它们交给缺省的异常处理程序,用户没必要对其进行处理。这类异常不处理,编译时不会报错,只是在运行时出现错误时才报告异常,因此咱们称之为运行时异常,全部RuntimeException的子类都是运行时异常。咱们也能够对运行时异常进行处理。

编译时异常

Exception中除了RuntimeException的子类,其余异常都是必需要处理的,若是不处理,编译时会报错,这些异常咱们称之为编译时异常。


异常体系的特色:异常体系中的全部类以及创建的对象都具有可抛性。

也就是说能够被throwthrows关键字所操做。

只有异常体系具有这个特色。



--------------

throwthrows的用法:


throw定义在函数内,用于抛出异常对象。

throws定义在函数上,用于抛出异常类,能够抛出多个用逗号隔开。



当函数内容有throw抛出异常对象,并未进行try处理。必需要在函数上声明,都在编译失败。

注意,RuntimeException除外。也就说,函数内若是抛出的RuntimeExcpetion异常,函数上能够不用声明。

--------------


若是函数声明了异常,调用者须要进行处理。处理方法能够throws能够try


--------------

异常处理语句:

try

{

须要被检测的代码;

}

catch ()

{

处理异常的代码;

}

finally

{

必定会执行的代码;

}


有三个结合格式:

1. try

{

}

catch ()

{

}


2. try

{

}

finally

{

}



3. try

{

}

catch ()

{

}

finally

{

}




注意:

1finally中定义的一般是 关闭资源代码。由于资源必须释放。

2finally只有一种状况不会执行。当执行到System.exit(0);fianlly不会执行。


--------------


自定义异常

定义类继承Exception或者RuntimeException

1,为了让该自定义类具有可抛性。

2,让该类具有操做异常的共性方法。


当要定义自定义异常的信息时,能够使用父类已经定义好的功能。

异常异常信息传递给父类的构造函数。

class MyException extends Exception

{

MyException(String message)

{

super(message);

}

}


自定义异常:按照java的面向对象思想,将程序中出现的特有问题进行封装。

--------------



异常的好处:

1,将问题进行封装。

2,将正常流程代码和问题处理代码相分离,方便于阅读。



异常的处理原则

1处理方式有两种:try 或者 throws

2,调用到抛出异常的功能时,抛出几个,就处理几个。

一个try对应多个catch

3多个catch,父类的catch放到最下面。

4catch内,须要定义针对性的处理方式。不要简单的定义printStackTrace,输出语句。

也不要不写。

当捕获到的异常,本功能处理不了时,能够继续在catch中抛出。

try

{

throw new AException();

}

catch (AException e)

{

throw e;

}


若是该异常处理不了,但并不属于该功能出现的异常。

能够将异常转换后,在抛出和该功能相关的异常。


或者异常能够处理,当须要将异常产生的和本功能相关的问题提供出去,

当调用者知道。并处理。也能够将捕获异常处理后,转换新的异常。

try

{

throw new AException();

}

catch (AException e)

{

// AException处理。

throw new BException();

}


好比,汇款的例子。


异常的注意事项

在子父类覆盖时:

1,子类抛出的异常必须是父类的异常的子类或者子集。

2,若是父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能抛。


Java中经常使用的包

java.lang

包含一些Java语言的核心类,如StringMathIntegerSystemThread,提供经常使用功能。

java.awt

包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)

java.net

包含执行与网络相关的操做的类。 

java.io

包含能提供多种输入/输出功能的类。

java.util

包含一些实用工具类,如定义系统特性、使用与日期日历相关的函数。

定义带包类

使用package语句加上包名来定义类所属于的包,包名所有小写

package语句为Java源文件的第一条语句

若是一个类中没有使用package语句,这个类为缺省无包名

一个类若是想被其余包中的类引用,必须使用public关键字修饰。构造函数也须要public

若是一个类被声明为public,那么必须和文件名同名

使用带包的类

在使用带包的类时须要使用全限定名(包名.类名

在每次写类名时都使用全限定名很麻烦,咱们能够使用import导入包,以后再使用就无需写包名了

星号*:导入一个包中全部类。优先匹配当前包中的类,若是当前包没有再匹配导入包中的类。

具体类名:导入指定一个类。不管当前包中是否有同名类,都直接匹配导入的类。

无包的类能够使用有包的类,有包的类不能使用无包的类

编译运行带包的类

编译一个带包的源文件,在生成class文件的同时须要生成包文件

编译命令:javac –d <目录> 源文件名.java

运行有包的类时须要加上包名

运行命令:java 包名.类名   


jar文件

什么是jar文件

jar文件是Java文件的一种压缩格式

通常来说,咱们会将一个软件系统的全部class文件打成一个jar文件以供别人使用

当咱们用到jar包中的类时,须要将jar文件的绝对路径加到classpath当中

如何压缩jar文件

将编译好的带包的class文件压缩成一个jar文件称为打jar

jar命令jar cvf jar包名.jar 要打包的文件/文件夹

运行jar文件命令 java -jar jar文件名.jar


经过jar.exe工具对jar的操做。

建立jarjar -cvf mypack.jar packa packb

查看jarjar -tvf mypack.jar [>定向文件]

解压缩jar -xvf mypack.jar

自定义jar包的清单文件jar –cvfm mypack.jar mf.txt packa packb


访问控制符




类的访问控制符有两种:

public关键字修饰:能够被全部的类访问

缺省为default:只能被同一包中的类访问


多线程

多线程概述

进程


几乎全部操做系统都支持进程的概念,全部运行中的任务一般对应一条进程(Process )。当一个程序进入内存运行,即变成一个进程。进程是处于运行过程当中的程序,而且具备必定独立功能,进程是系统进行资源分配和调度的一个独立单位

进程包含以下三个特征:

独立性:进程是系统中独立存在的实体,它能够拥有本身独立的资源,每个进程都拥有本身私有的地址空间。在没有通过进程自己容许的状况下,一个用户进程不能够直接访问其余进程的地址空间。

动态性:进程与程序的区别在于,程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集合。在进程中加入了时间的概念。进程具备本身的生命周期和各类不一样的状态,这些概念在程序中都是不具有的。

并发性:多个进程能够在单个处理器上并发执行,多个进程之间不会互相影响。


区别:

并发性(concurrency)和并行性(parallel )是两个概念,并行指在同一时刻,有多条指令多个处理器上同时执行;并发指在同一时刻只能有一条指令执行,但多个进程指令被快速轮换执行,使得在宏观上具备多个进程同时执行的效果。


多线程则扩展了多进程的概念,使得同一个进程能够同时并发处理多个任务。线程(Thread )也被称做轻量级进程(Lightweight Process )线程是进程的执行单元。就像进程在操做系统中的地位同样,线程在程序中是独立的、并发的执行流。当进程被初始化后,主线程就被建立了。对于绝大多数的应用程序来讲,一般仅要求有一个主线程,但咱们也能够在该进程内建立多条顺序执行流,这些顺序执行流就是线程每条线程也是互相独立的

线程是进程的组成部分,一个进程能够拥有多个线程,一个线程必须有一个父进程线程能够拥有本身的堆栈、本身的程序计数器和本身的局部变量,但再也不拥有系统资源,它与父进程的其余线程共享该进程所拥有的所有资源。由于多个线程共享父进程里的所有资源,所以编程更加方便;但必须更加当心,咱们必须确保线程不会妨碍同一进程里的其余线程。

一个程序运行后至少有一个进程,一个进程里能够包含多个线程,但至少要包含一个线程。

线程共享的环境包括:进程代码段、进程的公有数据等。利用这些共享的数据等,线程很容易实现相互之间的通讯。

多线程编程包含以下几个优势:

进程间不能共享内存,但线程之间共享内存很是容易。

系统建立进程须要为该进程从新分配系统资源,但建立线程则代价小得多,所以使用多线程来实现多任务并发比多进程的效率高

Java语言内置多线程功能支持,而不是单纯地做为底层操做系统的调度方式,从而简化了Java的多线程编。


线程的建立和启动

Java使用Thread类表明线程,全部的线程对象都必须是Thread类或其子类的实例。每条线程的做用是完成必定的任务,实际上就是执行一段程序流(一段顺序执行的代码)Java使用run方法来封装这样一段程序流


继承Thread类建立线程类


经过继承Thread类来建立并启动多线程的步骤以下:

1.定义Thread类的子类,并重写该类的run方法,该run方法的方法体就是表明了线程须要完成的任务。所以,咱们常常把run方法称为线程执行体。

2.建立Thread子类的实例,即便建立了线程对象。

3.用线程对象的start方法来启动该线程。


实现Runnable接口建立线程类


实现Runnable接口来建立并启动多条线程的步骤以下:

1.定义Runnab 1e接口的实现类,并重写该接口的run方法,该run方法的方法体一样是该线程的线程执行体

2.建立Runnable实现类的实例,并以此实例做为Threadtarget来建立Thread对象,该Thread对象才是真正的线程对象。


使用Runnable接口建立线程能够共享同一个线程类实例的资源。


两种方式所建立线程的对比

采用实现Runnable接口方式的多线程:

线程类只是实现了Runnable接口,还能够继承其余类

在这种方式下,能够多个线程共享同一个target对象,因此很是适合多个相同线程来处理同一份资源的状况,从而能够将CPU、代码和数据分开,造成清晰的模型,较好地体现了面向对象的思想。

劣势是:编程稍稍复杂,若是须要访问当前线程,必须使用Thread.currentThread()方法。


采用继承Thread类方式的多线程:

劣势是:由于线程类已经继承了Thread类,因此不能再继承其余父类。

优点是:编写简单,若是须要访问当前线程,无须使用Thread.currentThread()方法,直接使用this便可得到当前线程

实际上几乎全部的多线程应用均可采用第一种方式,也就是实现Runnable接口的方式。


线程的生命周期

当线程被建立并启动之后,它既不是一启动就进入了执行状态,也不是一直处于执行状态,在线程的生命周期中,它要通过新建(New)、就绪(Runnable)、运行(Running )、阻塞(Blocked)和死亡(Dead )五种状态。尤为是当线程启动之后,它不能一直霸占CPU独自运行,因此CPU须要在多条线程之间切换,因而线程状态也会屡次在运行、阻塞之间切换。


新建和就绪状态


当程序使用new关键字建立了一个线程以后,该线程就处于新建状态,此时它和其余Java对象同样,仅仅由Java虚拟机为其分配了内存,并初始化了其成员变量的值。此时的线程对象没有表现出任何线程的动态特征,程序也不会执行线程执行体中的线程执行体。

当线程对象调用了start()方法以后,该线程处于就绪状态Java虚拟机会为其建立方法调用栈和程序计数器,处于这个状态中的线程并无开始运行,它只是表示该线程能够运行了。至于该线程什么时候开始运行取决于jvm里线程调度器的调度


不要对已经处于启动状态的线程再次调用start()方法,不然将引起

IllegalThreadStateException异常。


运行和阻塞状态

若是处于就绪状态的线程得到了CPU,开始执行run方法的线程执行体,则该线程处于运行状态,若是计算机只有一个CPU,在任什么时候刻只有一条线程处于运行状态。固然,在一个多处理器的机器上,将会有多个线程并行(注意是并行:parallel)执行;但当线程数大于处理器数时,依然会有多条线程在同一个CPU上轮换的现象。

当发生以下状况下,线程将会进入阻塞状态:

线程调用sleep方法主动放弃所占用的处理器资源。

线程调用了一个阻塞式io方法,在该方法返回以前,该线程被阻塞。

线程试图得到一个同步监视器.但该同步监视器正被其余线程所持有。

线程在等待某个通知(notify )

程序调用了线程的suspend方法将该线程挂起。不过这个方法容易致使死锁,因此程序应该尽可能避免使用该方法。



线程状态转换图:


当运行状态的线程失去处理器资源时,该线程进入就绪状态。但有一个方法例外,调用yield()可让当前处于运行状态的线程转入就绪状态.


线程死亡

线程会以如下三种方式之一结束,结束后就处于死亡状态:

run()方法执行完成,线程正常结束。

线程抛出一个未捕获的ExceptionError.

真接调用该线程的stop()方法来结束该线程该方法容易致使死锁,一般不推荐使用。


注:

主线程结束时候,其余线程不受任何影响,并不会随之结束。一旦子线程启动起来后,它就拥有和主线程相同的地位,它不会受主线程的影响。



进程:是一个正在执行中的程序。

每个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。


线程:就是进程中的一个独立的控制单元。

线程在控制着进程的执行。


一个进程中至少有一个线程。


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


该进程中至少一个线程负责java程序的执行。

并且这个线程运行的代码存在于main方法中。

该线程称之为主线程。


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


1,如何在自定义的代码中,自定义一个线程呢?


经过对api的查找,java已经提供了对线程这类事物的描述。就Thread类。


建立线程的第一种方式:继承Thread类。

步骤:

1,定义类继承Thread

2,复写Thread类中的run方法。

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

3,调用线程的start方法,

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


发现运行结果每一次都不一样。

由于多个线程都获取cpu的执行权。cpu执行到谁,谁就运行。

明确一点,在某一个时刻,只能有一个程序在运行。(多核除外)

cpu在作着快速的切换,以达到看上去是同时运行的效果。

咱们能够形象把多线程的运行行为在互相抢夺cpu的执行权。


这就是多线程的一个特性:随机性。谁抢到谁执行,至于执行多长,cpu说的算。


为何要覆盖run方法呢?


Thread类用于描述线程。

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


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


建立线程的第二种方式:实现Runable接口

步骤:

1,定义类实现Runnable接口

2,覆盖Runnable接口中的run方法。

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

3,经过Thread类创建线程对象。

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

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

由于,自定义的run方法所属的对象是Runnable接口的子类对象。

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

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

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

实现方式好处:避免了单继承的局限性。

在定义线程时,创建使用实现方式。


两种方式区别

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

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


线程安全

经过分析,发现,打印出0-1-2等错票。


多线程的运行出现了安全问题。

问题的缘由:

当多条语句在操做同一个线程共享数据时,一个线程对多条语句只执行了一部分,尚未执行完,

另外一个线程参与进来执行。致使共享数据的错误。

解决办法:

对多条操做共享数据的语句,只能让一个线程都执行完。在执行过程当中,其余线程不能够参与执行。

Java对于多线程的安全问题提供了专业的解决方式


就是同步代码块


synchronized(对象)

{

须要被同步的代码


}

对象如同锁。持有锁的线程能够在同步中执行。

没有持有锁的线程即便获取cpu的执行权,也进不去,由于没有获取锁。


火车上的卫生间---经典。


同步的前提:

1,必需要有两个或者两个以上的线程。

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


必须保证同步中只能有一个线程在运行。

好处:解决了多线程的安全问题。


弊端:多个线程须要判断锁,较为消耗资源,


同步函数用的是哪个锁呢?

函数须要被对象调用。那么函数都有一个所属对象引用。就是this

因此同步函数使用的锁是this

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


经过验证,发现不在是this。由于静态方法中也不能够定义this


静态进内存是,内存中没有本类对象,可是必定有该类对应的字节码文件对象。

类名.class  该对象的类型是Class


静态的同步方法,使用的锁是该方法所在类的字节码文件对象。 类名.class


如何找问题:

1,明确哪些代码是多线程运行代码。

2,明确共享数据。

3,明确多线程运行代码中哪些语句是操做共享数据的。


死锁

当两个线程相互等待对方释放同步监视器时就会发生死锁Java虚拟机没有监测,也没有采用措施来处理死锁状况,因此多线程编程时应该采起措施避免死锁的出现。一旦出现死锁,整个程序既不会发生任何异常,也不会给出任何提示,只是全部线程处于阻塞状态,没法继续。

同步中嵌套同步。

线程通讯

在同步代码中能够使用锁对象的wait()方法让当前线程等待

使用锁对象的notify()方法能够将正在等待的线程唤醒

若是多个线程都在等待,notify()唤醒随机1

notifyAll()方法能够唤醒全部在等待的线程

 等待唤醒机制

//notifyAll();


/*

wait:

notify();

notifyAll();


都使用在同步中,由于要对持有监视器()的线程操做。

因此要使用在同步中,由于只有同步才具备锁。


为何这些操做线程的方法要定义Object类中呢?

由于这些方法在操做同步中线程时,都必需要标识它们所操做线程只有的锁,

只有同一个锁上的被等待线程,能够被同一个锁上notify唤醒。

不能够对不一样锁中的线程进行唤醒。


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


而锁能够是任意对象,因此能够被任意对象调用的方法定义Object类中。


 生产者、消费者

对于多个生产者和消费者。

为何要定义while判断标记。

缘由:让被唤醒的线程再一次判断标记。


为何定义notifyAll

由于须要唤醒对方线程。

由于只用notify,容易出现只唤醒本方线程的状况。致使程序中的全部线程都等待。


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

将同步Synchronized替换成现实Lock操做。

Object中的waitnotify notifyAll,替换了Condition对象。

该对象能够Lock 进行获取。

该示例中,实现了本方只唤醒对方操做。


Lock:替代了Synchronized

lock 

unlock

newCondition()


Condition:替代了Object wait notify notifyAll

await();

signal();

signalAll();

 Thread中的一些方法

stop方法已通过时。


如何中止线程?

只有一种,run方法结束。

开启多线程运行,运行代码一般是循环结构。


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


特殊状况:

当线程处于了冻结状态。

就不会读取到标记。那么线程就不会结束。


当没有指定的方式让冻结的线程恢复到运行状态是,这时须要对冻结进行清除。

强制让线程恢复到运行状态中来。这样就能够操做标记让线程结束。


Thread类提供该方法 interrupt();


join:

A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。

join能够用来临时加入线程执行。

yield:

暂停当前正在执行的线程对象,并执行其余线程。


后台线程有个特征:若是全部的前台线程都死亡,后台线程会自动死亡。

String

什么是API

API全名:Application Programming InterfaceAPI是应用程序编程接口,指一些预先定义好的类。

例如咱们想要一台电脑,并不须要本身生产每一个零件,只要从各个厂商买到组装电脑的零件就能够,而后根听说明书学会使用,将零件安装在一块儿就获得了电脑。电脑就像是咱们要的程序,而零件就是API,说明书就是帮助文档。

Java API

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

咱们能够经过查帮助文档来了解Java提供的API如何使用

Java中经常使用API

String

对字符串进行操做一般咱们使用String类,相关的还有StringBufferStringBuilder

集合类

集合是一种容器,用来存取对象(CollectionMap)

包装类

Java定义了一组包装类对基本数据类型进行了包装(IntegerDoubleBoolean)

时间对象

Java定义了一些类方便用户对时间、日期进行处理(DateCalendar)

系统类

Java定义了一些类针对系统进行操做(SystemRuntime)

IO

Java定义了一些类对数据传输进行了封装(输入输出流、File文件对象)

Socket

Java定义了一些类方便用户进行网络编程(SocketDatagramSocket)

String对象的存储

字符串是常量,一旦建立不能被修改。

字符串在程序中常用,虚拟机会将其缓存在String池中。

了解 String s = “abc” String s = new String(“abc”) 的区别。


String中经常使用方法


String类适用于描述字符串事物。

那么它就提供了多个方法对字符串进行操做。


常见的操做有哪些?

"abcd"


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, int fromIndex) :fromIndex指定位置开始,获取str在字符串中出现的位置。


int lastIndexOf(int ch)


2,判断。

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

boolean contains(str):

特殊之处:indexOf(str):能够索引str第一次出现位置,若是返回-1.表示该str不在字符串中存在。

因此,也能够用于对指定判断是否包含。

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


并且该方法便可以判断,有能够获取出现的位置。


2.2 字符中是否有内容。

boolean isEmpty(): 原理就是判断长度是否为0. 

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

boolean startsWith(str);

2.4 字符串是不是以指定内容结尾。

boolean endsWith(str);

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

boolean equals(str);

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

boolean equalsIgnoreCase();

3,转换。

3.1 将字符数组转成字符串。

构造函数:String(char[])

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


静态方法:

static String copyValueOf(char[]);

static String copyValueOf(char[] data, int offset, int count) 


static String valueOf(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);


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


4,替换

String replace(oldchar,newchar);


5,切割

String[] split(regex);


6,子串。获取字符串中的一部分。

String substring(begin);

String substring(begin,end);


7,转换,去除空格,比较。

7.1 将字符串转成大写或则小写。

String toUpperCase();

String toLowerCase();


7.2 将字符串两端的多个空格去除。

String trim();


7.3 对两个字符串进行天然顺序的比较。

int compareTo(string);

StringBuffer StringBuilder

StringBuffer是字符串缓冲区。


是一个容器。

特色:

1,长度是可变化的。

2,能够字节操做多个数据类型。

3,最终会经过toString方法变成字符串。


C create U update R read D delete


1,存储。

StringBuffer append():将指定数据做为参数添加到已有数据结尾处。

StringBuffer insert(index,数据):能够将数据插入到指定index位置。


2,删除。

StringBuffer delete(start,end):删除缓冲区中的数据,包含start,不包含end

StringBuffer deleteCharAt(index):删除指定位置的字符。

3,获取

char charAt(int index) 

int indexOf(String str) 

int lastIndexOf(String str) 

int length() 

String substring(int start, int end) 

 

4,修改。

StringBuffer replace(start,end,string);

void setCharAt(int index, char ch) ;


5,反转

StringBuffer reverse();

 

6

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

void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) 


JDK1.5 版本以后出现了StringBuilder.


StringBuffer是线程同步。

StringBuilder是线程不一样步。


之后开发,建议使用StringBuilder


升级三个因素:

1,提升效率。

2,简化书写。

3,提升安全性。



基本数据类型包装类

基本数据类型对象包装类。


byte Byte

short Short

int       Integer

long     Long

Boolean  Boolean

Float  Float

double Double

char         Character


基本数据类型对象包装类的最多见做用

就是用于基本数据类型和字符串类型之间作转换


基本数据类型转成字符串。


基本数据类型+""


基本数据类型.toString(基本数据类型值);


如: Integer.toString(34);//34整数变成"34";



字符串转成基本数据类型


xxx a = Xxx.parseXxx(String);


int a = Integer.parseInt("123");


double b = Double.parseDouble("12.23");


boolean b = Boolean.parseBoolean("true");


Integer i = new Integer("123");


int num = i.intValue();




十进制转成其余进制。

toBinaryString();

toHexString();

toOctalString();



其余进制转成十进制。

parseInt(string,radix);



JDK1.5版本之后出现的新特性。

Integer x = 4;//自动装箱。//new Integer(4)


x = x/* x.intValue() */ + 2;//x+2:x 进行自动拆箱。变成成了int类型。和2进行加法运算。

//再将和进行装箱赋给x



Integer m = 128;

Integer n = 128;


sop("m==n:"+(m==n));


Integer a = 127;

Integer b = 127;


sop("a==b:"+(a==b));//结果为true。由于ab指向了同一个Integer对象。

//由于当数值在byte范围内容,对于新特性,若是该数值已经存在,则不会在开辟新的空间。

集合

集合概述

为何出现集合类?

在面向对象的编程思想中,都是以对象的形式对事物进行描述的,为了保证对象的生命周期,咱们须要持有对象

在不少状况下,咱们不知道在程序中须要建立多少个对象,这时就不能依靠定义引用对象的变量来持有每个对象

存储对象的容器就能帮咱们解决这样的问题,而集合即是这样的容器

数组和集合类的区别

数组和集合类都是容器,都能存储对象

集合类的优点就在于长度可变

集合类的特色

集合类可用于存储对象

集合类的长度可变

一个集合能够存储多种类型的对象

集合接口

Collection接口

一个独立的元素的序列,这些元素服从一条或多条规则

Collection接口下主要分为List集合和Set集合

List集合的特色是元素有序、容许有重复元素

Set集合的特色是元素无存储顺序、不容许有重复元素


Collection定义了集合框架的共性功能。

1添加

add(e);

addAll(collection);


2删除

remove(e);

removeAll(collection);

clear();


3判断。

contains(e);

isEmpty();


4获取

iterator();

size();


5获取交集

retainAll();


6集合变数组

toArray();


1add方法的参数类型是Object。以便于接收任意类型对象。


2集合中存储的都是对象的引用(地址)

Map接口

一组成对的键值对对象,容许根据键来查找值

Map集合的键不容许有重复,因此Map的全部键构成了一个Set集合

主要学习HashMapTreeMap

Iterable接口

JDK1.5新定义的接口做为Collection的父接口

主要为了实现加强for循环


什么是迭代器呢?

其实就是集合的取出元素的方式。

如同抓娃娃游戏机中的夹子。


迭代器是取出方式,会直接访问集合中的元素。

因此将迭代器经过内部类的形式来进行描述。

经过容器的iterator()方法获取该内部类的对象。


List

List特色

元素有序,可重复。

咱们主要学习三种:ArrayListVectorLinkedList

这三种都是List接口的实现类,使用上彻底同样,只是实现原理不一样,效率不一样。

List集合判断元素是否相同,依据是元素的equals方法。

ArrayList

底层数组实现

查找快,增删慢

线程不安全

Vector

ArrayList基本同样

线程安全(线程同步),效率低


枚举就是Vector特有的取出方式。

发现枚举和迭代器很像。

其实枚举和迭代是同样的。


由于枚举的名称以及方法的名称都过长。

因此被迭代器取代了。

枚举郁郁而终了。

LinkedList

底层链表实现

增删块,查找慢


LinkedList:特有方法:

addFirst();

addLast();


getFirst();

getLast();

获取元素,但不删除元素。若是集合中没有元素,会出现NoSuchElementException


removeFirst();

removeLast();

获取元素,可是元素被删除。若是集合中没有元素,会出现NoSuchElementException



JDK1.6出现了替代方法。


offerFirst();

offerLast();



peekFirst();

peekLast();

获取元素,但不删除元素。若是集合中没有元素,会返回null


pollFirst();

pollLast();

获取元素,可是元素被删除。若是集合中没有元素,会返回null

存取元素

List集合元素存取方法一致

使用add()方法增长元素

因为List集合有序,能够使用get()方法获取元素

元素的迭代(Iterator)

经过集合对象的iterator()方法得到迭代器Iterator

经过Iterator迭代器的hasNext()方法判断是否存在下一个元素

经过Iterator迭代器的next()方法获取下一个元素

元素的迭代(Enumeration)

迭代Vector集合中的元素能够使用Enumeration

经过EnumerationhasMoreElements()方法判断是否还有元素

经过EnumerationnextElement()方法返回下一个元素


Collection

|--List:元素是有序的,元素能够重复。由于该集合体系有索引。

|--ArrayList:底层的数据结构使用的是数组结构。特色:查询速度很快。可是增删稍慢。线程不一样步。

|--LinkedList:底层使用的链表数据结构。特色:增删速度很快,查询稍慢。线程不一样步。

|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。由于效率低。



|--Set:元素是无序,元素不能够重复。、



List

特有方法。凡是能够操做角标的方法都是该体系特有的方法。


add(index,element);

addAll(index,Collection);


remove(index);


set(index,element);

get(index):

subList(from,to);

listIterator();

int indexOf(obj):获取指定元素的位置。

ListIterator listIterator();


List集合特有的迭代器。ListIteratorIterator的子接口。


在迭代时,不能够经过集合对象的方法操做集合中的元素。

由于会发生ConcurrentModificationException异常。


因此,在迭代器时,只能用迭代器的放过操做元素,但是Iterator方法是有限的,

只能对元素进行判断,取出,删除的操做,

若是想要其余的操做如添加,修改等,就须要使用其子接口,ListIterator


该接口只能经过List集合的listIterator方法获取。


Set

Set集合无序,不容许有重复元素

Set集合经过存入对象的equals方法来保证集合中没有重复元素

HashSet

HashSetSet的子类,所以也没有重复元素

底层使用哈希算法保证没有重复元素

存储对象时,先调用对象的hashCode()方法计算一个哈希值,在集合中查找是否有哈希值相同的对象。

若是没有哈希值相同的对象,直接存入。

若是有哈希值相同的对象,则和哈希值相同的对象进行equals()方法比较

equals()方法比较结果相同则不存,不一样就存入。

HashSet集合里存储的对象必须正确重写hashCodeequals方法

TreeSet

TreeSet集合经过二叉树算法保证无重复元素,并对元素进行排序

在使用TreeSet时必须指定比较的算法,指定的方式有两种:

天然顺序:将要存储的类实现Comparable接口,重写compareTo方法,在方法中指定算法

比较器顺序:在建立TreeSet时,传入一个比较器Comparator,在比较器的compare方法中指定算法


--Set元素是无序(存入和取出的顺序不必定一致),元素不能够重复。、

|--HashSet:底层数据结构是哈希表。是线程不安全的。不一样步。

HashSet是如何保证元素惟一性的呢?

是经过元素的两个方法,hashCodeequals来完成

若是元素的HashCode值相同,才会判断equals是否为true

若是元素的hashcode值不一样,不会调用equals


注意,对于判断元素是否存在,以及删除等操做,依赖的方法是元素的hashcodeequals方法。



|--TreeSet能够对Set集合中的元素进行排序。

底层数据结构是二叉树。

保证元素惟一性的依据:

compareTo方法return 0.


TreeSet排序的第一种方式:让元素自身具有比较性。

元素须要实现Comparable接口,覆盖compareTo方法。

也种方式也成为元素的天然顺序,或者叫作默认顺序。


TreeSet的第二种排序方式。

当元素自身不具有比较性时,或者具有的比较性不是所须要的。

这时就须要让集合自身具有比较性。

在集合初始化时,就有了比较方式。


当元素自身不具有比较性,或者具有的比较性不是所须要的。

这时须要让容器自身具有比较性。

定义了比较器,将比较器对象做为参数传递给TreeSet集合的构造函数。


当两种排序都存在时,以比较器为主。


定义一个类,实现Comparator接口,覆盖compare方法。


Set集合的功能和Collection是一致的。


泛型

泛型

因为集合能够存储不一样类型的数据,因此取元素时有可能会致使类型转换错误

JDK1.5增长了新特性泛型,为了减小操做集合时出错的概率

集合一旦声明了泛型,便只能存储同一类型的对象了


好处

1.将运行时期出现问题ClassCastException,转移到了编译时期。,

方便于程序员解决问题。让运行时问题减小,安全。,

2,避免了强制转换麻烦。



泛型格式:经过<>来定义要操做的引用数据类型。


在使用java提供的对象时,何时写泛型呢?

一般在集合框架中很常见,

只要见到<>就要定义泛型。


其实<> 就是用来接收类型的。


当使用集合时,将集合中要存储的数据类型做为参数传递到<>中便可。


泛型类。

何时定义泛型类?

当类中要操做的引用数据类型不肯定的时候,

早期定义Object来完成扩展。

如今定义泛型来完成扩展。

class Utils<QQ>

{

private QQ q;

public void setObject(QQ q)

{

this.q = q;

}

public QQ getObject()

{

return q;

}

}



泛型类定义的泛型,在整个类中有效。若是被方法使用,

那么泛型类的对象明确要操做的具体类型后,全部要操做的类型就已经固定了。

为了让不一样方法能够操做不一样类型,并且类型还不肯定。

那么能够将泛型定义在方法上。



特殊之处

静态方法不能够访问类上定义的泛型。

若是静态方法操做的应用数据类型不肯定,能够将泛型定义在方法上。


泛型定义在接口上。

interface Inter<T>

{

void show(T t);

}


? 通配符。也能够理解为占位符。

泛型的限定;

extends E: 能够接收E类型或者E的子类型。上限。

super E: 能够接收E类型或者E的父类型。下限

Map

Map集合的特色

Map存储了一系列键值的映射关系

Map集合须要保证键的惟一性

能够经过键得到值,反之则不能

Map集合存储元素使用put(key,value)方法

HashMap

线程不安全,存取速度快,容许存放null键,null值。 

经过HashSet原理保证键惟一性

Hashtable

线程安全,速度慢,不容许存放null键,null,已被HashMap替代。

TreeMap

经过二叉树算法保证键惟一性

对键进行排序,排序原理与TreeSet相同。

Properties

Hashtable的子类,因此也是线程安全的

用于读写配置文件的,通常配置项等号两边都是String,因此该集合中的两列保存的都是String类型的数据

这个集合中只能存String,因此不须要定义泛型。


Map集合:该集合存储键值对。一对一对往里存。并且要保证键的惟一性。

1,添加。

put(K key, V value) 

putAll(Map<? extends K,? extends V> m) 


2,删除。

clear() 

remove(Object key) 


3,判断。

containsValue(Object value) 

containsKey(Object key) 

isEmpty() 



4,获取

get(Object key) 

size() 

values() 


entrySet() 

keySet() 


Map

|--Hashtable:底层是哈希表数据结构,不能够存入nullnull值。该集合是线程同步的。jdk1.0.效率低。

|--HashMap:底层是哈希表数据结构,容许使用 null 值和 null 键,该集合是不一样步的。将hashtable替代,jdk1.2.效率高。

|--TreeMap:底层是二叉树数据结构。线程不一样步。能够用于给map集合中的键进行排序。



Set很像。

其实你们,Set底层就是使用了Map集合。


map集合的两种取出方式

1Set<k> keySetmap中全部的键存入到Set集合。由于set具有迭代器。

全部能够迭代方式取出全部的键,在根据get方法。获取每个键对应的值。


Map集合的取出原理:将map集合转成set集合。在经过迭代器取出。



2Set<Map.Entry<k,v>> entrySetmap集合中的映射关系存入到了set集合中,

而这个关系的数据类型就是:Map.Entry


Entry其实就是Map中的一个static内部接口。

为何要定义在内部呢?

由于只有有了Map集合,有了键值对,才会有键值的映射关系。

关系属于Map集合中的一个内部事物。

并且该事物在直接访问Map集合中的元素。

Map.Entry 其实Entry也是一个接口,它是Map接口中的一个内部接口。


工具类

 Collections

Collections

工具类,提供了对集合的经常使用操做

对集合进行查找

取出集合中的最大值,最小值

List集合进行排序


集合框架的工具类。

Collections:集合框架的工具类。里面定义的都是静态方法。


CollectionsCollection有什么区别?

Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。

它有两个经常使用的子接口,

List:对元素都有定义索引。有序的。能够重复元素。

Set:不能够重复元素。无序。


Collections是集合框架中的一个工具类。该类中的方法都是静态的

提供的方法中有能够对list集合进行排序,二分查找等方法。

一般经常使用的集合都是线程不安全的。由于要提升效率。

若是多线程操做这些集合时,能够经过该工具类中的同步方法,将线程不安全的集合,转换成安全的。


1,指定类型的数组到底要定义多长呢?

当指定类型的数组长度小于了集合的size,那么该方法内部会建立一个新的数组。长度为集合的size

当指定类型的数组长度大于了集合的size,就不会新建立了数组。而是使用传递进来的数组。

因此建立一个刚恰好的数组最优。


2,为何要将集合变数组?

为了限定对元素的操做。不须要进行增删了。


 Arrays

Arrays

工具类,提供了对数组的经常使用操做

将数组转成List集合

对数组进行排序

对数组进行二分查找

将数组转为字符串显示形式


Arrays:用于操做数组的工具类。

里面都是静态方法。

asList:将数组变成list集合


把数组变成list集合有什么好处?

能够使用集合的思想和方法来操做数组中的元素。


注意:将数组变成集合,不能够使用集合的增删方法。

由于数组的长度是固定。

contains

get

indexOf()

subList();


若是你增删。那么会反生UnsupportedOperationException,


若是数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。

若是数组中的元素都是基本数据类型,那么会将该数组做为集合中的元素存在。


JDK1.5新特性

 加强For循环

高级for循环


格式:

for(数据类型 变量名 : 被遍历的集合(Collection)或者数组)

{

}


对集合进行遍历。

只能获取集合元素。可是不能对集合进行操做。


迭代器除了遍历,还能够进行remove集合中元素的动做。

若是是用ListIterator,还能够在遍历过程当中对集合进行增删改查的动做。


传统for和高级for有什么区别呢?

高级for有一个局限性。必须有被遍历的目标。

建议在遍历数组的时候,仍是但愿是用传统for。由于传统for能够定义脚标。


 可变参数

方法的可变参数。

在使用时注意:可变参数必定要定义在参数列表最后面。

可变参数。

其实就是上一种数组参数的简写形式。

不用每一次都手动的创建数组对象。

只要将要操做的元素做为参数传递便可。

隐式将这些参数封装成了数组。

 静态导入

StaticImport  静态导入。


当类名重名时,须要指定具体的包名。

当方法重名是,指定具有所属的对象或者类。



import java.util.*;

import static  java.util.Arrays.*;//导入的是Arrays这个类中的全部静态成员。

import static java.util.Collections.*;


import static  java.lang.System.*;//导入了System类中全部静态成员。


其它工具类

 System

System

静态属性in为标准输入流,属于InputStream类型,read方法返回一个字节

静态属性out为标准打印流,属于PrintStream类型,print方法打印字符

能够用set方法修改属性inout

System.exit()方法退出Java虚拟机

System.gc()垃圾回收

System.getProperties()方法得到系统属性


由于PropertiesHashtable的子类,也就是Map集合的一个子类对象。

那么能够经过map的方法取出该集合中的元素。

该集合中存储都是字符串。没有泛型定义。


可不能够在jvm启动时,动态加载一些属性信息呢?


java –D<NAME>=<VALUE> xxxDemo

eg.

java –Dhh=tt HelloWorld


 Runtime

Runtime

表示系统运行时状态

exec方法执行命令 


Runtime对象

该类并无提供构造函数。

说明不能够new对象。那么会直接想到该类中的方法都是静态的。

发现该类中还有非静态方法。

说明该类确定会提供了方法获取本类对象。并且该方法是静态的,并返回值类型是本类类型。


由这个特色能够看出该类使用了单例设计模式完成。


该方式是static Runtime getRuntime();


 时间类

 Date

Date

使用new Date()建立时间对象表明当前系统时间

须要使用DateFormat类来进行格式化,才能显示想符合习惯的格式


 Calendar

Calendar

使用该类对时间进行操做比较方便

经过常量来表示时间的各类值,如一年中的某一天,一个月的某一天等

将对应的常量做为形参来调用相应的getaddset方法来操做对象

练习

计算出某一年的二月份有多少天?

设计一个方法能够计算工做时间,接收一个参数(工做日),方法打印出哪天完工。

 Math—Random

static double ceil(double d) 返回大于d的最小整数 注意 d = 12.3时,结果:13 

 d = -12.3 结果:-12

static double floor(double a) 返回小于a的最大整数,

static long round(double a) 返回a的四舍五入的整数


Math.random()Random.NextInt(int n)的使用;


IO

IO概述

IO流用来处理设备之间的数据传输

Java对数据的操做是经过流的方式

Java用于操做流的对象都在IO包中

流按操做对象分为两种:字节流与字符流。  字节流能够操做任何数据,字符流只能操做纯字符数据比较方便。

流按流向分为:输入流,输出流。


IO流经常使用基类

字节流的抽象基类:

InputStream OutputStream

字符流的抽象基类:

Reader Writer

由这四个类派生出来的子类名称都是以其父类名做为子类名的后缀。

如:InputStream的子类FileInputStream

如:Reader的子类FileReader

InputStreamReaderReader的子类


字符流的操做

读取文件

定义字符流关联指定文件

FileReader reader = new FileReader("Test.txt");

读取一个字符,返回int,该字符的码表值

int ch = reader.read();

关闭流,释放资源

reader.close();

写出文件

定义字符输出流关联指定文件

FileWriter writer = new FileWriter("Test.txt");

写出一个字符,接收int码表值

writer.write(97);

关闭流,释放资源

writer.close();

注意事项

文件路径

定义文件路径时Windows中的目录符号为“\”,但这个符号在Java中是特殊字符,须要转义。

能够用“\\”“/”表示。

读取文件

读取文件时必须保证文件存在,不然将抛出FileNotFoundException

写出文件

写出时文件如不存在时程序会建立新文件,如文件已存在则会清空原文件内容从新写入。

如需追加内容可调用FileWriter构造函数 HYPERLINK "mk:@MSITStore:D:\\ItCast\\doc\\J2SE6.0_CN.chm::/java/io/FileWriter.html" \l "FileWriter(java.lang.String,%20boolean)" FileWriter( HYPERLINK "mk:@MSITStore:D:\\ItCast\\doc\\J2SE6.0_CN.chm::/java/lang/String.html" \o "java.lang 中的类" String fileName, boolean append)

练习

拷贝一个文件

字符流待缓冲区的读写操做

自定义缓冲区读写

为何定义缓冲区

因为单个字符读写须要频繁操做文件,因此效率很是低。

咱们能够定义缓冲区将要读取或写出的数据缓存,减小操做文件次数。

缓冲区读取

先定义一个数组,而后调用FileReader读取一个数组的方法。

int read(char[] cbuf)

缓冲区写出

将要写出的数据存放在数组中,调用FileWriter方法,一次写出一个数组。

void write(char[] cbuf, int off, int len)

内置缓冲区的BufferedReaderBufferedWriter

Java提供了带缓冲功能的ReaderWriter类:BufferedReaderBufferedWriter

这两个类都是提供包装功能,须要提供其余流来使用,给其余流增长缓冲功能

当咱们调用BufferedReader读取数据时,程序会从文件中一次读取8192个字符用来缓冲

当咱们调用BufferedWriter写出数据时,程序会先将数据写出到缓冲数组,直到写满8192个才一次性刷出到文件

特有方法 newLine(),  readLine()

注意:BufferedReader 读取时 不会读取换行符,因此写入时会出现乱序,

在写入后加newLine();能够解决


Eg1.

需求:在硬盘上,建立一个文件并写入一些文字数据。


找到一个专门用于操做文件的Writer子类对象。FileWriter  后缀名是父类名。 前缀名是该流对象的功能。

*/

import java.io.*;

class  FileWriterDemo

{

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

{

//建立一个FileWriter对象。该对象一被初始化就必需要明确被操做的文件。

//并且该文件会被建立到指定目录下。若是该目录下已有同名文件,将被覆盖。

//其实该步就是在明确数据要存放的目的地。

FileWriter fw = new FileWriter("demo.txt");


//调用write方法,将字符串写入到流中。

fw.write("abcde");


//刷新流对象中的缓冲中的数据。

//将数据刷到目的地中。

//fw.flush();



//关闭流资源,可是关闭以前会刷新一次内部的缓冲中的数据。

//将数据刷到目的地中。

//flush区别:flush刷新后,流能够继续使用,close刷新后,会将流关闭。

fw.close();

}

}

Eg2.

/*

演示对已有文件的数据续写。

*/

import java.io.*;

class  FileWriterDemo3

{

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

{


//传递一个true参数,表明不覆盖已有的文件。并在已有文件的末尾处进行数据续写。

FileWriter fw = new FileWriter("demo.txt",true);


fw.write("nihao\r\nxiexie");


fw.close();

}

}

Eg.3

//C盘一个文本文件复制到D盘。


/*

复制的原理:

其实就是将C盘下的文件数据存储到D盘的一个文件中。


步骤:

1,在D盘建立一个文件。用于存储C盘文件中的数据。

2,定义读取流和C盘文件关联。

3,经过不断的读写完成数据存储。

4,关闭资源。

*/

import java.io.*;


class CopyText 

{

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

{

copy_2();

}



public static void copy_2()

{

FileWriter fw = null;

FileReader fr = null;

try

{

fw = new FileWriter("SystemDemo_copy.txt");

fr = new FileReader("SystemDemo.java");


char[] buf = new char[1024];


int len = 0;

while((len=fr.read(buf))!=-1)

{

fw.write(buf,0,len);

}

}

catch (IOException e)

{

throw new RuntimeException("读写失败");


}

finally

{

if(fr!=null)

try

{

fr.close();

}

catch (IOException e)

{

}

if(fw!=null)

try

{

fw.close();

}

catch (IOException e)

{

}

}

}


//C盘读一个字符,就往D盘写一个字符。

public static void copy_1()throws IOException

{

//建立目的地。

FileWriter fw = new FileWriter("RuntimeDemo_copy.txt");


//与已有文件关联。

FileReader fr = new FileReader("RuntimeDemo.java");


int ch = 0;


while((ch=fr.read())!=-1)

{

fw.write(ch);

}

fw.close();

fr.close();


}

}



装饰设计模式

什么状况下使用装饰设计模式

当咱们须要对一个类的功能进行改进、加强的时候

装饰模式的基本格式。

含有被装饰类的引用

经过构造函数传入被装饰类对象

和被装饰类含有一样的方法,其中调用被装饰类的方法,对其进行改进、加强

和被装饰类继承同一个类或实现同一个接口,能够当作被装饰类来使用

了解BufferedReaderBufferedWriter的原理。

BufferedReaderBufferedWriter都是装饰类,他们能够装饰一个ReaderWriter,给被装饰的ReaderWriter提供缓冲的功能。

就像咱们用BufferedReaderBufferedWriter装饰FileReaderFileWriter,使用的读写功能仍是FileReaderFileWriter的,但给这两个类的读写添加了缓冲功能。

练习

模拟一个BufferedReader类。

模拟一个LineNumberReader类。


装饰设计模式与继承的比较

MyReader//专门用于读取数据的类。

|--MyTextReader

|--MyBufferTextReader

|--MyMediaReader

|--MyBufferMediaReader

|--MyDataReader

|--MyBufferDataReader


class MyBufferReader

{

MyBufferReader(MyTextReader text)

{}

MyBufferReader(MyMediaReader media)

{}

}

上面这个类扩展性不好。

找到其参数的共同类型。经过多态的形式。能够提升扩展性。


class MyBufferReader extends MyReader

{

private MyReader r;

MyBufferReader(MyReader r)

{}

}



MyReader//专门用于读取数据的类。

|--MyTextReader

|--MyMediaReader

|--MyDataReader

|--MyBufferReader



之前是经过继承将每个子类都具有缓冲功能。

那么继承体系会复杂,并不利于扩展。


如今优化思想。单独描述一下缓冲内容。

将须要被缓冲的对象。传递进来。也就是,谁须要被缓冲,谁就做为参数传递给缓冲区。

这样继承体系就变得很简单。优化了体系结构。


装饰模式比继承要灵活。避免了继承体系臃肿。

并且下降了类于类之间的关系。


装饰类由于加强已有对象,具有的功能和已有的是相同的,只不过提供了更强功能。

因此装饰类和被装饰类一般是都属于一个体系中的。

字节流


基本操做与字符流相同

字节流能够操做任意类型数据

练习:拷贝一个Jpg文件


自定义缓冲区读写

原理和字符流相同,都是为了提升效率

定义数组缓冲数据,一次读取一个数组,一次写出一个数组,减小操做文件的次数

BufferedInputStreamBufferedOutputStream

BufferedReaderBufferedWriter原理相同,都是包装类

BufferedInputStreamBufferedOutputStream包装InputStreamOutputStream提供缓冲功能


转换流


字符流与字节流之间的桥梁

方便了字符流与字节流之间的操做

字节流中的数据都是字符时,转成字符流操做更高效

练习:转换System.in

注:转换流的输出流能够指定编码表


InputStreamReader,OutputStreamWriter


System类的setIn(),setout()方法能够改变输入输出设备


标准输入,输出

System类中的成员变量:inout

它们各表明了系统标准的输入和输出设备。

默认输入设备是键盘,输出设备是显示器。

System.in的类型是InputStream.

System.out的类型是PrintStreamOutputStream的子类FilterOutputStream 的子类.

练习:经过修改标准输入输出流,使用System.inSystem.out拷贝文件



流操做小结



 SHAPE  \* MERGEFORMAT 




 SHAPE  \* MERGEFORMAT 


1,

源:键盘录入。

目的:控制台。


2,需求:想把键盘录入的数据存储到一个文件中。

源:键盘。

目的:文件。


3,需求:想要将一个文件的数据打印在控制台上。

源:文件。

目的:控制台。


流操做的基本规律:

最痛苦的就是流对象有不少,不知道该用哪个。


经过三个明确来完成。


1,明确源和目的。

源:输入流。InputStream  Reader

目的:输出流。OutputStream  Writer

2,操做的数据是不是纯文本。

是:字符流。

不是:字节流。


3,当体系明确后,在明确要使用哪一个具体的对象。

经过设备来进行区分:

源设备:内存,硬盘。键盘

目的设备:内存,硬盘,控制台。


Eg.

1,将一个文本文件中数据存储到另外一个文件中。复制文件。

源:由于是源,因此使用读取流。InputStream Reader 

是否是操做文本文件。

是!这时就能够选择Reader

这样体系就明确了。


接下来明确要使用该体系中的哪一个对象。

明确设备:硬盘。上一个文件。

Reader体系中能够操做文件的对象是 FileReader


是否须要提升效率:是!。加入Reader体系中缓冲区 BufferedReader.



FileReader fr = new FileReader("a.txt");

BufferedReader bufr = new BufferedReader(fr);



目的:OutputStream Writer

是不是纯文本。

是!Writer

设备:硬盘,一个文件。

Writer体系中能够操做文件的对象FileWriter

是否须要提升效率:是!。加入Writer体系中缓冲区 BufferedWriter

FileWriter fw = new FileWriter("b.txt");

BufferedWriter bufw = new BufferedWriter(fw);



练习:将一个图片文件中数据存储到另外一个文件中。复制文件。要按照以上格式本身完成三个明确。



---------------------------------------


2,需求:将键盘录入的数据保存到一个文件中。

这个需求中有源和目的都存在。

那么分别分析

源:InputStream Reader

是否是纯文本?是!Reader

设备:键盘。对应的对象是System.in.

不是选择Reader吗?System.in对应的不是字节流吗?

为了操做键盘的文本数据方便。转成字符流按照字符串操做是最方便的。

因此既然明确了Reader,那么就将System.in转换成Reader

用了Reader体系中转换流,InputStreamReader


InputStreamReader isr = new InputStreamReader(System.in);


须要提升效率吗?须要!BufferedReader

BufferedReader bufr = new BufferedReader(isr);


目的:OutputStream  Writer

是不是存文本?是!Writer

设备:硬盘。一个文件。使用 FileWriter

FileWriter fw = new FileWriter("c.txt");

须要提升效率吗?须要。

BufferedWriter bufw = new BufferedWriter(fw);



**************

扩展一下,想要把录入的数据按照指定的编码表(utf-8),将数据存到文件中。

目的:OutputStream  Writer

是不是存文本?是!Writer

设备:硬盘。一个文件。使用 FileWriter

可是FileWriter是使用的默认编码表。GBK.

可是存储时,须要加入指定编码表utf-8。而指定的编码表只有转换流能够指定。

因此要使用的对象是OutputStreamWriter

而该转换流对象要接收一个字节输出流。并且还能够操做的文件的字节输出流。FileOutputStream


OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8");


须要高效吗?须要。

BufferedWriter bufw = new BufferedWriter(osw);


因此,记住。转换流什么使用。字符和字节之间的桥梁,一般,涉及到字符编码转换时,

须要用到转换流。



练习:将一个文本数据打印在控制台上。要按照以上格式本身完成三个明确。


File

File

用来将文件或者文件夹路径封装成对象

方便对文件与文件夹进行操做。

File对象能够做为参数传递给流的构造函数。

了解File类中的经常使用方法。


File类常见方法:

1,建立

boolean createNewFile():在指定位置建立文件,若是该文件已经存在,则不建立,返回false

和输出流不同,输出流对象一创建建立文件。并且文件已经存在,会覆盖。


boolean mkdir():建立文件夹。

boolean mkdirs():建立多级文件夹。

2,删除。

boolean delete():删除失败返回false。若是文件正在被使用,则删除不了返回falsel

void deleteOnExit();在程序退出时删除指定文件。



3,判断。

boolean exists() :文件是否存在.

isFile():

isDirectory();

isHidden();

isAbsolute();


4,获取信息。

getName():

getPath():

getParent():


getAbsolutePath() 

long lastModified() 

long length()



递归

函数本身调用本身。

注意:递归时必定要明确结束条件。

应用场景:

当某一功能要重复使用时。

练习:

列出一个文件夹下全部的子文件夹以及子文件

思考:

删除一个目录的过程是如何进行的?

复制一个目录的过程呢?


Properties

PropertiesHashtable的子类。

也就是说它具有map集合的特色。并且它里面存储的键值对都是字符串。


是集合中和IO技术相结合的集合容器。


该对象的特色:能够用于键值对形式的配置文件。


那么在加载数据时,须要数据有固定格式:键=值。


练习:限制程序运行次数。当运行次数到达5次时,给出,请您注册的提示。并再也不让该程序执行。


用于记录应用程序运行次数。

若是使用次数已到,那么给出注册提示。


很容易想到的是:计数器。

但是该计数器定义在程序中,随着程序的运行而在内存中存在,并进行自增。

但是随着该应用程序的退出,该计数器也在内存中消失了。


下一次在启动该程序,又从新开始从0计数。

这样不是咱们想要的。


程序即便结束,该计数器的值也存在。

下次程序启动在会先加载该计数器的值并加1后在从新存储起来。


因此要创建一个配置文件。用于记录该软件的使用次数。


该配置文件使用键值对的形式。

这样便于阅读数据,并操做数据。


键值对数据是map集合。

数据是以文件形式存储,使用io技术。

那么map+io -->properties.


配置文件能够实现应用程序数据的共享。


打印流

打印流:

该流提供了打印方法,能够将各类数据类型的数据都原样打印。


字节打印流:

PrintStream

构造函数能够接收的参数类型:

1file对象。File

2,字符串路径。String

3,字节输出流。OutputStream


字符打印流

PrintWriter

构造函数能够接收的参数类型:

1file对象。File

2,字符串路径。String

3,字节输出流。OutputStream

4,字符输出流,Writer


流的合并与切割

序列流

SequenceInputStream

能够将多个字节输入流整合成一个流,在使用这个流读取的时候,读到第一个流的末尾时继续读第二个,第二个读到末尾则继续读第三个,以此类推,直到读到最后一个流的末尾返回-1


import java.io.*;

import java.util.*;



/**

实现文件的切割与合并

@author yangmeicheng

*/

public class SplitStream 

{

public static void main(String[] args) 

{

//File file = new File("F:"+File.separator+"歌曲"+File.separator+"周杰伦 - 夜曲.ape");

//splitFile(file);

mergeFile();

}



public static void mergeFile()

{

ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();

FileInputStream fis = null;

for (int i=1;i<=7 ;i++ )

{

try

{

fis = new FileInputStream("D:"+File.separator+i+".part");

}

catch (FileNotFoundException e)

{

e.printStackTrace();

}

al.add(fis);

}


final Iterator<FileInputStream> it = al.iterator();


Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()

{

public boolean hasMoreElements()

{

return it.hasNext();

}


public FileInputStream nextElement()

{

return it.next();

}

};


SequenceInputStream sis = null;

BufferedOutputStream bos = null;


try

{

sis = new SequenceInputStream(en);

bos = new BufferedOutputStream(new FileOutputStream("d:\\yequ.mp3"));


int num = 0;

byte [] buff = new byte[1024*1024];


while ((num = sis.read(buff)) != -1)

{

bos.write(buff,0,num);

}

}

catch (IOException e)

{

throw new RuntimeException("合并失败");

}

finally 

{

if (null != sis )

{

try

{

sis.close();

}

catch (IOException e)

{

throw new RuntimeException("合并流读取失败");

}

}


if (null != bos )

{

try

{

bos.close();

}

catch (IOException e)

{

throw new RuntimeException("合并流写入失败");

}

}

}



}


public static void splitFile(File file)

{

BufferedInputStream bis = null;

BufferedOutputStream bos = null;


try

{

bis = new BufferedInputStream(new FileInputStream(file));

int num = 0;

int count = 1;

byte [] buff = new byte[1024*1024*4];

while ((num = bis.read(buff)) != -1)

{

bos = new BufferedOutputStream(new FileOutputStream("d:\\"+(count++)+".part"));

bos.write(buff,0,num);

}

}

catch ( IOException e)

{

throw new RuntimeException("切割失败");

}

finally 

{

if (null != bis )

{

try

{

bis.close();

}

catch (IOException e)

{

throw new RuntimeException("切割流读取失败");

}

}


if (null != bos )

{

try

{

bos.close();

}

catch (IOException e)

{

throw new RuntimeException("切割流写入失败");

}

}

}

}

}

对象序列化

ObjectOutputStream

能够将实现了Serializable的接口的对象转成字节写出到流中

ObjectInputStream

能够从流中读取一个ObjectOutputStream流写出的对象


静态成员变量不能持久化

transient 修饰 能够阻止成员被序列化


 管道流

管道流

PipedInputStream:管道输入流,能够从管道输出流中读取数据

PipedOutputStream:管道输出流,能够向管道输入流中写出数据


在创建管道输出流时能够在构造方法中将管道输入流传入,

或者用connect()方法将输入输出流接上,

建议:输出与输入在两个不一样的线程进行操做


随机读写

随机访问文件

RandomAccessFile



该类不是算是IO体系中子类。

而是直接继承自Object


可是它是IO包中成员。由于它具有读和写功能。

内部封装了一个数组,并且经过指针对数组的元素进行操做。

能够经过getFilePointer获取指针位置,

同时能够经过seek改变指针的位置。



其实完成读写的原理就是内部封装了字节输入流和输出流。


经过构造函数能够看出,该类只能操做文件。

并且操做文件还有模式:只读r,,读写rw等。


若是模式为只读 r。不会建立文件。会去读取一个已存在文件,若是该文件不存在,则会出现异常。

若是模式rw。操做的文件不存在,会自动建立。若是存则不会覆盖。


下载软件实现原理


操做基本数据类型的流

DataInputStreamDataOutputStream

能够按照基本数据类型占用空间大小读写数据


操做字节数组的流

ByteArrayOutputStream 写出到字节数组(内存)中,能够获取写出的内容装入一个字节数组。一般咱们用这个流来缓冲数据。

ByteArrayInputStream:能够从一个字节数组中读取字节。

CharArrayWriter:写出字符到字符数组(内存)中,能够获取写出的内容装入一个字符数组。

CharArrayReader:能够从一个字符数组中读取字符。


用于操做字节数组的流对象。


ByteArrayInputStream :在构造的时候,须要接收数据源,。并且数据源是一个字节数组。


ByteArrayOutputStream 在构造的时候,不用定义数据目的,由于该对象中已经内部封装了可变长度的字节数组。

这就是数据目的地。


由于这两个流对象都操做的数组,并无使用系统资源。

因此,不用进行close关闭。



在流操做规律讲解时:


源设备,

键盘 System.in,硬盘 FileStream,内存 ArrayStream

目的设备:

控制台 System.out,硬盘FileStream,内存 ArrayStream



用流的读写思想来操做数据。


字符编码

码表

ASCII:英文码表,每一个字符占1个字节。A65a97

GB2312:兼容ASCII,包含中文,每一个英文占1个字节(正数),中文占2个字节(2个负数)。 

GBK:兼容GB2312,包含更多中文,每一个英文占1个字节(正数),中文占2个字节(第一个负数、第二个可正可负)。 

Unicode:国际码表,每一个字符占2个字节。Java中存储字符类型就是使用的Unicode编码。

UTF-8:国际码表,英文占1个字节,中文占3个字节。


GUI(图形用户界面)

GUI概念

什么是GUI

GUIGraphical User Interface的缩写,图形化用户界面

awtswing

JavaGUI提供的对象都存在java.awtjavax.swing两个包中

awt依赖于本地系统平台,如颜色样式显示

swing跨平台

组件与容器

组件 Component,是GUI图形界面的组成单元。

容器Container,能够存放组件,也能够存放容器。


组件关系继承图


布局管理

FlowLayout(流式布局管理器)

从左到右的顺序排列。

BorderLayout(边界布局管理器)

东,南,西,北,中

GridLayout(网格布局管理器)

规则的矩阵

CardLayout(卡片布局管理器)

选项卡

GridBagLayout(网格包布局管理器)

非规则的矩阵


创建一个窗体

窗体中能够存放各类组件,因此窗体是容器Container。建立时咱们使用的是它的子类

Container的经常使用子类有两个,WindowPanelWindow是咱们经常使用的窗体,Panel是用来布局的不可见的。

Window也有两个经常使用子类,FrameDialogFrame是咱们经常使用的带有标题和边框的顶层窗口,Dialog是对话框。

全部AWT包中的类都会运行在AWT线程上

事件处理

事件处理机制

事件:用户对组件的一个操做。

事件源:发生事件的组件。

监听器:咱们须要处理某个事件,就须要在发生事件的组件上添加监听器,也就是java.awt.event包中XxxListener接口的子类。

事件处理器:监听器中的方法。监听器被添加在组件上以后,组件上发生了对应事件就会执行指定方法。


事件监听流程



经常使用事件分类


窗体事件,WindowEvent,窗体打开、关闭、正在关闭、激活、最小化等。

鼠标事件,MouseEvent,鼠标按下、抬起、进入、移出等。

键盘事件,KeyEvent,键盘按下、抬起等。

动做事件,ActionEvent,在某一组件上发生了定义好的动做,例如按钮上鼠标点击或按空格,菜单上鼠标点击或按回车等。



建立图形化界面:

1,建立frame窗体。

2,对窗体进行基本设置。

好比大小,位置,布局。

3,定义组件。

4,将组件经过窗体的add方法添加到窗体中。

5,让窗体显示,经过setVisible(true)


事件监听机制的特色:

1,事件源。

2,事件。

3,监听器。

4,事件处理。


事件源:就是awt包或者swing包中的那些图形界面组件。

事件:每个事件源都有本身特有的对应事件和共性事件。


监听器:将能够触发某一个事件的动做(不仅一个动做)都已经封装到了监听器中。


以上三者,在java中都已经定义好了。

直接获取其对象来用就能够了。


咱们要作的事情是,就是对产生的动做进行处理。


Socket网络编程

网络编程概述

IP地址(InetAddress类)

每台网络终端在网络中都有一个独立的地址,咱们在网络中传输数据就是使用这个地址。 

ipconfig:查看本机IP

ping:测试链接

本地回路地址:127.0.0.1

IPv44个字节组成,40-255。大概42亿,30亿都在北美,亚洲4亿。已经用尽。  

IPv68组,每组416进制数。

1a2b:0000:aaaa:0000:0000:0000:aabb:1f2f

1a2b::aaaa:0000:0000:0000:aabb:1f2f

1a2b:0000:aaaa::aabb:1f2f

1a2b:0000:aaaa::0000:aabb:1f2f

1a2b:0000:aaaa:0000::aabb:1f2f

端口号

每一个网络程序都须要绑定一个端口号,传输数据的时候除了肯定发到哪台机器上,还要明确发到哪一个程序。

端口号范围从0-65535

编写网络应用就须要绑定一个端口号,尽可能使用1024以上的,1024如下的基本上都被系统程序占用了。

经常使用端口

mysql: 3306

oracle: 1521

web: 80

tomcat: 8080

QQ: 4000

feiQ: 2425

网络协议

HYPERLINK "http://baike.baidu.com/view/25482.htm" \t "_blank" 计算机网络中进行数据交换而创建的规则、标准或约定的集合。

UDP

面向无链接,数据不安全,速度快。不区分客户端与服务端。

TCP

面向链接(三次握手),数据安全,速度略低。分为客户端和服务端。

Socket

通讯的两端都有Socket

网络通讯其实就是Socket间的通讯。

数据在两个Socket间经过IO传输。

Socket在应用程序中建立,经过一种绑定机制与驱动程序创建关系,告诉本身所对应的IPport


网络模型



UDP传输

发送

建立DatagramSocket

建立DatagramPacket

使用DatagramSocket发送DatagramPacket

关闭DatagramSocket

接收

建立DatagramSocket

建立DatagramPacket

使用DatagramSocket接收DatagramPacket

关闭DatagramSocket

TCP传输

客户端

建立Socket链接服务端

调用SocketgetInputStream()getOutputStream()方法获取和服务端相连的管道流

输入流能够读取服务端输出流写出的数据

输出流能够写出数据到服务端的输入流

服务端

建立ServerSocket

调用ServerSocketaccept()方法接收一个客户端请求,获得一个Socket

调用SocketgetInputStream()getOutputStream()方法获取和客户端相连的管道流

输入流能够读取客户端输出流写出的数据

输出流能够写出数据到客户端的输入流

URL-URLConnection

day24

正则表达式


正则表达式:符合必定规则的表达式。

做用:用于专门操做字符串。

特色:用于一些特定的符号来表示一些代码操做。这样就简化书写。

因此学习正则表达式,就是在学习一些特殊符号的使用。


好处:能够简化对字符串的复杂操做。

弊端:符号定义越多,正则越长,阅读性越差。



具体操做功能:


1,匹配:String  matches方法。用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false

2,切割:String split();


3,替换:String replaceAll(regex,str);若是regex中有定义组,能够在第二参数中经过$符号获取正则表达式中的已有的组。


4,获取:将字符串中的符合规则的子串取出。


操做步骤:

1,将正则表达式封装成对象。

2,让正则对象和要操做的字符串相关联。

3,关联后,获取正则匹配引擎。

4,经过引擎对符合规则的子串进行操做,好比取出。


正则表达式的构造摘要 

构造

匹配

 


字符

x

字符 x

\\


反斜线字符

\0n带有八进制值 0 的字符 n (0 <= n <= 7)

\0nn带有八进制值 0 的字符 nn (0 <= n <= 7)

\0mnn带有八进制值 0 的字符 mnn<= m <= 3<= n <= 7

\xhh带有十六进制值 0x 的字符 hh

\uhhhh带有十六进制值 0x 的字符 hhhh

\t制表符 ('\u0009')

\n新行(换行)符 ('\u000A')

\r回车符 ('\u000D')

\f换页符 ('\u000C')

\a报警 (bell) ('\u0007')

\e转义符 ('\u001B')

\cx


对应于 x 的控制符

 


字符类

[abc]ab c(简单类)

[^abc]任何字符,除了 ab c(否认)

[a-zA-Z]a z A Z,两头的字母包括在内(范围)

[a-d[m-p]]a d m p[a-dm-p](并集)

[a-z&&[def]]de f(交集)

[a-z&&[^bc]]a z,除了 b c[ad-z](减去)

[a-z&&[^m-p]]a z,而非 m p[a-lq-z](减去)

 


预约义字符类

.任何字符(与 HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "lt#lt" 行结束符可能匹配也可能不匹配)

\d数字:[0-9]

\D非数字: [^0-9]

\s空白字符:[ \t\n\x0B\f\r]

\S非空白字符:[^\s]

\w单词字符:[a-zA-Z_0-9]

\W非单词字符:[^\w]

 


POSIX 字符类(仅 US-ASCII

\p{Lower}小写字母字符:[a-z]

\p{Upper}大写字母字符:[A-Z]

\p{ASCII}全部 ASCII[\x00-\x7F]

\p{Alpha}字母字符:[\p{Lower}\p{Upper}]

\p{Digit}十进制数字:[0-9]

\p{Alnum}字母数字字符:[\p{Alpha}\p{Digit}]

\p{Punct}标点符号:!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

\p{Graph}可见字符:[\p{Alnum}\p{Punct}]

\p{Print}可打印字符:[\p{Graph}\x20]

\p{Blank}空格或制表符:[ \t]

\p{Cntrl}控制字符:[\x00-\x1F\x7F]

\p{XDigit}十六进制数字:[0-9a-fA-F]

\p{Space}空白字符:[ \t\n\x0B\f\r]

 


java.lang.Character 类(简单的  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "jcc#jcc" java 字符类型

\p{javaLowerCase}


等效于 java.lang.Character.isLowerCase()

\p{javaUpperCase}


等效于 java.lang.Character.isUpperCase()

\p{javaWhitespace}


等效于 java.lang.Character.isWhitespace()

\p{javaMirrored}


等效于 java.lang.Character.isMirrored()

 


Unicode 块和类别的类

\p{InGreek}Greek 块(简单 HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "ubc#ubc" )中的字符

\p{Lu}大写字母(简单 HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "ubc#ubc" 类别

\p{Sc}


货币符号

\P{InGreek}


全部字符,Greek 块中的除外(否认)

[\p{L}&&[^\p{Lu}]] 


全部字母,大写字母除外(减去)

 


边界匹配器

^


行的开头

$


行的结尾

\b


单词边界

\B


非单词边界

\A


输入的开头

\G


上一个匹配的结尾

\Z输入的结尾,仅用于最后的 HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "lt#lt" 结束符(若是有的话)

\z


输入的结尾

 


Greedy 数量词

X?


X,一次或一次也没有

X*


X,零次或屡次

X+


X,一次或屡次

X{n}


X,刚好 n

X{n,}


X,至少 n

X{n,m}


X,至少 n 次,可是不超过 m

 


Reluctant 数量词

X??


X,一次或一次也没有

X*?


X,零次或屡次

X+?


X,一次或屡次

X{n}?


X,刚好 n

X{n,}?


X,至少 n

X{n,m}?


X,至少 n 次,可是不超过 m

 


Possessive 数量词

X?+


X,一次或一次也没有

X*+


X,零次或屡次

X++


X,一次或屡次

X{n}+


X,刚好 n

X{n,}+


X,至少 n

X{n,m}+


X,至少 n 次,可是不超过 m

 


Logical 运算符

XY

X 后跟 Y

X|Y


X Y

(X)X,做为 HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "cg#cg" 捕获组

 


Back 引用

\n任何匹配的 nth  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "cg#cg" 捕获组

 


引用

\


Nothing,可是引用如下字符

\QNothing,可是引用全部字符,直到 \E

\ENothing,可是结束从 \Q 开始的引用

 


特殊构造(非捕获)

(?:X)


X,做为非捕获组

(?idmsux-idmsux) Nothing,可是将匹配标志 HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "CASE_INSENSITIVE#CASE_INSENSITIVE" i  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "UNIX_LINES#UNIX_LINES" d  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "MULTILINE#MULTILINE" m  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "DOTALL#DOTALL" s  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "UNICODE_CASE#UNICODE_CASE" u  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "COMMENTS#COMMENTS" x on - off

(?idmsux-idmsux:X)  X,做为带有给定标志  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "CASE_INSENSITIVE#CASE_INSENSITIVE" i  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "UNIX_LINES#UNIX_LINES" d  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "MULTILINE#MULTILINE" m  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "DOTALL#DOTALL" s  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "UNICODE_CASE#UNICODE_CASE" u  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "COMMENTS#COMMENTS" x on - off HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "cg#cg" 非捕获组 

(?=X)


X,经过零宽度的正 lookahead

(?!X)


X,经过零宽度的负 lookahead

(?<=X)


X,经过零宽度的正 lookbehind

(?<!X)


X,经过零宽度的负 lookbehind

(?>X)


X,做为独立的非捕获组


反斜线、转义和引用 

反斜线字符 ('\') 用于引用转义构造,如上表所定义的,同时还用于引用其余将被解释为非转义构造的字符。所以,表达式 \\ 与单个反斜线匹配,而 \{ 与左括号匹配。 

在不表示转义构造的任何字母字符前使用反斜线都是错误的;它们是为未来扩展正则表达式语言保留的。能够在非字母字符前使用反斜线,无论该字符是否非转义构造的一部分。 

根据  HYPERLINK "http://java.sun.com/docs/books/jls" Java Language Specification 的要求,Java 源代码的字符串中的反斜线被解释为  HYPERLINK "http://java.sun.com/docs/books/jls/third_edition/html/lexical.doc.html" \l "100850" Unicode 转义或其余 HYPERLINK "http://java.sun.com/docs/books/jls/third_edition/html/lexical.doc.html" \l "101089" 字符转义。所以必须在字符串字面值中使用两个反斜线,表示正则表达式受到保护,不被 Java 字节码编译器解释。例如,当解释为正则表达式时,字符串字面值 "\b" 与单个退格字符匹配,而 "\\b" 与单词边界匹配。字符串字面值 "\(hello\)" 是非法的,将致使编译时错误;要与字符串 (hello) 匹配,必须使用字符串字面值 "\\(hello\\)" 

字符类 

字符类能够出如今其余字符类中,而且能够包含并集运算符(隐式)和交集运算符 (&&)。并集运算符表示至少包含其某个操做数类中全部字符的类。交集运算符表示包含同时位于其两个操做数类中全部字符的类。 

字符类运算符的优先级以下所示,按从最高到最低的顺序排列: 

1    字面值转义    \x

2    分组[...]

3    范围a-z

4    并集[a-e][i-u]

5    交集[a-z&&[aeiou]]

注意,元字符的不一样集合实际上位于字符类的内部,而非字符类的外部。例如,正则表达式 . 在字符类内部就失去了其特殊意义,而表达式 - 变成了造成元字符的范围。 

行结束符

行结束符 是一个或两个字符的序列,标记输入字符序列的行结尾。如下代码被识别为行结束符: 

新行(换行)符 ('\n') 

后面紧跟新行符的回车符 ("\r\n") 

单独的回车符 ('\r') 

下一行字符 ('\u0085') 

行分隔符 ('\u2028')  

段落分隔符 ('\u2029) 

若是激活  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "UNIX_LINES" UNIX_LINES 模式,则新行符是惟一识别的行结束符。 

若是未指定  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "DOTALL" DOTALL 标志,则正则表达式 . 能够与任何字符(行结束符除外)匹配。 

默认状况下,正则表达式 ^ $ 忽略行结束符,仅分别与整个输入序列的开头和结尾匹配。若是激活  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "MULTILINE" MULTILINE 模式,则 ^ 在输入的开头和行结束符以后(输入的结尾)才发生匹配。处于  HYPERLINK "mk:@MSITStore:E:\\桌面\\api\\JDK_API_1_6_zh_CN.CHM::/java/util/regex/Pattern.html" \l "MULTILINE" MULTILINE 模式中时,$ 仅在行结束符以前或输入序列的结尾处匹配。 

组和捕获 

捕获组能够经过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组: 

1    ((A)(B(C)))

2    \A

3    (B(C))

4    (C)

组零始终表明整个表达式。 

之因此这样命名捕获组是由于在匹配中,保存了与这些组匹配的输入序列的每一个子序列。捕获的子序列稍后能够经过 Back 引用在表达式中使用,也能够在匹配操做完成后从匹配器获取。 

与组关联的捕获输入始终是与组最近匹配的子序列。若是因为量化的缘故再次计算了组,则在第二次计算失败时将保留其之前捕获的值(若是有的话)例如,将字符串 "aba" 与表达式 (a(b)?)+ 相匹配,会将第二组设置为 "b"。在每一个匹配的开头,全部捕获的输入都会被丢弃。 

(?) 开头的组是纯的非捕获 组,它不捕获文本,也不针对组合计进行计数。











Throwable


Error



Exception






子类






子类


RuntimeException






子类


 EMBED PBrush  


字符流


Reader


Writer


InputStreamReader


OutputStreamWriter


FileReader


FileWriter


BufferedReader


BufferedWriter


FileInputStream


字节流


FilterInputStream


FilterOutputStream


BufferedInputStream


BufferedOutputStream


InputStream


OutputStream


FileOutputStream