第一天 JDK安装、快捷键、JAVA语言特点
1.Java语言的概述
1.1 Java语言的背景
Java语言诞生于1995年,在编程语言排行榜占据重要的地位。
Java语言之父是高斯林,以前隶属于sun公司,现在隶属于oracle-sun公司(甲骨文)。
1.2 Java语言的主要版本
(1)JavaSE版本
- Java Platform, Standard Edition)称之为“Java平台标准版”。
- 主要用于编写桌面应用程序。
(2)JavaEE版本
- Java Platform,Enterprise Edition)称之为“Java平台企业版”。
- 主要用于编写具有B/S结构的电子商务网站、门户网站以及电信计费系统等。
(3)JavaME版本
- Java Platform,Micro Edition)称之为Java 平台微型版。
- 随着Android系统的普及,该技术已经走向淘汰。
2.开发环境的搭建和使用(重点)
2.1 jdk的下载和安装
(1)jdk的下载
下载方式一:直接去官网下载 -ww.sun.com/www.oracle.com
下载方式二:直接用谷歌/百度/搜狗搜索 jdk1.764位 下载和安装
(2)jdk的安装
若下载的是绿色版,则直接解压即可。
若下载的是安装版,根据提示一步步点击下一步即可,切记不要有中文路径。
3.2 相关的概念
javac.exe - Java语言的编译器,用于将高级源代码文件翻译成字节码文件。
java.exe - Java语言的解释器,用于启动java虚拟机进行字节码文件的解释并执行
jre - Java运行时环境信息,只要运行java程序就必须安装jre。
jdk - Java开发工具包,只要编写/开发Java语言程序就必须安装jdk,jdk自带jre。
JVM - Java虚拟机,并不是真实存在的主机,作为java程序和计算机之间的桥梁。
3.3 环境变量的概念和配置
(1)基本概念
环境变量就是指用于存放环境信息并且数值可以改变的量。
通常情况下若启动一个可执行文件需要增加路径才可以,当把路径放入环境变量中后,只需要通过可执行文件的名称就可以启动该程序。
(2)配置方式
计算机=> 右键,选择属性 => 高级系统设置 => 高级=> 环境变量 => 系统变量 => 找到Path变量点击编辑,将javac.exe所在的路径信息加入到该变量值的最前面,添加英文版的分号=> 一路点击确定即可。
切记Path变量值原来的内容不要改动,以避免带来灾难性的后果!!!
3.4 Java程序的开发流程
(1)新建文本文档,将默认的xxx.txt重命名为xxx.java。
(2)使用记事本的方式打开该文件,并编写Java代码保存。
(3)启动dos窗口,使用cd命令将路径切换到xxx.java所在的目录中。
(4)使用javac编译器根据xxx.java生成xxx.class文件。
(5)使用javaxxx解释并执行该文件。
3.5 常用的快捷键
ctrl+s - 保存
ctrl+a - 全选
ctrl+c - 复制
ctrl+x - 剪切
ctrl+v - 粘贴
ctrl+f - 查找
ctrl+z - 撤销
alt+tab - 切换任务窗口
windows+tab - 切换任务窗口
windows+d - 显示桌面
windows+e - 打开计算机的磁盘界面
windows+l - 实现锁屏
windows+r - 启动运行窗口,输入cmd再回车启动dos窗口
ctrl+alt+delete - 启动任务管理器
使用shift键可以进行中英文的切换。
3.6 常用的dos命令
d: - 表示切换到D盘
cd 目录名 - 表示切换到指定的目录中
cls - 表示清屏
dir -表示查看当前目录中的所有内容
cd .. - 表示切换到上一级目录
3.7 Java语言的特点
(1)Java语言是一门纯面向对象的编程语言。
(2)Java语言具有跨平台的特性,也就是同一份字节码文件可以在不同的平台上执行,
是因为有Java虚拟机负责翻译工作。
(3)Java语言具有自动垃圾回收机制。
第二、三天 变量和注释、数据类型及转换、运算符
1.变量和注释(重点)
1.1 变量的基本概念以及分类
当需要在程序中记录一个数据内容时,则需要声明一个变量来保存,变量本质上就是内存条中的一块区域。
由于记录的数据内容不同导致所需要的内存空间大小不同,在Java语言使用数据类型加以描述,而使用变量名来描述该内存空间的地址信息。
变量分类:按照被声明位置划分:局部变量、成员变量(也叫“实例变量”、“域”)、 静态变量(也叫类变量)。
http://blog.chinaunix.net/uid-26434689-id-3328442.html
静态变量(也叫类变量)是类中独立于方法之外的变量,用static 修饰。(static表示“全局的”、“静态的”,用来修饰成员变量和成员方法,或静态代码块(静态代码块独立于类成员,jvm加载类时会执行静态代码块,每个代码块只执行一次,按顺序执行))。
成员变量(也叫“实例变量”、“域”)也是类中独立于方法之外的变量,不过没有static修饰。
局部变量是类的方法中的变量。
看下面的伪代码说明:
public class Variable{ 类名
static int allClicks=0;//静态变量也叫类变量
String str="hello world";//实例变量也叫成员变量
public void method(){方法名
int i =0;//局部变量
}
}
成员变量也称为:“域”,“实例变量”,在实体类或数据类中被称为“属性”或“字段”。当成员变量可以改变时,被称为对象的状态。
常量:用final修饰,值一旦给定就不能修改
1.2 变量的声明和初始化
数据类型 变量名 = 初始值; - 其中=初始值是可以省略的,但分号不可以省略
如:
int id = 1001; - 推荐使用该方式
int id;
1.3 使用变量的注意事项
(1)使用变量之前必须声明。
(2)使用变量之前必须指定初始值。
(3)不允许声明同名的变量。
(4)每个变量都拥有自己独立的作用域(有效的范围)。
补充:
在方法体中声明的变量叫做局部变量,局部变量的作用域为:声明开始到方法体结束
1.4 标识符(变量名)的命名规则
(1)必须由字母、数字、下划线_以及美元$组成,其中数字不能开头。
如:id、name、name2等。
(2)不能使用Java语言中的关键字/保留字,也就是Java语言中用来代表特殊含义的单词
如:class、public、void、int等
(3)区分大小写,长度没有限制但不宜过长。
如:day 和 Day代表不同的标识符,不推荐使用。
(4)尽量使用英文单词的组合做到见名知意,虽然支持中文,但不推荐使用。
如:sendMsgToAll、minute、time、length 年龄
1.5 常见的编程规范
(1)尽量使用空格、缩进以及空行来提高代码的可读性和层次感。
(2)当类名由多个单词组成时,要求每个单词的首字母都要大写。
(3)当变量名由多个单词组成时,要求从第二个单词起每个单词的首字母要大写。
1.6 注释
单行注释 - 从//开始一直到本行的末尾之间的内容都是注释内容。
多行注释 - 从/*开始一直到*/结尾之间的内容都是注释内容。
其中多行注释要求不允许嵌套使用,如:/* /**/ */ 是错误的。
2.数据类型(重点)
2.1 数据类型的分类
在Java语言中将数据类型分为两大类:基本数据类型 和 引用数据类型。
其中基本数据类型主要有(8种):
byte/short/int/long - 用于描述整数数据的类型,如:666。
float/double - 用于描述小数数据的类型,如:3.14。
char - 用于描述字符数据的类型,如:'a'。
boolean - 用于描述真假信息的类型,如:true 和 false。
其中引用数据类型主要有:
数组、类、接口、枚举以及标注(了解)。
2.2 常用的进制(数学、理解基本数据类型)
日常生活中采用十进制加以描述,逢十进一,权重为:10^010^1 10^2 ...
计算机中采用二进制加以描述,逢二进一,权重为:2^02^1 2^2 ...
八进制和十六进制为了简化二进制的表示形式。
在计算机中采用二进制的最高位(最左边)来代表符号位,若该位是0则表示非负数,若该位是1则表示负数。
2.3 进制之间的转换(数学、理解基本数据类型)
(1)十进制和二进制之间的转换(要求每个人掌握)
a.正十进制转换为二进制的方式
1)除2取余法,让十进制整数不断地除以2取出余数,直到商为0将所有余数逆序排列
2)拆分法,将十进制整数拆分为若干个二进制权重的和,若该权重出现则下面写1,
若该权重没有出现则下面写0(推荐)。
如:12
128 64 32 16 8 4 2 1 12 = 8 + 4
0 0 0 0 1 1 0 0 12转换为二进制的结果是:00001100
b.正二进制转换为十进制的方式
1)加权法,让二进制的每个数字乘以当前位的权重最后相加。
如:00001100
0000 1100 => 0*2^7 + 0*2^6 + 0*2^5 +0*2^4 + 1*2^3 + 1*2^2 + 0*2^1 + 0*2^0
=> 0 + 0 + 0 + 0 + 8 + 4 + 0 +0
=> 12
c.负十进制转换为二进制的方式
1)先将该整数的绝对值转换为二进制,然后进行按位取反再加1.
如:-12
12转换为二进制:00001100 12的二进制:0000 1100
按位取反: 1111 0011 -12的二进制:11110100 +
再加1: 1111 0100 --------------------------
1 0000 0000(最高位溢出)
d.负二进制转换为十进制的方式
1)先进行按位取反加1,然后转换为十进制整数,最后添加负号
如:11110100
1111 0100进行按位取反:00001011
加1: 0000 1100
转换为十进制整数: 12
最后添加负号: -12
2.3原码反码补码扩展:
原码、反码以及补码的概念。
http://blog.csdn.net/u011080472/article/details/51280919
http://blog.csdn.net/liushuijinger/article/details/7429197
机器数:一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0,负数为1。
真值:将带符号位的机器数对应的真正数值称为机器数的真值。
例:0000 0001的真值 =+000 0001 = +1,10000001的真值 = –0000001 = –1
原码:如果机器字长为n,那么一个数的原码就是用一个n位的二进制数,其中最高位为符号位:正数为0,负数为1。剩下的n-1位表示概数的绝对值。
例如: X=+101011 , [X]原=00101011 X=-101011 , [X]原=10101011
位数不够的用0补全。
PS:正数的原、反、补码都一样:0的原码跟反码都有两个,因为这里0被分为+0和-0。
反码:反码就是在原码的基础上,符号位不变其他位按位取反(就是0变1,1变0)。
补码:
补码就是在反码的基础上按照正常的加法运算加1。
例如:X=-101011 , [X]原=10101011 ,[X]反=11010100,[X]补=11010101
PS:0的补码是唯一的,如果机器字长为8那么[0]补=00000000。
移码:
移码最简单了,不管正负数,只要将其补码的符号位取反即可。
例如:X=-101011 , [X]原=10101011 ,[X]反=11010100,[X]补=11010101,[X]移=01010101
(2)八进制和二进制之间的转换(熟悉)
a.二进制转换为八进制的方式
1)将每三位二进制合并为一位八进制,并使用0作为前缀代表八进制。
如:
010 110 => 026
b.八进制转换为二进制的方式
1)将每一位八进制拆分为三位二进制,并使用0b作为前缀代表二进制(jdk1.7)。
如:
075 => 0b111 101
(3)十六进制和二进制之间的转换(熟悉)
a.二进制转换为十六进制的方式
1)将每四位二进制合并为一位十六进制,并使用0x作为前缀代表十六进制。
如:
1010 0011 => 0xa3(十六进制中使用a~f来代表10 ~15).
b.十六进制转换为二进制的方式
1)将每一位十六进制拆分为四位二进制,并使用0b作为前缀代表二进制。
如:
0xab => 0b1010 1011
2.4 单个字节表示的整数范围(重中之重)
在计算机中单个字节表示八位二进制位,最高位(最左边)的二进制位代表符号位,若该位是0则表示非负数,若该位是1则表示负数,具体如下:
非负数的表示范围是:00000000 ~ 0111 1111 => 0 ~ 127 => 0 ~2^7-1
其中0000 0000转换为十进制整数就是0;
其中0111 1111转换为十进制整数:64 +32 + 16 + 8 + 4 + 2 + 1 = 127;
负数的表示范围是: 1000 0000 ~ 1111 1111 => -128 ~ -1 =>-2^7 ~ -2^0
其中1000 0000转换为十进制整数:
按位取反:01111111 => 加1:10000000 => 128 => -128;
其中1111 1111转换为十进制整数:
按位取反:00000000 => 加1:00000001 => 1 => -1;
综上所述:
对于单个字节的二进制来说,所能表示的十进制整数范围是:-128~ 127.
-2^7 ~ 2^7-1.
2.5 整数类型
在Java语言中用于描述整数的类型有:byte/short/int/long,推荐使用int类型。
其中byte类型在内存空间占1个字节的大小,表示范围是:-128 ~127(-2^7 ~ 2^7-1)
其中short类型在内存空间占2个字节的大小,表示范围是:-2^15 ~2^15-1。
(-32768 ~ 32767)。
其中int类型在内存空间占4个字节的大小,表示范围是:-2^31 ~2^31-1.
(正负二十一亿之间)
其中long类型在内存空间占8个字节的大小,表示范围是:-2^63 ~2^63-1.
(比int类型范围还大)
在程序中直接写出的整数数值叫做 直接量/常量/字面值,默认为int类型,如:666,若希望表示long类型的直接量,则需要在直接量的后面加上L或者l,推荐使用L。
扩展:
若希望表示比long类型范围还大的整数,则借助java.math.BigInteger类。
2.6 浮点类型
在Java语言中用于描述小数数据的类型有:float/double,推荐使用double类型。
其中float类型在内存空间中占4个字节的大小,叫做单精度浮点数。
其中double类型在内存空间中占8个字节的大小,叫做双精度浮点数。
在程序中直接写入的小数数据叫做直接量/常量/字面值,默认为double类型,若希望表示float类型的直接量,则需要在直接量的后面增加F或者f。
Floatdouble扩展:
float类型和double类型是不能实现精确计算的,为了得到精确的结果需要借助java.math.BigDecimal类加以描述。
有余力的同学课下可以查询float和double存储结构。
http://blog.csdn.net/zq602316498/article/details/41148063
float:4字节 32位
1bit(符号位)8bits(指数位) 23bits(尾数位) a = r^3其中r为底数 3是指数
double:8字节 64位
1bit(符号位)11bits(指数位) 52bits(尾数位)
2.7 布尔类型
在Java语言中用于描述真假信息的类型有:boolean,该类型的数值:true 和 false.
由于布尔类型只有两个数值因此使用一个二进位制就足够描述,但通常认为是1个字节
2.8 字符类型(熟悉)
在Java语言中用于描述字符信息的类型有:char,在内存空间中占2个字节的大小,通常用于描述单个字符,如:'a' '1''中'等。
在现实生活中使用更多的是多个字符组成的字符串,使用String类型加以描述,并且使用双引号括起来,如:"xiaomage"。
要求大家记住的ASCII数值有:
'A' - 65 'a' - 97 '0' - 48 空格 - 32 换行 - 10
要求大家记住的转义字符有:
\" - " \' - ' \\ - \ \t - tab键 \n - 换行符
3.基本数据类型之间的转换(熟悉)
复习:
Java语言基本数据类型有:byte、short、int、long、float、double、charboolean byte b = 10; - 10叫直接量,默认是int类型
基本数据类型之间的转换分为:自动类型转换 和 强制类型转换。
其中自动类型转换主要指:小范围向大范围之间的转换。
其中强制类型转换主要指:大范围向小范围之间的转换。
语法格式:目标类型 变量名 = (目标类型)源类型变量名;
如:byteb1 = (byte)s1;
经验:
当程序中出现大范围向小范围转换的代码时编译报错,若希望编译能够通过则需要按照上述方式进行强转,但强转带来的结果会改变原始数据,因此能不用则不用。
double sum = 0.0; int i =1;//sum如果声明为double则报错损失精度
for( i = 1; i <= num; i++ ){
System.out.println("数字:"+i);
sum = sum + 1.0/i;(推荐) //sum = sum +((double)1)/i;;//也可以
}
4.运算符(重点)
4.1 算数运算符
+ 表示加法运算符 - 表示减法运算符 * 表示乘法运算符 / 表示除法运算符
% 表示取模/取余运算符
注意事项:
(1)两个整数相除时结果取整数部分,丢弃小数部分。
(2)若希望结果是浮点数据,则需要进行处理,方式如下:
a.将其中一个操作数强转为double类型,则结果不会丢弃小数部分。
b.将其中一个操作数乘以1.0提升为double类型,则结果不会丢失小数部分(推荐)
(3)0不能做除数,0.0可以做除数,但结果是无穷大,因此以后编程不要使用0和0.0
作为除数。
经验:
运算符+ 既可以当做算数运算符处理,也可以当做字符串连接符处理,区分方式如下:
a.当运算符+两侧的操作数都不是字符串时,则看做算数运算符处理。
b.当运算符+两侧的操作数中只要有一个是字符串时,则看做字符串连接符处理。
System.out.println(100+200+"300");//输出300300
System.out.println("300"+100+200);//输出300200100
4.2 比较/关系运算符
> 表示是否大于 >= 表示是否大于等于 < 表示是否小于 <= 表示是否小于等于
== 表示是否等于 != 表示是否不等于
关系运算符参与的表达式结果为boolean类型,只有两种:true 和 false
4.3 自增减运算符
+ 表示加法运算符 ++ 表示自增运算符,也就是让变量自己的数值加1.
- 表示减法运算符 -- 表示自减运算符,也就是让变量自己的数值减1.
经验:
在以后的编程中尽量单独使用自增减运算符,不要和其他运算符搭配使用,以避免错误的发生。如:ia++;
4.4 逻辑运算符
&& - 表示逻辑与运算符,相当于"并且",同真为真,一假为假。
|| - 表示逻辑或运算符,相当于"或者",一真为真,同假为假。
! - 表示逻辑非运算符,相当于"取反",真为假,假为真。
短路特性:
对于逻辑与运算符来说,若第一个条件为假则整个表达式的条件一定为假,此时第二个条件可以跳过不执行。
对于逻辑或运算符来说,若第一个条件为真则整个表达式的条件一定为真,此时第二个条件可以跳过不执行。
4.5 条件/三目运算符
?: - 条件/三目运算符
条件表达式? 表达式1: 表达式2;
- 判断条件条件表达式是否成立
=> 若成立,则执行表达式1;
=> 若不成立,则执行表达式2;
4.6 赋值运算符
(1)简单赋值
= 表示将=右边的数据赋值给=左边的变量,去覆盖该变量原来的数值。
如:
ia = 10;
ia = ib = ic = 20; => ia、ib、ic最终的结果都是20.
笔试题:
分析以下四种形式的区别?
ia = 10; - 将数据10赋值给ia,覆盖ia原来的数值。
10 = ia; - 编译报错
ia == 10; - 判断ia是否等于10
10 == ia; - 判断10是否等于ia
(2)复合赋值
+= -= *= /= ......
如:
ia = ia + 10;(推荐,可读性更强)
=> ia += 10;
笔试题:
分析以下两种形式的区别?
byte b1 = 5; b1 += 2; //ok
byte b1 = 5; b1 = b1 + 2; //error
解析:
b1 += 2 真正等价的是:b1 =(byte)(b1 + 2);
4.7 移位运算符(了解)
<< 表示左移运算符,也就是按照二进制位向左移动,右边添加0.
>> 表示右移运算符,也就是按照二进制位向右移动,左边添加符号位.
>>> 表示无符号右移运算符,也就是按照二进制位向右移动,左边添加0.
4.8 位运算符(了解)
& 表示按位与运算符,同1为1,一0为0.(1看做真,0看做假)
| 表示按位或运算符,同0为0,一1为1.
~ 表示按位取反运算符,1为0,0为1.
^ 表示按位异或运算符,相同为0,不同为1.
4.9 运算符的优先级
(1)()的优先级极高。
(2) =的优先级极低。
(3) * / % 的优先级高于 + -,同级的运算符(从左到右)哪个在前先算哪个。
第四天 程序结构
三种程序结构:顺序、分支、循环结构
1.分支结构
1.1基本概念
当需要进行条件的判断和选择时,需要使用分支结构来进行处理。
1.2 if分支结构
(1)语法格式
if(条件表达式){
语句块1;
}
语句块2;
(2)执行流程
判断条件表达式是否成立
=> 若成立,则执行语句块1; => 执行语句块2;
=> 若不成立,则执行语句块2;
1.2.1if-else分支结构
(1)语法格式
if(条件表达式){
语句块1;
}
else{
语句块2;
}
语句块3;
(2)执行流程
判断条件表达式是否成立
=> 若成立,则执行语句块1; => 执行语句块3;
=> 若不成立,则执行语句块2;=> 执行语句块3;
1.2.2if-else if-else分支结构
(1)语法格式
if(条件表达式1){
语句块1;
}
else if(条件表达式2){
语句块2;
}
... ...
else{
语句块3;
}
语句块4;
(2)执行流程
判断条件表达式1是否成立
=> 若成立,则执行语句块1=> 执行语句块4;
=> 若不成立,则判断条件表达式2是否成立
=> 若成立,则执行语句块2 => 执行语句块4;
=> 若不成立,则执行语句块3 => 执行语句块4;
1.3 switch-case结构(熟悉)
(1)语法结构
switch(变量/表达式){// switch(byte、short、char、int、枚举、String )
case 字面值1: 语句块1; break;
case 字面值2: 语句块2; break;
... ...
default:语句块3;
}
语句块4;
若不加break,会从满足case条件的语句一直执行,直到default语句执行完,退出循环。
(2)执行流程
计算变量/表达式的结果
=> 判断结果是否等于字面值1
=> 若成立,则执行语句块1=> 执行break=> 执行语句块4;
=> 若不成立,则判断是否等于字面值2
=> 若成立,则执行语句块2 => 执行break=> 执行语句块4;
=> 若不成立,则执行语句块3 => 执行语句块4;
(3)注意事项
switch()中支持的类型:byte、short、char、int,从jdk1.5开始支持枚举类型,从jdk1.7开始支持String类型。
2.循环结构(重中之重)
2.1 基本概念
当需要重复做一件事时,可以使用循环结构来解决。
2.2 for循环 空语句
(1)语法结构
for(表达式1; 条件表达式2; 表达式3){
语句块1;(循环体)
}
语句块2;
(2)执行流程
执行表达式1=> 判断条件表达式2是否成立
=> 若成立,则执行语句块1 => 执行表达式3=> 判断条件表达式2是否成立
=> 若不成立,则执行语句块2
(3)for(;;)格式:1.必须要有两个分号”;”2.里面的条件表达式能计算出正确结果就行
(4)空语句:for(;;);等同于for(;;){;}括号里面只有“;”的语句,啥也不执行。
2.3 break和continue关键字
实例:TestForBreakContinue.java
break关键字用在循环中表示跳出当前循环,用在switch-case结构表示跳出当前结构。
continue关键字只能用在循环中,表示结束本次循环继续下一次循环(熟悉)。
break嵌套:break用于退出所在循环体。如果退出外层循环体,需要用标号的方式。
2.4 特殊的循环
for(;;) - 该循环中没有明确的循环条件,这样的循环叫做无限循环,俗称"死循环"。
该循环通常情况下与break关键字搭配使用
for(;;){
if(i>3) break;
i++;
}//i>4的时候跳出循环
2.5 for循环嵌套
1)语法格式
for(表达式1; 条件表达式2; 表达式3){
for(表达式4; 条件表达式5; 表达式6){
语句块7(循环体);
}
}
(2)执行流程
执行表达式1=> 判断条件表达式2是否成立
=> 若成立,则执行表达式4=> 判断条件表达式5是否成立
=> 若成立,则执行语句块7 => 执行表达式6=> 判断条件表达式5是否成立
=> 若不成立,则执行表达式3=> 判断条件表达式2是否成立
=> 若不成立,则结束整个循环
2.6 while循环
(1)语法格式
while(条件表达式){
循环体;
}
语句块;
(2)执行流程
判断条件表达式是否成立
=> 若成立,则执行循环体=> 判断条件表达式是否成立
=> 若不成立,则执行语句块;
(3)注意事项
a.while循环和for循环是完全可以互换的。
b.while循环通常使用在明确循环条件但不明确循环次数的场合中。
for循环通常使用在明确循环次数/范围的场合中。
c.while(true)等价于for(;;),都表示无限循环,俗称"死循环"。
(4)while(boolean)格式:1.()内可以使TRUE或者FALSE 2.可以是条件表达式,但是表达式结果只能是布尔类型。
2.7 do-while循环(熟悉)
(1)语法格式
do{
循环体;
}while(条件表达式);//注意分号
语句块;
(2)执行流程
执行循环体=> 判断条件表达式是否成立
=> 若成立,则执行循环体=> 判断条件表达式是否成立
=> 若不成立,则执行语句块
(3)注意事项
a.do-while循环通常使用在至少执行一次循环体的场合中。
b.do-while循环的条件表达式后面有分号,其他循环没有。
第五天 数组
1.一维数组
1.1 基本概念
变量本质上就是一块内存空间,用于记录单个数据,而且内容可以改变。
一维数组本质上就是一段连续的内存空间,用于记录多个数据类型相同的数据,内容可以发生改变,换句话说,一维数组就是一个容器。
数组名 - 主要指数组的名称,用于记录该连续内存空间的首地址信息。
数组元素 - 主要指存放在数组中的数据内容。
数组长度 - 主要指数组中存放的元素个数,通常使用 数组名.length来获取。
数组下标 - 主要指数组中元素的编号,从0开始一直到 数组名.length-1。
1.2 数组的声明
(1)数组声明的语法格式
数据类型[] 数组名称 = new 数据类型[数组的长度]; - 动态方式
如:
int[] arr = new int[5]; - 声明一个长度为5,元素类型为int的一维数组
int num = 5; - 声明一个初始值为5的变量
int arr[] = new int[5]; - 不推荐使用该方式
(2)注意事项
a.只有数组在声明的时候,[]中的数字代表数组的长度,否则一律代表下标。
b.当创建数组没有指定初始值时,采用默认初始化(参考ppt)。
(3)数组元素的初始化
数据类型[] 数组名称 = {初始值1,初始值2, ...}; - 静态方式
如:
int[] arr = {10, 20, 30, 40, 50}; - 声明一个长度为5元素类型为int的数组
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;
注意:基本类型的数组(数据元素为基本类型)创建后。元素类型为:BYTE、SHORT、CHAR、INT、LONG为0;FLOAT和DOUBLE为0.0;BOOLEAN为False。
1.3 数组的声明size() length length()方法:
1.length属性是针对Java中的数组来说的,要求数组的长度可以用其length属性;
2.length()方法是针对字符串来说的,要求一个字符串的长度就要用到它的length()方法;
3.java中的size()方法是针对泛型集合说的,如果想看这个泛型有多少个元素,就调用此方法来查看!
1.二维数组(熟悉)
1.1 基本概念
一维数组本质上就是一段连续的内存空间,用于记录多个类型相同的数据内容。
二维数组本质上就是由一维数组组成的数组,也就是说二维数组中的每个元素都是一个一维数组。
1.2 二维数组的声明
(1)语法格式
数据类型[][] 数组名称 = new 数据类型[行数][列数];
如:
int[][] arr = new int[2][5]; - 声明一个具有2行5列存放int类型元素的二维数组
其中行下标的范围是:0 ~1;
其中列下标的范围是:0 ~4;
arr代表什么? arr[0]代表什么? arr[0][0]代表什么?
解析:
arr代表二维数组的名称,用于记录该二维数组的首地址。
arr[0]代表二维数组的第一行,也就是一个一维数组。
arr[0][0]代表二维数组中的第一行第一列,也就是第一个元素值。
int[][]a= new int a[i][j];i代表行,j代表列
arr.length=i;代表二维数组的长度,也就是二维数组的行数。
arr[0].length=j;代表第一行的列数,也就是一维数组的长度。
(2)二维数组的初始化
数据类型[][] 数组名称 = {{元素值1,元素值2,...},{元素值3,元素值4,...},...};
如:
int[][] arr = {{1,2,3},{4,5,6}}; - 声明一个2行3列的二维数组
其中行下标就是:0 ~ 1;
其中列下标就是:0 ~ 2;
第六天 类和对象
1.对象概念
1.1 什么是对象?
万物皆对象。
1.2 什么是面向对象?
面向对象就是指以特征和行为的观点去分析现实世界中事物的方式。
1.3 什么是面向对象编程?
面向对象编程就是指先用面向对象的观点进行分析,再采用一门面向对象的编程语言进行翻译/表达的过程。
其中C语言是一门面向过程的编程语言。
其中C++语言是一门既面向过程又面向对象的编程语言。
其中Java语言是一门纯面向对象的编程语言。
1.4 为什么需要面向对象编程?
面向对象编程是软件产业化发展的需求。
2.5 如何学好面向对象编程?
深刻理解面向对象的三大特征:封装、继承、多态。
2. 类
2.1类的基本概念
类就是"分类"的概念,也就是对同一类事物的统称,描述该类事物共同的特征和行为
类是抽象的概念,是创建对象的模板,而对象是客观存在的实体,占用一块内存空间
类是一种引用数据类型,包含用于描述特征的成员变量,以及用于描述行为的成员方法(JAVA中可以忘记函数概念)。
2.2 类的定义
(1)类定义的语法格式
class 类名{
类体;
}
类定义的一般形式如下
[类定义修饰符] class <类名>
{ //类体
[成员变量声明]
[构造函数]
[成员方法]
}
注意:
通常情况下,当类名由多个单词组成时,每个单词的首字母都要大写。驼峰命名法。
2.3 成员变量 以及初始化
(1)成员变量声明的语法格式
class 类名{
数据类型 成员变量名 = 初始值; - 其中=初始值是可以省略的
}
如:
class Person{
String name; //用于描述姓名的成员变量
int ageNum; //用于描述年龄的成员变量
double weight; //用于描述体重的成员变量
}
注意:
通常情况下,当成员变量名由多个单词组成时,要求从第二个单词起首字母大写。
2.X补充:局部变量 成员变量区别
局部变量 - 主要指声明在方法体中的变量,作用域从声明开始一直到方法体结束。
成员变量 - 主要指声明在类体中的变量,作用域从声明开始一直到类体结束。
成员变量有两种:
A:一种就是类变量或静态变量 这类变量前面加static关键字修饰
这类变量一旦赋值它的值就在你new出来的任何一个实例中具有相同的值
B:另一种叫做实例变量 前面不加static关键字修饰,每一个new出来的新实例都
可以对他赋予自己需要的值
成员变量和局部变量在内存中的分配
对于成员变量和局部变量:成员变量就是方法外部,类的内部定义的变量;局部变量就是方法或语句块内部定义的变量。局部变量必须初始化。 形式参数是局部变量,局部变量的数据存在于栈内存中。栈内存中的局部变量随着方法的消失而消失。 成员变量存储在堆中的对象里面,由垃圾回收器负责回收。 如以下代码:
(2)成员变量默认初始化
2.4 对象的创建
(1)语法格式
new 类名();
如:
new Person(); - 表示新建一个Person类型的对象,叫做匿(无)名对象;
(2)使用方式
使用new运算创建对象的过程叫做类的实例化,也叫作构造对象,当创建对象后需要在堆区申请一块内存空间,用于记录该对象独有的成员变量信息。
2.5 引用(引用数据类型声明的变量名)
(1)基本概念
引用:使用引用数据类型声明的变量名叫做引用变量,简称为"引用"。用于记录新建对象在堆区中的内存地址信息,便于再次访问该对象。
(2)语法格式
类名 引用变量名;
如:
Person p;
Person p = new Person();
注意:
当需要访问成员变量时,使用 引用.成员变量名 的方式进行。
p.name = "zhangfei";
p.age = 30;
2.6成员方法 (格式返回值调用)
2.6.1语法格式
class 类名{
返回值类型 成员方法名(形参列表){
方法体;
}
}
如:
class Person{
void show(){
System.out.println("没事出来秀一下!");
}
}
2.6.2成员方法的详解
(1)返回值类型
返回值就是指从方法体内向方法体外传递的数据内容。
返回值类型就是指返回值的数据类型。
当返回的数据内容为66时,则返回值类型写为:int;
当返回的数据内容为3.14时,则返回值类型写为:double;
当返回的数据内容为"hello"时,则返回值类型写为:String;
在方法体中使用return关键字返回数据并结束方法,如:return 66; return num。
return关键字后面可以跟:字面值、变量、表达式以及方法的调用等。
当方法体中没有可以返回的数据内容时,则返回值类型写:void即可。
(2)形参列表
形式参数就是指从方法体外向方法体内传入的数据内容,语法格式:数据类型 形参名
形参列表就是形参的集合,格式为:数据类型 变量名1,数据类型 变量名2,...
当传入的数据内容为66时,则形参列表写为:int i;
当传入的数据内容为3.14时,则形参列表写为:double d;
当传入的数据内容为"hello"时,则形参列表写为:String s;
当传入的数据内容为66和"hello"时,则形参列表写为:inti, String s;
当不需要传递任何数据到方法体内时,则形参列表位置啥也不写即可。
(3)方法体
方法体就是用于描述方法功能的语句块,通常用于多条语句的打包,从而提高代码的复用性和可维护性。
2.6.3方法的调用
(1)语法格式
引用/对象.成员方法名(实参列表);
如:
p.show();
(2)使用方式
实参列表主要用于进行形参列表的初始化工作,因此参数的个数、类型以及顺序等都必须与形参列表保持一致。
实参可以传递字面值、变量、表达式、方法的调用等。
2.7构造方法
1.1 构造方法(重中之重)
(1)语法格式
class 类名{
类名(形参列表){
构造方法体;
}
}
如:
class Person{
Person(){
...
}
}
(2)注意事项
a.构造方法的方法名称与类名完全相同。
b.构造方法是没有返回值类型的,连void都没有。
c.当new一个新对象时,会自动调用构造方法来进行该对象成员变量的初始化工作。
d.构造方法只能被publicprivate等访问修饰符修饰
e.构造方法只能在new的时候被调用。其他情况不能用。参考下图
(3)默认构造方法
当一个类中没有自定义任何形式的构造方法时,编译器会自动添加一个无参的空构造方法,该构造方法叫做默认/缺省构造方法,如:Person(){}
当类中出现了自定义构造方法后,则编译器不再提供任何版本的构造方法。
(4)构造方法重载
(5)建议:
1、建议自定义无参数构造方法,不要依赖编译器,防止出现错误。
2、当类中无成员变两个或者变量都为常量(final)时,建议不提供任何版本的构造。
3、当类中有非常量成员变量时。建议提供两个构造方法:一个无参数、一个全参数。
2.8 方法的重载(Overload)
(1)基本概念
在同一个类中,方法名相同参数列表不同之间的方法构成重载关系。
原理:编译器根据参数列表不同,底层生成绑定到不同名称的方法。
(2)重载的主要形式
方法重载的形式有:参数的个数不同、参数的类型不同以及参数的顺序不同。
与参数的变量名和返回值类型无关,但建议返回值类型最好相同。
判断方法能否构成重载的依据:调用该方法时能否区分即可。
java.io.PrintStream类中提供了大量的重载方法,print()和println()方法。
(3)重载的主要作用
重载的作用在于:调用者只需要记住一个方法名就可以调用不同版本的方法,从而达到不同的效果,具体调用的版本由实际参数来决定。
3. This关键字(指针)
3.1调用对象参数对象
如:
class A{}
class B{
void show(A a){ ... }
}
A a = new A();
B b = new B();
b.show(a);
调用对象:其中对象b是用于调用show()方法的,因此叫做调用对象。
参数对象:其中对象a是用于作为实参传递给show()方法的,因此叫做参数对象。
3.2 基本概念(当前对象)
对于构造方法来说,this关键字代表当前正在构造的对象。
对于成员方法来说,this关键字代表当前正在调用的对象。
原理解析:
当使用不同的对象调用同一个方法时,那么方法体中的this代表的对象也就不同,当访问成员变量时相当于使用this.的(我的)方式访问,因此最终的结果也就不同。
3.3 使用方式(就近原则)
(1)当形参变量名和成员变量名相同时,在方法体中(就近原则)会优先选择形参变量名,若希望使用成员变量名,则需要在变量名的前面加上this.明确要求使用成员变量(掌握)。
(2)使用this.的方式调用成员方法(了解)。
(3)在构造方法的第一行使用this(实参)的方式调用本类中的其他构造方法(了解)。
3.4 This构造方法
下图:this("name", 67, true);和this(); 只能同时出现一个。否则构造器陷入死循环编译报错。
3.5 空指针类型异常
4. 方法的传参和参数数目不确定
1.1 方法的传参过程(原理、尽量理解)
publicint max(int a,int b){......}
int a = 5; int b = 6;
int res = m.max(a,b);
(1)main()方法是程序的入口,为main()方法分配变量的内存空间并初始化。
(2)调用max()方法,为max()方法的形参变量分配内存空间。
(3)使用实际参数为形式参数进行初始化,也就是将实参的数值赋值给形参的内存空间
(4)执行max()方法的方法体,执行完毕后释放形参变量的内存空间
(5)main()方法得到max()方法的返回值并继续向下执行。
参数数目变化:
返回值 方法名(数据类型… 变量名) eg: int num(int… a)
其中变量名a是数组通过下标访问元素
public static int num(int... a) {
intsum = 0;
for(int i = 0; i < a.length; i++) {
sum+= a[i];
}
returnsum;
}
要求大家重点掌握的内容:
a.当使用基本数据类型作为形参时,在方法体中改变形参变量的数值不会影响到实参;
b.当使用引用数据类型作为形参时,在方法体中改变形参变量指向的数值时,则会
影响到实参指向的数值,因为形参和实参指向同一块区域。
c.当使用引用数据类型作为形参时,在方法体中改变形参变量的指向后在更改指向的
内容,则不会对实参指向的内容产生影响,因为形参和实参指向不同的区域。
5. 递归和递推
(1)基本概念
递归就是指在方法体中调用该方法自身的形式。
(2)使用原则
a.寻找递归的规律,并指定退出条件。
b.递归使得问题简单化,而不是复杂化。
c.递归可能会影响程序的执行性能,此时需要使用递推替代之。
斐波那契数列递归:
斐波那契数列递推:
第七、八天 封装、继承、重写、static、 super、this、单例、构造块、静态语句块
1. 封装
1.1 基本概念
当一个类中没有做任何处理时,则测试类中可以任意访问该类中的成员,此时就有可能带来一些合法但不合理的数值,
为了避免该问题的发生就需要对类中的成员进行保护处理,而这种处理方式就叫做类的封装。
换句话说,封装就是一种为了保证成员变量值合理的机制。
1.2 封装的流程
(1)使用private关键字修饰成员变量,表示私有化。
(2)提供公有的get成员变量/set成员变量方法供外界使用,在方法体中进行合理性判断
(3)在构造方法体中调用set成员变量的方法进行合理性判断。
如下图:
2.static关键字(重点)
1.1 基本概念
通常情况下,类中的成员变量都隶属于对象层级,也就是每创建一个对象都会拥有独立的一份,当所有对象共享同一份数据时并单独记录时会导致内存空间的浪费,此时可以使用static关键字修饰该成员变量表达静态的概念,当使用static关键字修饰之后该成员变量就从对象层级提升到类层级,被所有对象共享与对象是否创建无关。
访问方式:推荐类名.的,不建议使用对象/引用.的方式访问。static修饰的加载到方法区
1.2 使用方式
(1)在非静态的成员方法中既可以访问非静态的成员,也可以访问静态的成员;
(成员:成员变量 + 成员方法 类层级的内容被所有对象共享) 下图show()方法。
(2)在静态的成员方法只能访问静态的成员,不能访问非静态的成员;下图test()方法。
(成员:成员变量 + 成员方法 调用静态方法时可能还没有创建任何的对象)
(静态的成员方法中是没有this关键字的)
(3)只有隶属于类层级被所有对象共享的内容才能使用static关键字修饰;
(不能滥用static)
示例代码:
D:\兄弟连视频\day09\code\ TestStatic.java
3. 构造块和静态语句块(熟悉)
a. 构造块就是指在类中直接使用{}括起来的语句块;
b. 静态语句块就是指在类中直接使用static{}括起来的语句块;
c.抽象类里面可以用构造块{}和static{}(JDK1.7语法不报错 但是没意义)
d.接口里面不可以用构造块和{}static{}(JDK1.7语法上报错)
d. static{;} 静态语句块 前面不能加任何修饰符。
执行流程: 静态语句块 => 构造块 => 构造方法体;
4. 单例设计模式
(1)基本概念
在某些特殊场合中,当一个类对外提供一个对象且只能提供一个对象时,这样的类叫做单例类,而编写单例类的设计形式和编程套路就叫做单例设计模式。实例:任务管理器只能开一个。
(2)实现流程
a.私有化构造方法,使用private关键字修饰;
b.提供本类的引用指向本类的对象,并使用privatestatic共同修饰;
c.提供公有的get成员方法负责将对象返回出去,并使用static修饰;
(3)实现方式
单例设计模式的实现方式有两种:饿汉式 和 懒汉式,以后的开发中推荐饿汉式;
示例代码:
D:\兄弟连视频\day09\code\ Singleton.java和TestSingleton.java
5. 继承
5.1继承的由来和概念
示例代码:
D:\兄弟连视频\day09\code\ Person.java和Student.java
当多个类中有相同的特征和行为时,就可以将相同的内容提取出来组成一个新的类,在编写这多个类时只需要继承这个新的类就可以复用相同的特征和行为,从而提高代码的复用性和可维护性。
换句话说,继承就是一种实现代码复用和提高可维护性的机制。
在Java语言中使用extends(子类父类继承)( 和implements(实现接口) )关键字来表达继承关系。
如:
class Student extends Person{ ... ...}
其中Person类叫做超类/父类/基类。
其中Student类叫做派生类/子类。
5.2 注意事项
(1)子类可以继承父类中的成员方法以及成员变量
(私有的成员变量也可以继承但不能直接访问)
子类不能继承父类的内容有:构造方法和私有成员方法。
父类中的构造方法是不能继承的,但是在实例化子类的时候会调用父类的构造方法。
http://blog.csdn.net/wangyl_gain/article/details/49366505
http://www.cnblogs.com/H-BolinBlog/p/5331195.html
(2)无论使用何种形式构造子类的对象,都会默认调用父类的无参构造方法来构造
子类对象中包含的父类对象,也就是对父类中成员变量进行初始化,相当于
super()调用的效果。
(3)Java语言只支持单继承不支持多继承,也就是说一个子类只能有一个父类,
但一个父类可以有多个子类。
(4)不能滥用继承,必须满足逻辑关系:子类 is a父类。比如:狗是动物。
5.3 extends关键字
5.4继承中的构造方法
6. super、this关键字(熟悉)
6.1基本概念
this关键字 可以代表本类的对象;
super关键字 可以代表父类的对象;
6.2使用方式
使用this.的方式可以访问本类的成员变量和成员方法;
使用super.的方式可以访问父类的成员变量和成员方法;
使用this(实参)的方式可以调用本类中的其他构造方法;
使用super(实参)的方式可以调用父类中的构造方法;
要求大家掌握的内容:
a.使用this.的方式可以用于区分同名的成员变量和局部变量;
b.使用super.的方式可以调用父类中被覆盖的方法;
c.使用super(实参)的方式可以调用父类的构造方法;
7.方法的重写(Override重点)
示例代码:
D:\兄弟连视频\day09\code\ Student.java和Person.java的show()方法
(1)基本概念
当子类继承父类中的方法不足以满足子类的需求时,就可以在子类中重新写一个和父类中方法一模一样的方法,这种形式叫做方法的重写/覆盖。
(2)方法重写的原则(拷贝方法名称列表就行了)
a.要求方法名相同、参数列表相同、返回值类型相同,从jdk1.5开始允许返回子类.
b.访问权限不能变小,可以相同或变大。
c.不能抛出更大的异常(异常机制)。
(3)Java中静态属性和方法可以被继承,不可以被重写(Override)而是被隐藏。静态方法推荐用 (类名.方法名)的方式来调用。(不推荐 对象.方法名的方式)
实例:
第九天 包、访问控制符、final、 对象创建的过程
1. 访问控制
1.1 包的定义
package 包名; - 表示指定单层目录
package 包名1.包名2.包名3....; - 表示指定多层目录
- 用于管理文件方便,更重要的是可以避免同名文件导致的错误发生。
命名格式:org.apache.(公司名称)commons(项目名).lang(模块).StringUtil(类名)
1.2 常用的访问控制符(权限修饰符)
public - 表示公有的/公开的
protected - 表示保护的
默认访问符 - 表示默认的
private - 表示私有的
1.3 访问控制符的权限信息
访问控制符 访问控制权限 本类 本包中的类 子类 其他类
-------------------------------------------------------------------
public 公开的 ok ok ok ok
protected 保护的 ok ok ok no
默认控制符 默认的 ok ok no no
private 私有的 ok no no no
要求大家掌握的内容:
a.public关键字修饰的内容表示可以在任意位置访问。
b.private关键字修饰的内容表示只能在本类的内部访问。
c.通常情况下,成员变量都是用private修饰,成员方法都使用public修饰。
d. 访问控制符不能修饰static{;}静态语句块
1.4类的修饰 修饰词顺序
修饰词顺序:[访问权限] [abstract] [static] [final] [transient][volatile] [synchronized] [native] [strictfp]
2.final关键字(重点)
2.1 基本概念
final本意为“最终的,不可更改的”,修饰类、成员方法以及成员变量。
2.2 使用方式:不能重写、不能继承、必须初始化
final关键字修饰类,表示该类是最终的,体现在该类不能被继承。
- 防止滥用继承,如:java.lang.System类/String类等
final关键字修饰成员方法,表示该方法是最终的,体现在该方法不能被重写。
- 防止不经意间造成的方法重写,
如:java.text.SimpleDateFormat类中的format()方法
final关键字修饰成员变量,表示该成员变量必须初始化而且不能更改。
- 防止不经意间造成的修改,如:java.lang.Thread类中的MAX_PRIORITY。
补充:
在Java语言中很少单独使用static和final关键字修饰成员变量,通常都是使用public static final共同修饰成员变量表示常量的概念。
通常的命名规范是:所有字母都大写,不同单词之间使用下划线连接。
如:
public static final double PI = 3.14;
3.对象创建的过程
3.1 单个对象创建的执行过程
示例代码:
D:\兄弟连视频\day10\code\ TestObjectCreate.java
(1)在执行代码之前需要将类的字节码信息读入内存空间中的方法区,叫类的加载。
(2)main()方法时程序的入口,当执行new TestObjectCreate()时表示在堆区申请空间
(3)若成员变量没有指定初始值时,则采用默认初始化方式进行,否则采用指定的
初始值进行初始化。
(4)执行构造块中的语句,可以对成员变量进行再次修改。
(5)执行构造方法体中的语句,可以对成员变量进行再次修改。
(6)此时对象构造完成,继续执行main()方法中的后续代码。
3.2 子类对象创建的执行过程
示例代码:
D:\兄弟连视频\day10\code\ TestSubObject.java TestSuperObject.java
Father.java和sun.java
(1)先加载父类的字节码信息,因此先执行父类的静态语句块。
(2)再加载子类的字节码信息,因此执行子类的静态语句块。
(3)执行父类的构造块,再执行父类的构造方法体,此时父类的对象构造完成。
(4)执行子类的构造块,再执行子类的构造方法体,此时子类的对象构造完成。
(5)继续执行main()方法中后续的代码。
第十、十一天 多态、接口、 内部类 Object类、包装类
1.多态(重中之重、难点)
1.1 基本概念
多态就是指同一种事物表现出来的多种形态。
宠物:狗、猫、鸟、小强、...
整数:byteb1 = 10; short s1 = 10; int l1 = 10;
多态:Pet p= new Dog(); Pet p = new Cat();//Cat Dog都是Pet子类 。
父类变量/引用指向子类对象
1.2 语法格式
示例代码:
D:\兄弟连视频\day10\code\ Person.java Student.java
父类类型 引用变量名 = new 子类类型(); - 父类的引用指向了子类的对象
如:
Person p = new Student();
p.show();
解析:
a.在编译阶段p是Person类型的,只能调用Person类中的show()方法,否则编译报错;
b.在运行阶段p真正指向的对象是Student类型的,最终调用Student类的show()方法;
1.3 多态的效果
(1)父类的引用能直接调用父类中的成员方法。
(2)父类的引用不能直接调用子类中的成员方法。
(3)父类的引用可以直接调用父子类都有的成员方法。
对于非静态的成员方法来说,父类的引用最终调用子类重写以后的版本;
对于静态的成员方法来说,父类的引用最终调用父类自己的方法,与对象无关;
调用静态方法:建议用 类名.静态方法
1.4 引用数据类型之间的转换
(1)当子类类型向父类类型转换时,只需要发生自动类型转换即可。
Person ps = new Student(“A”,11,1001);//(小到大)自动转换
(2)当父类类型向子类类型转换时,需要进行强制类型转换,语法格式如下:
子类类型 引用变量名 = (子类类型)父类类型的引用名;
Person ps = new Person(); Students = (Student) ps;
(3)引用类型之间的转换必须发生在父子类之间,否则编译报错;
Person ps = new Person(); String s1 = (String) ps;//报错
(4)当父类类型的引用被强制转换为子类类型时,编译阶段不会报错,但若转换的
子类类型并不是该引用真正指向的类型,则运行阶段产生类型转换异常。
类型转换异常:java.lang.ClassCastException
(5)为了避免上述错误的发生,建议只要进行强制类型转换则应该先使用instanceof
进行判断只有条件成立时再进行强制类型转换。
1.5 instanceof运算符 区分==equals
语法格式如下:
if(父类引用 instanceof 子类类型) - 判断父类引用是否真正指向该子类类型
instanceof为一个操作符 可以理解为是 - 若是则返回true,否则返回false。
实例:class Animal{}; class Dog extends Animal{}; class Cat extendsAnimal{};
Animalanimal = new Dog();
animal instanceof Animal = = True;
animal instanceof Dog = = True;
animal instanceof Cat = = False;
区分==和equals:
https://www.cnblogs.com/dolphin0520/p/3592500.html
http://blog.csdn.net/t12x3456/article/details/7341515
==就是用来比较值是否相等。equals方法是用来比较两个对象的引用是否相等。
1)对于 = =运算符,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等; 如果作用于引用类型的变量,则比较的是所指向的对象的地址。
2)对于equals方法,注意:equals方法不能作用于基本数据类型的变量。
如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。
3)对于instanceof: (class A实例)instanceof (class B) A显式声明的类型与右边类B必须是同种类或者是B的子类才返回TRUE;
1.6实际应用
示例代码:
D:\兄弟连视频\day10\code\ Rect.java和Shape.java和Circle.java和 TestShape.java
使用父类的引用作为方法的形参时,可以屏蔽不同子类的差异性实现通用的编程,换句话说,就是编写一份通用的代码可以处理不同的子类对象,而且打印不同的结果。
2.抽象类(重点)
2.1 什么是抽象方法?
示例代码:
D:\兄弟连视频\day10\code\ TestAbstract.java 和 SubTestAbstract.java
抽象方法就是指不能具体实现的方法,也就是没有方法体,并使用abstract修饰。
语法格式:
访问控制符abstract 返回值类型 方法名称(形参列表);
如:
public abstract void cry();
2.2 什么是抽象类?
抽象类就是使用abstract关键字修饰的类,抽象类是不能构造对象的。看下图
2.3 注意事项
(1)抽象类中可以有成员变量、构造方法以及成员方法。
(2)抽象类中可以没有抽象方法,也可以有抽象方法。
(3)拥有抽象方法的类必须是抽象类。
(4)抽象类中有非抽象的构造方法(构造方法只能被public private等访问修饰),但是无法实例化(无法new抽象类),是为了防止生成抽象类后调用抽象方法(所以封死了构造方法)。
2.4 实际意义
抽象类的实际意义不在于实例化对象而在于被继承,当一个类继承抽象类就必须要重写抽象类中的抽象方法,否则该类也得声明为抽象类。
因此抽象类对子类具有强制性和规范性,叫做模板设计模式。
经验分享:
在以后的开发中推荐使用多态的语法格式在方法体中使用,因为当使用多态的语法时则调用的所有方法一定是父类中拥有的方法,若希望更换子类对象时,只需要将new后面的类型加以改变而其他代码立刻生效,因此提高了代码的可维护性和可扩展性。
该方式的缺点在于父类的引用不能直接访问子类的独有成员变量和成员方法。
推荐:TestAbstract ta = new SubTestAbstract(); ta.show();
3. 接口
3.1 基本概念
示例代码:
D:\兄弟连视频\day11\code\ Money.java和Metal.java和Gold.java和TestInterface.java(public static final double PI = 3.14;)
接口就是一种比抽象类还抽象的类,该接口是不能实例化对象,更重要的是,接口中的所有方法都是抽象方法。
声明类的关键字是class,而声明接口的关键字是interface。
继承类的关键字是extends,而实现接口的关键字是implements。
3.2 注意事项
(1)接口中的所有变量都必须由public static final共同修饰(可省略不报错但是极不推荐),也就是常量。
(2)接口中的所有方法都必须由public abstract共同修饰(可以省略其中任何一个关键字也可以都省略),也就是抽象方法。
3.3 类和接口之间的关系
类和类之间的关系 使用extends关键字表达继承的关系 支持单继承
类和接口之间的关系 使用implements关键字表达实现的关系 支持多实现
接口和接口之间的关系 使用extends关键字表达继承的关系 通常认为单继承
3.4 接口和抽象类之间的区别(笔试题)
(1)声明抽象类的关键字是class,声明接口的关键字是interface。
(2)继承抽象类的关键字是extends,实现接口的关键字是implements。
(3)继承抽象类只支持单继承,而实现接口可以支持多实现。
(4)抽象类中可以有构造方法,而接口中没有构造方法。
(5)抽象类中可以有成员变量,而接口只允许有常量。
(6)抽象类中可以有成员方法,而接口只允许有抽象方法。
(7)抽象类中增加方法可以不影响子类,但接口中增加方法一定会影响子类。
4.内部类(了解)
4.1 基本概念
当把一个类的定义写在另外一个类的类体中时,那么把写在内部的类叫做内部类,该内部类所在的类叫外部类。
类中的内容主要有:成员变量、构造方法、成员方法、构造块、静态语句块、内部类
4.2 语法格式
class 外部类名{
class 内部类名{
}
}
4.3 主要作用
当一个类存在的价值仅仅是为某一个类单独服务时,就可以将该类定义为所服务类的内部类,内部类可以直接访问所在类的私有成员,而不再需要公有的get/set方法等。
内部类一般情况下对外不可见,除了包含它的外部类其他类无法访问到它。
4.4 内部类的主要分类
普通内部类 - 将一个类的定义直接写在另外一个类的内部(了解)。
静态内部类 - 使用static关键字修饰的内部类(了解)。
- 普通的外部类是不允许使用static关键字修饰。
局部内部类 - 将一个类的定义直接写在一个方法体的内部(了解)。
- 该类的作用域仅限于方法体的内部。
匿名内部类 - 指没有名字的内部类,用于构造父类/接口类型的对象(重点)。
4.5 匿名内部类(重点、难点) 回调模式:略
示例代码:
D:\兄弟连视频\day11\code\ SubA.java 和A.java和TestA.java
(1)语法格式
父类/接口类型 引用名 =new 父类/接口类型(){
进行方法的重写
};
(2)经验分享
当使用接口类型的引用作为方法的形参时,实参的传递方式有两种:
a.自定义类实现接口,并创建该类的对象作为实参传递给形参。
b.自定义匿名内部类来构造接口的引用,使用接口引用作为实参传递给形参。
A是一个interface
5. Object类(重点)
5.1基本概念
java.lang.Object类是类层次结构的根类,任何类向上查找父类总是可以找到Object
5.2 常用的包
java.lang包 - 该包是Java核心包,包中的所有类和接口等由JVM自动导入。
- 如:java.lang.System/String类等
java.util包 - 该包是Java工具包,包中提供了大量的工具类。
- 如:java.util.Scanner/Random类等
java.io包 - 该包是Java中的输入输出包,包中提供了大量操作文件的类等。
- 如:java.io.FileInputStream类等。
java.net包 - 该包是Java中网络包,包中提供了大量进行网络通信的类等。
- 如:java.net.ServerSocket类等。
5.3常用的方法
示例代码:
D:\兄弟连视频\day11\code\ Student.java TestStudent.java
Object() - 使用无参形式构造对象。
boolean equals(Object obj) - 用于判断调用对象是否与参数对象obj相等。
- 该方法默认比较两个对象的地址信息是否相等,等价于 = = 的效果。
-重写equals最好要重写hashCode()方法
int hashCode() - 用于返回调用对象的哈希码值(对象内存地址的编号)。
- 当两个对象调用equals()方法相等时,则各自调用该方法的返回值必须相同。
- 当两个对象调用equals()方法不相等时,各自调用该方法的返回值可以相同,
但最好不相同。
- 要求只要重新equals()方法就一定要重写hashCode()方法来保证上述约定。
String toString() - 用于返回调用对象的字符串形式。
- 通常该方法返回的字符串内容有:包名.类名@哈希码的十六进制。
- System.out.println(里面内容编译器自动转换为String类型);
6.包装类和数学处理类
6.1 包装类的由来
Java语言是一门纯面向对象的编程语言,万物皆对象。
Person p = new Person();
int num = 10;
在某些特殊场合(集合)中要求所有的数据都是对象,那么对于基本数据类型的变量来说若要使用则需要进行对象化的处理,此时就需要借助包装类将变量包装成对象。
6.2 常用的包装类
int => java.lang.Integer类(重点)
double => java.lang.Double类
byte => java.lang.Byte类
short => java.lang.Short类
long => java.lang.Long类
float => java.lang.Float类
boolean => java.lang.Boolean类
char => java.lang.Character类
6.3 Integer类(重点)
示例代码:
D:\兄弟连视频\day11\code\ TestInteger.java
(1)基本概念
java.lang.Integer类是对int类型的包装类,该类的内部提供了int类型的成员变量。
该类被final关键字。
(2)常用的方法
该类是Object类的间接子类,并且在该类的内部重写了equals()、hashCode()、toString()方法
Integer(int value) - 根据参数指定的整数值构造对象。
Integer(String s) - 根据参数指定的字符串构造对象。
int intValue() - 表示以int类型返回该对象的数值。
static int parseInt(String s) - 用于将参数指定的字符串转换为int类型并返回。
(3)装箱和拆箱
从int类型向Integer类型的转换过程 叫做装箱。
从Integer类型向int类型的转换过程 叫做拆箱。
从jdk1.5开始提供了自动装箱和自动解箱的机制,也就是说不需要方法直接转换。
6.4 BigDecimal类(了解)
示例代码:
D:\兄弟连视频\day11\code\ TestBigDecimal.java
(1)基本概念
java.math.BigDecimal类用于实现浮点数据的精确计算。
(2)常用的方法
BigDecimal(String val) - 根据参数指定的字符串内容来构造对象。
BigDecimal add(BigDecimal augend)
- 用于计算调用对象和参数对象的和并返回。
BigDecimal subtract(BigDecimal subtrahend)
- 用于计算调用对象和参数对象的差并返回。
BigDecimal multiply(BigDecimal multiplicand)
- 用于计算调用对象和参数对象的积并返回。
BigDecimal divide(BigDecimal divisor)
- 用于计算调用对象和参数对象的商并返回。
6.5 BigInteger类(了解)
示例代码:
D:\兄弟连视频\day11\code\ TestBigInteger.java
(1)基本概念
java.math.BigInteger类主要用于描述long类型不足以表示的数据。
(2)常用的方法
BigInteger(String val) - 根据参数指定的字符串来构造对象。
成员方法与上述类中的方法同名。
第十二天 String类 正则表达式StringBuilder 日期类
1.String类
示例代码:
D:\兄弟连视频\day12\code\
1.1 基本概念 常量池
java.lang.String类用于描述字符串,在Java程序中的所有字符串字面值都可以作为该类的实例描述,如:“hello”。
该类描述的字符串是个常量,字符串的内容不可改变。
如:
String name = "zhangfei";
| | |
引用数据类型 引用变量名 字符串字面值
name = "guanyu"; - 表示修改引用变量名name的指向,而不是指向的内容。
笔试题:
String str = ""; 和 String str = null;之间有区别吗?
解析:
有区别,前面的表示有字符串对象,但里面没有内容;后面的表示连字符串对象都没有
常量池:http://blog.csdn.net/dajunxing/article/details/48056419
http://www.cnblogs.com/javaminer/p/3923484.html
http://www.cnblogs.com/SaraMoring/p/5687466.html
1.2 常用的方法(练熟、记住)
(1)常用的构造方法
String() - 使用无参的方式构造对象。
String(byte[] bytes) - 根据参数指定的byte数组来构造对象。
String(byte[] bytes, int offset, int length)
- 根据参数指定byte数组中从offset位置开始的length个字节来构造对象。
String(String original) - 根据参数指定的字符串来构造对象。
String(StringBuffer buffer) - 根据参数指定的引用来构造对象。
String(StringBuilder builder) - 同上
(2)常用的成员方法
char charAt(int index) - 根据参数指定的下标返回对应的字符。
int length() - 用于返回字符串的长度。
int compareTo(String anotherString) - 用于比较调用对象和参数对象的大小。
- 若调用对象和参数对象相等,则返回0;若大于则返回正数;若小于返回负数
-分别使用两个字符串中对应位置的字符从头开始进行比较,若第一个字符能够
区分大小则比较结束,否则使用下一个位置的对应字符进行比较。
- 当字符串的前面内容相同时,则长度更大的字符串比较大。
如:
"hello" 'h' 'e' 'l' 'l' > 'h' 返回正数,证明"hello"字符串比较大
"hehe" 'h' 'e' 'h'
"hello" 'h' 'e' ... 存在的字符串内容相同时,则大小取决于长度
"helloworld" 'h' 'e' ...
int compareToIgnoreCase(String str) - 比较字符串的大小,不考虑大小写。
- 也就是相同字母的大小写之间比较的结果是相等,如:'a''A'是相等的。
boolean equals(Object anObject) - 比较两个字符串内容是否相等
boolean equalsIgnoreCase(StringanotherString) - 比较是否相等,不考虑大小写
boolean contains(CharSequence s) - 判断当前字符串是否包含参数指定的内容
boolean endsWith(String suffix) - 判断当前字符串是否以参数字符串为结尾
boolean startsWith(String prefix) - 判断当前字符串是否以参数字符串开头
String toLowerCase() - 用于将当前字符串中的所有字符转换为小写。
String toUpperCase() - 用于将当前字符串中的所有字符转换为大写。
String trim() - 用于去除字符串两端的空白字符。
byte[] getBytes() - 用于将字符串类型转换为byte数组。
char[] toCharArray() - 用于将字符串转换为char数组。
int indexOf(int ch) - 返回参数指定字符在当前字符串中第一次出现的索引位置。
int indexOf(int ch, int fromIndex)
- 从fromIndex位置开始查找字符第一次出现的位置
int indexOf(String str) - 从当前字符串中查找str第一次出现的位置并返回。
int indexOf(String str, int fromIndex) - 从fromIndex位置开始查找。
int lastIndexOf(int ch) - 返回当前字符串中字符ch最后一次出现的索引位置。
int lastIndexOf(int ch, int fromIndex) - 从fromIndex位置开始查找
int lastIndexOf(String str) - 返回当前字符串中字符串str最后一次出现索引位置
int lastIndexOf(String str, int fromIndex) -从fromIndex位置开始查找
String substring(int beginIndex) - 获取从beginIndex位置开始到结尾的子字符串
String substring(int beginIndex, intendIndex)
- 获取当前字符串中从beginIndex位置开始一直到endIndex位置(不包含)。
1.3 split拆分和replace方法
2. 正则表达式(百度现成的)
包:java.util.regex
(1)基本概念
正则表达式本质上就是一个字符串,通常使用^开头使用$结尾,可以省略.
该字符串用于进行用户输入数据的格式验证/检查,若不匹配则报错。
关键方法:matches str.matches (reg)
(2)常用的规则 [表示一位]、{表示多位}
[abc] - 表示可以出现a、b 或 c。
[^abc] - 表示可以出现任何字符,除了 a、b 或 c。
[a-zA-Z] - 表示可以出现a到z或A到Z,两头的字母包括在内,可以出现任何字母。
. - 表示可以出现任何字符。
\d - 表示可以出现任何数字,相当于[0-9]。
\D - 表示可以出现任何非数字,相当于[^0-9]。
\s - 表示可以出现任何空白字符,相当于[\t\n\x0B\f\r]。
\S - 表示可以出现任何非空白字符,相当于[^\s]。
\w - 表示可以出现任何单词字符,相当于[a-zA-Z_0-9],
也就是由字母、数字以及下划线组成。
\W - 表示可以出现任何非单词字符,相当于[^\w]。
X? - 表示X可以出现一次或一次也没有,也就是0 ~ 1次。
X* - 表示X可以出现零次或多次,也就是0 ~ n次。
X+ - 表示X可以出现一次或多次,也就是1 ~ n次。
X{n} - 表示X可以出现恰好 n 次。
X{n,}- 表示X可以出现至少 n 次,也就是 >= n次。
X{n,m} - 表示X可以出现至少 n 次,但是不超过 m 次,也就是 >= n 并且<= m次。
Variablemust provide either dimension expressions or an array initializer
3.StringBuilder类和StringBuffer类(查手册会用即可)
1.1 基本概念
由于String类描述的字符序列是无法更改的,当需要描述多个相近的字符串时,不能对同一个字符串进行修改只能单独保存,因此对内存空间的消耗比较大,此时可以使用StringBuilder类和StringBuffer类来替代之,这两种类型描述的字符序列可以更改。
StringBuffer类是jdk1.0就有的类,支持线程安全,因此效率比较低。
StringBuilder类是jdk1.5提供的类,不支持线程安全,因此效率比较高(推荐)。
1.2 常用的方法
StringBuilder(String str) - 根据参数指定的内容构造对象,容量为16 + str长度
int capacity() - 用于返回调用对象的容量。
int length() - 用于返回调用对象中的字符个数。
StringBuilder insert(int offset, String str)
- 用于将str插入当前字符串中下标为offset的位置。
StringBuilder append(String str)
- 用于将字符串str的内容插入到当前字符串的末尾位置。
StringBuilder delete(int start, int end)
- 用于删除当前字符串中从start(包含)开始到end(不包含)结束。
StringBuilder replace(int start, int end,String str)
- 用于将当前字符串中start和end之间的字符串使用str进行替换。
StringBuilder reverse() - 用于反转字符序列。
4.日期相关的类(查手册会用即可)
示例代码:
D:\兄弟连视频\day12\code\ TestCalendar.java TestDate.java TestSimpleDateFormat.java
4.1 Date类
(1)基本概念
java.util.Date类用于描述特定的瞬间,可以精确到毫秒。
(2)常用的方法
Date() - 使用无参的形式构造对象,默认采用当前系统时间来初始化。
Date(long date) - 根据参数指定的毫秒数来构造对象。
- 其中毫秒数为指定日期和时间距离1970年1月1日 0时0分0秒。
- 1秒 =1000毫秒 1毫秒 =1000微秒 1微秒 =1000纳秒
- 该方法与File类中的一个方法是绝配。
long getTime() - 用于获取当前对象距离1970年1月1日0时0分0秒的毫秒数。
void setTime(long time) - 用于设置距离上述时间的毫秒数来更改当前对象。
4.2 SimpleDateFormat类
(1)基本概念
记得:import java.text.SimpleDateFormat;
java.text.SimpleDateFormat类用于格式化和解析日期类型的数据。
通俗来说,该类就是用于实现Date类型和String类型之间的转换。
(2)常用的方法
SimpleDateFormat(String pattern) - 根据参数指定的格式来构造对象。
- 其中参数字符串中的内容:y-年、M-月、d-日、H-时、m-分、s-秒
String format(Date date) - 用于将参数指定的日期对象转换为String类型并返回。
Date parse(String source) - 用于将String类型转换为日期类型并返回。
4.3 Calendar类
(1)基本概念
java.util.Calendar类用于描述特定的瞬间,该类中的方法用于取代Date类过时方法
该类是一个抽象类,不能实例化对象的。
(2)常用的方法
static Calendar getInstance() - 用于获取该类的一个实例(多态)。
void set(int year, int month, int date, inthourOfDay, int minute, int second) - 用于指定年月日时分秒信息的。
Date getTime() - 用于将Calendar类型的对象转换为Date类型并返回。
4.4 TimeStamp时间戳
第十三、十四天 集合类(容器)Collections Map
示例代码:
D:\兄弟连视频\day14\code 和day15\code\
1 .综述
1.1 基本概念
定义:Java.util中的接口 Collection<E>又被称为Java Collections framework。Java容器的用途是保存对象,根据数据结构不同将其划分为Collection和Map。
当需要记录多个类型不同/相同的数据时,则声明一个集合记录即可,集合就是容器。
数组 - 本质上就是内存中的一块连续存储空间,用于记录多个类型相同的数据。
- 一旦声明数组之后则长度固定,无法改变。
- 插入和删除元素不方便,可能会导致大量元素的移动。
- 支持下标访问,可以实现随机访问。
- 既可以存放基本类型的数据,也可以存放引用类型的数据。
集合 - 内存空间可以连续也可以不连续,记录的数据类型可以相同也可以不同。
- 集合的长度是可以随时动态调整。
- 插入和删除元素可以不移动大量的元素。
- 可以支持下标访问,随机访问。
- 只可以存放引用类型的数据,基本类型的数据不可以。
1.2 基本分类
在Java语言中将集合框架分为两大类:Collection接口 和 Map接口。
其中Collection接口中操作元素的基本单位是:单个元素。
其中Map接口中操作元素的基本单位是:单对元素。
通常情况下,Collection接口很少使用,更多地使用该接口的子接口:List接口、Queue接口、以及Set接口。
1.3 Collection接口的常用方法(熟练、记住)
boolean add(E e) - 用于将参数指定的元素e放入当前集合.
- 成功返回true,否则false。
boolean addAll(Collection<? extends E>c)
- 用于将参数指定集合中的所有元素一个一个放入当前集合中。
boolean remove(Object o) - 用于从当前集合中移除参数指定的单个元素。
boolean removeAll(Collection<?> c) - 用于从当前集合移除参数指定所有元素。
void clear() - 用于清空当前集合。
boolean contains(Object o) - 用于判断是否包含单个元素。
boolean containsAll(Collection<?>c) - 判断是否包含参数指定所有元素
boolean isEmpty() - 判断是否为空
int size() - 获取元素的个数
boolean retainAll(Collection<?> c)-计算当前集合和参数集合的交集放入当前集合
Iterator<E> iterator() - 获取当前集合的迭代器。
2.List接口(重中之重)
示例代码:D:\兄弟连视频\day14\code\TestCollection.java和TestList.java
2.1 基本概念
java.util.List接口是Collection接口的子接口,元素有先后次序并且可以重复。
该接口的主要实现类有:ArrayList类、LinkedList类、Stack类、Vector类。
其中ArrayList类的底层是采用动态数组来进行管理的,访问方便,增删不方便。
其中LinkedList类的底层是采用链表来进行管理的,访问不方便,增删方便。
其中Stack类的底层是采用动态数组来进行管理的,但该类具有后进先出的特性,简称为LIFO(lastin first out),汉语名称为:栈。
其中Vector类的底层是采用动态数组实现的,与ArrayList类相比是早期的类,支持线程安全,效率比较低,因此推荐使用ArrayList类。
2.2 常用的方法 E - 在此 collection 中保持的元素的类型
booleanadd( E e) - 用于将指定元素添加到此列表的结尾。
voidadd(int index, E element) - 用于将元素element插入到index的位置。
booleanaddAll(int index, Collection<? extends E> c)
- 用于将集合c中的所有元素插入到当前集合中index位置。
// boolean add(E,e) 将集合c2看做一个整体放入集合c1中。boolean= c1.add(c2)。
E remove(int index) - 用于删除当前集合中下标为index位置的元素并返回。
E set(int index, E element) - 用于使用element替换下标为index位置元素并返回
E get(int index) - 用于获取index位置的元素并返回。
publicboolean retainAll(Collection<?> c)
c1.retainAll(c2) :取c1和c2的交集并放入c1中。
publicboolean containsAll(Collection<?> c)
c1.containsAll(c2) 如果c1包含容器c2中的所有元素,则返回 true。
boolean contains(Object o)
c1.contains(“abc”) 如果此列表中包含指定的元素,则返回 true。
contains调用集合包含对象的equals方法与待判断对象比较。一般要重写equals
List<E> subList(int fromIndex, inttoIndex)
- 用于获取fromIndex位置(包含)到toIndex位置(不包含)的视图并返回。
- 只是获取数据并没有申请新的存储空间单独保存。
3.泛型机制Stack栈
示例代码:D:\兄弟连视频\day14\code\ TestStack.java
目前集合中之所以可以存放不同类型的数据,是因为将每个元素都看做Object类型放入的,当从集合中取出元素时默认也是Object类型,为了表达该元素真实的类型就需要强制类型转换,此方式可能引发类型转换异常。
为了避免上述错误的发生,从jdk1.5开始要求使用集合时加上泛型机制,也就是在集合类型的后面使用<数据类型>的方式明确规定可以存放的数据内容,若放入其他类型数据则编译报错,如:
List<String> l1 = newLinkedList<String>();
泛型的本质就是参数化类型,也就是将数据类型作为实参传递给该接口/类中的形参E,从此E全部被替换为实参类型。
jdk中的K,V,T,E等泛型名称很多人以为是固定写法,其实这些名称是可以改的,比如改成zhangsan,lisi都可以,jdk为了容易看懂,所以用K表示键,V表示值,T表示type类型,E表示enum枚举,其实这四个都只是符号,都是表示泛型名称,下面的例子的T全部可以换成E,也可以换成K,V,zhangsan,都没关系。
? 表示不确定的类型
Object java中所有类的父类。
http://blog.csdn.net/xswh520/article/details/9160875
4.Queue队列接口(重点)
示例代码:D:\兄弟连视频\day14\code\ TestQueue.java
4.1 基本概念
java.util.Queue接口是Collection接口的子接口,与List接口是平级关系。
该接口的主要实现类是:LinkedList类,增删比较方便。
队列就是一种具有先进先出特性的数据结构,简称为FIFO(firstin first out)。
4.2 常用的方法
boolean offer(E e) - 用于将参数指定的元素放入当前队列的末尾。
E poll() - 用于获取队列的首元素并移除,若队列为空则返回null。
E peek() - 用于获取队列的首元素,若队列为空则返回null。
这里简单对其重复的方法做点简单的区分。
offer,add区别:
一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,多出的项就会被拒绝。
这时新的 offer 方法就可以起作用了。它不是对调用add() 方法抛出一个unchecked 异常,而只是得到由 offer()返回的 false。
poll,remove区别:
remove()和 poll() 方法都是从队列中删除第一个元素。remove() 的行为与Collection 接口的版本相似,
但是新的 poll() 方法在用空集合调用时不是抛出异常,只是返回 null。因此新的方法更适合容易出现异常条件的情况。
peek,element区别:
element()和 peek() 用于在队列的头部查询元素。与 remove() 方法类似,在队列为空时,element() 抛出一个异常,而 peek() 返回 null
4.Set接口(重点)
示例代码:D:\兄弟连视频\day14\code\ TestSet.java和TestTreeSet.java
4.1 基本概念
java.util.Set接口是Collection接口的子接口。元素没有先后次序并且不允许重复。
该接口的主要实现类:HashSet类 和 TreeSet类。
其中HashSet类的底层是采用哈希表进行管理的。
其中TreeSet类的底层是采用二叉树进行管理的。
4.2 HashSet类
4.3 TreeSet类
常用方法:Set<Integer> s1 = new TreeSet<Integer>(); 一般TreeSet只存放同一种泛型的元素。方便实现Comparable接口。
(1)什么是二叉树?
二叉树就是指每个节点最多只有两个子节点的树形结构。
(2)什么是有序二叉树?
有序二叉树就是指满足以下三个条件的树形结构,又叫做二叉查找树。
a.左子树中的任何节点元素值都小于根节点元素值。
b.右子树中的任何节点元素值都大于根节点元素值。
c.左右子树的内部也要满足上述规则。
(3)TreeSet类的要求
当使用TreeSet类存放元素时必须要指定元素比较大小的规则,具体方式如下:
a.使用元素的自然排序来指定规则,让元素类型实现java.lang.Comparable接口.
b.使用比较器来指定规则,创建TreeSet对象时指定java.util.Comparator接口。
4.4 Comparable接口和Comparator接口
Comparable接口:
Comparator接口
4.5常用的工具类
java.util.Arrays类主要提供了大量用于操作数组的工具方法。
java.util.Collections类主要提供了大量用于操作集合的工具方法。
5. Iterator迭代器常用的方法
参考Collection接口即可。
Iterator<E> iterator()
- 用于获取当前集合中的迭代器,可以迭代/遍历/获取集合中的每个元素。
boolean hasNext() - 根据迭代器判断当前集合是否拥有可以访问的元素。
E next() - 用于获取集合中的一个元素。
void remove() - 用于从集合中移除迭代器返回的最后一个元素。
注意:
当使用迭代器访问集合中的所有元素时,切记不允许使用集合中的remove()方法删除元素,否则会引发并发修改异常,建议使用迭代器自己的remove()方法删除。
6. 增强版的for循环(foreach)
(1)语法格式
for(元素类型 变量名 : 数组名/集合名){
循环体;
}
(2)执行流程
每次从数组/集合取出一个元素赋值给变量名在循环体中使用,直到取完所有元素为止 。
总结:
对于Set集合(无序)中的元素访问方式有3种:toString()、迭代器、for each结构。
对于List集合(有序)的元素访问方式有4种:除了上述3种方式,还有get()方法。
7.Map接口(重点)
示例代码:D:\兄弟连视频\day15\code\ TestTreeSet.java和TestMap.java
7.1 基本概念
java.util.Map<K,V>集合用于存放键值对,其中键不允许重复,只能对应一个值。
类型参数:
K - 此映射所维护的键(Key)的类型
V - 映射值(Value)的类型
该接口的主要实现类:HashMap类 和 TreeMap类。
7.2 常用的方法
V put(K key, V value) - 用于将参数指定的key和value组成一对放入当前集合中。
- 当该方法实现增加的功能时返回null,但实现修改的功能时则返回之前的旧值
V remove(Object key) - 用于根据参数指定的key从当前集合移除,返回对应value
boolean containsKey(Object key) - 用于判断参数指定的key是否存在。
boolean containsValue(Object value) - 用于判断参数指定的value是否存在。
V get(Object key) - 根据参数指定的key返回对应的value,若不存在则返回null。
Set<Map.Entry<K,V>> entrySet()- 用于获取包含映射关系的Set视图。如下图:
- 通俗来说,就是将Map集合转换为Set集合。
- K getKey() - 用于获取调用对象中的key.
- V getValue() - 用于获取调用对象中的value。
Set<K> keySet() - 用于获取包含键的Set视图。
7.3 HashMap
第十五天 异常Exception
示例代码:
D:\兄弟连视频\day15\code 和day16\code\
1. 基本概念
异常就是不正常的意思,在Java语言中主要指在运行阶段产生的错误。
Java.lang.Throwable 类是 Java 语言中所有错误或异常的超类。
该类的主要实现子类有:Error类 和Exception类。
其中Error类主要用于描述比较严重的错误,无法通过编码来解决。
其中Exception类主要用于描述轻微的错误,可以通过编码等方式解决。
2. 基本分类
Java.lang.Exception类的所有已知子类分为以下两大类:
RuntimeException - 运行时异常,也叫做非检测性异常。
IOException和其它所有异常 - 其它异常,也叫做检测性异常。
- 检测性异常就是指在编译阶段可以被编译器检测出来的异常。
注意:
当程序执行过程中发生异常并没有手动编码处理时,则采用默认处理方式,通常终止程序的执行并打印异常名称、异常原因以及异常的位置等信息,导致后续代码无法执行。
Java.lang.RuntimeException类的主要子类:
ArithmeticException - 算数异常
ArrayIndexOutOfBoundsException - 数组下标越界异常(间接子类)
NullPointerException - 空指针异常
ClassCastException - 类型转换异常
NumberFormatException - 数字格式异常(间接子类)
StringIndexOutOfBoundsException - 字符串下标越界异常(间接子类)
ConCurrentModificationException - 并发修改异常
3. 非检测异常的处理
在以后的开发中可以使用if()条件判断来避免绝大多数非检测异常的发生。
4. 异常的捕获try catch finally语句
(1)语法格式
try{
编写所有可能发生异常的语句块;
}
catch(异常类型 变量名){
编写处理当前异常类型的语句块;
}
... ...
finally{
编写无论是否发生异常都应该执行的语句块;
}
(2)注意事项
当需要编写多个catch()分支,切记小范围的异常类型应该放在大范围异常类型的上面。
懒人的写法:
catch(Exception e){ ...}
finally{}中通常编写用于进行善后处理的语句块,比如:关闭文件、断开数据库等。
5. 异常的抛出throws
(1)基本概念
当某些特殊场合中发生了异常却无法处理或者不便于处理时,就可以将异常抛给该方法的调用者,这个过程就叫异常的抛出/转移。可以通过throws关键字抛出异常。
(2)语法格式
返回值类型 方法名(形参列表) throws异常类型1,异常类型2,...{ 方法体; }
如:
public void show() throws Exception { }
(3)方法重写的原则
a.要求方法名相同、参数列表相同以及返回值类型相同,从jdk1.5开始允许返回子类
b.访问权限不能变小,可以相同或者变大。
c.不能抛出更大的异常。
注意:
子类中重写的方法可以抛出与父类中方法一样的异常、更小的异常以及不抛出异常,
但不能抛出更大的异常,也不能抛出额外的异常。
6. 自定义异常
(1)自定义异常的由来
当需要在程序中表达年龄不合理的异常时,在java官方库中并没有对应的异常类型,此时就需要自定义异常类来表达该错误,从而提高代码的可读性。
(2)自定义异常的步骤
a.自定义xxxException类继承自Exception类或者其子类。
b.提供无参的构造方法和字符串作为参数的构造方法。
自定义构造方法:(继承父类Exception的构造方法)
要抛出异常的代码:
(3)异常对象的抛出
throw new 异常类型();
7. throws和throw区别
throws:用于抛出异常的声明。
格式:返回值类型 方法名(形参列表) throws 异常类型1,异常类型2,...{ 方法体; }
位置:throws在方法体外,在方法名(形参列表)之后。
后面:throws后面可以跟多个异常类型。
throw:用于抛出一个异常对象。
格式:throw new 异常类型();
位置:throw在方法体里面。
后面:throws后面只能跟一个对象。
8. 运行异常类的子类异常7个
算术异常:ArithmeticException
数组下标越界异常:ArrayIndexOutOfBoundsException
字符串下标越界异常:StringIndexOutOfBoundsException
空指针异常类:NullPointerException
数据类型转换异常:ClassCastException
数据格式异常:NumberFormatException(间接子类)
并发修改异常: ConcurrentModificationException
第十六、十七天 File类 IO流
1.File类(重点)
示例代码:
D:\兄弟连视频day16\code\TestFile.java
1.1 基本概念
java.io.File类用于作为文件和目录路径信息的抽象表示,可以获取文件和目录的属性信息,如:名称、大小等信息。但是不能对文件的内容进行访问。
1.2 常用的方法
构造方法: File(String pathname) - 根据参数指定的路径名来构造对象。
boolean exists() - 用于判断文件或目录是否存在。
String getName() - 用于获取文件或目录的名称。
long length() - 用于获取文件的长度/大小。
long lastModified() - 用于获取文件的最后一次修改时间。
- 返回距离1970年1月1日0时0分0秒之间的毫秒数
- 与Date类中的Date(long)构造方法搭配使用
String getAbsolutePath() - 用于返回绝对路径信息。
绝对路径 - 主要指从根目录开始的路径信息,如:c:/... d:/..
相对路径 - 主要指从当前目录开始的路径信息,如:./code ./code/code
. 代表当前目录 .. 代表当前目录的上一级目录
在以后的开发中推荐使用相对路径。
boolean delete() - 用于删除文件或目录。
boolean createNewFile() - 用于创建新的空文件。
boolean mkdir() - 用于创建目录。
boolean mkdirs() - 用于创建多级/层目录。
File[] listFiles() - 用于获取指定目录中的所有内容并返回。
boolean isFile() - 用于判断调用对象关联的是否为一个文件。
boolean isDirectory() - 用于判断调用对象关联的是否为一个目录。
1.3 目录FileFilter接口
2.I/O流
示例代码:
D:\兄弟连视频day16\code\和day17\code\
2.1 基本概念
I/O就是Input/Output的简写,也就是输入/输出,换句话说,也就是读取/写入操作。
I/O流就是指像流水一样不间断地进行读写的操作。
2.2 基本分类
根据读写操作的基本单位不同分为:字节流 和 字符流。
其中字节流就是指以字节为基本单位进行读写的流,可以处理任何文件。
字符流就是指以字符(2个字节)为基本单位进行读写的流,只能处理文本文件。
根据读写操作/数据流动的方向不同分为:输入流 和 输出流(站在程序的角度)。
其中输入流就是指读取文件中的内容输入到程序中的流,也就是读文件。
其中输出流就是指将程序中的内容输出到文件中的流,也就是写文件。
数据传输方式:
节点流(直接和文件打交道)和包装流(程序和文件之间有管道,不直接接触)。
2.3 I/O流的框架
字节流的顶层父类为:InputStream类 和OutputStream类。 - 抽象类
其中InputStream类的主要子类有:
FileInputStream类、DataInputStream类、ObjectInputStream类。
其中OutputStream类的主要子类有:
FileOutputStream类、DataOutputStream类、ObjectOutputStream类。
字符流的顶层父类为:Reader类 和 Writer类。 - 抽象类
其中Reader类的主要子类有:
BufferedReader类、InputStreamReader类、StringReader类。
其中Writer类的主要子类有:
BufferedWriter类、OutputStreamWriter类、StringWriter类。
补充:
PrintStream类是OutputStream类的间接子类。
2.4 FileOutputStream类(重中之重)
(1)基本概念
java.io.FileOutputStream类用于将图像数据之类的原始字节流写入到输出流中。
(2)常用的方法
FileOutputStream(String name) - 根据参数指定的文件路径构造对象并建立关联。
FileOutputStream(String name, booleanappend) - 以追加的方式建立关联。
void write(int b) - 用于写入参数指定的单个字节。b自动找对应的ASCII码值。
void write(byte[] b, int off, int len)
- 用于将数组b中从off位置开始的len个字节写入。
void write(byte[] b) - 用于将参数指定整个数组的内容写入。
void close() - 关闭输出流并释放有关的资源。
2.5 FileInputStream类(重中之重) -1和1
(1)基本概念
java.io.FileInputStream类主要用于读取图像数据之类的原始字节流。
(2)常用的方法
FileInputStream(String name) - 根据参数指定的路径名来构造对象。
int read() - 用于从输入流中读取一个字节并返回。
- 当读取到文件末尾时则返回-1,否则返回读取到的数据内容。
int read(byte[] b, int off, int len)
- 从输入流中读取len个字节的数据放入数组b中下标为off的位置上。
- 当读取到文件末尾时则返回-1,否则返回读取到的字节个数。
int read(byte[] b)
- 用于从输入流中读取b.length个字节到数组b中。
int available()
- 用于返回通过此输入流可以读取到的文件大小。
void close()- 关闭输出流并释放有关的资源。
注意:
文件调用 FileOutputStream.write(-1);-1默认是INT型4个字节(32位,32个1)。但是voidwrite(int b)方法只能写入一个字节(8位),所以读取的是低8位,即:1111 1111。
文件调用FileInputStream.read();但是int read( )方法只能读取一个字节(8位),但是返回一个int型4个字节,32位。所以前面补32-8=24个0。即:00000000 0000 0000 0000 0000 1111 1111。所以返回255。
文件拷贝:FISFOS
2.6 DataOutputStream类(熟悉)
(1)基本概念
java.io.DataOutputStream类用于将基本类型的数据写入输出流中。
(2)常用的方法
DataOutputStream(OutputStream out) - 根据参数指定的引用来构造对象。
- 其中OutputStream类是抽象类,实参需要传递子类的对象。
void writeInt(int v) - 用于将参数指定的整型变量值写入输出流中。
void close()
2.7 DataInputStream类(熟悉)
(1)基本概念
java.io.DataInputStream类用于从输入流中读取基本类型的数据。
(2)常用的方法
DataInputStream(InputStream in) - 根据参数指定的引用来构造对象。
- 其中InputStream类是抽象类,实参需要传递子类的对象。
int readInt() - 用于从输入流中读取一个整型数据并返回。
void close()- 用于关闭IO流
2.8 BufferedReader类(重点)
(1)基本概念
java.io.BufferedReader类用于读取单个字符、字符数组以及一行字符内容。
(2)常用的方法
BufferedReader(Reader in) - 根据参数指定的引用来构造对象。
- 其中Reader类是个抽象类,实参需要传递子类的对象。
- 子类对象选择InputStreamReader类型的对象,选择FileInputStream类型对象
String readLine() - 用于读取一行字符串内容并返回。
void close() - 用于关闭IO流
2.9 BufferedWriter类(重点)
(1)基本概念
java.io.BufferedWriter类用于写入单个字符、字符数组以及一行字符内容。
(2)常用的方法
BufferedWriter(Writer out) - 根据参数指定的引用来构造对象。
- 其中Writer类是个抽象类,实参需要传递子类的对象。
- 子类对象选择OutputStreamWriter类的对象,选择FileOutputStream类型对象
void write(String s, int off, int len)
- 用于将字符串s中从下标为off位置开始的len个字符写入输出流中。
void newLine() - 用于写入行分隔符。
void close() - 关闭该流的缓冲。
void write(String str) - 从Writer类继承下来的方法,用于写入参数指定的字符串
voidflush() - 刷新该流的缓冲。对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush()将会使内存中的数据立刻写出
2.10 PrintStream类(重点)
(1)基本概念
java.io.PrintStream类用于方便地打印各种格式的数据。
(2)常用的方法
PrintStream(OutputStream out) - 根据参数指定的引用构造对象。
- 其中OutputStream类是抽象类,实参需要传递子类的对象。
void print(String s) - 用于打印参数指定的字符串。
void println(String x) - 用于打印字符串并终止该行。
void write(byte[] buf, int off, int len)
- 将 len 字节从指定的初始偏移量为 off 的 byte 数组写入此流。
void close()
(3)PrintStream与BufferedReader相对应。
2.11 ObjectOutputStream类(重点)
(1)基本概念
java.io.ObjectOutputStream类用于将Java语言的对象整体写入到输出流中。
只能将支持 java.io.Serializable 接口的对象写入流中。(类必须实现该接口)
类通过实现 java.io.Serializable 接口以启用其序列化功能。
所谓的序列化就是指将对象中需要保存的相关信息有效地组织成字节序列的过程。
(2)常用的方法
ObjectOutputStream(OutputStream out) - 根据参数指定的引用来构造对象。
- 其中OutputStream类是抽象类,因此实参需要传递子类的对象。
void writeObject(Object obj) - 用于将参数指定的对象写入到输出流中。
void close()
User是一个类且已经实现java.io.Serializable 接口
2.12 ObjectInputStream类(重点)
(1)基本概念
java.io.ObjectInputStream类用于从输入流中读取整个对象。
(2)常用的方法
ObjectInputStream(InputStream in) - 根据参数指定的引用构造对象。
- 其中InputStream类是抽象类,因此实参需要传递子类的对象。
Object readObject() - 用于读取一个对象并返回。
- 无法通过该方法的返回值来判断是否读取到文件末尾。
void close()
经验:
当需要向文件中写入多个对象时,建议先将多个对象放入集合中,再将整个集合看做一个对象整体写入文件中,此时读取文件中的内容只需要读取一次就结束。
2.13 转换类InputStreamReader和OutputStreamReader
(1)基本概念
java.io. InputStreamReader:输入时,实现字节流到字符流的转换,提高操作的效率(前提是,数据是文本数据)。= = ==》解码:字节数组---->字符串
java.io. InputStreamReader:输出时,实现字符流到字节流的转换,提高操作的效率(前提是,数据是文本数据)。= = ==》解码:字符串 ---->字节数组
2.14 标准的输入输出流
System.in:标准输入流(键盘输入) System.out:标准输出流(显示器输出)
第十八、十九天 线程
示例代码:
D:\兄弟连视频day18和day19\code\
1.线程的基本概念和基本操作
1.1 线程、进程 基本概念
程序 - 数据结构 + 算法,主要指存放在硬盘/磁盘上的可执行文件。
进程 - 主要指运行在内存中的程序。
目前主流的操作系统都支持多进程,为了让操作系统在同一时间可以执行多个任务,但进程是重量级的,新建进程对系统的资源消耗比较大,因此不建议启动过多的进程。
线程就是指进程内部的程序流,也就是说操作系统支持多进程,在每一个进程的内部又可以支持多线程,并且线程是轻量级的,新建线程会共享所在进程的资源。
因此在以后的开发中都使用多线程的机制。
操作系统中通常都采用时间片轮转法来保证多个任务的并发执行,所谓的并发就是指宏观并行,微观串行。
1.2 Thread类
2.线程的创建和主要方法
2.1 线程的创建(重中之重)
(1)线程的创建方式
java.lang.Thread类用于描述线程,Java 虚拟机允许应用程序并发地运行多个执行线程。
创建线程的主要方式:
a.自定义类继承Thread类并重写run()方法,创建该类的对象调用start()方法。
b.自定义类实现Runnable接口并重写run()方法,创建该类的对象作为创建Thread类对象的实参,最后使用Thread类的对象调用start()方法。
(2)线程创建的相关方法
Thread() - 使用无参的方式构造对象。
Thread(String name) - 使用参数指定的名称来构造对象。
Thread(Runnable target) - 根据接口类型的引用来构造对象。
Thread(Runnable target, String name) - 根据接口引用和名称来共同构造对象。
void run() - 当调用对象是根据参数指定的接口引用构造时,则最终调用该接口引用所指向对象的run()方法,否则该方法啥也不做并返回。
void start() - 用于启动线程,JVM会调用该线程的run()方法。
(3)多线程的原理分析
其中执行main()方法的线程叫做主线程,执行run()方法的线程叫做新线程/子线程。
对于start()方法之前的代码来说,只会被主线程执行一次,当start()方法调用成功之后,线程的个数瞬间由1个变成了2个,其中新创建的子线程去执行run()方法中的代码块,而主线程继续向下执行,于是两个线程同时执行产生了交错的打印结果。
当run()方法的代码执行完毕后表示子线程结束;当main()方法的代码执行完毕后表示主线程结束,各自独立运行互不影响;主线程和子线程的先后执行次序没有明确的规定,由系统的调度算法来决定。
注意:
线程创建和启动的两种方式相比,采用继承的方式相对来说代码量简单但是可维护性比较差,而实现接口的方式代码相对复杂但可维护性更高,因此推荐使用实现接口的方式。
继承方式:
实现接口方式:
2.2 线程的名称和编号(熟悉)
long getId() - 用于获取线程的编号/标识符并返回。
String getName() - 用于获取线程的名称并返回。
void setName(String name) - 用于修改线程的名称为参数指定的内容。
static Thread currentThread() - 用于返回当前正在执行的线程对象的引用。
2.3 线程的主要状态(熟悉)
新建状态 - 当使用new创建线程对象之后进入的状态。
- 此时线程并没有开始执行。
就绪状态 - 调用start()方法之后进入的状态。
- 此时线程依然没有开始执行。
运行状态 - 当线程调度器调用已经就绪完成的线程后进入的状态。
- 此时线程开始执行。
- 当时间片执行完毕后但任务没有完成时回到就绪状态。
消亡状态 - 当时间片执行完毕后并且任务已经完成时进入的状态。
- 此时线程已经终止。
阻塞状态 - 当线程在执行的过程中发生了阻塞事件进入的状态,如:sleep()方法。
- 当阻塞解除后进入就绪状态。
2.4 Thread类的常用方法
static void yield() - 让出CPU的执行权,转而去执行其他的线程(了解)。
static void sleep(long millis) - 让当前正在执行的线程休眠参数指定的毫秒数。
static void sleep(long millis, int nanos) - 让线程休眠参数指定的毫秒 + 纳秒。
- 1秒 =1000毫秒 1毫秒 =1000微秒 1微秒 =1000纳秒
void interrupt() - 用于中断线程,通常用于睡眠的打断(了解)。
int getPriority() - 用于获取当前线程的优先级。
void setPriority(int newPriority) - 用于修改线程的优先级为参数指定的数值。
- 优先级高的线程表示获取时间片的机会越多,但不保证一定先执行。
boolean isDaemon() - 用于判断当前线程是否为守护线程。
void setDaemon(boolean on) - 用于设置该线程为守护线程。
void join() - 用于等待调用对象所描述的线程终止。
void join(long millis) - 等待调用对象终止的最长时间为参数指定的毫秒。
void join(long millis, int nanos) - 用于等待参数指定的毫秒 + 纳秒。
- 守护线程又叫做后台线程,当所有非守护线程结束时,守护线程随之结束。
3.线程的同步机制(重点)
3.1 基本概念
当多个线程在同一时刻访问同一种共享资源时,可能会造成数据的不一致问题,此时就需要对线程的操作进行协调,而线程之间的协调和通信就叫做线程的同步机制。
3.2 解决方案
由程序可知:当线程一还没有来得及将最新余额写入后台数据库时,线程二已经开始执行, 导致最终的结果不正确。
解决方案: 将多个线程的并行操作改为串行操作即可。
引发问题: 当多个线程依次串行执行时,会导致执行的效率比较低,因此能不用则不用。
3.3 实现方式
为了解决上述问题,可以使用Java语言中synchronized关键字来保证线程操作的原子性,也就是说当线程执行锁定的代码时必须执行完毕才会释放CPU的执行权。
具体方式如下:
(1)使用同步语句块的方式来保证原子性,语法格式如下:
synchronized(类类型的引用){//可以用synchronized(this)
编写需要锁定的代码块;
}
注意:
多个线程所使用的锁对象必须是同一个对象,否则无法实现同步的效果。
因此通常推荐使用this关键字。
(2)使用synchronized关键字来修饰整个方法。
3.4 原理分析
当多个线程启动后各自独立运行都去抢占对象锁,若其中一个线程抢到了对象锁则可以放心地执行锁定的所有代码,其他线程进入阻塞状态,直到该线程执行完毕所有锁定代码后自动释放对象锁,此时等待的其他线程又可以抢占对象锁,抢到的线程去执行锁定的代码,抢占不到的线程继续保持阻塞状态。
3.5 死锁的概念
线程一执行的代码:
void run(){
synchronized(a){ 持有对象锁a,等待对象锁b
...
synchronized(b){
... ...
}
}
}
线程二执行的代码:
void run(){
synchronized(b){ 持有对象锁b,等待对象锁a
...
synchronized(a){
... ...
}
}
}
在以后的开发中尽量不要使用同步语句块的嵌套结构!!!
3.6 Object类中的常用方法
void wait() - 用于让当前正在执行的线程进入阻塞状态,直到其他线程调用notify()或者notifyAll()方法(开发中推荐)。
void wait(long timeout) - 用于让当前线程进入阻塞状态,直到其他线程调用方法或者参数指定的毫秒数已经过去了。
void notify() - 用于唤醒等待的单个线程(随机)。
void notifyAll() - 用于唤醒等待的所有线程。
3.7 线程池
第十九、二十天 网络编程
示例代码:
D:\兄弟连视频day20\code\
1.网络编程的常识(记住)
1.1 七层网络协议模型
ISO(国际标准委员会组织)将数据的传递从逻辑上划分为了以下七层:
应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。
当发送数据时需要按照上述七层的先后次序一层层进行加包处理,然后再发出。
当接收到数据时需要按照上述七层的相反次序一层层进行拆包处理,然后再解析。
1.2 常见的网络协议
http - 超文本传输协议,浏览网页时可以使用该协议。
ftp -文件传输协议, 上传和下载文件时使用该协议。
tcp -传输控制协议, 进行网络通信时使用该协议。
udp -用户数据报协议,进行网络通信时使用该协议。视频缓存。
ip -Internet Protocol互联网协议,是上述协议的底层协议。
协议 - 本质上就是一种约定/规则,用于实现双方有效的通信。
1.3 IP地址(重点)
如:
192.168.1.1 - 绝大多数路由器的登录地址,进行Mac地址过滤。
IP地址 - 是互联网中的唯一标识,可以通过IP地址定位到具体某一台主机。
IP地址本质上是由32位二进制组成的整数,叫做ipv4,当然也有128位二进制组成的整数,叫做ipv6,目前使用主流的还是ipv4.
日常生活中采用点分十进制表示法来进行IP地址的描述,也就是将IP地址的每个字节转换为一个十进制整数,不同的十进制整数之间采用小数点分隔。
如:
0x01 02 03 04 => 1.2.3.4
查看IP地址:
在windows系统的dos窗口中使用命令:ipconfig ipconfig/all
在linux系统的终端窗口中使用命令: ifconfig /sbin/ifconfig
1.4 端口号(重点)
IP地址 - 可以定位到具体某一台设备/主机。
端口号 - 可以定位某台设备/主机中的具体某个进程。
网络通信/编程提供:IP地址 + 端口号。
端口号本质上就是由16位二进制组成的整数,范围是:0 ~ 65535,其中0 ~1024之间的端口号通常被系统占用,因此编程时需要从1025开始使用。
2. 基于tcp协议的编程模型(重点)
2.1 基本概念
C/S架构 -C(Client 客户端)/S(Server服务器)
B/S结构 -B(Browser 浏览器)/S(Server服务器)
Socket - 本意"插座",在网络编程中表示用于通信的逻辑载体/端点,俗称“套接字”。
2.2 编程模型
服务器:
(1)创建ServerSocket类型的对象,并绑定参数指定的端口号。
(2)等待客户端的连接请求,调用accept()方法。
(3)得到Socket类型的对象并使用输入输出流进行通信。
(4)关闭Socket并释放有关的资源。
客户端:
(1)创建Socket类型的对象,并提供服务器的IP地址和端口号。
(2)使用输入输出流进行通信。
(3)关闭Socket并释放有关的资源。
2.3 相关类和方法的解析
(1)ServerSocket类
java.net.ServerSocket类用于描述服务器套接字。
ServerSocket(int port) - 根据参数指定的端口号来创建对象并绑定。
Socket accept() - 监听并接收客户端的连接请求,若无客户端连接则进入等待状态。
void close() - 用于关闭套接字。
(2)Socket类
java.net.Socket类用于描述客户端套接字。套接字是两台机器间通信的端点。
Socket(String host, int port) - 根据参数指定的IP地址和端口号创建对象。
InputStream getInputStream() - 用于获取当前套接字的输入流。
OutputStream getOutputStream() - 用于获取当前套接字的输出流。
void close() - 用于关闭套接字。
3.tcp协议和udp协议的比较(笔试题)
(a)tcp协议
tcp协议 - 传输控制协议,是一种面向连接的协议,类似于打电话。
- 建立连接=> 进行通信 => 断开连接
- 在通信的整个过程中全程保持连接
- 保证了数据传递的可靠性和有序性
- 是一种全双工的字节流通信方式
- 服务器压力比较大,资源消耗比较多,而且数据传递的效率相对比较低。
(b)udp协议
udp协议 - 用户数据报协议,是一种非面向连接的协议,类似于写信。
- 在通信的整个过程中不需要保持连接。
- 不保证数据传递的可靠性和有序性
- 是一种全双工的数据报通信方式
- 服务器压力比较小,资源消耗比较少,但数据传递的效率相对比较高。
4.基于udp协议的编程模型(重点)
4.1 编程模型
主机A(接收方):
(1)创建DatagramSocket类型的对象,并与参数指定的端口绑定。
(2)创建DatagramPacket类型的对象,等待接收数据。
(3)调用receive()方法来接收数据。
(4)关闭Socket并释放有关的资源。
主机B(发送方):
(1)创建DatagramSocket类型的对象。
(2)创建DatagramPacket类型的对象,并提供接收方的IP地址和端口号。
(3)调用send()方法来发送数据。
(4)关闭Socket并释放有关的资源。
4.2 相关类和方法的解析
(1)DatagramSocket类
java.net.DatagramSocket类用于描述发送或接收数据报的套接字,也就是包裹投递/接收点
DatagramSocket() - 使用无参的形式构造对象。
DatagramSocket(int port) - 根据参数指定的端口号来构造对象。
void receive(DatagramPacket p) - 用于接收数据并存放到参数指定的包裹中。
void send(DatagramPacket p) - 用于将参数指定的包裹发送出去。
void close() - 关闭套接字并释放有关的资源。
(2)DatagramPacket类
java.net.DatagramPacket类用于描述数据报信息的。
DatagramPacket(byte[] buf, int length)
- 用于构造一个能接收长度为length的数据包,将数据存放在buf中。
DatagramPacket(byte[] buf, int length,InetAddress address, int port)
- 用于构造一个将长度为length的数据报,发送给主机address上的port端口。
InetAddress getAddress() - 用于获取发送方/接收方的IP地址信息。
int getPort() - 用于获取发送方/接收方的端口号信息。
int getLength() - 用于获取发送/接收的数据长度。
(3)InetAddress类
java.net.InetAddress类用于描述互联网协议地址,也就是IP地址信息。
static InetAddress getLocalHost() - 用于获取本地主机的地址信息。
static InetAddress getByName(String host) - 用于根据主机名来获取地址信息。
String getHostName() - 用于获取主机名信息并返回。
String getHostAddress() - 用于获取ip地址信息并返回。
第二十一天 反射
示例代码:
D:\兄弟连视频day21\code\
1.基本概念
如:
Person p = new Person(); - 在运行阶段只能创建Person类型的对象
p.show(); - 在运行阶段只能调用show()方法
反射本质上就是一种实现动态编程的机制,也就是说在运行阶段才能确定创建何种类型的对象以及调用何种方法的机制,具体的类型和方法由实参决定。
目前主流的框架技术底层都是采用反射机制实现的。
2 Class类
2.1基本概念
Class类的实例表示正在运行的Java应用程序中的类和接口,也就是代表一种数据类型。
Class类没有公共构造方法,Class类的实例是在类加载的过程中由Java虚拟机和类加载器自动构造的。
2.2获取Class类实例/对象的主要方式
a.使用数据类型.class的方式来获取对应的Class对象。
b.使用对象.getClass()方法的调用来获取对应的Class对象。
c.使用包装类.TYPE的方式可以获取对应基本类型的Class对象。
d.使用Class.forName()的方式来获取参数指定类型的Class对象。
基本数据类型:a和c 引用数据类型:a和b和d
2.3常用的方法
T - 由此 Class 对象建模的类的类型(要实例化的对象类型)
static Class<?> forName(StringclassName) - 用于获取参数指定类型的Class对象。
T newInstance() - 使用当前正在调用对象所代表的类来构造新对象。
- 若当前正在调用对象代表String类,调用此方法就相当于newString()来构造对象。
- 若当前正在调用对象代表Person类,调用此方法就相当于new Person()来构造对象。
Constructor<T>getConstructor(Class<?>... parameterTypes)
- 用于获取当前正在调用对象所代表的类中参数指定的单个公共构造方法并返回。
Constructor<?>[] getConstructors()
- 用于获取当前正在调用对象所代表的类中所有的公共构造方法并返回。
Field getDeclaredField(String name)
- 用于获取当前正在调用对象所代表的类中参数指定的单个成员变量并返回。
Field[] getDeclaredFields()
- 用于获取当前正在调用对象所代表的类中所有的成员变量并返回。
Method getMethod(String name,Class<?>... parameterTypes)
- 用于获取当前正在调用对象所代表的类中参数指定的单个公共成员方法并返回。
Method[] getMethods()
- 用于获取当前正在调用对象所代表的类中所有的公共成员方法并返回。
3. Constructor类
3.1基本概念
java.lang.reflect.Constructor<T>类用于描述获取到的单个构造方法。
3.2常用的方法
T newInstance(Object... initargs)
- 用于当前正在调用对象所代表的构造方法来构造新实例,参数进行新实例初始化工作
参数(Object...initargs): 其中…代表可变长参数,
initargs- 将作为变量传递给构造方法调用的对象数组;基本类型的值被包装在适当类型的包装器对象(如 Float 中的 float)中。
例如: (Object... initargs)就是 ("zhangfei",30)
Class c1 =Class.forName("xdl.day21.Person");//获得class
Constructor ct =c1.getConstructor(String.class, int.class);//获得Constructor类ct
System.out.println(ct.newInstance("zhangfei", 30)); //用ct构造新实例
4 Field类
4.1基本概念
java.lang.reflect.Field类用于描述获取到的单个成员变量。
4.2常用的方法
Object get(Object obj)
- 用于获取对象obj中当前正在调用对象所代表成员变量的数值并返回。
- 若参数传入Person类型的p对象,当前正在调用的对象代表成员变量name时,
调用该方法表示返回p.name的数值。
void set(Object obj, Object value)
- 用于将obj对象中当前正在调用对象所代表成员变量的数值修改为value。
- 若参数传入Person类型的p对象,当前正在调用的对象代表成员变量name时,
调用该方法则表示p.name= value的效果。
void setAccessible(boolean flag)
- 用于设置是否进行Java语言的访问检查,若给true则表示取消检查。
5 Method类
5.1基本概念
java.lang.reflect.Method类用于描述获取到的单个成员方法。
5.2常用的方法
Object invoke(Object obj, Object... args)
- 用于使用obj对象调用当前正在调用对象所代表的成员方法,实参传递args并返回。
- 若参数传入Person类型的p对象,当前正在调用的对象代表成员方法getName()时,调用该方法则表示p.getName(args)的效果。
6. JavaBean的概念
JavaBean本质上就是一种习惯性的编程规范,并不是明确的编程规则/语法要求,具体如下:
(1)要求遵循JavaBean规范的类必须在一个包中;
(2)要求遵循JavaBean规范的类必须有无参的构造方法;
(3)要求遵循JavaBean规范的类必须私有化成员变量;
(4)要求遵循JavaBean规范的类必须提供公有的get和set成员方法;
(5)要求遵循JavaBean规范的类支持序列化操作;
第二十一、二十二天 设计原则、模式
示例代码:
D:\兄弟连视频day21\code\
1. 设计原则
1.1 项目/软件开发的流程
需求分析文档=> 概要设计文档 => 详细设计文档 => 编码和测试=> 安装和调试
=>维护和升级
1.2 常用的设计原则
http://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html
(1)开闭原则(Open Close Principle OCP)
- 对扩展开放,对修改关闭。
- 为了保证程序的可维护性和复用性更高,尽量避免错误的发生。
- 任何软件都是bug(臭虫、漏洞)的。
如:
public class Person{
private String name;
... ...
}
public class SubPerson extends Person{
private int age;
}
(2)里氏代换原则(LiskovSubstitution Principle LSP)
- 任何父类可以出现的地方,子类一定可以出现。
- 子类 is a 父类,体现在继承和多态方面。
如:
public class TestShape{
public void draw(Shape s){
s.show();
}
}
TestShape ts = new TestShape();
ts.draw(new Circle(1, 2, 3));
(3) 依赖倒转原则(DependenceInversion Principle DIP)
- 尽量依赖于抽象类和接口,而不是具体实现类。
- 抽象类和接口对子类具有强制性和规范性。
如:
public abstract class A{
void show();
}
public class B extends A{
@Override
void show(){
....
}
}
(4)接口隔离原则(InterfaceSegregation Principle ISP)
- 尽量依赖于小接口而不是大接口,避免接口的污染。
如:
public interface RunAnimal{
public void run();
}
public interface FlyAnimal{
public void fly();
}
public class Dog implements RunAnimal{
public void run(){ ...}
}
(5) 迪米特法则(Demeter Principle最少知道原则)(DP)
- 高内聚,低耦合。
- 内聚就是指一个实体/模块尽量将该模块需要具备的所有功能都聚集在内部。
- 耦合就是指一个实体/模块尽量少于其他实体/模块有关联。
(6)合成复用原则(Composite ReusePrinciple CRP)
- 尽量使用合成的原则,而少使用继承。
如:
public class A{
public void show(){ ... ...}
}
public class B{
A a;
public B(A a){
this.a = a;
}
public void test(){
//调用A类中的show()方法
a.show();
}
}
2.常用的设计模式
2.1 基本概念
http://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html
设计模式(Designpattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
通俗来说,就是使用在固定场合中的固定套路。
2.2 基本分类
创建型模式 - 工厂方法模式、抽象工厂模式、单例设计模式、...(要求会写)
结构型模式 - 装饰器模式、代理模式、...(要求看懂)
行为型模式 - 模板方法模式、观察者模式、...(以后讲到)
常见算法
示例代码:
D:\兄弟连视频day22\code\
1.常用的查找算法(重点)
1.1 线性查找算法(顺序查找算法)
(1)算法流程
a.使用目标元素与样本数列中的第一个元素起依次进行比较;
b.若找到与目标元素相等的元素,则表示查找成功;
c.若目标元素与样本数列中的所有元素都比较完毕也没找到相等的元素,则表示查找失败;
1.2 二分查找算法(折半查找算法)
示例代码:D:\兄弟连视频day22\code\TestFind.java
(1)算法流程
a.假定样本数列中的元素都是从小到大排列的;
b.使用目标元素与样本数列中的中间元素比较大小,若相等则表示查找成功;
c.若目标元素小于中间元素,则去中间元素的左边进行查找,重复步骤b;
d.若目标元素大于中间元素,则去中间元素的右边进行查找,重复步骤b;
e.若目标元素与所有该比较元素比较完毕后也没有相等的元素,则表示查找失败;
2.常用的排序算法(重点)
示例代码:D:\兄弟连视频day22\code\TestFind.java
2.1 冒泡排序算法(重中之重)
示例代码:D:\兄弟连视频day22\code\TestSort.java
(1)算法流程
a.比较相邻位置的两个元素,若第一个元素比较大则交换两个元素的位置;
b.从开始的第一对一直到结尾最后一对,经过这一步最后的元素将是这组元素中的最大值;
c.重复步骤b持续对越来越少的元素进行两两比较,直到处理完毕所有元素为止;
(直到任意两个相邻位置的元素都无需发生交换为止)
2.2 插入排序算法(熟悉)
(1)算法流程
a.从第一个元素起,认定该元素已经有序;
b.取出下一个元素与左边的有序数列从右向左依次进行比较;
c.若取出的元素小于左边的元素,则将左边的元素右移;
d.重复步骤c,直到取出元素大于等于左边的元素时,则将取出的元素插入到左边元素的右边 e.重复步骤b,直到处理完毕所有元素为止;
2.3 选择排序算法(熟悉)
(1)算法流程
a.从第一个元素起依次取出,并且假定取出的元素为这一组元素中的最小值,
使用min记录下标;
b.使用min记录的元素与后续元素依次比较大小;
c.若找到了比min记录的元素还小的元素,则使用min变量重新记录该元素的下标;
d.直到min记录的元素与后续所有元素比较完毕后,交换min记录的元素与最开始假定的
元素,经过这一步最前面的元素将是这组元素中的最小值;
e.重复步骤a,直到处理完毕所有元素为止;
2.4 快速排序算法(重点)
(1)算法流程
a.找到样本数列中的中间元素作为基准值单独保存起来;
b.分别使用左右两边的元素与基准值比较大小,将所有比基准值小的元素放在基准值
的左边,将所有比基准值大和相等的元素放到基准值的右边,这个过程叫做分组;
c.经过这一步,左边的元素小于基准值,右边的元素大于等于基准值,但左右两边
的分组内部不一定有序,此时需要对左右两边的分组进行再次分组;
d.直到处理完毕所有元素为止;
常见面试题:
1. wait()和sleep()区别:
http://www.cnblogs.com/renhui/p/6069353.html
解释:
sleep(有参数)方法是Thread类里面的,主要的意义就是让当前线程停止执行,让出cpu给其他的线程,但是不会释放对象锁资源以及监控的状态,当指定的时间到了之后又会自动恢复运行状态。
wait()方法是Object类里面的,主要的意义就是让线程放弃当前的对象的锁,进入等待此对象的等待锁定池,只有针对此对象调动notify方法后本线程才能够进入对象锁定池准备获取对象锁进入运行状态。
区别是:
(a)sleep()有参数:毫秒 wait()无参数
(b)sleep()睡眠时,保持对象锁,仍然占有该锁;而wait()睡眠时,释放对象锁。
但是wait()和sleep()都可以通过interrupt()方法打断线程的暂停状态,从而使线程立刻抛出InterruptedException(但不建议使用该方法)。
2. final, finally,finalize
http://www.cnblogs.com/xiaomoxian/p/5184520.html
final:关键字通常指的是“无法改变的”
final可以修饰变量(必须给赋值且值不能更改)、方法(无法被重写)和类(无法被继承)。
finally:关键字。对于一些代码,可能会希望无论try块中的异常是否抛出,它们都能够执行。这通常适用于善后(内存回收之外)的工作。
finalize():方法。垃圾回收器准备释放内存的时候,会先调用finalize()。
(1).对象不一定会被回收。
(2).垃圾回收不是析构函数。
(3).垃圾回收只与内存有关。
(4).Java GC(GarbageCollection,垃圾收集,垃圾回收)机制和finalize()都是靠不住的,只要JVM还没有快到耗尽内存的地步,它是不会浪费时间进行垃圾回收的。
3. 修饰词顺序:
[访问权限] [abstract] [static] [final] [transient] [volatile] [synchronized][native] [strictfp]
4. run方法和start方法
java Thread中,run方法和start方法的区别,下面说法错误的是?
这里需要注意Thread的start()与run()方法:
用start()方法才能真正启动线程,此时线程会处于就绪状态,一旦得到时间片,就会调用线程的run()方法进入运行状态;
而run()方法只是普通的方法,如果直接调用run()方法,则会按照顺序执行主线程这一个线程
1.start方法
用start方法来启动线程,是真正实现了多线程, 通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法。但要注意的是,此时无需等待run()方法执行完毕,即可继续执行下面的代码。所以run()方法并没有实现多线程。
2.run方法
run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码。
5.Collection与Collections的区别?
java.util.Collection:
1、是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。
2、Collection接口在Java类库中有很多具体的实现。比如SET LIST
3、Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。
实例: publicinterface Collection<E> extends Iterable<E> {}
List l1 = newLinkedList(); l1.add(newName("Kael","M"));
java.util.Collections:
1、是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。但是可以被调用。
实例:Collections.sort(l1);
http://blog.csdn.net/hz_lizx/article/details/54909082
6.构造器Constructor是否可被override(覆盖)?
https://www.cnblogs.com/guweiwei/p/6596542.html
构造器Constructor不能被继承,因此不能重写Override,但可以被重载Overload。
Constructor不能被继承,所以Constructor也就不能被override。每一个类必须有自己的构造函数,负责构造自己这部分的构造。子类不会覆盖父类的构造函数,相反必须负责在一开始调用父类的构造函数。
7.数组有没有length()这个方法?String有没有length()这个方法?
数组有
## JAVA基础 标签(空格分隔): JAVA后端
####3.开发环境的搭建和使用 #####3.2 相关的概念 ### 第二章 变量和注释、数据类型及转换、运算符、编码 ####X.JAVA中堆栈和内存分配(重点) - 1. 寄存器:最快的存储区,由编译器根据需求进行分配,我们在程序中无法控制。 [参考链接:](https://www.cnblogs.com/happyPawpaw/p/4443323.html) - 可以认为Java中的引用就是指针,是一种限制的指针,不能参与整数运行和指向任意位置的内存,并且不用显示回收对象。 ```Java Person p = new Person(); //创建了一个Person实例,也被称为Person对象,这个Person对象被赋给p变量 **c 中变量、变量名、变量地址、指针、引用:** - 变量,就是一个房间,它有编号(地址),他有名字(变量名),他有内容(里面的人)、 ```C语言 int a = 3; // a 是名字,3 是内容,地址可以假设是0x 12345678 (通常就是32位地址)、0x12345678 这个房间里面住的是一个int。 int *pi = &a; // pi 是名字,内容就是a的地址,0x12345678; 所以,你懂的, int & b = a; // 同样的0x12345678 这个房间,刚才他有个名字a,现在又有个名字b了、 ####1.变量和注释(重点) - 变量(域/field): **静态变量**(也叫类变量)是类中独立于方法之外的变量,用static 修饰。(static表示“全局的”、“静态的”,用来修饰成员变量和成员方法,或静态代码块(静态代码块独立于类成员,jvm加载类时会执行静态代码块,每个代码块只执行一次,按顺序执行))。 ``` 成员变量也称为:“域”,“实例变量”,在实体类或数据类中被称为“属性”或“字段”。当成员变量可以改变时,被称为对象的状态。 #####1.2 变量的声明和初始化
(3)十六进制和二进制之间的转换(熟悉) 综上所述: 扩展: Float double扩展: #####2.7 布尔类型 ####3.基本数据类型之间的转换(熟悉) 基本数据类型之间的转换分为:自动类型转换 和 强制类型转换。 经验: 经验: 关系运算符参与的表达式结果为boolean类型,只有两种:true 和 false 经验: 笔试题: (2)复合赋值 笔试题: #####4.7 移位运算符(了解) #####4.8 位运算符(了解) #####4.9 运算符的优先级 ##### - ASCII码 ##### - Unicode:编码标准 ##### - 码点(code point): ##### - 字符集(charset):计算机可以表示的字符组成了一个集合。 ##### - 字符集编码(Character encoding): ### 第三章 程序结构 (2)执行流程 (2)执行流程 case 字面值1: 语句块1; break; (3)注意事项 (2)执行流程 for (int i = 0; i != 1; i += 0.1) { (2)执行流程 (3)注意事项 (4)while(boolean)格式:1.()内可以使TRUE或者FALSE 2.可以是条件表达式,但是表达式结果只能是布尔类型。 (2)执行流程 (3)注意事项 ### 第四章 数组 #####1.2 数组的声明 ####2.二维数组(熟悉) #####2.2 二维数组的声明 arr代表什么? arr[0]代表什么? arr[0][0]代表什么? (2)二维数组的初始化 public static void main(String[] args) { int[] cpArr = arr1; int[] cpArr2 = Arrays.copyOf(arr1, 2 * arr1.length); ``` /** public static void main(String[] args) { // 数组用于存放10%...15%不同的汇率 // 定义二维数组balances 用于存储余额 // 设置第一行余额balances[0][i]全部为10000 // 两层for循环嵌套 计算未来几年利息interest balances[i][j] = oldBalance * (1 + interest); } ``` ### 第五章 类和对象 1.2 什么是面向对象? 1.3 什么是面向对象编程OOP? 1.4 为什么需要面向对象编程? 1.5 如何学好面向对象编程? ####2.类 类定义的一般形式如下 #####2.3 成员变量 以及初始化 **注意:** 成员变量和局部变量在内存中的分配 (2)成员变量默认初始化 #####2.4 对象的创建 (2)使用方式 #####2.5 引用(引用数据类型声明的变量名) (2)语法格式 注意: #####2.6 成员方法 (格式返回值调用)
(2)形参列表 (3)方法体 2.6.3 方法的调用 (2)使用方式 (2)注意事项 (3)默认构造方法 ##### 2.8 方法的重载( Overload) (2)重载的主要形式 判断方法能否构成重载的依据:调用该方法时能否区分即可。 (3)重载的主要作用 #####3.2 基本概念(当前对象) #####3.3 使用方式(就近原则) public class Test { public Test(String name, int age, boolean boyFriend) { ``` - 1:NullPointerException由RuntimeException派生出来,是一个运行级别的异常。意思是说可能会在运行的时候才会被抛出,而且需要看这样的运行级别异常是否会导致你的业务逻辑中断。 public int max(int a,int b){......} (1)main()方法是程序的入口,为main()方法分配变量的内存空间并初始化。 参数数目变化: public static int num(int... a) { 要求大家重点掌握的内容: - (1)基本概念 - 方法调用自身方法 public class Test { public static Long fibonacciRecursive(int i) {// 递归 if (i <= 2) { } } public static void main(String[] args) { Long result = fibonacciRecursive(0); ```
####1. 封装 #####1.1 基本概念 #####1.2 封装的流程 ####2.static关键字(重点) ####3. 构造块和静态语句块(熟悉) 执行流程: 静态语句块 => 构造块 => 构造方法体; (2)实现流程 (3)实现方式
#####6.2使用方式 使用this(实参)的方式可以调用本类中的其他构造方法; 要求大家掌握的内容: ####7.方法的重写(Override 重点) (1)基本概念 ### 第七章 包、访问控制符、 final、 对象创建的过程 #####1.3 访问控制符的权限信息 ####2.final关键字(重点) #####2.2 使用方式:不能重写、不能继承、必须初始化 **补充:** ####3.对象创建的过程 #####3.2 子类对象创建的执行过程 ### 第八章 多态、接口、 内部类 Object类、包装类 解析:
(3)引用类型之间的转换必须发生在父子类之间,否则编译报错; #####补充: 区分==和equals: ####2.抽象类(重点) #####2.2 什么是抽象类? #####2.4 实际意义 ####3. 接口 #####3.1 基本概念 - 接口就是一种比抽象类还抽象的类,该接口是不能实例化对象,更重要的是,接口中的所有方法都是抽象方法。 #####3.2 注意事项 public interface Comparable<T>{ #####3.3 类和接口之间的关系 #####3.4 接口和抽象类之间的区别 #####3.5 接口方法冲突 public interface Person { public class Student implements Named, Person { @Override
``` #####4.2 语法格式 } #####4.3 主要作用 #####4.4 内部类的主要分类 #####4.5 匿名内部类(重点、难点) 回调模式:略 Object() - 使用无参形式构造对象。 在某些特殊场合(集合)中要求所有的数据都是对象,那么对于基本数据类型的变量来说若要使用则需要进行对象化的处理,此时就需要借助包装类将变量包装成对象。 #####6.2 常用的包装类 #####6.3 Integer类(重点) (1)基本概念 (2)常用的方法 (3)装箱和拆箱 #####6.4 BigDecimal类(了解) (1)基本概念 (2)常用的方法 (2)常用的方法
#####1.1 基本概念 常量池 name = "guanyu"; - 表示修改引用变量名name的指向,而不是指向的内容。 笔试题: (2)常用的成员方法 boolean contains(CharSequence s) - 判断当前字符串是否包含参数指定的内容 int indexOf(int ch) - 返回参数指定字符在当前字符串中第一次出现的索引位置。 #####1.3 split拆分和replace方法 (2)常用的规则 [表示一位]、{表示多位} ####3.StringBuilder类和StringBuffer类(查手册会用即可) ####4.日期相关的类(查手册会用即可) (2)常用的方法 #####4.2 SimpleDateFormat类 (2)常用的方法
#####4.4 TimeStamp时间戳
####1 .综述 #####1.2 基本分类 boolean isEmpty() - 判断是否为空 #####2.2 常用的方法 E - 在此 collection 中保持的元素的类型 ####4.Queue队列接口(重点) #####4.2 常用的方法 (1)什么是二叉树? (3)TreeSet类的要求 #####4.4 Comparable接口和Comparator接口 注意:
(2)执行流程 总结: ####7.Map接口(重点) #####7.1 基本概念 ### 第十一章 异常Exception ####1. 基本概念 ####2. 基本分类 注意: Java.lang.RuntimeException类的主要子类: ####3. 非检测异常的处理 ####4. 异常的捕获try catch finally语句 (2)语法格式 (3)方法重写的原则 注意: ####6. 自定义异常 (2)自定义异常的步骤 throw:用于抛出一个异常对象。 ####8. 运行异常类的子类异常7个
####2.I/O流 补充: (2)常用的方法 (2)常用的方法 注意: (2)常用的方法 2.7 DataInputStream类(熟悉) (2)常用的方法 (2)常用的方法 (2)常用的方法 (2)常用的方法 (2)常用的方法 (2)常用的方法 经验: ### 第十三章 线程 ####1.线程的基本概念和基本操作 ####2.线程的创建和主要方法 void run() - 当调用对象是根据参数指定的接口引用构造时,则最终调用该接口引用所指向对象的run()方法,否则该方法啥也不做并返回。 (3)多线程的原理分析 注意: ####3.线程的同步机制(重点) ### 第十四章 网络编程 ####1.网络编程的常识(记住) 客户端: (2)Socket类 (b)udp协议 主机B(发送方): (2)DatagramPacket类 (3)InetAddress类 ### 第十五章 反射 ####1. 基本概念 ####2. Class类 #####2.2 获取Class类实例/对象的主要方式 ####3. Constructor类 #####3.2 常用的方法 #####4.2常用的方法 ### 第十六章设计原则、模式 public class SubPerson extends Person{ (2)里氏代换原则(Liskov Substitution Principle LSP) public class B extends A{ (4)接口隔离原则(Interface Segregation Principle ISP)
(5) 迪米特法则(Demeter Principle最少知道原则)(DP) public class B{ ####2.常用的设计模式 ####3.常见算法 #####1.常用的查找算法(重点) #####2.常用的排序算法(重点) ######2.1 冒泡排序算法(重中之重) (1)算法流程 ######2.2 插入排序算法(熟悉) ######2.3 选择排序算法(熟悉) ######2.4 快速排序算法(重点) ####常见面试题: 5.Collection与Collections的区别? 数组有 String有 10.Integer和int的区别? JAVA内省反射机制三部曲:http://www.cnblogs.com/zqmingok/articles/1713520.html 12.黑盒测试白盒测试 5.$方式一般用于传入数据库对象,例如传入表名. MyBatis排序时使用order by 动态参数时需要注意,用$而不是# 18. 4种创建线程池的方式。 newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。 newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。 线程各自获取monitor,不会有等待。 如果不同线程监视同一个实例对象,就会等待;如果不同的实例,不会等待。 双亲委派模型: 某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。 快捷键: alt+/ : 代码联想 * shift+alt+s:代码构建工具 ctrl+shift+x|y :切换选中字符大小写 ctrl+d : 删除鼠标所在当前行 * ctrl+t : 查看选中类名的子父类结构 * alt+↑ : 光标所在行代码向上移动一行 alt+↓ : 光标所在行代码向下移动一行 ctrl+alt+↑ : 光标所在行代码向上复制一行 ctrl+alt+↓ : 光标所在行代码向下复制一行 shift+回车 : 向当前光标所在位置的下一行插入一行空行, 并将光标移至新的空行中 (忽略代码的回车键) * ctrl+1 : 帮助 * ctrl+2 : 快捷变量的生成 * ctrl+shift+o : 全局导包
|
String有
int | length() |
8.什么是反射API?它是如何实现的?
http://blog.csdn.net/BuddyUU/article/details/52458241
在JDK中,主要由以下类来实现Java反射机制,这些类(除了第一个)都位于java.lang.reflect包中
Class类:代表一个类,位于java.lang包下。
Field类:代表类的成员变量(成员变量也称为类的属性)。
Method类:代表类的方法。
Constructor类:代表类的构造方法。
Array类:提供了动态创建数组,以及访问数组的元素的静态方法。
short s1= 1; s1 = s1 + 1;有什么错? shorts1 = 1; s1 += 1;有什么错?
http://bbs.itheima.com/thread-127149-1-1.html
short s1= 1; s1 = s1 + 1; 第二句Typemismatch: cannot convert from int to short 1默认为INT类型。
对于+=Java也会自动强转。对于b+=1,Java会转成b = (short)(b+1)。
同样,对于+=Java也会自动强转。对于b+=1,Java会转成b = (short)(b+1)
9.abstract class和interface有什么区别?
抽象类{
抽象方法();
}只能被继承无法被实例化
Interface接口{
抽象方法和成员变量集合
}
1.一个类可以实现多个接口 ,但却只能继承最多一个抽象类。
2.抽象类可以包含具体的方法 , 接口的所有方法都是抽象的。
3.抽象类可以声明和使用字段 ,接口则不能,但接口可以创建静态的final常量。
4.接口的方法都是public的,抽象类的方法可以是public,protected,private或者默认的package;
5.抽象类可以定义构造函数,接口却不能。
什么时候使用接口和抽象类?
看你想实现什么功能。使用抽象类是为了代码的复用,而使用接口的动机是为了实现多态性。
10.Integer和int的区别?
int 是基本类型,直接存数值,而integer是对象,用一个引用指向这个对象
1.Java 中的数据类型分为基本数据类型和复杂数据类型
int 是前者而integer 是后者(也就是一个类);因此在类进行初始化时int类的变量初始为0.而Integer的变量则初始化为null.
int i =1;Integeri= new Integer(1);(要把integer当做一个类看);但由于有了自动装箱和拆箱 (http://www.cnblogs.com/shenliang123/archive/2012/04/16/2451996.html),
使得对Integer类也可使用:Integeri= 1;
总而言之:如果我们定义一个int类型的数,只是用来进行一些加减乘除的运算or作为参数进行传递,那么就可以直接声明为int基本数据类型,但如果要像
对象一样来进行处理,那么就要用Integer来声明一个对象
11.JAVA内省机制
http://blog.csdn.net/hahalzb/article/details/5972421
1).内省(Introspector)是Java 语言对Bean类属性、事件的一种缺省处理方法。例如类 A 中有属性 name, 那我们可以通过getName,setName 来得到其值或者设置新的值。通过getName/setName 来访问 name 属性,这就是默认的规则。
JAVA内省反射机制三部曲:http://www.cnblogs.com/zqmingok/articles/1713520.html
12.黑盒测试白盒测试
白盒测试:是通过程序的源代码进行测试而不使用用户界面。这种类型的测试需要从代码句法发现内部代码在算法,溢出,路径,条件等等中的缺点或者错误,进而加以修正。
黑盒测试:又被称为功能测试、数据驱动测试或基于规格说明的测试,是通过使用整个软件或某种软件功能来严格地测试, 而并没有通过检查程序的源代码或者很清楚地了解该软件的源代码程序具体是怎样设计的。测试人员通过输入他们的数据然后看输出的结果从而了解软件怎样工作。
13.hashcode和equals
https://www.jianshu.com/p/893231579218
1、如果两个对象相等(equals()返回 true),那么它们的hashCode()一定要相同;
2、如果两个对象hashCode()相等,它们并不一定相等(equals()不一定返回 true)。
14.HashTable和HashMap的区别详解
http://blog.csdn.net/fujiakai/article/details/51585767
HashMap是基于哈希表实现的,每一个元素是一个key-value对,其内部通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长。
HashMap是非线程安全的,只是用于单线程环境下,多线程环境下可以采用concurrent并发包下的concurrentHashMap。
HashMap 实现了Serializable接口,因此它支持序列化,实现了Cloneable接口,能被克隆。
二、Hashtable简介
Hashtable同样是基于哈希表实现的,同样每个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长。
Hashtable也是JDK1.0引入的类,是线程安全的,能用于多线程环境中。
Hashtable同样实现了Serializable接口,它支持序列化,实现了Cloneable接口,能被克隆。
15.mybatis中#{}和${}的区别
1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:orderby #user_id#,如果传入的值是111,那么解析成sql时的值为order by"111", 如果传入的值是id,则解析成的sql为order by"id".
2. $将传入的数据直接显示生成在sql中。如:order by $user_id$,如果传入的值是111,那么解析成sql时的值为order byuser_id, 如果传入的值是id,则解析成的sql为order byid.
3. #方式能够很大程度防止sql注入。
4.$方式无法防止Sql注入。
5.$方式一般用于传入数据库对象,例如传入表名.
6.一般能用#的就别用$.
MyBatis排序时使用order by动态参数时需要注意,用$而不是#
16.redis、memcache、mongoDB有哪些区别
https://segmentfault.com/q/1010000002588088
Memcached
Memcached的优点:
Memcached可以利用多核优势,单实例吞吐量极高,可以达到几十万QPS(取决于key、value的字节大小以及服务器硬件性能,日常环境中QPS高峰大约在4-6w左右)。适用于最大程度扛量。
支持直接配置为sessionhandle。
坑少。
Memcached的局限性:
只支持简单的key/value数据结构,不像Redis可以支持丰富的数据类型。
无法进行持久化,数据不能备份,只能用于缓存使用,且重启后数据全部丢失。
无法进行数据同步,不能将MC中的数据迁移到其他MC实例中。
Memcached内存分配采用SlabAllocation机制管理内存,value大小分布差异较大时会造成内存利用率降低,并引发低利用率时依然出现踢出等问题。需要用户注重value设计。
Redis
Redis的优点:
支持多种数据结构,如 string(字符串)、 list(双向链表)、dict(hash表)、set(集合)、zset(排序set)、hyperloglog(基数估算)
支持持久化操作,可以进行aof及rdb数据持久化到磁盘,从而进行数据备份或数据恢复等操作,较好的防止数据丢失的手段。
支持通过Replication进行数据复制,通过master-slave机制,可以实时进行数据的同步复制,支持多级复制和增量复制,master-slave机制是Redis进行HA的重要手段。
单线程请求,所有命令串行执行,并发情况下不需要考虑数据一致性问题。
支持pub/sub消息订阅机制,可以用来进行消息订阅与通知。
支持简单的事务需求,但业界使用场景很少,并不成熟。
Redis的局限性:
Redis只能使用单线程,性能受限于CPU性能,故单实例CPU最高才可能达到5-6wQPS每秒(取决于数据结构,数据大小以及服务器硬件性能,日常环境中QPS高峰大约在1-2w左右)。
支持简单的事务需求,但业界使用场景很少,并不成熟,既是优点也是缺点。
Redis在string类型上会消耗较多内存,可以使用dict(hash表)压缩存储以降低内存耗用。
:)以下是我个人的补充
Mc和Redis都是Key-Value类型,不适合在不同数据集之间建立关系,也不适合进行查询搜索。比如redis的keys pattern这种匹配操作,对redis的性能是灾难。
Mogodb
mogodb是一种文档性的数据库。先解释一下文档的数据库,即可以存放xml、json、bson类型系那个的数据。这些数据具备自述性(self-describing),呈现分层的树状数据结构。redis可以用hash存放简单关系型数据。
mogodb存放json格式数据。
适合场景:事件记录、内容管理或者博客平台,比如评论系统。
nosq的产品目前很多,架构师的选择导向主要有以下两个因素:
1)适合应用程序的使用场景,比如评论系统用比较适合使用mogodb,而mc也可以实现(应用程序把数据转化成json存入,但是部分数据更新不方便)
2)团队开发比较熟悉的技术,比如一个团队一直在使用mc,因而有限选择mc,而不是redis。
还有中严重的状况,开发团队一直使用mogodb,在适合kv nosq的场景下而继续选择mogodb。
17.Request中getContextPath、getServletPath、getRequestURI、request.getRealPath的区别。
假定你的webapplication 名称为news,你在浏览器中输入请求路径:
http://localhost:8080/news/main/list.jsp
1.1 System.out.println(request.getContextPath());得到工程名
打印结果:/news1.2System.out.println(request.getServletPath());得到当前页面所在目录下全名称
打印结果:/main/list.jsp
1.3System.out.println(request.getRequestURI()); 得到包含工程名的当前页面全路径
打印结果:/news/main/list.jsp
1.4System.out.println(request.getRealPath("/")); 得到页面所在服务器的全路径:
打印结果:F:\Tomcat6.0\webapps\news\test
18. 4种创建线程池的方式。
http://blog.csdn.net/yellowjianokok/article/details/52550257
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,LIFO, 优先级)执行。
19. synchronized(class)、synchronized(this)与synchronized(object)
Synchronized:在多线程的情况下,由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问。
JAVA中synchronized关键字能够作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。
synchronized
void
f() { /* body */ }
和void f() { synchronized(this) { /*body */
} }
是完全等价的。
class与this的几种情况:
synchronized(class)
synchronized(this)
线程各自获取monitor,不会有等待。
synchronized(this)
synchronized(this)
如果不同线程监视同一个实例对象,就会等待;如果不同的实例,不会等待。
synchronized(class)
synchronized(class)
如果不同线程监视同一个实例或者不同的实例对象,都会等待。
20.静态代码块(static block )作用
静态代码块(staticblock ),不包含在任何方法体中当类被载入时,自动执行静态代码块,且只被执行一次经常用于类属性的初始化。
21.类加载机制和双亲委派模型
http://www.importnew.com/18548.html
类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7个阶段。其中准备、验证、解析3个部分统称为连接(Linking)。如图所示。
加载:
1.通过一个类的全限定名来获取定义此类的二进制字节流
2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
3. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口;
连接:
1.验证:确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
2.准备:正式为类变量分配内存并设置类变量初始值的阶段,内存放在方法区。
3. 解析:是虚拟机将常量池内的符号引用替换为直接引用的过程。
初始化:才真正开始执行类中定义的java程序代码。初始化阶段是执行类构造器<clinit>()方法。
双亲委派模型:
从Java虚拟机的角度来说,只存在两种不同的类加载器:一种是启动类加载器(BootstrapClassLoader),这个类加载器使用C++语言实现(HotSpot虚拟机中),是虚拟机自身的一部分;另一种就是所有其他的类加载器,这些类加载器都有Java语言实现,独立于虚拟机外部,并且全部继承自java.lang.ClassLoader。
某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
快捷键:
Eclipse常见快捷键:
重置
Eclipse
界面:
Windows--Perspective--Reset Perspective
重置
ECLIPSE
alt+/ :
代码联想
*
shift+alt+s:
代码构建工具
ctrl+shift+x|y :
切换选中字符大小写
ctrl+d :
删除鼠标所在当前行
*
ctrl+t :
查看选中类名的子父类结构
*
ctrl+o :
查看光标所在类的成员
(
方法
,
属性
,
代码块
) *
alt+
↑
:
光标所在行代码向上移动一行
alt+
↓
:
光标所在行代码向下移动一行
ctrl+alt+
↑
:
光标所在行代码向上复制一行
ctrl+alt+
↓
:
光标所在行代码向下复制一行
shift+
回车
:
向当前光标所在位置的下一行插入一行空行
,
并将光标移至新的空行中
(
忽略代码的回车键
) *
ctrl+1 :
帮助
*
ctrl+2 :
快捷变量的生成
*
ctrl+shift+o :
全局导包
开发工具快捷键
ctrl+N
:新建
ctrl+1
:提示错误信息
ctrl+D
:删除
ctrl+/
:行注释
ctrl+\
:取消行注释
ctrl+shift+/
:代码段注释
ctrl+shift+\
:取消代码段注释
ctrl+H
:快速查找任何文件信息、字符信息
ctrl+shift+O
:导包
ctrl+T
:查找类
(
支持模糊查找
)
ctrl+R
:查找文件(支持模糊查找、支持资源文件查找)
ctrl+shift+I
:
debug
模式下,查看当前执行代码信息
ctrl+G
:定位文件
(
不常用
)
DUBUG模式开发
注意:从今天开始,包括后续进入企业中,所有开发环境下的项目启动,都要用
debug
模式启动。
F5
:进入方法内
F6
:执行下一步
F7
:跳出方法外
F8
:执行到下一个断点