JAVASE笔记回顾

第一部分,JAVA基础和面向对象

part01 入门与开发环境搭建

1: 计算机基础知识(了解)
(1)计算机
(2)计算机硬件
(3)计算机软件
系统软件:windows,linux,mac
应用软件:QQ,YY,扫雷,CS/F
(4)软件开发
就是用开发工具和计算机语言作出软件
(5)计算机语言
人与计算机的交流方式
(6)人机交互
A:图像界面方便,简单,直观。
B:DOS 窗口方式要有控制台, 要记住不少的命令, 麻烦。
(7)键盘功能键和快捷键的介绍(掌握)
A:键盘功能键
tab
shift
ctrl
alt
空格
enter
windows 键
PrtSc
上下左右
B:键盘快捷键(补齐中文意思)
ctrl+A 全选
ctrl+C 赋值
ctrl+V 粘贴
ctrl+X 前切
ctrl+Z 撤销
ctrl+S 保存
(8)经常使用的DOS 命令
A:如何打开控制台
win+R -- cmd -- 回车
B:经常使用的命令
d:回车切换盘符
cd demo 回车进入目录
cd.. 返回上一级目录
cd\ 返回跟目录
cls 清屏
exit 退出
2: Java 语言概述
(1)Java 语言的发展史
Java 之父-- 詹姆斯·高斯林(James Gosling)
(2)Java 语言的平台
A:J2SE 基础版,桌面应用
B:J2ME 微型版,手机开发(android,ios)
C:J2EE 企业版,全部浏览器访问的应用程序。
注意:JDK5 之后更名JavaSE,JavaME,JavaEE
J2SE 是学习其余两门的基础。
(3)Java 语言的特色
其余的不少特色...
开源:源代码开放
跨平台:在任意操做系统下均可以使用。
(4)跨平台
经过火星人和中国,德国人的交流知道的原理,找一个翻译。而java 语言的这个翻译是jvm 。
注意:java 语言是跨平台的,jvm 不是跨平台的。
(5)JRE 和JDK(掌握)
JRE: JVM + class library 运行环境:虚拟机+核心类库
JDK: JRE + tools 开发工具包:运行环境+
一句话:有JDK 开发的软件,必须在JRE 上运行,并由JVM 保证跨平台。
3:JDK 的下载与安装(掌握)
(1)JDK 的下载。
经过官网: http://www.oracle.com
(2)JDK 的安装
A:傻瓜式安装, 会点击下一步便可。
B:注意:
a:请不要在中文目录和有特殊字符的目录(空格)
b:请把全部开发相关的软件放到一个目录中。
C:JRE 是不须要单独安装的。
4:HelloWorld 案例
(1)开发工具
A:记事本windows 自带的
B:高级记事本EditPlus
C:集成开发工具Eclipse/MyEclipse
(2)一个HelloWorld 案例
最终代码:
class Demo
{
public static void main(String[] args)
{
System.out.println("Hello World");
}
}
解释:
A:java 语言的最基本单位是类。用class 表示
定义类的格式:
class 类名
B:程序若是要运行, 就必须有main 方法, 它是被jvm 调用。
格式:
public static void main(String[] args)
C:程序若是要输出一些内容, 就必须使用输出语句。
格式:
S ystem.out.println("Hello World");
(3)一个Java 程序的执行。
A:开发源程序(.java 文件)
Demo.java
B:经过javac 命令编译(.class)
javac Demo.java
C:经过java 命令执行
java Demo
(4)常见的错误及注意事项
A:文件扩展名致使编译失败。把隐藏文件扩展名给显示出来。
win7,win8 的同窗若是不会单独问我。
B:非法字符错误
只要看到是非法字符, 确定是中英文问题。
由于咱们要求全部的符号所有是英文状态的。
C:注意大小写问题
class -- Class
String -- string
System -- system
D:括号的对应问题
在java 程序中,括号都是成对出现的。
因此建议在编写程序时,请遇到括号,成对打。
E:main 方法格式错误
public static void main(String [] args){ }
F:当java 源文件发生变化后, 请重写编译在运行
G:缩进问题:写代码遇到{}缩进一个tab 位置。
5:环境变量
(1)path 环境变量的做用
让javac 和java 命令能够在任意的目录下使用。
(2)path 环境变量的配置(掌握)
A:只修改path
D:\develop\Java\jdk1.7.0_45\bin;之前的path
**B:先创建一个JAVA_HOME,后修改path**
新建:JAVA_HOME 值是D:\develop\Java\jdk1.7.0_45
修改:%JAVA_HOME%\bin;之前的path
推荐使用B 方案。
(3)classpath 环境变量的配置
让指定的class 文件在任意目录均可以被访问。
技巧: 在最左边配置一个;
这样作的好处就是可以先在当前目录下查找并执行。 java

part02 常量、数据类型与运算符

1:常量
(1)在程序的运行过程当中其值是不能够发生改变的量。
(2)常量的分类:
1:字面值常量
1:整数常量
12,-23
2:实数常量
12.5,-65.43
3:字符常量
'a','A','0'
4:字符串常量
"hello"
5: 布尔常量
true,false
6:空常量null
2:自定义常量
(3)常量能够直接被输出。
2:进制
(1)是一种进位的方式,X 进制表示逢x 进1 。
(2)Java 中整数常量的表示
1: 二进制由0,1 组成。以0b 开头。JDK7 之后的新特性。
2: 八进制由0-7 组成。以0 开头。
3: 十进制由0-9 组成。默认就是十进制。
4: 十六进制由0-9, A-F(不区分大小写)组成, 以0x 开头。
(3)进制转换:
1: 其余进制到十进制
系数: 就是每一位上的数据。
基数: X 进制, 基数就是X 。
权: 在右边, 从0 开始编号, 对应位上的编号即为该位的权。
结果: 把系数*基数的权次幂相加便可。:
2: 十进制到其余进制
除基取余, 直到商为0, 余数反转。
3: 快速转换
1): 8421 码。
2): 二进制--八进制(3 位组合)
3): 二进制--十六进制(4 位组合)
3: 变量(掌握)
(1)程序的运行过程当中, 在指定范围内发生改变的量。
(2)格式:
数据类型 变量名= 初始化值;
变形格式:
数据类型 变量名;
变量名= 初始化值;
举例:
方式1: byte b = 10;
方式2: byte b;
b = 10;
4: 数据类型(掌握)
(1)分类
基本类型: 4 类8 种。
引用类型: 类, 接口, 数组。(了解)
(2)基本类型
整型:
byte 1个字节
short 2个字节
int 4个字节
long 8个字节
浮点型:
float 4个字节
double 8个字节
字符型:
char 2个字节
布尔型:
boolean 不明确。能够认为是1 个字节。
注意:
整数默认是int 类型。long 类型须要加L 或者l 后缀。
浮点数默认是double 类型。float 类型须要加F 或者f 后缀。
(3)类型转换
1: boolean 类型不参与转换。
2: 隐式转换(从小到大)
byte,short,char -- int -- long -- float -- double
3: 强制转换(从大到小)
格式:(数据类型)数据;
(4)面试题
byte b1 = 3;
byte b2 = 4;
byte b3 = b1 + b2;
byte b4 = 3 + 4;//报错,int类型没法赋值给byte类型
5: 运算符(掌握)
(1)就是把常量和变量链接的符号, 通常参与运算使用。
(2)分类:
算术运算符
赋值运算符
关系运算符
逻辑运算符
位运算符
三元运算符
(3)算术运算符:+,-,*,/,%,++,--
+: 正号, 加法, 字符串链接符。
System.out.println("5+5="+5+5);//5+5=55
System.out.println(5+5+"=5+5");//10=5+5
%: 模运算, 取余数
左边若是大于右边, 结果是余数。
左边若是小于右边, 结果是左边。
左边若是等于右边, 结果是0 。
正负号跟左边一致。
++/--:
++ 其实至关于把数据+1
单独使用:在数据的先后, 结果一致。
参与操做使用:
若是在数据的后边, 数据先操做, 在++/--
若是在数据的前边, 数据先++/--, 在操做。
(4)赋值运算符
=,+=,-=,*=,/=,%=
int a = 10;
把10 赋值给int 类型的变量a 。
a += 20;
把左边和右边的和赋值给左边。
注意事项:
a = a + 20;
a += 20;
结果是等价的,效果不是等价的。
+=运算内含了强制类型转换功能。
好比:
s hort s = 2;
s+=3;
等价于
s = (short)(s+3);
(5)关系运算符
==,!=,>,>=,<,<=
特色: 关系运算符的结果都是boolean 类型。
请千万注意: == 不要写成=
(6)逻辑运算符
&,|,!,^,&&,||
&:有false 则false
|:有true 则true
!:true 变false,false 变true
^:相同false,不同true
&&:有false 则false
||:有true 则true
&&和&的区别是: 若是左边有false 了, 右边将不再执行。
||和|的区别是: 若是左边有true 了, 右边将不再执行。
开发中经常使用:
&&,||,?!(s+3)?; linux

part03 运算符与流程控制语句

1: 运算符(掌握)
(1)位运算符(了解)
^ : 一个数据对同一个数据^两次, 结果仍是数据自己。
举例: a ^ b ^ b = a
(2)条件运算符
格式:
条件表达式?表达式1:表达式2
执行流程:
根据条件表达式返回的是true 仍是false, 决定结果是什么。
若是是true,就把表达式1 做为结果。
若是是false,就把表达式2 做为结果。
举例:
int a = 100;
int b = a > 50 ? 200 : 100;
请问b 的值?200
2: 面试题(理解)
(1)请用最有效率的代码写出2 乘以8
2<<3
(2)请交换两个变量。
int a = 10;
int b = 20;
开发: 临时变量
int temp = a;
a = b;
b = temp;
面试: 位^运算符
a = a ^ b;
b = a ^ b;//即b=a^b^b=a
a = a ^ b;//即a=a^b^a=b
3: if 语句(掌握)
(1)用于作判断使用的。
常见于对某个范围进行判断, 或者几个变量进行判断, 还有就是boolean 表达式的判
断。
(2)格式:
A:第一种格式: 一种状况
if(条件表达式)
{
语句体;
}
执行流程:
若是条件表达式为true, 就执行语句体;
不然, 什么都不执行。
B:第二种格式: 两种状况
if(条件表达式)
{
语句体1;
}
else
{
语句体2;
}
执行流程:
若是条件表达式为true, 就执行语句体1;
不然, 就执行语句体2;
特殊:
能够和条件表达式在某些状况下进行替换。
通常是在赋值的状况下能够。
举例:
获取两个数中的最大值。
C:第三种格式: 多种状况
if(条件表达式1)
{
语句体1;
}
else if(条件表达式2)
{
语句体2;
}.
..
else
{
语句体n;
}
执行流程:
若是条件表达式1 为true, 就执行语句体1;
若是条件表达式2 为true, 就执行语句体2;
...不然, 就执行语句体n;
D:注意事项
a:何时时候哪种if 语句。
第一种格式在判断条件为一种状况下使用。
第二种格式在判断条件为两种状况下使用。
第三种格式在判断条件为多种状况下使用。
b:每一种if 语句其实都是一个总体, 若是有地方执行了,
其余的就不执行了。
c:若是if 或者else 里面控制的语句体是一条语句, 是能够省略大括号的,
可是, 若是是控制多条语句, 就必须写上大括号。
建议: 永远写上大括号。
d:大括号和分号通常不同时出现。
E:做用域
全部变量的定义只在它所属的大括号内有效。
(3)案例:
A:根据键盘录入的成绩, 判断等级。
B:根据键盘录入的月份, 输出该月份所对应的季节。
4: switch 语句(掌握)
(1)用于作选择使用的。通常用于几个常量的判断。
switch 会把几个常量值直接加载到内存, 在判断的时候, 效率要比if 高。
因此, 针对几个常量的判断, 通常选择switch 语句。
(2)switch 语句的格式:
switch(表达式)
{
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
case 值3:
语句体3;
break;
...
default:
语句体n;
break;
}
A:针对格式的解释
switch:表示这里使用的是switch 语句, 后面跟的是选项。
表达式: byte,short,int,char
JDK5 之后能够是枚举(之后讲)
JDK7 之后能够是字符串(后面讲)
case:表示这里就是选项的值, 它后面的值未来和表达式的值进行匹配。
case 后面的值是不可以重复的。
break:
switch 语句执行到这里, 就结束了。
default:
当全部的case 和表达式都不匹配的时候, 就走default 的内容。
它至关于if 语句的else 。通常不建议省略。
B:执行流程
进入switch 语句后, 就会根据表达式的值去找对应的case 值。
若是最终没有找到, 那么, 就执行default 的内容。
C:注意事项:
a:default 总体能够省略吗?
能够,可是不建议。
b:default 的位置能够放到前面吗?
能够,可是不建议。
c:break 能够省略吗?
能够,可是不建议。
default 在最后, break 是能够省略的。
case 后面的break 能够省略, 可是结果可能有问题。
d:switch 语句何时结束呢?
就是遇到break 或者执行到程序的末尾。
(3)案例:
A:根据键盘录入的日期(1-7),输出对应的星期日期。
B:根据键盘录入的月份, 输出该月份所对应的季节。(选作)
5: Scanner 的使用(掌握)
(1)Scanner 是JDK5 之后设计的用来接收键盘录入数据使用的。
(2)目前咱们要经过键盘录入int 类型数据,必须按照以下步骤:
A:导包
import java.util.Scanner;
B:建立对象,封装键盘录入
Scanner sc = new Scanner(System.in);
C:调用方法,获取数据
int number = sc.nextInt();android

part04 循环结构

1: 循环(掌握)
(1)若是发现有不少重复的内容的时候就考虑使用循环改进代码,让代码看起来简洁了。
(2)循环的组成
A:循环体,就是要作的事情。
B:初始化条件:通常定义的是一个初始变量
C:判断条件:用于控制循环的结束。
D:控制条件:用于控制变量的变化。通常都是一个++/--操做。
(3)循环的分类:
A:for循环ios

for(初始化条件;判断条件;控制条件)
{循环体;}
执行流程:
a:先执行初始化条件;
b:执行判断条件
c:根据判断条件的返回值:
true:执行循环体。
false:就结束循环。
d:最后执行控制条件。返回到b 继续。
B:while循环:先判断再循环面试

初始化条件;
while(判断条件)
{
循环体;
控制条件;
}
执行流程:
a:先执行初始化条件;
b:执行判断条件
c:根据判断条件的返回值:
true:执行循环体。
false:就结束循环。
d:最后执行控制条件。返回到b 继续。
C:do...while循环:先循环再判断(循环至少执行一次)
初始化条件;
do{
循环体;
控制条件;
}while(判断条件);
执行流程:
a:先执行初始化条件;
b:执行循环体和控制条件;
c:执行判断条件
d:根据返回值
true:返回b。
false:就结束循环。
注意:
a:通常使用for循环或者while 循环,并且这两种循环是能够等价转换的。
b:do...while 循环至少执行一次循环体。
(4)案例: (掌握)
A:求5 的阶乘。
B:水仙花。
C:统计叠多少次, 能叠成珠穆朗玛峰的高度。
(5)循环嵌套: (理解)
A:也就是循环语句的循环体是一个循环语句。
B:经过输出
****
****
****
咱们不断的改进。发现了一个问题:
外循环控制行数,内循环控制列数。
(6)案例: (理解)
A:正三角形
内循环的判断条件: y<=x
for(int x=0; x<5; x++)
{
for(int y=0; y<=x; y++)
{
System.out.print("*");
}
System.out.println();
}
B:倒三角形
内循环的初始化条件: y=x
for(int x=0; x<5; x++)
{
for(int y=x; y<5; y++)
{
System.out.print("*");
}
System.out.println();
}
C:九九乘法表
2: break 和continue(掌握)
(1)有时咱们须要对循环进行一些控制终止,就用到两个关键字:
break 和continue
(2)特色:
A:它们都必须在循环中(break 还能够在switch 中) 。
通常在循环的判断中。
B:若是单独使用break 和continue,后面是不能有语句的。
(3)区别:
A:break 结束当前循环。
B:continue 结束本次循环,进入下一次循环。
(4)如何退出嵌套循环: (了解)
用带标签的循环。
格式:
标签名: for(){
for(){if()
{
break 标签名;
}
}
}
3:应用场景(总结)
(1)变量:发现有一个数据是变化的时候就用变量。
(2)if 语句:若是是一个范围的判断,boolean 类型的表达式的判断,几个数据的判断。
(3)switch 语句:几个数据的判断。通常这种状况有限选择switch 。
(4)for 语句:若是次数或者范围特别明确。(水仙花)
(5)while 语句:若是次数或者范围不明确。(珠穆朗玛峰)正则表达式

part05 函数与数组

1: 函数(掌握)
(1)定义在类中,有特定功能的一段小程序。
(2)函数的格式:
修饰符 返回值类型 函数名(形参类型 形式参数1, 形参类型 形式参数2...)
{
函数体;
reutrn 返回值;
}
A:修饰符public static
B:返回值类型程序最终结果的数据类型
C:函数名其实就是函数的名称,方便咱们调用。
D:参数
形参类型数据类型
形式参数就是接收实际参数的变量
实际参数就是实际参与操做的变量(常量)
E:函数体就是按照正常的逻辑完成功能的代码。
F:返回值就是程序的最终结果
G:reutrn 返回值哪里调用程序,return 就把结果返回到哪里。
(3)函数的特色:
A:函数与函数之间是平级关系。不能在函数中定义函数。
B:运行特色:函数只有被调用才会被执行。
(4)案例:
有明确返回值的例子:
A:求两个数据的和
B:求两个数据的最大值
C:比较两个数是否相等
void 类型例子:
A:nn 乘法表
B:根据给定的行和列输出一个*组成的长方形
(5)函数的调用
A:有明确返回值
a:单独调用通常没有意义。
b:输出调用可是若是想拿结果继续操做 就有问题了。因此,不好。
c:赋值调用推荐方式。
B:void 类型
单独调用
(6)函数重载
A:函数名相同,参数列表不同(个数不同,对应的类型不同) ,与返回值类型无关。
B:举例:
public static int sum(int a,int b){...}
public static int sum(int a,int b,int c){...}
public static int sum(float a,float b){...}
2: 数组(掌握)
(1)数组是存储同一种类型的多个元素的容器。
(2)好处:数组中的元素会被自动从0 开始编号,方便获取。
(3)格式:
A:int[] arr = new int[3];
B:int arr[] = new int[3];
C:int[] arr = new int[]{1,2,3};
D:int[] arr = {1,2,3};
推荐A 和D 。
(4)Java 内存图:
A:栈:存储局部变量使用,使用完毕立马消失。
B:堆:全部new 出来的都在堆里面。
a:每个实体都有地址值
b:每个实体内的内容都有默认值
整数:0
浮点数:0.0
字符:'\u0000'
布尔:false
c:在垃圾回收器空闲的时候被回收。
C:方法区
D:本地方法区
E:寄存器
(5)操做:
数组的索引:index
数组的长度:arr.length();
数组名
A:数组的遍历算法

for(int a:arr){操做a;}
B:数组获取最值:max();min();
C:数组的查找:二分查找
(6)二维数组:数组里面套了一层数组
格式:
A:int[][] arr = new int[3][2];
B:int[][] arr = new int[3][];
C:int[][] arr = {{1,2,3},{4,5},{6,7,8,9}};
遍历:
应用:遍历求和。数据库

part06 面向对象

1: Java 中的参数传递问题
基本类型:形式参数的改变对实际参数没有影响。
引用类型:形式参数的改变直接影响实际参数,形参改变意味着地址值改变
2: 面向对象(理解)
(1)面向对象:是基于面向过程的一种思想。
面向过程:以函数为基础,关注实现过程。--具备某种功能的模块
面向对象:以对象为基础,关注实现结果。--具备某些功能的一个系统(有机总体)
(2)面向对象的思想特色:
A:是一种更符合人们思考习惯的思想。
B:把复杂的事情简单化了。
C:把咱们从执行者变成了指挥者。
举例:
买电脑,洗衣,作饭,旅游。
(3)事物是如何体现的呢?
A:属性:有哪些特征
B:行为:有哪些功能
(4)类与对象的关系:
把事物转换成类:
A:成员变量
定义在类中方法外。
B:成员方法
和之前的区别是去掉static 。
类:是相关的属性和行为的集合,是一个抽象的概念。
对象:是某种事物的具体存在,是类的具体表现形式。
举例:
类:学生
对象:张三
(5)案例:
A:学生类
B:手机类
C:汽车类
(6)如何使用呢?
A:建立对象
格式:
类名 对象名= new 类名();(其实是调用类的构造器来建立对象)
B:使用成员变量和成员方法
对象名.成员变量
对象名.成员方法编程

part07 面向对象的特征之一:封装

1: 封装(理解)
(1)隐藏实现的细节,提供公共的访问方式。
类,方法等其实都是封装的具体体现。
(2)private 关键字
A:用于修饰成员变量和成员方法。
B:被修饰的内容在其余类中是不能够被访问的。
(3)常见的应用:
类中的全部成员变量私有,给出对应的get/set 方法。
代码体现:
class Student
{
private String name;
private int age;
public Student(){}
public Student(String name,int age)
{
this.name = name;
this.age = age;
}
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setAge(int age)
{
this.age = age;
}
public int getAge()
{
return age;
}
}
2: 构造方法(构造器)
(1)格式及特色
格式:
访问权限修饰符 类名(参数...){}
访问权限修饰符:
public,private
特色:
A:方法名和类名相同
B:没有返回值类型
C:没有具体的返回值
(2)注意事项:
A:若是你不给构造方法,jvm 会自动给你一个无参构造方法。
B:若是你给出了构造方法,那么jvm 将不再提供无参构造方法。
此时若是要使用无参构造方法:只能本身提供
推荐:永远手动给出无参构造方法。
3: this 关键字(掌握)
(1)是一个关键字。表明当前类对象的引用。
简单记:在方法中,哪一个对象调用方法this 就表明谁。
除了静态方法外,全部的方法中有隐含的有一个this 引用
(2)应用场景:
解决局部变量隐藏成员变量问题。
4:static 关键字
(1)是一个关键字。能够修饰成员变量和成员方法。
(2)静态的特色:
A:随着类的加载而加载
B:优先于对象存在
C:被类的全部对象共享
D:能够经过类名调用
(3)静态的注意事项:
A:在静态方法中是没有this 关键字的。
B:静态方法只能访问静态成员。
(4)静态内容的调用:
A:被对象调用
B:被类名调用
推荐被类名调用。
(5)何时该用static 呢?
若是某个内容是全部对象共享的就用静态修饰。
举例:
水杯和饮水机。
厕所和人。
老师和学生。
5:Math 类的随机数(掌握)
类名调用静态方法。
包: java.lang
类: Math
方法: public static double random():
java.lang 包下的类是不用导包就能够直接使用的。
产生1-100 之间的随机数:
int number = (int)(Math.random()*100)+1;小程序

part08 面向对象的特征之二:继承

1: 继承(掌握)
(1)把多个类中的相同的属性和行为进行抽取,封装到一个类中,而后再创建新类的时候,不须要从头作起,继承刚才定义的那个类便可。
(2)好处:
A:提升代码的复用性。
B:让类与类之间产生了一个关系,是多态的前提。
(3)何时使用继承?
A:若是类之间存在着:is a 的关系,就能够考虑使用继承。
B:不要为了继承部分功能,而去使用继承。
(4)继承的特色:
A:Java 只支持单继承,不支持多继承。(一个儿子只能一个爹)
为何?若是支持多继承,就会出现调用不明确的问题。
B:Java 支持多层(重)继承。
(5)super 和this 的区别?
A:super 是一个关键字,表明父类的存储空间标识。(能够理解为父亲的引用)
B:它和this 的用法类似
a:成员变量
this.变量-- 本类的
super.变量-- 父类的
b:构造方法
this(...) -- 本类的
super(...) -- 父类的
c:成员方法
this.方法名() -- 本类的
super.方法名() -- 父类的
(6)子父类中成员变量的用法:
A:名称不同,这个太简单了。
B:名称相同,子类对象的在使用的时候:
先找子类局部范围
再找子类成员范围
最后找父类成员范围
(7)子父类中成员方法的用法:
A:名称不同,这个太简单了。
B:名称相同,子类对象的在使用的时候:
先找子类的
再找父类的
C:方法重写
在子类中,方法声明(修饰符,返回值,方法名,参数列表)相同的状况。
注意事项:
a:父类中私有方法是不能被重写
b:子类方法的访问权限必定要大于等于父类的访问权限
c:静态只能重写静态(静态跟类相关)
(8)子父类中构造方法的用法:
A:子类的初始化过程当中,首先会去执行父类的初始化动做。
由于子类的构造方法中默认有一个super() 。
为何?子类要使用父类的成员变量,这个初始化必须在子类初始化以前完成。
因此子类的初始化过程当中会先执行父类的初始化。
B:若是父类没有无参构造方法
A:使用super 调用父类的带参构造。推荐方式。
B:使用this 调用自己的其余构造。
2: 代码块(面试题, 理解)
(1)执行顺序:
静态代码块(随着类的加载而加载)--> 构造代码块(每次建立对象时调用)--> 构造方法(初始化对象)
(2)注意事项:
静态代码块只执行一次
3:final(掌握)
(1)是一个关键字,能够用于修饰类、成员变量、成员方法。
(2)特色:
它修饰的类不能被继承。
它修饰的成员变量是一个常量。
它修饰的成员方法是不能被子类重写的。

part09 面向对象的特征之三:多态;抽象类、接口

1:多态(掌握)
(1)对象在不同时刻表现出来的不同状态。
举例:狗(狗、宠物、动物)

典型表现形式:用接口来接收类所建立的对象
(2)多态的前提
A:要有继承或者实现关系。
B:要有方法的重写/实现。
C:要有父类引用或者父接口引用指向子类对象。
注意:多态有三种体现形式:
类多态
抽象类多态
接口多态
(3)多态中的成员特色:
A:成员变量
编译看左边,运行看左边。
B:成员方法
编译看左边,运行看右边。
为何?由于方法存在重写,而变量没有。
举例:孔子扮父。
(4)多态的弊端:
父类(接口)引用不能使用子类特有功能。
为了解决这个弊端须要向下转型。
Fu f = new Zi(); //向上转型
Zi z = (Zi)f; //向下转型
Zi z = new Zi();
(5)多态的好处:
能够提升代码的扩展性和可维护性。
2:抽象类:声明具备某些功能的一种类
(1)若是多个类中存在相同的方法声明,而方法体不同样,咱们就能够只提取方法声明。
若是一个方法只有方法声明,没有方法体,那么这个方法必须用抽象修饰。而一个类中若是有抽象方法,这个类必须定义为抽象类。
(2)抽象类的特色
A:抽象类和抽象方法必须使用abstract 修饰
B:抽象类不能被实例化
C:抽象类有构造方法,用于子类实例化使用
D:若是一个类是抽象类,那么继承它的子类要么是抽象类,要么重写全部抽象方法。
(3)抽象类的成员特色
A:成员变量能够变量也能够是常量
B:拥有构造方法
C:成员方法能够有抽象方法也能够有非抽象方法(全是抽象方法或者非抽象方法都是能够的)
(4)抽象类的几个小问题
A:抽象类不能被实例化,为何有构造?用于子类实例化使用。
B:一个类没有抽象方法,为何定义为抽象类?不想被实例化,或者是抽取出来的一个规则类
C:abstract 不能和哪些关键字共存:final、private、static
3:接口(理解)
(1)若是一个抽象类中的方法都是抽象的, 这个时候, java 就提供了一种
更抽象的表示形式:----接口
接口:interface
实现:implements
格式:
interface 接口名{}
class 类名implements 接口名{}
(2)接口的特色:
A:接口不能被实例化。
B:一个类若是实现了接口:要么是抽象类、要么实现接口中的全部方法。
(3)接口的成员特色:
A:成员变量只能是常量(只能读不能改)。默认修饰符public static final
B:成员方法只能是抽象方法。默认修饰符public abstract
推荐:永远手动给出修饰符。
(4)接口的思想特色:
A:对外暴露的规则
B:是功能的扩展
C:下降耦合度
耦合:类与类的关系
内聚:类本身完成某件事情的能力
编程追求的目标:高内聚低耦合
D:接口能够多实现。
(5)类,接口的关系
A:类与类
继承关系,只能单继承能够多层继承。
B:类与接口
实现关系,能够单实现也能够多实现;还能够在继承一个类的同时实现多个接口。
C:接口与接口
继承关系,能够单继承也能够多继承。
(6)抽象类和接口的关系
接口是一种特殊的抽象类,比抽象类更抽象,接口里的方法全为抽象方法

part10 包、权限修饰符、内部类

1:包(掌握)
(1)包其实就是文件夹,用于区分相同的类名。
(2)格式:package 包名1.包名2...;
(3)带包的编译和运行
1:手动建包;2:自动建包
2:导包(掌握)
(1)通常来讲用一个类,须要用该类的全路径名称。若是多个地方使用就比较麻烦,因此java 提供了导包操做。
(2)格式:
import 包名1.包名2...类名;
//下面这种属于把指定包下的类都导入。这种用法不推荐。咱们应该用谁导谁。
import 包名1.包名2...*;
(3)package,import,class 的顺序
package -- import -- class
3: 四种权限修饰符(掌握)
 image
4:注意,常见规则以下:
之后,全部的类都用public 修饰。而且在一个java 文件中只写一个类。
之后,全部的成员变量用private 修饰。
之后,全部的成员方法用public 修饰。
若是是抽象类或者接口:
public abstract + ...
之后,全部的构造方法用public 修饰。
若是类是工具类或者单例类:构造用private 修饰
5:内部类
(1)把类定义在一个类的内部。
(2)访问特色:
1:内部类能够直接访问外部类成员,包括私有
2:外部类要想访问内部类成员,必须建立对象。
(3)内部类分类:
1:成员位置:private 安全;static 方便调用
2:局部位置:定义在方法中
局部内部类访问局部变量必须加final 修饰,延迟生命周期。
(4)匿名内部类
1:是定义在局部位置的没有名字的内部类。
2:前提:存在一个类、抽象类或者接口。
3:格式
new  类或者接口名()
{重写方法;}
本质理解:其实这是一个继承类或者实现接口的匿名的子类对象。
4:使用
当你看到方法的形式参数是接口或者抽象类的时候,用匿名内部类改进。

匿名内部类只能使用一次,一般用来简化代码书写。

 

第二部分 经常使用API和集合

part11 IDE和Object类

Eclipse
1:Eclipse 的概述
(1)eclipse 的由来:由IBM 一个小组开发
(2)eclipse 的特色
A:彻底由Java 语言编写的工具。
B:不须要安装
C:免费的:eclipse.org
D:开源的
E:扩展性很是强
(3)eclipse 和MyEclipse 的区别
A:MyEclipse 是基于eclipse 加入了一些用于开发Web 的插件并对这些本身开发的插件进行收费。
B:特色MyEclipse 集成性很好。
(4)在使用eclipse 以前,系统中必需要先有JDK 或者JRE 。
由于eclipse 就是用Java 语言编写的程序,因此须要jvm 的解释执行。
A:对于高版本的MyEclipse,内部已经集成了JDK 。因此安装后会用本身的JDK 来执行MyEclipse 。
2:Eclipse 安装
A:解压Eclipse 压缩包
B:复制到制定的目录(不要有中文、空格或其余非法字符)
3:Eclipse 的使用
A:打开软件的界面
B:新建一个项目(工程)
C:在项目下的src(源码包)下创建包
D:在包下创建类
E:在类里边写代码
F:编译源文件(代码写完保存的时候会自动生成class 文件, 在项目的bin 目录下。)
G:执行class 文件(右键-- Run As -- Java Application)
H:结果显示在Console 控制台上
4:Eclipse 的基本设置
A:在代码最左侧前面, 右键- Show Line Numbers, 如何取消?再次选择
B:java 代码字体,Window -- Preferences -- Appearance -- Colors and Fonts -- Java --
Java Editor -- 选择右边的Edit 进行修改便可。
C:若是不当心把界面给弄没了不要担忧有复位操做,window -- reset ...
5:Eclipse 的内容辅助键
Alt+/
main 方法:先写main 而后alt+/最后Enter
输出语句:先写syso 而后alt+/最后Enter
for 循环:先写for 而后alt+/最后Enter
6:Eclipse 的快捷键
(A,E,F 必须掌握)
A:alt+/ 内容辅助键:补充类或者接口名,帮咱们起变量名,new 后面直接提示等。
B:ctrl+/ 单行注释,在按一次,取消单行注释
C:ctrl+shift+/ 对选中的区域进行多行注释的封装
D:ctrl+shift+\ 用于取消多行注释,只要光标在多行注释中便可
E:ctrl+shift+o 对使用了其余包中的类或者接口进行自动导入
F:ctrl+shift+f 对代码进行格式化
G:alt+上键向上移动当前行或者选中行
H:alt+下键向下移动当前行或者选中行
I:ctrl+d 删除当前行,或者删除选中行
J:ctrl+shift+x 将选中部分的字母大写
K:ctrl+shift+y 将选中部分的字母小写
L:ctrl+1 光标放在编译中出现红色波浪线提示的内容上,在该快捷键能够获取建议的处理方式
M:F3 能够查看类或者方法的源码,前提是该原码已经关联。
7:Eclipse 的自动给出set,get 方法
右键--source--(set, get 方法)Generate Setters and Getters
(有参构造)Generate Constructor using Fields...
(无参构造)Generate Constructors form Superclass..
8:Eclipse 删除和导入项目
删除:选中项目-- 右键delete ...
A:从工做台中删除
B:从硬盘删除
导入:在项目所在位置的空白处右键--》Import --》General --》Existing Project...(最长的那个)
9:Eclipse 的debug 调试
A:如何加断点
在你想看从哪里执行的程序的左边双击便可。(不要在注释上作)
在哪里加?哪里不会加哪里,最好在每一个方法的第一条语句上加。
B:如何使用
右键-- Debug As -- Java Application
弹出一个界面问你:是否打开调试界面。yes是否记住个人选择。选中框框便可
C:查看哪里
左边:程序运行到哪里了
右边:变量的变化过程
D:怎么继续:F6 执行一行。
E:去除断点
方式1:在点击的那个地方再次点击
方式2:在debug 调试界面--BreakPoints -- remove All...
F:补充:
F5 跳入;F8 跳到下一个断点
演示建立对象的整个过程
Object 类的方法
1:建立Student 对象并打印效果
A:打印他的时候,默认调用的他的toString 方法
B:Student 没有toString 方法,调用的是Object 的toString 方法
C:object 的toString 方法返回值是包名...类名+@+16 进制地址值,咱们通常使用toString 方法都要重写他
2:关于==作比较的问题
A:基本类型的比较:比较的是值
B:引用类型的比较:比较的是引用类型所指向的地址值
3:本身实现对象的成员变量数据的比较
“2”,“3”目的是为了引出Object 中的equals 方法
4:Object 中的equals 方法
源码其实就是用“==”比较的两个变量或对象的引用

对于string和包装类,object类的equals()方法比较规则为:若是两个对象类型和内容一致则返回true;

也可自定义重写object的equals()方法:好比两个都是person类而且属性name也相同返回true。
5:String 类中的equals 方法
equals比较两个字符串是否同样

“==”比较的是变量或对象的引用
1: Scanner 注意事项
存在的问题:当录入数据依次是int String,而且分别使用nextInt()和next()方法获取数据的时候会接受不到String 数据。
解决办法:
1). 在录入完int 后从新建立一个新的Scanner 对象
2). 用字符串接受,而后把字符串转成int 类型
2:数据结构思想:拿时间换空间,拿空间换时间
例子: 需求:一个网站有一个功能,当填入你的年龄的时候就能自动判断你是哪一个年龄段
0-9 岁, 儿童
10-19 岁, 少年
20-29 岁, 青年
30-39 岁, 壮年
40-49 岁, 中年
50-59 岁, 中老年
60 岁以上, 老年
代码实现例子:
String[] ages = {"儿童","少年","青年","中年","中老年","老年"};
System.out.println(ages[age/10]);

part12 经常使用API--String类

2: String 类(掌握)
(1)字符串:多个字符组成的一串数据。
(2)构造方法:
A:String s = new String();无参构造
B:String s = new String(byte[] bys);byte 数组转成字符串
C:String s = new String(byte[] bys,int index,int length);
从哪一个地方截取byte 数组几个转成字符串(把字节数组的一部分转为字符串)
D:String s = new String(char[] chs);
字符数组转字符串(把字符数组的一部分转为字符串)
E:String s = new String(char[] chs,int index,int length);
从哪一个地方截取char 数组几个转成字符串
F:String s = new String(String str);字符串里传一个字符串
G:String s = "hello";
(3)字符串的特色及面试题
A:字符串一旦被赋值就不能改变。
注意:字符串的值不能改变,没有说引用变量不能改变。
B:面试题:
a:String s1 = new String("hello")和String s2 = "hello"的区别。

s1是一个对象,存在于堆中,能够调用string类中的方法;s2是是一个字符串常量,不能够操做string类中的方法。
b:请写出结果:
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1==s2);//false地址值不同
System.out.println(s1.equals(s2));//true内容同样
String s3 = new String("hello");
String s4 = "hello";
System.out.println(s3==s4);//false不具可比性
System.out.println(s3.equals(s4));//true内容同样
String s5 = "hello";
String s6 = "hello";
System.out.println(s5==s6);//true变量值同样
System.out.println(s5.equals(s6));//true
(4)成员方法
A:判断功能
boolean equals(Object obj):判断字符串的内容是否相同,区分大小写。boolean equals(obj)
boolean equalsIgnoreCase(String str):判断字符串的内容是否相同,不区分大小写。boolean equalsIgnnoreCase(str)
boolean contains(String str):判断字符串对象是否包含给定的字符串。boolean contains(str)
boolean startsWith(String str):判断字符串对象是否以给定的字符串开始。boolean startWith(str)
boolean endsWith(String str):判断字符串对象是否以给定的字符串结束。boolean endWith(str)
boolean isEmpty():判断字符串对象是否为空,数据是否为空。boolean isEmpty()
B:获取功能
int length():获取字符串的长度。int length()
char charAt(int index):返回字符串中给定索引处的字符。char charAt(index)
int indexOf(char ch):返回指定字符在此字符串中第一次出现的索引。int indexOf(ch)
int indexOf(String str):返回指定字符串在此字符串中第一次出现的索引。int indexOf(str)
int indexOf(int ch,int fromIndex):返回在此字符串中第一次出现指定字符的索引,从指定的索引开始搜索。
int indexOf(String str,int fromIndex):返回在此字符串中第一次出现指定字符串的索引,从指定的索引开始搜索。
String substring(int start):截取字符串,返回从指定位置开始截取后面的字符串。string substring(start)
String substring(int start,int end):截取字符串,返回从指定位置开始到指定位置结束截取后的字符串。
C:转换功能
byte[] getBytes():把字符串转换成字节数组。byte[] getBytes()
char[] toCharArray():把字符串转换成字符数组。char[] toCharArray()
static String copyValueOf(char[] chs):把字符数组转换成字符串。
static String valueOf(char[] chs):把字符数组转换成字符串。String valueOf(chs)
static String valueOf(int i):把int(基本类型)转换成字符串。String valueOf(int)
String toLowerCase():把字符串变成小写。String toLowerCase()
String toUpperCase():把字符串变成大写。String toUpperCase()
String concat(String str):拼接字符串。String concat(str)
D:其余功能
a:替换功能
String replace(char oldChar,char newChar):用新的字符去替换指定的旧字符。replace(oldCh,newCh)
String replace(String oldString,String newString): 用新的字符串去替换指定的旧字符串。
b:切割功能
String[] split(String regex):按照规定的格式切割字符串成字符串数组。string[] split(regex)//传入正则表达式
c:去除两端空格功能
String trim():去除字符串两端空格。string trim()
d:字典顺序比较功能
int compareTo(String str):按字典顺序(Unicode 编码顺序)若是第一个相同比较第二个依次类推。
int compareToIgnoreCase(String str) :按字典顺序( Unicode 编码顺序)若是第一个相同比较第二个依次类推不区分大小写
(5)案例
A:模拟用户登陆(用到了判断equals 功能,若是有的用户名不区分大小写还能够用equalsIgnorCase)
String username = "admin";
String password = "admin";
// 三次机会
for (int x = 0; x < 3; x++) {
// x 0,1,2
// 键盘录入数据:用户名和密码。
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名: ");
String name = sc.nextLine();
System.out.println("请输入密码: ");
String pwd = sc.nextLine();
// 把数据进行比较。
if (username.equals(name) && password.equals(pwd)) {
System.out.println("恭喜你,登陆成功");
// 引入曾经的猜数字小游戏。
break;
} else {
if ((2 - x) == 0) {
System.out.println("帐号被锁定,请与站长联系");
} else {
// 2,1,0
System.out.println("登陆失败,你还有" + (2 - x) + "次机会");
}
}
}
B:字符串遍历(用到了charAt 功能)
for (int x = 0; x < s.length(); x++) {
char ch = s.charAt(x);
System.out.println(ch);
}
C:统计字符串中大写、小写、数字字符出现的次数(用到了charAt 功能)
String s = "Hello12345World";
// 定义三个统计变量
int bigCount = 0;
int smallCount = 0;
int numberCount = 0;
// 遍历字符串。
for (int x = 0; x < s.length(); x++) {
char ch = s.charAt(x);
// 判断是属于哪一种范围
if (ch >= 'A' && ch <= 'Z') {
bigCount++;
} else if (ch >= 'a' && ch <= 'z') {
smallCount++;
} else if (ch >= '0' && ch <= '9') {
numberCount++;
}
}
D:把字符串的首字母大写,其余小写(用到了截取、链接、转大小写功能)
String str2 =str.substring(0,1).toUpperCase().concat(str.substring(1).toLowerCase());
E:大串中小串出现的次数(用到了截取、indexOf 功能)
public int getCount(String maxString, String minString) {
// 定义统计变量
int count = 0;
// 在大串中查找小串一次
int index = 0;
// 若是返回值不是-1,说明小串在大串中是存在的。
// 判断
while ((index = maxString.indexOf(minString)) != -1) {小串在大串中第一次出现的索引
// 统计变量++
count++;
// 把查找过的数据给截取掉,从新赋值给大串
maxString = maxString.substring(index + minString.length());
}
return count;
}
F:学习indexOf 过程当中发现contains()的底层就是用的indexOf()
public boolean contains(CharSequence s) {
return indexOf(s.toString()) > -1;
}

part13 经常使用API:Arrays、system、stringbuffer、interger

1:数组操做(理解原理,并要求会写该算法的代码)
1):冒泡排序原理:相邻元素两两比较,大的日后走,第一次完毕后最大值就在最大索引处。(升序)
2):冒泡排序代码
public static void bubbleSort(int[] arr) {
// 外循环控制次数
for (int x = 0; x < arr.length - 1; x++) {
// 内循环控制每一次的比较过程
/*
* 第一次,全部元素都参与比较,也就是0 个元素不参与。
* 第二次,有1 个元素不用参与。
* 第三次,有2 个元素不用参与。...
*/
// -1 是为了防止索引越界
// -x 是为了减小比较的次数
for (int y = 0; y < arr.length - 1 - x; y++) {
if (arr[y] > arr[y + 1]) {
// 数据交换
int temp = arr[y];
arr[y] = arr[y + 1];
arr[y + 1] = temp;
}
}
}
}
3):查找
--普通查找:数组无序
--二分查找(折半查找):数组有序
4):二分查找的代码:根据值查所在索引
public static int getIndex(int[] arr,int value)
{
int maxIndex = arr.length-1;
int minIndex = 0;
int midIndex = (maxIndex+minIndex)/2;
while(arr[midIndex]!=value){
if(arr[midIndex]>value)
{
maxIndex = midIndex - 1;
}
else if(arr[midIndex]<value)
{
minIndex = midIndex + 1;
}
if(minIndex > maxIndex)
{
return -1;
}
midIndex = (maxIndex+minIndex)/2;
}
return midIndex;
}
2:Arrays 工具类的使用
(1)Arrays 是针对数组操做的工具类。
(2)成员方法:
public static String toString(数组):把数组变成字符串。String toString(arr[])
public static void sort(数组):对数组进行排序(升序) 。void sort(arr[])
public static int binarySearch(int[] arr,int value):二分查找int binarySerch(arr[],value)
3:System 的方法(掌握)
(1)系统类提供了静态的变量和方法供咱们使用。
(2)成员方法:
public static void exit(int value):退出jvm,非0 表示异常退出。void exit(value)
public static long currentTimeMillis():返回当前系统时间的毫秒值。(通常用来测试一个程序执行的快慢)
返回的是和1970 年1 月1 日午夜之间的时间差
public static void arraycopy(Object src,int srcPos,Object dest,int destPos,intlength):从指定源数组中复制一个数组, 复制从指定的位置开始,到目标数组的指定位置结束。
4:StringBuffer:便可变长的String
(1)字符个数能够发生改变的字符串类,字符串缓冲区类。
(2)构造方法:
A:StringBuffer():默认容量16
B:StringBuffer(int capacity):指定容量
C:StringBuffer(String str):把字符串转换成StringBuffer
(3)成员方法:
A:添加功能
public StringBuffer append(int i):在末尾追加元素。StringBuffer append(int)
public StringBuffer insert(int index,int i):在指定位置添加元素。StringBuffer insert(index,int)
B:删除功能
StringBuffer deleteCharAt(int index):删除指定位置字符。StringBuffer deleteCharAt(index)
StringBuffer delete(int start, int end):删除指定开始位置和结束位置间的字符。StringBuffer delete(start,end)
C:替换功能
StringBuffer replace(int start, int end, String str):把开始到结束位置的字符用一个新的字符串给替换。
D:截取功能
String substring(int start):从指定位置到末尾截取。String substring(start)
String substring(int start, int end): 从指定位置到结束位置截取。
E:反转功能
StringBuffer reverse():字符串反转。StringBuffer reverse()
(4)案例:
字符串反转。
StringBuffer sb = new StringBuffer("abc");
sb.reverse();
String result = new String(sb);
System.out.println(result);//cba
5:基本类型包装类(掌握)
(1)基本类型的数据咱们只能使用值,不能作更多的操做。为了方便咱们操做java 就把每种基本类型进行了包装,提供方法供咱们使用。
(2)基本类型和包装类的对应关系
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
(3)Integer 构造方法
A:Integer i = new Integer(int num);
B:Integer i = new Integer(String s);
注意:s 必须是一个由数字字符组成的字符串。
(4)String 和int 类型的转换
A:String -- int:parseInt(str)
Integer:public static int parseInt(String s)
B:int -- String:toString(int)/valueOf(int)
Integer:public static String toString(int i)
String:public static String valueOf(int i)
(5)JDK5 之后的新特性
A:自动装箱基本类型--引用类型
B:自动拆箱引用类型--基本类型
举例:
Integer i = 100;// 默认至关于new Integer(100)
i += 200;// 等价于i = new Integer(i.intValue()+200);
//由于i += 200 底层调用的是intValue()方法, 因此咱们要加一层判断,防止报空指针异常
if (i != null) {
i += 200;
System.out.println(i);
}
(6)面试题:byte 常量池
Integer i1 = new Integer(127);
Integer i2 = new Integer(127);
System.out.println(i1 == i2);// false
System.out.println(i1.equals(i2));// true
Integer i3 = new Integer(128);
Integer i4 = new Integer(128);
System.out.println(i3 == i4);// false
System.out.println(i3.equals(i4));// true
Integer i5 = 128;
Integer i6 = 128;
System.out.println(i5 == i6);// false
System.out.println(i5.equals(i6));// true
//byte 常量池。byte 范围内的值直接赋值给Integer,是从常量池里面获取的。
Integer i7 = 127;
Integer i8 = 127;
System.out.println(i7 == i8);// true
System.out.println(i7.equals(i8));// true
(7)案例:
把字符串中的数字字符排序。
需求:"23 98 16 38 42"
结果:"16 23 38 42 98"
代码:
String s = "23 98 71 54 60";
// 字符串转字符串数组
String[] strArray = s.split(" ");
// 字符串数组转int 数组(数字才能够比较大小,字符无法比较大小)
int[] arr = new int[strArray.length];//此时尚为空数组 
// 循环遍历对arr数组依次赋值
for (int x = 0; x < arr.length; x++) {
arr[x] = Integer.parseInt(strArray[x]);
}
//int[]数组排序
Arrays.sort(arr);
//把排序后的int[] -- String
StringBuffer sb = new StringBuffer();
for(int x=0; x<arr.length ;x++){
sb.append(arr[x]).append(" ");//在sb字符串末尾追加元素
}
String result = sb.toString().trim();//去除字符串两端空格
System.out.println(result);

**:关于学习方法:
A:常常回顾,每次回顾都会有新的发现
B:常常练习
C:概括总结错误
D:自学习惯锻炼本身独立思考问题的能力,用代码去实现你的思路。
**:面试题:随机给出一个数组,要求把越靠近50 的数往左排;
public static void main(String[] args) {
int[] arr = { 1, 2, 4, 7, 9, 12, 2, 3, 4, 89, 100, 105, 88, 50, 49, 48,
48, 47, 99, 60, 40, 30, 70 };
// int[] arr= {1,4,5,7,8,22,44};
arr = sort50(arr);
System.out.println(Arrays.toString(arr));
}
public static int[] sort50(int[] arr) {//靠近50的排序方法
// 从小到大排
Arrays.sort(arr);
/*
* 若是数组里面全部的数都大于50就返回原数组
*/
if (arr[1] >= 50) {
return arr;
/*
* 若是数组里面全部的数都小于50,
*/
} else if (arr[arr.length - 1] <= 50) {
int[] arrtemp = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
arrtemp[arr.length - 1 - i] = arr[i];
}
return arrtemp;
/*
* 若是数组里面有大于50 的也有小于50 的
*/
} else {
// 外循环控制次数
for (int x = 0; x < arr.length - 1; x++) {
// 内循环控制每一次的比较过程
/*
* 第一次, 全部元素都参与比较, 也就是0 个元素不参与。第二次,有1
个元素不用参与。第三次, 有2 个元素不用参与。...
*/
// -1 是为了防止索引越界
// -x 是为了减小比较的次数
for (int y = 0; y < arr.length - 1 - x; y++) {
if (Math.abs(arr[y] - 50) > Math.abs(arr[y + 1] - 50)) {
// 数据交换
int temp = arr[y];
arr[y] = arr[y + 1];
arr[y + 1] = temp;
}
}
}
/*// 选择排序法
for (int i = 0; i < arr.length - 1; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (Math.abs(arr[i] - 50) > Math.abs(arr[j] - 50)) {
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
}*/
}
return arr;
}

part14 经常使用API:date、对象数组和综合案例

1:实际开发中经常遇处处理时间和日期的状况,Java中提供了date类来处理。
2:Date
(1)日期类。
构造方法:
Date():默认指当前系统时间。
Date(long time):根据给定的毫秒值生成一个时间。
(2)完成以下操做(日期和毫秒值的转换)
Date --> long:Date.getTime()
Date d = new Date();
long time = d.getTime();
long –> Date:Date的有参构造或Date.setTime()
long time = ???;
Date d = new Date(time);
或D
ate d2 = new Date();
d2.setTime(time);
(3)DateFormat 类(日期和字符串的转换)
String –> Date:日期格式对象.parse(string)
public Date parse(String source)
注意:若是是字符串到日期,你指定的格式必须和字符串的格式匹配。
2013-12-12
yyyy-MM-dd
2013/11/11
yyyy/MM/dd
Date –> String:日期格式对象 .format(date)
public final String format(Date date)
须要本身指定格式,常见的格式:
yyyy 年MM 月dd 日HH:mm:ss
yyyy 年MM 月dd 日
HH:mm:ss
yyyy-MM-dd HH:mm:ss
2: Calendar
(1)Calendar 是日历类,能够获取任意指定日历值,而后自由组合。
Calendar 是抽象类不能实例化,可是他提供了获取其实例的方法
Calendar c = Calendar.getInstance();// 多态
(2)成员方法:
get(日历字段):根据给定的日历字段获取值
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int date = c.get(Calendar.DATE);
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);
int second = c.get(Calendar.SECOND);
String s = year + "年" + (month + 1) + "月" + date + "日" + " " + hour
+ ":" + minute + ":" + ((second>9)?second:"0"+second);
set(年,月,日):给日历设定指定的年, 月, 日
add(日历字段,值):给指定的日历字段添加或者减去给定的值。取决于值的正负。
(3)案例:请说出任意一年的2 月份是多少天。
Calendar c = Calendar.getInstance();
Scanner sc = new Scanner(System.in);
int year = sc.nextInt();
c.set(year, 3, 1);// 把日期设置为2013 年3 月1 日
c.add(Calendar.DATE, -1);// 把日期往前推1 日
System.out.println(c.get(Calendar.DATE));
3:对象数组
用以放置对象的数组
4:案例:对象数组改进登录注册
UserDao:操做接口
UserDaoImpl:操做类实现操做接口
User:存储学生数据的对象(能够存储用户名, 密码, 邮箱等等)
UserTest:测试类
代码: 只给你们写一个UserDaoImpl 和UserTest,其余的比较简单
/**
* 用户操做实现类
**
如何实现呢? 若是是注册一个用户用User 保存便可。可是注册确定不止一个用户, 因此咱们得想一想用什么存储?
目前咱们学过的可以存储的:对象,对象数组。经过分析最终选择对象数组。可是这样作有问题:对象数组须要定义数组, 定义数组就得知道长度。但是没法肯定数组长度。因此对象数组不够好。最终选择集合。不过集合还没学呢, 因此如今只能使用对象数组。本身给一个固定长度: 5
*/
public class UserDaoImpl implements UserDao {
// 定义成员变量的数组
private static User[] users = new User[5];//用户数组
private static int index = 0;
@Override
public boolean isLogin(String username, String password) {//登陆
/*
* 遍历数组,获取到每个对象,而后再拿对象的用户名和密码和传递过来的用户名和密码进行比较
*/
boolean flag = false;
for (int x = 0; x < users.length; x++) {
User user = users[x];
// 判断用户是否为null
if (user != null) {

//对比穿过来的用户名和密码
if (user.getUsername().equals(username) && user.getPassword().equals(password)) {
flag = true;
break;
}
}
}
return flag;
}
@Override
public void regist(User user) {//注册
users[index++] = user;
}
}
----------------------------------------------------------------
import java.util.Scanner;
public class UserTest {
public static void main(String[] args) {
while (true) {
System.out.println("欢迎来到XXX");
System.out.println("1:登陆");
System.out.println("2:注册");
System.out.println("3:退出");
System.out.println("请选择: ");
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
switch (line) {
case "1":
System.out.println("欢迎来到登陆界面");
System.out.println("请输入用户名: ");
String username = sc.nextLine();
System.out.println("请输入密码: ");
String password = sc.nextLine();
UserDao ud = new UserDaoImpl();// 多态用法
// 具体类用法
UserDaoImpl udi = new UserDaoImpl();
boolean flag = udi.isLogin(username, password);
if (flag) {
System.out.println("开始玩游戏吧");
System.exit(0);
} else {
System.out.println("登陆失败,返回主界面");
}
break;
case "2":
System.out.println("欢迎来到注册界面");
// 键盘录入用户信息
System.out.println("请输入用户名: ");
String newUsername = sc.nextLine();
System.out.println("请输入密码: ");
String newPassword = sc.nextLine();
System.out.println("请输入邮箱: ");
String newEmail = sc.nextLine();
System.out.println("请输入电话: ");
String newPhone = sc.nextLine();
// 把数据用对象进行封装
User user = new User();
user.setUsername(newUsername);
user.setPassword(newPassword);
user.setEmail(newEmail);
user.setPhone(newPhone);
// 建立用户操做类对象
UserDaoImpl newUdi = new UserDaoImpl();
// 调用注册方法
newUdi.regist(user);
System.out.println("注册成功");
break;
case "3":
// System.out.println("谢谢你的使用");
// System.exit(0);
// break;
default:
System.out.println("谢谢你的使用");
System.exit(0);
break;
}
}
}
}

part15 集合:cllection和list接口

1: 集合(理解)
(1)java 是一种面向对象语言,若是要针对多个对象进行操做就必须对多个对象进行存储,而对多个元素进行存储,数组有弊端---长度固定,数组将不能知足变化的要求,因此java 就提供了集合。
(2)集合的特色:
一、长度能够发生改变
二、只能存储对象
三、能够存储多种类型对象(通常存储的仍是同一种)
(3)集合和数组的区别
一、长度问题
数组固定;集合可变
二、存储元素问题
数组能够是基本类型,也能够是引用类型;集合只能是引用类型。
三、是否同一类型
数组元素类型一致;集合元素类型能够不一致。
(4)集合体系的由来
集合是存储多个元素的容器,可是因为数据结构不同,java 就提供了多种集合类。而这多种集合类有共性的功能,因此经过不断的向上抽取最终造成了集合体系无标题
结构。
数据结构:数据存储的方式。
程序= 算法+ 数据结构
(5)如何学习和使用一个继承体系呢?
学习顶层:由于顶层定义的是共性内容。
使用底层:由于底层才是具体的实现。
2: Collection 的功能(掌握)
(1)Collection 的功能
一、添加功能:add()
boolean add(Object obj):向集合中添加一个元素。
boolean addAll(Collection c):向集合中添加一个集合的元素。
二、删除功能:clear()/remove()
void clear():删除集合中全部的元素。
boolean remove(Object obj):删除集合中指定的元素。
boolean removeAll(Collection c):删除集合中指定的集合元素,只要有数据删除,则返回true 。
三、判断功能:isEmpty()/contains()
boolean isEmpty():判断集合是否为空。
boolean contains(Object obj):判断集合是否包含指定的元素。
boolean containsAll(Collection c):判断集合是否包含指定的集合中的元素。只有全部数据包含了才返回true 。
四、遍历功能:iterator迭代器
Iterator iterator():迭代器。
hasNext():判断是否还有元素
next():获取下一个元素
五、长度功能:size()
int size():得到集合的元素个数。
六、交集功能:retainAlll()
boolean retainAll(Collection c):判断集合中是否有相同的元素。若是有两个集合A 和B ,A 对B 作交集,A 集合保存的是交集元素,B 集合不发生改变,返回值表示的是A 集合是否发生过改变。
七、转换功能:toArray()
Object[] toArray():把集合变成数组。
(2)迭代器的使用
一、使用步骤
a、经过集合对象获取迭代器对象。
b、经过迭代器对象判断。
c、经过迭代器对象获取。
二、迭代器原理
因为多种集合的数据结构不同因此存储方式不同,因此取出方式也不同。此时就把判断和获取功能定义在了一个接口中,未来遍历哪一种集合的时候只要该集合内部实现这个接口便可。
(3)集合的常见使用步骤:
一、建立集合对象
二、建立元素对象
三、把元素添加到集合中
四、遍历集合
a、经过集合对象获取迭代器对象。
b、经过迭代器对象判断。
c、经过迭代器对象获取。
(4)Collection 存储字符串和自定义对象并遍历。
一、存储字符串
Collection c = new ArrayList();//建立集合
//String s = "hello";
//c.add(s);
c.add("hello");//添加元素
c.add("world");
c.add("java");
Iterator it = c.iterator();//迭代器进行遍历
while(it.hasNext())
{
String s = (String)it.next();
System.out.println(s);
}
二、存储自定义对象
Collection c=new ArrayList();//定义集合
Student s1=new Student("林青霞",26);//定义元素
c.add("s1");//添加元素
Iterator it=c.iterator();//迭代器遍历
while(it.hasNext())
{
String s=(String)it.next();
System.out.println(s);
}
3: List 的特有功能
(1)List 的特色
List 是Collection 接口下的一个子接口
特色:元素有序可重复。
Set 也是Collection 接口下的一个子接口
特色:元素无序惟一。
(1)List 的特有功能
一、添加功能:add(index,obj)
void add(int index,Object obj): 在指定位置添加元素。
二、删除功能:remove(index)
Object remove(int index): 根据指定索引删除元素,并把删除的元素返回
三、修改功能:set(index,obj)
Object set(int index,Object obj):把指定索引位置的元素修改成指定的值,返回修改前的值。
四、获取功能:get(index)/indexOf(obj)/ListIterator--list迭代器
Object get(int index): 获取指定位置的元素
int indexOf(Object obj): 返回指定元素在集合中第一次出现的索引。
ListIterator listIterator():list迭代器
五、截取功能:subList(fromIndex,toIndex)
List subList( int fromIndex, int toIndex )截取集合。
(2)List 的遍历方式
一、Iterator 迭代器
二、ListIterator 迭代器(仅做了解)
三、普通for+get()
(3)ListIterator 迭代器
ConcurrentModificationException 并发修改异常
ConcurrentModificationException
①:为何出现这个异常:由于咱们在用迭代器遍历的时候,经过集合对元素进行了操做
②:如何解决呢:
A:经过迭代器遍历的时候,用迭代器进行操做集合元素ListIterator
B:普通for 循环遍历集合的时候,经过集合对元素进行操做

part16 集合:List实现类、泛型

1:常见的数据结构
栈,队列,数组,链表
栈:先进后出,类比水桶
队列:先进先出,类比出水管
数组:查询快(含有索引),增删慢
链表:查询慢(没有索引),增删快

扩展知识:

image
2: List 的三个儿子
(1)List 的三个儿子特色:
List
|--ArrayList
底层数据结构是数组,查询快,增删慢
线程不安全,效率高
|--Vector
底层数据结构是数组,查询快,增删慢
线程安全,效率低
|--LinkedList
底层数据结构是链表,查询慢,增删快
线程不安全,效率高
(2)案例:ArrayList 存储自定义对象去重复
需求:ArrayList 若是存储的是学生,那么怎么去除重复元素呢?
问题:如何知道学生是重复的?
需求:若是学生的姓名和年龄相同,我就认为是同一个学生,即重复值。
问题分析:经过简单分析咱们估计是判断那里出问题了。
看判断的方法。而咱们又知道,判断的方法是API 提供的不是本身写的。因此看源码,经过看原码发现,底层依赖的是equals()方法。因为学生类中并无equals()方法,因此默认用的是Object 的方法。而Object 类的方法,默认比较的是地址值。因为学生对象都是new 出来的地址值确定不同样,因此从这个角度考虑结论是正确的。可是不符合咱们的需求。怎么办呢?此时要重写equals()方法,让它按照咱们的需求来比较。
代码:
public static void main(String[] args) {
ArrayList array = new ArrayList();
Student s1 = new Student("郑成功", 40);
Student s2 = new Student("戚继光", 50);
Student s3 = new Student("戚继光", 50);
Student s4 = new Student("岳飞", 36);
Student s5 = new Student("岳飞", 40);
Student s6 = new Student("林则徐", 30);
array.add(s1);
array.add(s2);
array.add(s3);
array.add(s4);
array.add(s5);
array.add(s6);
// 建立新集合
ArrayList array2 = new ArrayList();
// 遍历旧集合,获取到每个元素
Iterator it = array.iterator();
while (it.hasNext()) {
Student s = (Student) it.next();
// 在新集合中判断, 看是否存在这个元素
if (!array2.contains(s)) {
// 若是s 不再array2 中存在就添加
array2.add(s);
}
}
// array2 就是没有重复元素的集合。
// 遍历array2
for (int x = 0; x < array2.size(); x++) {
Student s = (Student) array2.get(x);
System.out.println(s.getName() + "***" + s.getAge());
}
}
(3):Vector 的特有功能
A: 添加功能。
void addElement( Object obj )  
B: 获取功能。
public Object elementAt( int index )
public Enumeration elements()//枚举:用于存储“稳定的”数据集
类Enumeration 里边有两个方法。(相似于迭代器)
boolean hasMoreElements()
Object nextElement()
public int size()
(4):LinkedList 的特有功能
A: 添加功能
void addFirst( Object o ):将指定元素插入此列表的开头。
void addLast( Object o ):将指定元素添加到此列表的结尾。
B: 获取功能
Object getFirst()
Object getLast()
C: 删除功能
Object removeFirst()
Object removeLast()
(5):面试题:用LinkedList 模拟栈数据结构
package cn.itcast_02;
A:第一步,自定义栈集合的类。
import java.util.LinkedList;
//自定义栈集合
public class MyStack {
//经过LinkedList 模拟栈数据结构
private LinkedList list;
public MyStack()
{
list = new LinkedList();
}
public void add(Object obj)
{
list.addFirst(obj);
}
public Object get(int index)
{
return list.get(index);
}
public int size()
{
return list.size();
}
}
B: 在测试类中测试。
package cn.itcast_02;
public class MyStackTest {
public static void main(String[] args) {
MyStack ms = new MyStack();
ms.add("hello");
ms.add("world");
ms.add("java");
for (int x = 0; x < ms.size(); x++) {
String s = (String) ms.get(x);
System.out.println(s);
}
}
}
(6)到底使用谁根据需求看
是否要安全:
是:Vector
否:ArrayList,LinkedList
查询多:ArrayList
增删多:LinkedList
若是什么都不知道用ArrayList 。
3: 泛型(理解)
(1)泛型是一种把明确类型的工做放在了建立对象或者调用方法时候才去明确的特殊的类型。
(2)格式:<数据类型>
(3)好处:
A:解决了黄色警告线问题
B:把运行期间的转换异常给提早到了编译期间
C:优化了程序设计,不须要作强制类型转换了
1):泛型类
需求:我能不能不用重载方法,就能够实现同一个方法输出不同类型的数据呢?
package cn.itcast_03;
//尖括号中的QQ 表明的是任意类型,QQ 也能够用其余任意字母代替(自定义)
public class Tool<QQ> {
//这里的QQ 必须和上边尖括号中的名字同样,qq 是变量名,能够自定义
public void show(QQ qq)
{
//输出QQ 类型的变量qq
System.out.println(qq);
}
}
2):泛型方法
为了保证方法传递不同的参数,就在类上明确了类型。这样的话,它要是可以在调用方法的时候,才去明确类型该有多好呢
public class Tool
{
public <BYD> void show( BYD byd )
{
System.out.println( byd );
}
}
3):泛型接口
A:定义Inter接口的代码。
package cn.itcast_03;
public interface Inter<BMW> {
public abstract void show(BMW bmw);
}
B:接口Inter 的实现类InterImpl 中的代码。
package cn.itcast_03;
public class InterImpl<BMW> implements Inter<BMW> {
@Override
public void show(BMW bmw) {
System.out.println(bmw);
}
4:加强for 循环
(1)格式:
for(数组或者Collection 集合的元素类型 变量: 数组或者Collection 集合的对象)
{
   直接使用变量便可。
}
(2)好处:
方便了数组和Collection 集合的遍历。
(3)注意(注意):
A:加强for 是用来替代迭代器的。其底层就是调用的迭代器
B:不要在用加强for 遍历集合的时候,用集合对集合自己进行修改。
(4)遍历List 集合体系三种方式
1):迭代器
2):普通for+get
3):加强for(实际开发时时候用)
Collection 集合遍历两种方式
1):迭代器
3):加强for(工做时候用)

part17 集合:set实现类

面试题:用集合改进登录注册案例
本次用集合改进“登录注册”,仅仅是把包cn.itcast.dao.impl中的类UserDaoImpl 中的内容给修改了下。
public class UserDaoImpl implements UserDao {
//建立集合对象
private static ArrayList<User> array = new ArrayList<User>();
@Override
public boolean isLogin(String username, String password) {
// 遍历数组,获取到每个对象,
// 而后再拿对象的用户名和密码和传递过来的用户名和密码进行比较
boolean flag = false;
//遍历集合获取每个用户,若是存在就修改标记为true
for(User u : array)
{
if(u.getUsername().equals(username) &&
u.getPassword().equals(password))
{
flag = true;
break;
}
}
return flag;
}
@Override
public void regist(User user) {
//将该用户添加到集合中
array.add(user);
}
}
1:Set(掌握)
(1)Set 的特色:
元素无序惟一。(注意和List 的对比:元素有序可重复。)
注意:这里的顺序是指存储和取出顺序。
2:HashSet:保证惟一的方法---hashCode()和equals()
(1)HashSet:不保证元素的迭代顺序,且不保证该顺序恒久不变。
(2)怎么保证的呢?
HashSet 底层数据结构是哈希表。它依赖两个方法:hashCode()和equals()
顺序:
首先,判断hashCode()值是否相同。
相同:继续走equals()方法,根据其返回值:
true:说明元素重复,不添加到集合。
false:说明元素不重复,添加到集合。
不同:直接添加到集合。
(3)重写hashCode()和equals()方法:
hashCode():
把对象的全部成员变量值相加便可。
若是是基本类型就加值。若是是引用类型就加哈希值。
public int hashCode()
{
return this.name.hashCode() + this.age + this.sex +this.score ;
}
equals():
A:this==obj
B:!(obj instanceof Student)
C:全部成员变量的值比较,基本类型用==,引用类型用equals()
3:TreeSet:保证惟一的方法----实现comparable接口或comparator比较器接口
(1)TreeSet:根据构造方法的不用,选择使用天然排序或者比较器排序。按照实际的需求可对元素进行排序而且保证惟一。
(2)如何保证元素惟一的:
排序:底层结构是二叉树,按照树节点进行存储和取出。
两种实现:
A:天然排序(元素具有比较性):TreeSet 的无参构造,要求对象所属的类实现Comparable 接口。
public int compareTo( Studetn s )
{
//需求是比较年龄
int num = this.age - s.age ;
//因为对象有多个成员变量,不能根据其中的某一个决定其余的。
//当某一个相同的时候还须要判断其余的是不是也是相同的。
int num2 = ( num == 0 ) ? ( this.name.compareTo( s.name ) ) :
num ;
return num2;
}
B:比较器排序(集合具有比较性):TreeSet 的带参构造,要求构造方法接收一个实现了Comparator 接口的对象。
TreeSet<Student> ts = new TreeSet<Student> ( new
Comparator<Student>
{
@Override
public int compare ( Student s1 , Student s2)
{
//按照年龄排序从小到大
int num = s1.getAge() - s2.getAge();
//次要条件
int num2 = ( num == 0 ) ? (
s1.getName().compareTo(s2.getName()) ) : num;
return num2;
}
} );
//建立元素对象
Student s1 = new Student(“张三”, 24);
Student s2 = new Student(“李四”, 30);
Student s1 = new 。。。。。。
//添加元素
ts.add(s1);
ts.add(s2);
...........
for( Student s : ts )
{
System.out.println(s.getName() + "*****" + s.getAge());
}
惟一:根据返回值是否为0 。
注意:若是同时有两种方案以比较器为主。
(3)案例:TreeSet 存储自定义对象按照姓名长度排序
public int compareTo( Studetn s )
{
//需求是比较姓名的长度
int num = this.name.length() - s.name.length() ;
//不少时候,别人给咱们的需求其实只是一个主要需求
//还有不少的次要需求是须要咱们本身进行分析的。
//比较姓名的内容
int num2 = ( num == 0 ) ? ( this.name.compareTo( s.name ) ) : num ;
//继续分析,姓名长度和内容都相同的状况下,年龄还可能不同样
//因此当姓名长度和内容都相同的时候,再比较下年龄
int num3 = ( num2 == 0 ) ? ( this.age - s.age ) : num3 ;
return num3;
}
(4)原理:二叉树保证元素惟一排序
A:第一个添加的数据做为根节点。
B:从第二个开始,
每个数据从根节点开始比较,
若是大了往右边放,若是小了往左边放,若是相同则替换。
C:从根节点开始,获取数据的规则:按照每一个数据的:左,中,右原则。
4: Collection 体现的集合总结
Collection
|—List:元素有序可重复
   |—ArrayList:底层数据结构是数组,查询快增删慢
   线程不安全,效率高。
   |—LinkedList:底层数据结构是链表,查询慢增删快
   线程不安全,效率高。
   |—Vector:底层数据结构是数组,查询快增删慢
   线程安全,效率低。
|—Set:元素无序,惟一
   |—HashSet:底层数据结构是哈希表。
   保证元素惟一性:依赖两个方法---hashCode()和equals() 。
   |—TreeSet:底层数据结构是二叉树。
   保证元素惟一: 根据返回值是不是0,判断元素是否重复。
   排序有两种方案:
      元素具有比较性实现Comparable 接口
      集合具有比较性实现Comparator 接口
5: 在集合中的数据结构问题
ArrayXxx:底层数据结构是数组,查询快增删慢
LinkedXxx:底层数据结构是链表,查询慢增删快
HashXxx:底层数据结构是哈希表,跟两个有关:hashCode()和equals()
TreeXxx:底层数据结构是二叉树:两种排序方式:Comparable 接口天然排序和Comparator 接口比较器排序
6: 何时,使用哪一种Collection 集合。
元素惟一吗?
惟一:Set
须要排序吗?
  须要:TreeSet
  不须要:HashSet
  不知道:用HashSet 。
不惟一:List
须要安全码?
  须要:Vector
  不须要:ArrayList 和LinkedList
     查询多:ArrayList
     增删多;LinkedList
     不知道,用ArrayList 。
7:Collections工具类
(1)Collections 是针对Collection 集合操做的工具类。
public static void sort ( List list ):排序。
public static <T> int binarySearch( List list, T key ):二分查找。
public static void reverse( List list ):反转。
public static T max( Collection coll ):最大值。
public static void shuffle( List list ):随机置换(至关于“洗牌”)
(2)面试题:
Collection 和Collections 的区别?
Collection:是Collection 集合的顶层接口,定义了Collection 集合的共性方法。
Collections:是一个collection集合的工具类,定义了针对Collection 集合操做的功能,有排序、查找、反转等。
(3)案例:斗地主洗牌发牌小游戏
public static void main(String[] args) {
// 买牌
// 表示花色的数组
String[] colors = { "黑桃", "红桃", "梅花", "方块" };
// 表示点数的数组
String[] numbers = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10","J", "Q", "K" };
// 造一个牌盒
ArrayList<String> array = new ArrayList<String>();
array.add("大王");
array.add("小王");
// 循环装牌
for (String c : colors) {
for (String n : numbers) {
array.add(c.concat(n));
}
}
// 显示全部牌
// System.out.println(array);
// 洗牌
Collections.shuffle(array);
// 显示全部牌
// System.out.println(array);
// 发牌
ArrayList<String> linString = new ArrayList<String>();
ArrayList<String> zhouString = new ArrayList<String>();
ArrayList<String> meString = new ArrayList<String>();
// 用普通for
for (int x = 0; x < array.size() - 3; x++) {
if (x % 3 == 0) {
linString.add(array.get(x));
} else if (x % 3 == 1) {
zhouString.add(array.get(x));
} else if (x % 3 == 2) {
meString.add(array.get(x));
}
}
// 看牌
System.out.println("linString:" + linString);
System.out.println("zhouString:" + zhouString);
System.out.println("meString:" + meString);
// 看底牌
for (int x = array.size() - 3; x < array.size(); x++) {
System.out.print(array.get(x) + " ");
}
}

part18 集合:Map

1:Map
(1)Map 是一个键值对形式的集合,它的元素都是有键和值组成。
(2)Map 和Collection 的区别?(面试题)
A:Map 是由键值对组成的集合,Map 的键(key)是惟一的,值(value)能够重复。
B:Collection 是有单列数据组成的集合,它的儿子List 是能够重复的,Set 是惟一的。
(3)HashMap 和Hashtable 的区别?(面试题)
HashMap:线程不安全效率高,容许null 键和值。
Hashtable:线程安全效率低,不容许null 键和值。
(4)Map 的功能:
A:添加功能
V put(K key, V value) 当key 在集合中不存在时添加元素;当key 在集合中存在的时候替换元素。
B:判断功能
boolean containsValue( Object value ) 判断指定的值是否在集合中存在。
boolean isEmpty() 判断集合是否为空。
C:删除功能
void clear() 清除全部键值对数据。
V remove( Object key ) 根据指定的键删除键值对。
D:获取功能
Set<Map.Entry<K,V>> entrySet() 键值对对象的集合(注:entry登记,记录)
Object get( Object key ):根据键获取值。
Set<K> keySet():全部键的集合
Collection<V> values() 全部值的集合。
E:长度功能
int size()
(5)Map 的两种遍历方式
A:丈夫找妻子:根据键来找值
a:把全部丈夫给集合起来:Set<K> keySet()
b:遍历丈夫集合:获取到每个丈夫:加强for 或迭代器
c:让丈夫去找妻子:get(Object key)
// 建立集合对象
Map<String, String> map = new HashMap<String, String>();
// 往集合里边添加元素
map.put("郭靖", "黄蓉");
map.put("杨过", "小龙女");
map.put("牛郎", "织女");
// 获得全部的丈夫对象
Set<String> husbandSet = map.keySet();
// 用迭代器的方式来作
Iterator it = husbandSet.iterator();
while(it.hasNext())
{
String husband = (String)it.next();
String wife = map.get(husband);
System.out.println(husband +"-----"+ wife);
}
// 用加强for 来作
for (String s : husbandSet) {
// 根据“丈夫”找到“妻子”--根据键获取值
String wife = map.get(s);
System.out.println(s + "******" + wife);
}
B:根据结婚证找丈夫和妻子:根据键值对来找键和值
a:获取全部结婚证的集合,Set<> entrySet()
b:遍历结婚证集合,获取到每个结婚证对象:迭代器或加强for
c:经过结婚证对象获取丈夫和妻子getKey()和getValue()
// 建立集合对象
Map<String, String> map = new HashMap<String, String>();
// 往集合里边添加元素
map.put("郭靖", "黄蓉");
map.put("杨过", "小龙女");
map.put("牛郎", "侄女");
// 找到全部的“结婚证”即全部的键值对封装到一个集合中备用
Set<Map.Entry<String, String>> set = map.entrySet();
// 方式2 遍历,这样每次遍历我都会获得一个键值对
for (Map.Entry<String, String>  en : set) {
// 获得键和值,而后打印
String key = en.getKey();
String value = en.getValue();
System.out.println(key + "****" + value);
}
2:HashMap
(1)HashMap 存储字符串并遍历
键:String
值:String
(2)HashMap 存储自定义对象并遍历
键:String
值:Student
(3)HashMap 存储自定义对象并遍历
键:Student(重写hashCode 和equals 方法,自动生成)
值:String
需求:若是对象的成员变量值都相同则认为是同一个对象。
3:TreeMap
(1)TreeMap 存储字符串并遍历
键:String
值:String
(2)TreeMap 存储自定义对象并遍历
键:String
值:Student
(3)TreeMap(传入一个比较器comparator)存储自定义对象并遍历
键:Student
值:String
需求:若是对象的成员变量值都相同则认为是同一个对象,同时还要按照年龄排序。
4:案例(理解)
(1)统计字符串中每一个字符出现的次数。
//建立集合对象
TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>();
String str = "cbxzbvavdvgd";
//将字符串转成字符数组
char[] chs = str.toCharArray();
//遍历字符数组
for (char ch : chs) {
//将拿到的字符去集合中找对应的值,根据返回值进行相应的操做
Integer i = tm.get(ch);
if (i == null) {
tm.put(ch, 1);
} else {
i++;
tm.put(ch, i);
}
}
//将获得的键值对集合,根据转变成字符串并将结果按照要求的格式打印出来
//建立可变字符串对象
StringBuilder sb = new StringBuilder();
//获得集合中全部的键并遍历
Set<Character> set = tm.keySet();
for(char ch:set)
{
//根据键找到对应的值, 而后按照要求的格式拼接
Integer i = tm.get(ch);
sb.append(ch).append("(").append(i).append(")");
}
//将结果转成字符串, 并输出
String result = sb.toString();
System.out.println(result);
(2)HashMap 嵌套HashMap 的使用。
//建立集合对象--czbk
HashMap<String,HashMap<String,String>> czbk = new
HashMap<String,HashMap<String,String>>();
//建立并添加元素对象yr 和jy
HashMap<String,String> yr = new HashMap<String,String>();
yr.put("01", "zhangsan");
yr.put("02", "lisi");
czbk.put("yr",yr );
HashMap<String,String> jy = new HashMap<String,String>();
jy.put("01", "wangwu");
jy.put("02","zhaoliu");
czbk.put("jy", jy);
//遍历集合
//建立集合对象--czbk
HashMap<String,HashMap<String,String>> czbk = new
HashMap<String,HashMap<String,String>>();
//建立并添加元素对象yr 和jy
HashMap<String,String> yr = new HashMap<String,String>();
yr.put("01", "zhangsan");
yr.put("02", "lisi");
czbk.put("yr",yr );
HashMap<String,String> jy = new HashMap<String,String>();
jy.put("01", "wangwu");
jy.put("02","zhaoliu");
czbk.put("jy", jy);
//遍历集合
//先拿到czbk 集合中全部的键, 并遍历
Set<String> czbkKeys = czbk.keySet();
for(String czbkKey :czbkKeys)
{
//打印czbk 集合中的键
System.out.println(czbkKey);
//在czbk 集合中, 根据键拿到对应的值, 由于值也是一个键值对集合, 因此我
们在遍历一次
HashMap<String,String> hm=czbk.get(czbkKey);
//拿到(czbk 的值集合)中的全部的键
Set<String> set = hm.keySet();
//遍历, 根据键找到对应的值, 并将结果输出
for(String s :set)
{
String value = hm.get(s);
System.out.println("\t"+s+"***"+value);
}
}
(3)HashMap 嵌套ArrayList 的使用。

part19 异常

异常
1:异常的概述
写完代码,代码下面有红线就是异常;运行程序控制台显示报错了,就是异常
2:异常的体系
Throwable
Error:严重的问题,一般出现的是重大的问题
好比运行的类不存在或者内存溢出等,不须要处理,可是确定是要修改代码的(找到哪一个地方有严重错误),
不然整个程序都运行不起来
Exception:不严重
编译期异常:强制要求咱们处理
运行期异常:能够不处理,也能够处理
若是不处理:程序能够运行起来,可是运行到报错处
咱们在编程的过程当中确定会有不少问题的存在
为了方便表示问题缘由、类型、位置。java 就提供了异常对象供咱们使用
异常:
程序出现的不正常状况
对应的异常
Throwable 类
---Error(错误)严重的
一般出现重大问题:运行的类不存在或者内存溢出,不需处理,而是须要修改代码
---Exception(异常)不严重的
---编译期间的,这个须要处理
---运行期间的,这个不须要处理的,须要修改代码或者传递参数
若是出现问题,咱们本身没有处理,jvm 会才用的处理方式
他就是异常的类型缘由、位置直接显示在控制台,后面的代码是不能执行的
A,编写处理代码:
基本格式
try{
    可能发生问题的代码
}catch(异常类名,变量名){
异常处理代码
}
B,抛出
代码中有多个异常该怎么处理,一个个的用异常处理方案解决
针对全部问题写一个try catch,一个try 多个catch
注意:
在异常处理中,一旦try 里出问题了直接跳到catch 里处理
注意一个问题,异常或者错误都是以他们所在的体系父亲做为后缀
catch 顺序:
若是异常是平级关系没有顺序;若是有子父关系,父类要放在最后
**jdk7 新特性,多个catch 用一个处理
格式:catch(异常1 | 异常2 |、、、变量名){}

part20 递归

递归定义:方法定义调用方法自己的现象。
public void show(){
show();
}
注意事项:
A:递归必定要有出口,不然就会死递归。
B:递归的次数不要过多,不然内存溢出。
举例:
public void show(int n)
{
if(n==0)//出口条件,结束递归的条件
{
System.exit(0);
}
else{
System.out.println("hell");
show(n-1);
}
}
作递归的题思路
1)找递归出口
2)找递归规律
举例:用递归求5!
出口:1!=1
规律:n!=n*(n-1)!
public static int jc(int n) {
if (n == 1) {
// 出口
return 1;
} else {
// 规律
return n * jc(n - 1);
}
}
案例:用递归求斐波那契数列
public static int fun(int n) {
if (n == 1 || n == 2) {
return 1;
} else {
return fun(n - 1) + fun(n - 2);
}
}
用递归求下列数列的第二十项的值: 1, 1, 2, 4, 7, 13, 24...
private static int sum(int i) {
if(i ==1){
return 1;
}else if(i==2){
return 1;
}else if(i==3){
return 2;
}else{
return sum(i-3) +sum(i-2)+ sum(i-1);
}
}
应用: 1:在控制台输出D:\jkdong\20160430 全部的java 文件的绝对路径。
private static void showFiles(File file) {
// 获取该目录下的全部文件或者文件夹的File[]数组。
File[] fileArray = file.listFiles();
//有时候一些有权限的文件不能获取, 因此fileArray 有可能为null 因此要
加入判断
if(fileArray!=null){
// 遍历File[]数组, 获取到每个File 对象
for (File f : fileArray) {
// 判断该File 对数是不是目录
if (f.isDirectory()) {
showFiles(f);
} else {
// 文件
if (f.getName().endsWith(".java")) {
System.out.println(f.getAbsolutePath());
}
}
}
}
}
2:删除指定的目录(目录是带有目录或者文件的)
private static void deleteFiles(File file) {
//第1 步封装文件夹
File[] fileArray = file.listFiles();//1,test_deleteFiles; 2.1,aaa_deleteFiles;
2.2,bbb_deleteFiles;
if (fileArray != null) {
//若是封装的文件夹不为空,那么就进行遍历,得到每个文件或文件夹
for (File f : fileArray) {
if (f.isDirectory()) {
//若是被封装文件夹的子文件仍是个文件夹,那么继续封装起来
进行判断
deleteFiles(f);
} else {
//若是被封装起来的子文件夹正好就是个文件,那么直接删除
System.out.println(f.getName() + "***" + f.delete());
}
}
}
System.out.println(file.getName() + "***" + file.delete());
// 若是文件夹为空,直接删除. 当if 语句执行完时,就表示每次封装的目录下
的文件被删除完毕。
}

part21 IO 流

IO 流总结:
基本字符输出流:FileWriter

A:建立字符输出流FileWriter 对象(并传入一个写入的位置)
FileWriter fw = new FileWriter("a.txt");//必须初始化
B:调用写数据的功能
fw.write("hello,io你好");
C:刷新缓冲区
fw.flush();
D:释放资源(jvm 不会自动回收流的资源, 除非你手动标记该流已成为垃圾)
fw.close();

基本字符输入流:FileReader
//建立字符输入流对象(而且明确你要从哪一个文件读数据)

FileReader fr = new FileReader("FileWriterDemo.java");
//方式1:一次读取一个字符
int ch = 0;
while((ch=fr.read())!=-1){//若是数据没有读取时将返回-1
//若是有数据则返回int 类型(字符的int 值),并自动移动到下一个数据位置等待读取
S ystem.out.print((char) ch);
}

//方式2:一次读取一个字符数组

char[] chs = new char[1024];
int len = 0;
while ((len = fr.read(chs)) != -1) {//len 表示read(chs)读取到多少个字符
//若是实际读取长度是-1 的状况,那么说明已经读取到结尾了
System.out.print(new String(chs, 0, len));//new String(chs, 0, len)
//是为了写入实际读入的数据, 不然读取到最后的时候可能会有误差
}
//释放资源
fr.close();
高效字符输出流:BufferedWriter

//建立高效字符输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("c.txt"));
// 写入数据
bw.write("hello");
bw.flush();
// 释放资源
bw.close();

高效字符输入流:BufferedReader

BufferedReader br = new BufferedReader(new FileReader("c.txt"));
// 方式一:一次读取一个字符
int ch = 0;
while ((ch = br.read()) != -1) {
System.out.print((char) ch);
}
// 方式二:一次读取一个字符数组
char[] chs = new char[1024];
int len = 0;
while ((len = br.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}

//方式3:一次读取一行

String line = null;
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
// 释放资源
br.close();

基本字节输出流:FileOutputStream

A:建立字节输出流对象
FileOutputStream fos = new FileOutputStream("a.txt");
B:调用写数据的方法
fos.write(97);
C:释放资源
fos.close();

注意:写数据的方法有
   write(byte b)
   write(byte[] bys);
   write(byte[] bys, int start,int lenth);
   追加写入用两个参数构造
   FileOutputStream fos = new FileOutputStream("a.txt",true);

基本字节输入流:FileInputStream

FileInputStream fis = new FileInputStream("b.txt");
//方式1:一次读一个字节
int by = 0;
while ((by = fis.read()) != -1) {
System.out.println(by);
}
//方式2:一次读一个字节数组
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
System.out.print(new String(bys, 0, len));
}
//释放资源
fis.close();
高效字节输出流:BufferedOutputStream

BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("4.mp4"));
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("d:\\11.java"));
byte[] bys = new byte[1024];
int len = 0;
while((len=bis.read(bys))!=-1){
bos.write(bys,0,len);
}
bos.close();
bis.close();

高效字节输入流:BufferedInputStream

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
"d:\\copy.java"));
byte[] bys = new byte[1024];
int len = 0;
while((len=bis.read(bys))!=-1){
System.out.print(new String(bys, 0, len));
}
bis.close();
注意:对于文本能够用字符流也可用字节流,对于二进制数据(图片,音频,视频等)只能使用字节流

 

题目实例:

1: 复制MP3 加入异常处理的标准代码
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream("d:\\Copy.java"));
bos = new BufferedOutputStream(new FileOutputStream("copy1.java"));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2: 键盘录入数据写入文本文件
// 封装数据源
Scanner sc = new Scanner(System.in);
// 封装目的地
BufferedWriter bw = new BufferedWriter(new FileWriter("sc.txt"));
String line = null;
while((line=sc.nextLine())!=null){//"null"
if("over".equals(line)){
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
sc.close();
3: 在ArrayList 里面存储了3 个字符串元素, 请把这三个元素写入文本文件。并在每一个元素
后面加入换行
ArrayList<String> array = new ArrayList<String>();
array.add("hello");
array.add("world");
array.add("java");
BufferedWriter bw = new BufferedWriter(new FileWriter("array.txt"));
//遍历集合
for(String str : array){
bw.write(str);
bw.newLine();
bw.flush();
}
bw.close();
4:从集合读取数据写入到文件
BufferedReader br = new BufferedReader(new FileReader("bw.txt"));
ArrayList<String> array = new ArrayList<String>();
String line = null;
while ((line = br.readLine()) != null) {
array.add(line);
}
br.close();
// 遍历集合
for (String s : array) {
System.out.println(s);
}
5: 编写复制文件的工具类
/**
**
@author itcast 工具类, 专门用于复制文本文件, 图片等
*/
public class Copys {
private Copys() {
}//工具类的构造方法通常私有, 不容许new
/**
* 复制文本文件
**
@param src
* 数据源
* @param dest
* 目的地
*/
public static void copyFile(String src, String dest) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(src));
BufferedWriter bw = new BufferedWriter(new FileWriter(dest));
char[] chs = new char[1024];
int len = 0;
while ((len = br.read(chs)) != -1) {
bw.write(chs, 0, len);
bw.flush();
}
bw.close();
br.close();
}
/**
* 复制二进制流数据
**@param src
* 数据源
* @param dest
* 目的地
*/
public static void copyBinaryData(String src, String dest)
throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
src));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(dest));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
bis.close();
}
}
6:综合题:将d:\java 目录下的全部.java 文件复制到d:\jad 目录下, 并将原来文件的扩展名从.java 改成.jad
方法一:先更名再复制
// 封装d:\\java 这个目录
File srcFile = new File("d:\\hellodong");
// 获取该目录全部知足条件的File[]数组。
File[] fileArray = srcFile.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
System.out.println(dir+"---"+name);
return new File(dir, name).isFile() && name.endsWith(".java");
}
});
//判断是否存在目的地目录, 若是没有, 就建立。
File destFile = new File("d:\\jad");
if(!destFile.exists()){
destFile.mkdirs();
}
// 遍历File[]数组, 获取到每个File 。
for (File file : fileArray) {
// file -- d:\\java\\Constant.java -- 数据源
//最终的结果: d:\\jad\\Constant.jad -- 目的地
//复制前更名
String name = file.getName(); //Constant.java
String newName = name.replace(".java", ".jad");//Constant.jad
File newFile = new File(destFile,newName);//d:\\jad\\Constant.jad
//复制文件
BufferedReader br = new BufferedReader(new FileReader(file));
BufferedWriter bw = new BufferedWriter(new FileWriter(newFile));
String line = null;
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
方法二: 先复制后更名
// 封装d:\\java 这个目录
File srcFile = new File("d:\\java");
// 获取该目录全部知足条件的File[]数组。
File[] fileArray = srcFile.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir, name).isFile() && name.endsWith(".java");
}
});
// 判断是否存在目的地目录, 若是没有, 就建立。
File destFile = new File("d:\\jad");//"d:\\jad\\ChangeNameDemo.java"
if (!destFile.exists()) {
destFile.mkdir();
}
// 遍历File[]数组, 获取到每个File 。
for (File file : fileArray) {
//file -- d:\\java\\Constant.java
String name = file.getName();//Constant.java--》d:\\java\\Constant.java
File newFile = new File(destFile, name); //d:\\jad\\Constant.java
BufferedReader br = new BufferedReader(new FileReader(file));
BufferedWriter bw = new BufferedWriter(new FileWriter(newFile));
String line = null;
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
//复制完毕后更名
File[] destFileArray = destFile.listFiles();
for(File file : destFileArray){
//file -- d:\\jad\\Hello.java
//结果-- d:\\jad\\Hello.jad
String name = file.getName(); //Hello.java
String newName = name.replace(".java", ".jad");//Hello.jad
File newFile = new File(destFile,newName);//d:\\jad\\Hello.jad
file.renameTo(newFile);
}

part22 其它流、编码表、properties

转换流
1:标准的输入输出流
public static final InputStream in
System.in -- InputStream (字节输出流) 底层是BufferedInputStream
public static final PrintStream out
System.out -- PrintStream (字节输入流)
注意: 必须经过标准输入流才能从控制台录入数据
必须经过标准输出流才能把数据写入控制台显示
2.字节输入流转成字符输入流
方法:
字节流通向字符流的桥梁
InputStream --> InputStreamReader --> BufferedReader
3:字节输出流转字符输出流
方法:
OutputStream -- > OutputStreamWriter --> BufferedWriter
4:编码问题
流的编码问题:字符流=字节流+编码表
若是你想在IO 流中使用指定编码下数据,用转换流。
编码问题其实很简单,永远使用同一种编码便可。
FileReader=FileInputStream+GBK
FileWriter=FileOutputStream+GBK
//写入的时候用的字符流的UTF-8 编码
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"), "UTF-8");

// 指定编码UTF-8
osw.write("中国");
osw.close();
//那么读出的时候若是用字符流也应该用UTF-8 编码
InputStreamReader isr = new InputStreamReader(new FileInputStream(
"osw.txt"), "UTF-8");
char[] chs = new char[1024];
int len = isr.read(chs);
String str = new String(chs, 0, len);
System.out.println(str);
打印流
PrintStream:字节打印流
PrintWriter:字符打印流
打印流特色:
A:能够写入任意类型的数据。
B:能够自动刷新。必须先启动而且是使用println,printf 及format 方法才有效。
C:能够直接对文件进行写入。
哪些流对象是能够直接对文件进行操做的?
看构造方法, 是否有同时接受File 和String 类型的参数构造。
注意: 打印流只有写数据的,没有读取数据的。
案例: 用打印流复制文本文件
// 封装数据源
BufferedReader br = new BufferedReader(new FileReader(
"PrintWriterDemo.java"));
// 封装目的地
PrintWriter pw = new PrintWriter(new FileWriter("Copy.java"), true);
String line = null;
while((line=br.readLine())!=null){
pw.println(line);
}
pw.close();
br.close();
注意:
A:读取文件的时候,若是是文件夹,会出现:FileNotFoundException: test (拒绝访问。)
B:写文件的时候,若是没有后缀名,它也会自动生成一个文件 而这个种类型的文件经过记事本类型的软件是能够打开的。
序列化流
序列化:把对象按照流同样的方式传输或者存储。
ObjectOutputStream 将Java 对象的基本数据类型和图形写入OutputStream 。
void writeObject(Object obj)
反序列化:把网络中的流数据或者文件中的流数据还原成对象。
ObjectInputStream:ObjectInputStream 对之前使用ObjectOutputStream 写入的基本数据和对象进行反序列化
Object readObject()
注意问题:
A:若是类的对象想被序列化流操做,请实现序列化接口。
B:看到了类实现了Serializable 接口,若是想解决黄色警告线请点击鼠标。
java.io.NotSerializableException 没有实现序列化接口异常
类经过实现java.io.Serializable 接口以启用其序列化功能。
该接口被称为序列化接口,是一个标记接口。没有任何功能须要实现。
类一旦实现了该接口,那么该类的对象就能够被序列化流进行操做。
Properties
Properties:是一个表示属性集的集合。能够从流中加载数据或者把数据保存到流中。键和值都是字符串。是惟一一个能够和IO 流结合使用的集合类。
Properties 的父亲是Hashtable,因此知道它是一个Map 体现的。那么就存储数据并遍历。
Properties 做为集合的特殊功能:
1: 修改功能
public Object setProperty(String key,String value)
2: 获取功能
public String getProperty(String key)
public String getProperty(String key,String defaultValue)
public Set<String> stringPropertyNames()
System 类的一个方法: public static Properties getProperties():系统属性
Properties 做为和IO 流结合使用的集合的特殊功能:
public void list(PrintStream out): 把集合中的数据按照键值对的形式存储到文本文
件中。
public void list(PrintWriter out): 把集合中的数据按照键值对的形式存储到文本文件
中。
public void load(InputStream inStream): 从文本文件中把数据加载到集合中。
public void load(Reader reader): 从文本文件中把数据加载到集合中。
注意: 对文本文件是有要求的, 要求数据必须是键值对形式。
public void store(OutputStream out,String comments): 把集合中的数据保存到文本
文件中。
public void store(Writer writer,String comments): 把集合中的数据保存到文本文件
中。
注意:store 和list 方法的区别list 的参数值能是PrintWriter 或PrintStream
而store 的参数是PrintStream 或者Writer
综合案例: 我有一个学生类,这个类包含一下成员变量:姓名,语文成绩,数学成绩,英语成绩。
请从键盘录入5 个学生信息,而后按照本身定义的格式存储到文本文件中;要求被存储的学生按照分数从高到低排序。
// 写一个学生类,有4 个成员变量。
System.out.println("学生信息录入开始");
// 须要用到排序,定义TreeSet 集合
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// 主要条件
int num = s2.getSum() - s1.getSum();
// 分析次要条件
// 当总分相同,还得继续比较每一门的分数是否相同
int num2 = (num == 0) ? s1.getChinese() - s2.getChinese() : num;
int num3 = (num2 == 0) ? s1.getMath() - s2.getMath() : num2;
// 当语文,数学,英语成绩都相同的还得继续判断姓名是否相同。
int num4 = (num3 == 0) ? s1.getName().compareTo(s2.getName())
: num3;
return num4;
}
});
for (int x = 0; x < 5; x++) {
// 用Scanner 实现键盘录入。
Scanner sc = new Scanner(System.in);
// 键盘录入数据
System.out.println("请输入第" + (x + 1) + "个学生的姓名:");
String name = sc.nextLine();
System.out.println("请输入第" + (x + 1) + "个学生的语文成绩:");
int chinese = sc.nextInt();
System.out.println("请输入第" + (x + 1) + "个学生的数学成绩:");
int math = sc.nextInt();
System.out.println("请输入第" + (x + 1) + "个学生的英语成绩:");
int english = sc.nextInt();
// 把数据封装到学生对象中
Student s = new Student();
s.setName(name);
s.setChinese(chinese);
s.setMath(math);
s.setEnglish(english);
ts.add(s);
}
// 遍历集合,获取到集合中的每个数据,用输出流写到文本文件。
BufferedWriter bw = new BufferedWriter(new FileWriter("students.txt"));
bw.write("姓名\t 语文\t 数学\t 英语");
bw.newLine();
bw.flush();
for (Student s : ts) {
StringBuilder sb = new StringBuilder();
sb.append(s.getName()).append("\t").append(s.getChinese()).append("\t").append(s.getMath()).append("\t").append(s.getEnglish());
bw.write(sb.toString());
bw.newLine();
bw.flush();
}
bw.close();
System.out.println("学生信息录入成功");

part23 多线程

多线程:应用程序有多条执行路径。
进程:正在运行的应用程序。
线程:一条路径,进行的执行单元。
注意:线程是依赖于进程,而进程是操做系统直接建立的。
Java 语言是不能直接调用操做系统的属性的。C 语言能够。
为何要使用多线程?何时使用?为了提升效率。
当要操做的代码比较多(耗时),循环次数比较多的时候就可使用多线程。
多线程怎么实现呢?
方式1:继承Thread 类
A: 建立一个类(MyThread),继承Thread 类。
B: 重写Thread 类中的run()方法。
C: 启动并执行线程。
注意:这里是不能直接调用run()方法,须要调用start()方法。start()方法作了两件事:
A:启动线程。
B:自动调用run()方法。
同一个线程对象start()两次,会报一个异常:IllegalThreadStateException(线程状态异常。)
Thread 类的两个方法:
public final String getName(); 获取线程名称(Thread-编号, 编号是从0 开始)
public final void setName(String name); 设置线程名称。
public static void sleep(long mills); 让当天线程睡一段时间(根据传过来的毫秒值)
线程执行的随机性的原理:因为CPU 在作着高效的切换。程序的执行,其实就是在抢CPU 资源。
方式2:实现Runnable 接口。
A: 建立一个类(MyRunnable)实现Runnable 接口。
B: 重写run()方法。
C: 建立类(MyRunnable)的实例。
D: 把类(MyRunnable)的实例,作为Thread 类的构造参数传递。
注意事项:
由于MyRunnable 这个类是实现了Runnable 接口,因此在类中不能直接使用Thread 类的getName()这个方法。
怎么用呢?
public static Thread currentThread(); 返回正在执行的线程的引用(Thread.currentThread().getName())
既然有了第一种实现方式,为何要有第二种实现方式?
A:避免了单继承的局限性。
B:实现Runnable 接口的方式,只建立了一个资源对象,更好的实现了数据(my)和操做(start())的分离。
开发中经常使用:实现Runnable 接口的方式。
多线程的生命周期图:
A: 新建(建立一个线程对象)
B: 就绪(具有执行资格, 不具有执行权)
C: 有可能发生阻塞(不具有执行资格和执行权)
sleep(),wait()
notify()
D: 运行(具有执行资格和执行权)
E: 死亡(线程对象变为垃圾, 等待垃圾回收器回收。)
多线程模拟买票出现了负数和重复值? 产生缘由是什么? 怎么解决呢?
产生负数:
public class TicketRunnable implements Runnable {
public int tickets = 200;
@Override
public void run() {
while (true) {
//t1,t2,t3,t4 都进来了
//最后一次tickets 的值是1
if (tickets > 0) {
/*
* t1 知足, 进来了,
* t2 进来了,
* t3,
* t4 都进来了
* */
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*
* t1 醒了, 抢到了资源, 打印: 第一张票,完了之后, tickets 的值变成了0
* t2 醒了, 抢到了资源, 打印: 第0 张票, 完了之后, tickets 的值变成了-
1
* t3 醒了, 抢到了资源, 打印: 第-1 张票, 完了之后, tickets 的值变成了-
2
* t4 醒了, 抢到了资源, 打印: 第-2 张票, 完了之后, tickets 的值变成了-
3
* */
System.out.println(Thread.currentThread().getName() + "正在出售第"
+ (tickets--) + "张票");
}
}
}
}
产生重复值:
关键点:ticket--(ticket = ticket - 1)
A:获取ticket 的值。
B:修改ticke 的值。
C:把修改后的值,从新赋值给ticket 。
当步骤A 执行完后,还没来得及执行B,这个时候别的线程抢到了资源,打印的就是重复值。
产生缘由:
因为线程的随机性和延迟性,致使线程访问共享数据出现了问题。
解决方案:找到可能出问题的代码,而后把可能出问题的代码用锁锁起来。
A:如何找可能出问题的代码?
一、是否有共享数据。
二、是否有多条语句操做共享数据。
三、是否在多线程环境中。
这三点也是多线程产生问题的缘由。
B:怎么锁?
能够采用同步代码块的方式锁。
synchronized (锁对象)
{
要被锁的代码。
}
注意:
一、锁对象能够是任意对象。
二、多个线程的锁对象必须是同一个。不然可能会出现锁不住的状况。
锁的状态:开,关。
不同同步机制的锁对象分别是什么?
同步代码块:能够是任意类型。
同步方法:把synchronized 定义在方法的声明上。(写在方法的返回值的数据类型以前)
public synchronized void show();
this 。
静态方式:
当前类的字节码文件对象。
类名.class
之后使用同步代码块仍是同步方法?
看需求,可是同步的代码越少越好,因此通常使用同步代码块。
若是一个方法中全部的代码都被加锁了,那么能够考虑使用同步方法。
线程间的通讯问题:
线程通讯:不同种类的线程间对共享数据的操做问题。
用学生类的案例来演示线程通讯;
学生类: Student (资源类)
设置值: SetStudent (一个共享数据, 实现了Runnable 接口)
获取值: GetStudent(一个共享数据, 实现了Runnable 接口)
测试类:
正常的逻辑:
针对输出:( GetStudent)
判断是否有数据, 若是有就输出数据, 没有的话, 就等待设置。
(喝水: 判断水杯是否有水, 若是有就喝, 若是没有, 就等待小蜜去接水)
针对设置; (SetStudent)
判断是否有数据, 若是有就等待输出, 若是没有, 就设置。
(接水: 判断水杯是否有水, 若是有等待喝, 若是没有, 就接水。)
定义了一个标记: true 表明有数据, false 表明没有数据。
面试题: wait()方法和sleep()这个方法有什么区别?
wait(): Object 类下的方法, 不须要传递参数。释放锁对象, 释放资源。
sleep(): Thread 类, 须要传递参数, 不释放锁对象。
等待唤醒机制的原理:
Object 类中的两个方法:
wait(): 让当前线程处于等待状态。
notify(): 唤醒等待的线程。
线程的优先级;
public final void setPriority(int newPriority); 设置线程的优先级
public final int getPriority(); 获取线程的优先级
线程默认的优先级是5, 范围是1-10.
注意:
线程的优先级越高, 并不表明该线程必定第一个执行。
线程优先级能够再必定程度上, 让该线程获取较多的执行机会。
线程的拓展:
暂停线程:
public static void yield(); 暂停当前正在执行的线程对象, 并执行其余线程。
何时用?
他可让线程更和谐一点的运行, 避免出现成片数据的状况。
注意: 若是想要真正的实现数据依次输出, 还得使用等待唤醒机制。
加入线程:
public final void join(); 等待该线程终止。
何时用?
当某个线程(A)须要在某个线程(B)执行结束后才执行, 就可使用“加入线
程” 。
例子: 当线程B 执行完后才能执行线程A,
守护线程:
public final void setDaemon(boolean on); 设置线程为守护线程, 一旦前台线程(主
线程)结束了, 守护线程紧跟着就结束了。
main 方法也是一个线程。

part24 网络编程

网络编程概述
计算机网络:
概念:地理位置不同的多台计算机, 网络线路链接。网络管理软件, 网络协议,实现资源共享和信息传递
分类: 局域网,城域网,广域网,万维网
网络编程:用来实现网络互联的不同计算机运行的程序间数据交换
网络模型:网络之间使用何种规则进行通讯
osi 七层参考模型
物理层,定义物理设备,传输比特流
数据链路层,mac 地址的封装与解封装(交换机)
网络层,ip 地址的封装与解封装(路由器), 数据包
传输层,定义传输协议和端口号(tcp udp)
会话层,发起会话或者接受会话请求
表示层,解释加密解密压缩解压缩(完成翻译)
应用层,终端应用,直接使用的软件,面向用户
tcp/ip 模型
主机到网络层--物理层, 链路层
网际层--网络层
传输层--传输层
应用层--会话层, 表示层, 应用层
网络通讯三要素
网络通讯(Socket 通讯, 套接字编程)
实现网络互连的不同计算机上运行的程序间能够进行信息交换
即用java 语言实现不同计算机间的通讯
三要素:
IP 地址:Ip 是网络中每一台计算机的惟一标识
端口:用于标识进程的逻辑地址,不同的进程(应用程序)拥有不同的端口
协议:定义通讯规则--udp 和tcp 协议
IP 地址
概念:网络中的计算机的惟一标识
表示形式:点分十进制计数法--192.168.0.100
二进制对应的十进制
二进制太长不方便记忆
每段(8 位)范围0~255
ip 地址分类
A 类1.0.0.1-127.255.255.254(10.x.x.x 是私有地址)
B 类128.0.0.1--191.255.255.254(172.16.0.0--172.31.255.255 为私有)
C 类192.0.0.1--223.255.255.254
D 类224.0.0.1--223.255.255.254
E 类240.0.0.1--247.55.255.254
ip 地址组成
网络号码+主机地址
A 类第1 段为网络号码, 后3 个是本地主机的地址: 256^3 个主机(广域网)
B 类前2 段为网络号码, 后2 个是本地主机的地址: 256^2 个主机(校园网)
C 类前3 段为网络号码, 后1 个是本地主机的地址: 256 个主机(局域网)
查看本机ip: win+r-->cmd-->ipconfig /all
查看网络是否有问题: ping+ip 地址
ping:127.0.0.1 本机回环地址: 检查本机环境是否有问题
ping:x.x.x.x 别人地址检查外部环境是否有问题
ping:x.x.x.x -t 向。。一直发包
端口号:
每一个网络进程至少有一个逻辑端口
用于标识进程的逻辑地址, 不同进程标识不同样
有效端口: 0~65535(255^2).其中0~1024 是系统使用或者保留端口
**协议: 定义的通讯规则
udp 协议
数据打包(将数据源和目的地封装成数据包)
数据有限制(数据包限制在64k)
面向无链接(不须要创建链接)
不可靠协议
速度快
举例: QQ 群聊, 短信
tcp 协议: 三次握手协议--请求, 回应, 发送
创建链接通道
数据没有限制
面向链接的协议(三次握手)
可靠
速度慢
举例: 蓝牙, QQ 单聊, 打电话
用什么: 看需求
Socket 编程
是为网络编程提供一种机制, 包装了端口和ip 地址
特色:
数据两端都独有Socket
网络通讯实际就是Socket 通讯
数据在两个Socket 间经过IO 传输
Socket 通讯--套接字编程--网络编程
InetAddress 类
ip 地址的包装类, 该类的构造方法是私有的,
怎么该类的对象:
InetAddress getByName(String host),根据主机名返回对应的ip 地址(对象
形式)
注意: 参数能够是主机名也能够是ip 地址
成员方法:
getHostAddress();返回ip 地址(字符串)
getHostName();返回主机名
udp 发送步骤
建立发送端Socket 发送对象
DatagramSocket 类的无参构造
建立数据并把数据打包
DatagramPacket(byte[] bys,length,InetAddress ip,port(端口号))
发送数据
send(DatagramPacket dp)
释放资源
ds.close();
udp 接收步骤
建立接受端Socket 对象
DatagramSocket(int port)
建立数据包(接收容器)
DatagramPack(byte[] bys,int length)
调用接收方法
receive(dp)
*解析数据包, 把数据显示在控制台, 从包里拿到须要的对象
从数据包中得到ip(字符串ip)
InetAddress getAddress()
InetAddress getHostAddress()
从数据包中得到客户端发的数据
byte[] getData();
int getLength();//获取实际长度
释放
ds.close();
注意:
发送接收的端口必定要一致
一个端口不能够被多个程序使用
案例: 聊天室(掌握)
Scoket 类
Tcp 协议客户端的步骤
建立客户端Socket 对象
Socket(host,port) host 能够是ip 地址
创建链接
获取输出流, 写数据便可, 往服务器发送数据
OutputStream getOutputStream();
释放资源
tcp 协议服务器端步骤
建立服务器Socket 对象
ServerSocket(int port)
监听链接
public Socket accept();监听并接收到此套接字的链接
获取输入流, 读取数据并显示
public InputStream getInputStream()
释放
注意:
必须先开服务器端, 而后再开启客户端, 不然程序会出错
键盘录入数据写入文本文件
数据写进去了, 但服务器反馈没有成功
缘由:

part25 正则反射

正则表达式:
概述:就是符合某种规则的字符串。
需求:
判断是不是QQ 号码。(5-15 位数字,不能以0 开头)
[1-9][0-9]{4,14}
规则字符: Pattern 类
A:字符
n 字符n 自己出现一次
\\ 在正则中,两个\表示一个\
\r 回车
\n 换行
B:字符类
[abc] a,b,c 任意一个字符出现一次
[^abc] 任意字符,a,b,c 除外
[a-zA-Z] 全部的英文字母一次
[0-9]任意数字一次
C:预约义字符类
. 单独的一个点表示任意字符一次
\d 任意数字一次, 至关于[0-9]
\w 单词字符(字母, 数字, _),至关于[a-zA-Z_0-9]
D:边界匹配器
^ 行的开头
$ 行的结尾
\b 这里出现的不能是单词字符
E:数量词
n? 字符n 一次或一次都没有
n* 字符n 零次或者屡次
n+ 字符n 一次或者屡次(至少一次)
n{a} 字符n 刚好出现a 次
n{a,} 字符n 至少出现a 次
n{a,b} 字符n 至少出现a 次, 不超过b 次
基本功能:
判断功能:
public boolean matches(String regex); 判断该字符串是否与给定的正则表达式匹配。
切割功能:
public String[] split(String regex); 按照给定的正则切割该字符串
替换功能:
public String replaceAll(String regex, String replacement);
用指定的字符串来替换字符串中全部符合正则规则的字符串。
regex:正则,用来检索要替换的字符串
replacement:用来替换的字符串。
获取功能:
使用的是模式对象Patter 和匹配器Matcher 对象。
Matcher 类下的两个方法:
public boolean find();尝试查找与该模式匹配的输入序列的下一个子序列。
理解:就是大串中查找小串,看是否有符合规则的小串。
public String group();
返回由之前匹配操做所匹配的输入子序列。
理解:就是返回刚才查找到的,符合规则的小串。
A: 经过字符输入流来读取文本文件。
B: 对读到的每一行数据进行校验。
C: 若是数据符合需求, 就把该数据存到集合中。
D: 遍历集合。
反射:
概述:在运行期间,能够经过Class 文件对象(字节码文件对象)来使用构造方法,成员变量,成员方法。
怎么获取Class 文件对象:
A:Object 类中的getClass()方法。
B:数据类型的静态的class 属性(类名.class)
C:Class 类中的forName(String className); 注意;className 的名字要是带全路径的。
开发中经常使用第三种,由于它能够结合配置文件使用。
注意:一个类能够有多个对象,可是只能有一个Class 文件对象。

part26 设计模式

概述:把类似的东西抽取出来的模型分类建立型模式:建立对象。--工厂模式,单例模式结构型模式:类与类的关系(研究对象间的关系)--装饰模式行为型模式:对象可以作什么。--模版模式GOF 设计模式(23 种)人:闫闳(国内研究设计模式较早的)建立型模式:工厂模式简单工厂模式AnimalDogCatAnimal工厂方法模式原理首先咱们先写一个动物的抽象工厂类, ()当咱们须要一个新对象的时候, 按照以下操做写一个该该类的实体类去继承动物类写一个该类的工厂类去继承动物类而后在该类的工厂类中建立该类对象AnimalDogCatPigAnimalFactoryDogFactory extends AnimalFactoryCatFactory extends AnimalFactoryPigFactory extends AnimalFactory测试类单例模式:类在内存中只存在一个对象--如网站访问统计、windows 打印服务应用: 线程池, 数据库链接池面试题: 写出一个单例设计模式分析: 类在内存中只存在一个对象外界不能随意建立对象把构造方法私有类自己要建立一个对象静态方法只能访问静态, 对象要加静态为了不让外界经过类名直接访问就加私有经过公共的方式提供给别人: public 修饰的方法为了让外界可以直接经过类名访问该方法, 须要对方法加静态饿汉式: (开发中用)类一加载就建立对象public Student {private Student(){}//类一加载就建立对象private stattic Student s = new Student();public static Student getStudent(){return s;}}Student s = Student.getStudent();懒汉式:(面试中用):何时用就何时建立对象jdk 中的单例模式:RunTome 类public Student {private Student(){}//何时用就何时建立对象//面试时别忘加锁private synchronized stattic Student s = null;public static Student getStudent(){if(s==null){s = new Student();}return s;}}为何懒汉式: (面试中用)懒汉式是延迟加载: 何时用, 何时建立对象懒汉式有线程安全问题: 方法上加锁装饰模式: 一种是经过继承实现, 一种是经过实现接口实现对类原有的功能进行修饰和包装扩展实现步骤:找到装饰的抽象事物Phone建立一个实体类(PhoneImple)只有打电话功能, 来实现或者继承第一步的抽象事物(Phone 接口)建立一个装饰类(PhoneDecorate), 来实现Phone 接口, 调用实体类对象装饰类子类继承装饰类, 重写装饰类的方法, 实现功能扩充Phone 接口PhoneImpl 具体实现类PhoneDecorate 抽象类ColorPhoneDecorate 具体装饰类GuangGaoPhoneDecorate 具体装饰类模板方法模式最优体现是以抽象类的形式体现的打印模板类打印方法: 具体的三个抽象方法具体实现类1具体实现类2需求: 模仿刚才的代码, 用模板方法模式设计一个计算, 程序运行时间的模板类long start = System.currentTimeMillis();code()long end = System.currentTimeMillis();

相关文章
相关标签/搜索