目录
打开DOS命令窗口,执行java HelloWorld。执行原理?
ClassLoader是在哪个位置上搜索HelloWorld.class字节码文件的?
关于JAVA源程序当中的注释:
什么是注释?注释的作用是什么?
JAVA中的注释怎么写呢?
Public class和class的区别:
关于JAVA语言当中的标识符:
什么是标识符?
标识符的命名规则?【不按照这个规则来,编译器会报错,这是语法】
标识符的命名规范?【只是一种规范,不属于语法,不遵守规范编译器不会报错】
关于java语言当中的变量:使用所有的基础语法开发系统业务
什么是变量?
数据类型的作用?
声明/定义变量的语法格式:
变量声明之后怎么赋值?
声明和赋值可以放到一起完成。
变量赋值之后,可以重新赋值,变量的值可变化:
通常访问一个变量包括两种访问方式:
变量在一行上可以声明多个,变量必须先声明,再赋值才能访问。
变量的作用域
关于变量的分类
数据类型
数据类型的作用是什么?
八种基本数据类型各自占用空间大小是多少?
什么是二进制?
转义字符 \
运算符
字符串连接运算符
三元运算符(三目运算符\条件运算符)
控制语句
方法
方法的基础语法
方法怎么调用
方法在执行过程当中,在JVM中的内存是如何分配的?内存是如何变化的?
面向对象【Java语言的核心机制,最重要的内容,Java语言的特色】
类和对象的概念
类的定义
对象的创建和使用
内存
空指针异常
定义类的语法:
Eclipse快捷键
封装
对象和引用
this关键字
Static关键字
继承
关于Java语言当中方法的覆盖(Override【官方的】/Overwrite)
多态
Final关键字
Package and import
关于访问控制权限
关于单例模式
super关键字
抽象类abstract
接口interface
Object类
toString(); *
public boolean equals(Object obj); *
finalize();
public native int hashCode();
clone();
内部类
静态内部类
成员内部类
类与类之间关系
实现关系
关联关系
聚合关系
合成关系
依赖关系
异常处理
异常的基本概念
异常的分类
异常的捕获和处理
声明抛出 throws
捕捉 try…catch…
getMessage()和printStackTrace()
finally语句块
自定义异常
方法覆盖与异常
数组
数组概要
一堆数组的声明和使用
静态初始化
动态初始化
什么时候使用动态初始化?什么时候使用静态初始化?
深入一维数组
关于main方法中的参数列表 String[] args
关于数组的拷贝
利用数组简单的模拟栈
二维数组的声明和使用
二维数组特点:
关于二维数组的动态初始化
数组的排序
冒泡排序算法
选择排序算法
数组的查找
Arrays工具类
常用类
String
字符串常用的方法
正则表达式
StringBuffer和StringBuilder
StringBuffer和StringBuilder是什么?
工作原理
StringBuffer, StringBuilder和String最大的区别?
如何优化StringBuffer和StringBuilder?
StringBuffer和StringBuilder的区别?
基本数据类型对应的8个包装类
基本数据类型与其包装类型
继承结构
以java.lang.Integer类型为例,讲解8种类型
关于Integer中常用的方法
Integer int String 三种类型相互转换
JDK5.0新特性
自动装箱(auto_boxing)和自动拆箱(auto_unboxing)
日期相关类
格式化日期
获取特殊日期
Data构造方法加参数
日历 Calendar
数字相关类
DecimalFormat
BigDecimal
Random
集合
Collection继承结构图
单向链表
双向链表
Map继承结构图
Collecton类中常用方法
boolean add(Object), void clear(), boolean isEmpty()
Iterator iterator()
boolean contains(Object)
boolean remove(Object o)
深入remove方法
List集合
List集合存储元素特点:
深入List集合
Set
HashSet
SortedSet和TreeSet
SortedSet集合存储元素为什么可以自动排序?
Map
关于Map集合中常用的方法。
Propertier
SortedMap & TreeMap
Collections集合工具类
为什么引入泛型?
泛型的优点和缺点
泛型语法如何实现
增强for循环 foreach
流与文件见文章2
注意:
路径中”..”表示上级目录
路径中”.”表示当前目录
单行注释
//单行注释,只注释当前行
多行注释
/*
多行注释
*/
javadoc注释
/**
* Javadoc注释
* Javadoc注释
*
*/
注意:这种注释是比较专业的注释,该注释信息会被javadoc.exe工具解析提取并生成帮助文档
需要记忆:
例:
public class UserService{
public void login(String username, String password){
}
}
例:
SystemService
UserService
CustomerService
关于字面值: JavaSelf01
字面值:
字面值就是数据
字面值是JAVA源程序的组成部分之一。包括标识符和关键字它们都是JAVA源程序的组成部分
数据在现实世界中是分门别类的,所以数据在计算机编程语言当中也是有类型的:【数据类型】
注意:
变量要求:
变量中存储的具体的“数据”必须和变量的“数据类型”一致,当不一致的时候编译报错。
例如:
Int i;
Int age;
Int length;
Int size;
Int num
其中int是数据类型,I,age,length,size,num都是变量名
语法格式:
变量名 = 字面值;
要求:字面值的数据类型必须和变量的数据类型一致。
=等号是一个运算符,叫做赋值运算符,赋值运算符先运算等号右边的表达式,表达式执行结束后的结果赋值给左边的变量。
例:
int i = 10;
int i = 10;
i = 20;
i = 100;
有了变量的概念后,内存空间得到了重复的使用
i = 20;//set
System.out.println(i);//get
在方法体当中的JAVA代码,是遵守自上而下的顺序依次执行的,逐行运行
特点:第二行的代码必须完整的结束之后,第三行程序才能执行。
在同一个“作用域”当中,变量名不能重名,但是变量可以重新赋值。
什么是作用域?
只要记住一句话:
根据变量声明的位置来分类:
在方法体当中声明的变量叫做局部变量
在方法体外【类体之内】声明的变量叫做成员变量
在不同的作用域当中,变量名可以相同的;
在同一个作用域当中,变量名是不能相同的。
数据类型的作用是指导JVM在运行程序的时候给该数据分配多大的内存空间
Java中的数据类型包括2种:
关于基本数据类型
基本数据类型包括4大类8小种:
第一类:整数型
byte. short. int. long
第二类:浮点型
float, double
第三类::布尔型
boolean
第四类:字符型
char
字符串不属于基本类型,属于”引用数据类型“,字符属于基本数据类型
基本数据类型 | 占用空间大小【单位:字节】 |
byte | 1 |
short | 2 |
int | 4 |
long | 8 |
float | 4 |
doule | 8 |
boolean | 1 |
char | 2 |
计算机在任何情况下都只能识别二进制【现代计算机底层采用交流电的方式,接通和断开就两种状态,计算机只识别1或0,其他不认识】
数据的一种表示形式,十进制表示满10进1原则,二进制表示满2进1原则
字节( byte):
1 byte = 8 bit 【1字节 = 8比特位】1个比特位表示一个二进制位
1 KB = 1024 Byte
1 MB = 1024 KB
1 GB = 1024 MB
1 TB = 1024 GB
1 TB = 1024 * 1024 * 1024 * 1024 * 8 Bit
整数型当中的byte类型,占用1个字节,所以byte类型的数据占用8个比特位,那么byte类型的取值范围?
ASCII码
a=> 97【01100001】
A => 65
0 => 46
a –(按照ASCII解码)à01100001
01100001—(按照ASCII编码)àa
编码和解码时采用同一套字典/对照表,不会出现乱码
当解码和编码的时候采用的不是同一套对照表,会出现乱码问题
Java语言采用的编码方式:
现在在实际开发中,一般使用UTF-8编码方式较多,【统一编码方式】
short和char所表示的种类总数是一样的,只不过char可以表示更大的正整数,因为char没有负数。
关于8种数据类型的默认值:
转义字符出现在特殊字符之前,会将特殊字符转换成普通字符
\n 换行符
\t 制表符
\’ 普通的单引号
\\ 普通的反斜杠
\” 普通的双引号
关于java语言中的整数型:
关于浮点型数据类型:
double和float在计算机内部二进制存储的时候存储的都是近似值
在现实世界当中有些数字是无限循环的,计算机资源是有限的,用有限的资源存储无限的数据只能存储近似值
关于布尔型数据类型:
关于基本数据类型之间的互相转换:
byte < short < int < long < float < double
注意:
当整数字面值没有超出byte , short , char的取值范围,可以直接赋值给byte , short , char 类型的变量
byte, short, char混合运算时,各自先转换成int类型再做运算
多种数据类型混合运算,先转换成容量最大的那种类型再做运算
+ 求和
- 相减
* 乘积
/ 商
% 求余【取模】
++ 自加1
-- 自减1
注意:
一个表达式当中有多个运算符,运算符有优先级,不确定的加小括号,优先级得到提升。没有必要专门记忆运算符优先级。
优先级:
() ! +(正号) =(负号)
~ ++ --
乘除模除:/ * %
加减:+ -
位运算符:>> <<
关系运算符:& | && ||
运算符 |
名称 |
说明 |
& |
逻辑与[并且] |
两边的算子都是true,结果才是true |
| |
逻辑或【或者】 |
两边的算子只要有一个是true,结果就是true |
! |
逻辑非 |
取反,!false = true;!true = false,这是一个单目运算符 |
^ |
逻辑异或 |
两边的算子只要不一样,结果就是true |
&& |
短路与 |
|
|| |
短路或 |
|
- 逻辑运算符要求两边算子都是布尔类型,并且逻辑运算符最终的运算结果也是一个布尔类型
- 短路与和逻辑与最终的运算结果是相同的,只不过短路与存在短路现象
- 短路或和逻辑或最终的运算结果是相同的,只不过短路或存在短路现象
- 什么情况下发生短路现象?
- 什么时候选择使用逻辑与运算符?什么时候选择使用短路与运算符?
数字 + 数字 à 数字【求和】
数字 + “字符串“ à ”字符串“【字符串连接】
布尔表达式 ? 表达式1 : 表达式2
(a)Byte i = 10;
I += 5; 等同于:I = (byte)(i+5);
(b)Int k = 10;
K += 5;等同于:k = (int)(k+5);
(c)Long x = 10L;
Int y = 20;
Y += x;等同于:y = (int)(y+x);
重要结论:扩展类的赋值运算符不改变运算结果类型。假设最初这个变量的类型是byte类型,无论怎么进行追加或追减,最终该变量的数据类型还是byte类型。
1. 选择结构
a) If, if.. else
i. If
1. 属于选择结构,if语句又被称为分支语句/条件控制语句
a) 语法结构:四种编写方式
i. If(布尔表达式){
Java语句;
…
}
ii. If(布尔表达式){
Java语句;
…
}else{
Java语句;
…
}
iii. If(布尔表达式){
Java语句;
}else if(布尔表达式){
Java语句;
…
}else if(布尔表达式){
Java语句;
…
} else if(布尔表达式){
Java语句;
…
}
else if(布尔表达式){
Java语句;
…
}
else if(布尔表达式){
Java语句;
…
}
iv. If(布尔表达式){
Java语句;
…
}else if(布尔表达式){
Java语句;
…
}else if(布尔表达式){
Java语句;
…
}else{
Java语句;
…
}
b) 对于java中的if语句来说,只要有一个分支执行,真个if语句全部结束
c) 以上的第二种/第四种编写方式都带有else分支,这两种方式可以保证会有分支执行
d) 所有的控制语句都是可以嵌套使用的,只要合理嵌套就行
注意:嵌套使用的时候,代码格式要保证完美
e) If语句的分支中,只有一条java语句的话,大括号可以省略不写
ii. 接收用户键盘输入,从键盘到内存。【输入的过程】
b) Switch
i. Switch语句也属于选择结构,也是分支语句
ii. Switch语句的语法结构:
一个比较完整的switch语句应该这样编写:
Switch(int 或String类型的字面值或变量){
Case int或String类型的字面值或变量:
Java语句;
Java语句;
…
Break;
Case int或String类型的字面值或变量:
Java语句;
Java语句;
…
Break;
Case int或String类型的字面值或变量:
Java语句;
Java语句;
…
Break;
Default:
Java语句;
…
}
iii. Switch语句执行原理:
Switch后面小括号当中的“数据”和case后面的“数据”进行一一匹配,匹配成功的分支执行。按照自上而下的顺序依次匹配。
iv. 匹配成功的分支执行,分支当中最后有“break”语句的话,整个switch语句终止。
v. 匹配成功的分支执行,分支当中最后没有“break”语句的话,直接进入下一个分支执行(不进行匹配)这种现象被称为case穿透现象。【提供break;语句可以避免穿透】
vi. 所有分支都没有匹配成功,当有default的语句话,会执行default分支当中的程序
vii. Switch后面和case后面只能是int或者String类型的数据,不能是探测其他类型。
1. 当然byte, short, char也可以直接写到switch和case后面,因为它们可以进行自动类型转换。Byte, short, char可以自动转换成int类型
2.
viii. Case可以合并:
Switch(i){
Case 1:case 2:case 3:case 10:
System.out.println(“hello”);
}
ix.
2. 循环结构
a) For
i. 循环结构:
在程序当中,总有一些反复的执行的代码。把需要反复执行的代码片段放到“循环体”,再联合计数器,共同控制这段需要反复执行的代码
ii. For循环的语法结构
For(初始化表达式; 布尔表达式; 更新表达式){
//需要重复执行的代码片段【循环体:由java语句构成】
}
iii. For循环的执行过程/原理【非常重要】
1. 初始化表达式、布尔表达式、更新表达式都不是必须的【但两个分号是必须的】
2. 初始化表达式最先执行,并且再整个for循环当中只执行一次
3. 布尔表达式必须是true/false,不能是其他值
4. For的执行过程:
a) 执行初始表达式,并且该表达式只执行一次
b) 判断布尔表达式的结果是true/false
i. 布尔表达式true
执行循环体
执行更新表达式
判断布尔表达式的结果是true/false
执行循环体
执行更新表达式
判断布尔表达式的结果是true/false
……
ii. 布尔表达式false
执行结束
iii.
c)
iv.
b) While
i. While循环的语法结构:
1. While(布尔表达式){
循环体;
}
2.
ii. While循环的执行原理:
1. 先判断bool表达式的结果:
a) True
i. 执行循环体
1. 判断布尔表达式的结果:
a) Ture
i. 执行循环体
ii. 判断布尔表达式的额结果
iii. False:循环结束
iii. While循环的循环次数:
1. 0-N次
2. 注意:while循环的循环体可能一次都不执行
c) Do…while{}
i. Do while循环的语法结构
Do{
循环体;
}while(布尔表达式);
ii. Do while循环的执行原理
iii. Do while循环的执行次数
1 -N次【至少一次】
iv. 使用do while 循环的注意事项:
Do while循环语句最终有个分号别丢了
3. 控制循环语句
a) Break
i. Break是java语句当中的关键字,被翻译为”中断,折断”
ii. Break + “;”可以成为一个单独的完整的java语句:break;
iii. Break语句使用在switch语句当中,用来终止switch的语句执行。
iv. Break语句同样可以使用在循环语句当中,用来终止循环的执行
v. Break终止哪个循环?
vi. Break语句使用在for, while, do while循环语句当中用来跳出循环,终止循环的执行。因为当循环到某个条件的时候,后续的循环没必要执行了,在执行也是耗费资源,所以可以终止循环,这样可以提高程序的执行效率。
vii. 在默认情况下,break语句终止的是离它最近的循环语句,当然也可以指定终止某个循环,需要给循环起名,采用这种语法:break 循环名称
b) Continue
i. Continue表示:继续/go on/下一个
ii. Continue也是一个continue关键字加一个分号构成一个单独完成的java语句,主要出现循环语句当中用来控制循环的执行
iii. Break和continue的区别?
1. Break表示循环不执行了
2. Continue表示终止当前“本次”循环,直接进入下一次循环继续执行
iv. Continue也有这样的语法:
Continue + 循环名称
方法的基础语法
方法怎么定义,语法结构:
[修饰符列表]返回值类型 方法名(形式参数列表){
方法体;
}
对以上的语法结构进行解释说明:
关于修饰符列表
- 可选项,不是必须的
- 目前统一写成public static【以后讲】
- 方法的修饰符列表当中有“static”关键字的话,怎么调用这个方法?
- 类名.方法名(实际参数列表);
返回值类型
- 什么是返回值?
一个方法是可以完成某个特定功能的,这个功能结束后大多数都是需要返回最终执行结果的,执行结果可能是一个具体存在的数据。而这个具体存在的数据就是返回值。
- 返回值类型?
返回值是一个具体存在的数据,数据都是有类型的,此处需要指定的是返回值的具体类型
- 返回值可以指定哪些类型?
Java任意一种类型都可以,包括基本数据类型和所有的引用数据类型。
- 也可能方法结束执行之后不反悔任何数据,java中规定,当一个方法执行结束后不反悔任何数据的话,返回值类型位置必须编写:void关键字
- 返回值类型可以是:
Byte, short, int, float, double, char, String, void, Boolean …
- 返回值类型若不是void,表示这个方法执行结束之后必须返回一个具体的数值。当方法执行结束的时候没有返回任何数据的话编译器报错。
- 返回值:
Return 值;
并且要求“值”的数据必须和方法的返回值类型一致,不然编译器报错。
- 返回值类型是void的时候,在方法体当中不能编写“return 值”这样的语句。
- 只要带有return关键字的语句执行,return语句所在的方法结束。
- 方法名:
- 只要是合法的标识符就行
- 方法名最好见名知意
- 方法名最好是动词
- 方法名首字母要求小写,后面每个单词首字母大写
- 方法体必须由大括号括起来,方法体当中的代码有顺序,遵循自上而下的顺序依次执行。并且方法体由java语句构成,每一个java语句以“;“结尾。
- 形式参数列表:简称形参
- 形参是局部变量
- 形参的个数可以是0 -N 个
- 多个形参之间用逗号隔开
- 形参中起决定性作用的是形参的数据类型,形参的名字就似乎局部变量的名字。
方法怎么调用
- 方法只定义不去调用是不会执行的,只有在调用的时候才会执行。
- 语法规则:《方法的修饰符列表当中有static》
类名.方法名(实参列表):<这是一条java语句,表示调用某个类的某个方法,传递这样的实参>
方法的重复机制overload
方法的本质:
方法就是一段代码片段,并且这段代码片段可以完成某个特定的功能,并且可以被重复的使用。
方法的优点:
代码得到了重复使用
方法定义在类体当中,在一个类当中可以定义多个方法,方法编写的位置没有先后顺序,可以随意
方法体当中不能在定义方法
方法体由java语句构成,方法体中的代码遵守自上而下的顺序依次执行。
方法的调用不一定在main方法当中,可以在其他方法当中。只要是程序可以执行到的位置,都可以取调用其他方法。
方法调用的时候实参和形参要求个数对应相同,数据类型对应相同
类型不同的时候要求能够进行相应的自动类型转换
方法的调用:
方法的修饰符列表当中有static关键字,完整的调用方式是:
类名.方法名(实参列表);
但是,有的时候“类名.”可以省略
M1方法和m2方法在同一个类体当中,“类名.”可以省略使用
建议在1个java源文件当中只定义1个class
方法的返回值类型不是void的时候
返回值类型不是void的时候,要求方法必须百分百的执行“return 值;”这样的语句来完成值的返回,没有这个语句编译器会报错。
一个方法有返回值的时候,当我们调用这个方法的时候,方法返回了一个值,对于调用者来说,这个返回值可以选择接收,也可以选择不接收。
深入return语句
带有return关键字的java语句只要执行,所在的方法执行结束
在同一个作用域当中,return语句下面不能编写任何代码,因为这些代码永远都执行不到,所以编译报错。
在返回值类型是void的方法当中使用“return;”语句
“return;”出现在返回值为void的方法当中主要是为了结束当前的方法
方法在执行过程当中,在JVM中的内存是如何分配的?内存是如何变化的?
方法只定义,不调用,是不会执行的,并且在JVM中也不会给该方法分配“运行所属”的内存空间。只有在调用这个方法的时候,才会动态的给这个方法分配所属的内存空间。
在JVM内存划分上,有这样三块主要的内存空间(除了这三块之外还有其他的内存空间)
方法区内存
堆内存
栈内存
关于栈数据结构
栈:stack,是一种数据结构
数据结构反应的是数据的存储形态
JavaSE当中的集合 使用了大量的数据结构
方法执行的时候,代码片段存在哪里?方法执行的时候执行过程的内存在哪里分配?
- 方法代码片段属于.class字节码文件的一部分,字节码文件在类加载的时候,将其放到了方法去当中,所以JVM中的三块主要的内存空间中方法区内存最先有数据,存放了代码片段。
- 代码片段虽然在方法区内存当中只有一份,但是可以被重复调用。每一次调用这个方法的时候,需要给该方法分配独立的活动场所,在栈内存中分配。【栈内存中分配方法运行的所属内存空间】
方法在调用的瞬间,会给该方法分配独立的内存空间,在栈中分配,此时发生压栈动作,方法执行结束之后,给该方法分配的内存空间全部释放,此时发生弹栈动作。
- 压栈:给方法分配内存
- 弹栈:释放该方法的内存空间
局部变量在栈中存储,局部变量在运行阶段内存在栈中分配。
方法执行过程中的内存分配
- 重点:方法调用的时候,在参数传递的时候,实际上传递的是变量中保存的那个值传过去了。
方法的重载机制
- 不适用overload,程序存在的缺点?
- 方法虽然功能不同,但是功能是相似的,都是求和。功能相似的方法起了不同的名字,这对于程序员来说调用的时候不方便,程序员需要记忆更多的方法才能 完成调用。【不方便】
- 代码不美观
- Overload的优点:
- 程序员调用方法的时候比较方便,虽然调用的是不同的方法,但是就像在使用一个方法一样,不需要记忆更多的方法名。
- 代码美观
- 前提:功能相似的时候,方法名可以相同
- 功能不同的时候,尽可能让方法名不同
方法的递归调用
什么是递归?
方法自身调用自身
递归是很耗费栈内存的,递归算法可以不用尽量不用。
Java.lang.StackOverflowError
栈内存溢出错误
错误发生无法挽回,只有一个结果,就是JVM停止工作
递归必须有结束条件,没有结束条件一定会发生栈内存溢出错误。
递归即使有了结束条件,即使结束条件是正确的,也可能会发生栈内存溢出错误,因为递归太深了。
注意:递归可以不使用尽量别用
但有些情况下功能的实现必须依靠递归
面向过程和面向对象的区别
面向对象的三大特征
类描述的是对象的共同特征
共同特征例如:身高特征
这个身高特征在访问的时候,必须先创建对象,通过对象去访问这个特征,因为这个特征具体到某个对象上之后,值不同。有的对象身高1.80,有的对象身高2.80
一个类主要描述什么信息呢?
一个类主要描述的是状态 + 动作。
状态信息:名字/身高/性别/年龄
动作信息:吃/唱歌/跳舞/学习
状态à一个类的属性
动作à一个类的方法
类{
属性:描述对象的状态信息
方法:描述对象的动作信息
}
注意:
状态和动作当具体到某个对象上之后,发现最终的结果可能不一样。
对象和对象之间有共同特征,但是具体到对象之后有数据的差异。
语法结构:
[修饰符列表] class 类名 {
属性;
方法;
}
学生类:描述所有学生对象的共同特征:
学生对象有哪些状态信息:
学生对象有哪些动作信息:
重点:属性通常是采用一个变量的形式来完成定义的。
1. public class Student{
2. //类体 = 属性 + 方法
3. //属性【存储数据采用变量的方式】
4. //由于变量定义在类体当中,方法体之外,这种变量称为成员变量
5.
6. //所有学生都有学号信息
7. //但是每个学生的学号都是不同的
8. //所以要访问这个学号必须先创建对象,通过对象去访问学号信息
9. //学号信息不能直接通过“类”去访问,所以这种成员变量又被叫做:实例变量
10. //对象又被称为实例,实例变量又被称为对象变量。[对象级别的变量]
11. //不创建对象,这个no变量的内存空间是不存在的,只有创建了对象,这个no变量内存空间才会创建。
12. int no;
13. int age;
14. boolean sex;
15. String name;
16. String addr;
17. }
18.
19. //成员变量没有手动赋值的话,系统赋默认值
20. //默认值
21. /**
22. * 数据类型 默认值
23. * -------------------------------------
24. * byte, short, int , long 0
25. * float, double 0.0
26. * boolean false
27. * char \u0000
28. * 引用数据类型 null 空值
29. */
1. public class OOTest01{
2. public static void main(String[] args){
3.
4. //int是基本数据类型
5. //i是变量名
6. //10是一个int类型的字面值
7. int i = 10;
8. //通过一个类可以实例化N个对象
9. //实例话对象的语法:new 类名()
10. //new运算符的作用是创建对象,在JVM堆内存当中开辟新的内存空间
11. //方法区内存:在类加载的时候,class字节码代码片段被加载到该内存空间中
12. //栈内存(局部变量):方法代码片段执行的时候,会给该方法分配内存空间,在栈中压栈。
13. //堆内存:new的对象在堆内存中存储
14.
15. //Student是一个引用数据类型
16. //s是一个变量名
17. //new Student()是一个学生对象
18. //s;是一个局部变量[在栈内存中存储]
19. Student s = new Student();
20.
21. //什么是对象?new运算符创建在堆内存中开辟的内存空间称为对象
22. //什么是引用?引用是一个变量,只不过这个变量中保存了另一个java对象的内存地址
23. //Java语言当中,程序员不能直接操作堆内存,java中没有指针,不像C语言
24. //Java语言当中,程序员只能通过“引用”去访问堆内存当中对象内部的实例变量
25.
26. //访问实例变量的语法格式:
27. //读取数据:引用.变量名
28. //修改数据:引用.变量名 = 值;
29. /*
30. int stuNo = s.no;
31. String stuName = s.name;
32. int stuAge = s.age;
33. boolean stuSex = s.sex;
34. String stuAddr = s.addr;
35.
36. System.out.println("学号:" + stuNo);
37. System.out.println("姓名:" + stuName);
38. System.out.println("年龄:" + stuAge);
39. System.out.println("性别:" + stuSex);
40. System.out.println("地址:" + stuAddr);
41. */
42. System.out.println("学号:" + s.no); //0
43. System.out.println("姓名:" + s.name); //null
44. System.out.println("年龄:" + s.age); //0
45. System.out.println("性别:" + s.sex); //false
46. System.out.println("地址:" + s.addr); //null
47.
48. s.no = 10;
49. s.name = "Jack";
50. s.age = 20;
51. s.sex = true;
52. s.addr = "北京";
53.
54. System.out.println("学号:" + s.no); //10
55. System.out.println("姓名:" + s.name); //Jack
56. System.out.println("年龄:" + s.age); //20
57. System.out.println("性别:" + s.sex); //true
58. System.out.println("地址:" + s.addr); //北京
59.
60. //再通过类实例化一个全新的对象
61. //stu是一个引用
62. //stu同时也是一个局部变量
63. //Student是变量的数据类型
64. Student stu = new Student();
65.
66. System.out.println(stu.no);
67. System.out.println(stu.name);
68. System.out.println(stu.age);
69. System.out.println(stu.sex);
70. System.out.println(stu.addr);
71.
72. //编译报错:no这个实例变量不能直接采用“类名”的方式访问
73. //因为no是实例变量,对象级别的变量,变量存储在java对象的内部,必须先有对象
74. //通过对象才能访问no这个实例变量,不能直接通过类名访问
75. //System.out.println(Student.no);
76.
77. }
78. }
79.
80. /**
81. * 局部变量再栈内存中存储
82. * 成员变量中的实例变量在堆内存的java对象内部存储
83. *
84. * 实例变量是一个对象一份,100个对象有100份
85. */
1. public class Address{
2. //城市
3. String city;
4. //街道
5. String street;
6. //邮编
7. String zipCode;
8.
9. }
1. public class User{
2.
3. //用户编号
4. int no;
5. //用户名
6. String name;
7. //家庭住址
8. Address addr;
9. }
1. public class OOTest{
2. public static void main(String[] args){
3. User u = new User();
4.
5. System.out.println(u.no); //0
6. System.out.println(u.name); //null
7. System.out.println(u.addr); //null
8.
9. //修改User对象内部实例变量
10. u.no = 110;
11. u.name = "Jack";//"Jack"是一个Java对象,属于String对象
12. u.addr = new Address();
13.
14. u.addr.city = "北京";
15. u.addr.street = "朝阳";
16. u.addr.zipCode = "11111111111111";
17.
18. //在main方法当中目前只能看到一个引用“u”
19. //一切都是只能通过u来进行访问
20. System.out.println(u.name + "居住的城市为:" + u.addr.city);
21. System.out.println(u.name + "居住的街道为:" + u.addr.street);
22. System.out.println(u.name + "邮编为:" + u.addr.zipCode);
23.
24.
25.
26. }
27. }
28. /**------------输出结果-------------
29. * 0
30. * null
31. * null
32. * Jack居住的城市为:北京
33. * Jack居住的街道为:朝阳
34. * Jack邮编为:11111111111111
35. */
1. public class OOTest01{
2. public static void main(String[] args){
3. User u = new User();
4. //u.addr = new Address();
5.
6. Address a = new Address();
7. u.addr = a;
8.
9. System.out.println(u.addr.city);
10.
11. a.city = "天津";
12.
13. System.out.println(u.addr.city);
14. }
15. }
16. /**-----------输出结果-------------
17. * null
18. * 天津
19. */
JVM(Java虚拟机)主要包括三块内存空间:栈内存,堆内存,方法区内存
堆内存和方法区内存各有一个;一个线程一个栈内存。
方法在调用的时候,该方法所需要的内存空间在栈内存中分配,称为压栈;方法执行结束的时候,该方法所属的内存空间释放,称为弹栈
栈中主要存储的是方法体当中的局部变量
方法的代码片段以及整个类的代码片段都被存储到方法区内存中,在类加载的时候这些代码片段会载入
在程序执行过程中,使用new运算符创建的java对象,存储在堆内存中,对象内部有实例变量,所以实例变量存储在堆内存中。
变量分类:
静态变量存储在方法区内存中
三块内存当中变化最频繁的是栈内存,最先有数据的是方法区内存,垃圾回收器主要针对的是堆内存
垃圾回收器【自动垃圾回收机制,GC机制】什么时候会考虑将某个Java对象的内存回收呢?
当堆内存当中的java对象成为垃圾数据的时候,会被垃圾回收器回收。
什么时候内存中的java对象会变成垃圾呢?
没有更多的引用指向它的时候
这个对象无法访问,因为访问对象只能通过引用的方式访问
1. public class Customer{
2. int id;
3. }
1. public class OOTest{
2. public static void main(String[] args){
3.
4. Customer c = new Customer();
5. System.out.println(c.id);
6.
7. //以下程序编译可以通过,因为符合语法
8. //运行出现空指针异常
9. //空引用访问“实例”相关的数据一定会出现空指针异常
10. //java.lang.NullPointerTxception
11. c = null;
12. System.out.println(c.id);
13. }
14. }
15.
16. //实例相关的数据表示,这个数据访问的时候必须有对象的参与。这种数据就是实例相关的数据。
17.
18. /**-----------------运行结果--------------------
19. * PS D:\study\java\javaworkspace\Customer> javac OOTest.java
20. * PS D:\study\java\javaworkspace\Customer> java OOTest
21. * 0
22. * Exception in thread "main" java.lang.NullPointerException
23. * at OOTest.main(OOTest.java:8)
24. */
[修饰符列表] class 类名{
属性;
方法;
}
属性通常采用变量来表示,既然是变量那么变量肯定有数据类型【数据类型包括:基本数据类型 + 引用数据类型】
属性对应的是状态信息
Alt + / 自动补全
Ctrl + Shift + F文本格式化
1. 为什么要封装?封装的好处?
a) 封装之后,对于那个事物来说,看不到这个事物复杂的那一面,只能看到该事物简单的那一面。复杂性封装,对外提供简单的操作入口。照相机就是一个很好的封装案例,照相机的实现原理非常复杂,但是对于使用照相机的人来说操作起来非常方便。
b) 封装之后才会形成真正的“对象”,真正的“独立体”
c) 封装就意味着以后的程序可以重复使用,并且这个事物应该适应性比较强,在任何场合都可以使用
d) 封装之后,对于事物本身,提高了安全性。【安全级别高】
2. 封装的步骤:
a) 所有属性私有化,使用private关键字进行修饰,private表示私有的,修饰的所有数据只能在本类中访问。
b) 对外提供简单的操作入口,也就是说以后外部程序想要访问age属性,必须通过这些简单的入口进行访问。
i. 对外提供两个公开的方法,分别是set方法和get方法
1. 想修改属性,调用set方法
2. 想读取属性,调用get方法
c) Set方法的命名规范:
Public void set+属性名首字母大写(形参){
}
d) Get方法命名规范:
Public 返回值类型 get+属性名首字母大写(形参){
}
e)
访问一个属性的访问形式:
像读取这个属性的值,读取get
想修改这个属性的值,修改set
Setter and getter方法没有static 关键字
有static关键字修饰方法怎么调用:类名.方法名(实参);
没有static关键字修饰的方法怎么调用:引用.方法名(实参);
3. 构造方法
a) 构造方法又被称为构造函数/构造器/Constructor
b) 构造方法语法结构:
[修饰符列表] 构造方法名 (形参列表) {
构造方法体;
}
c) 普通方法的语法结构:
[修饰符列表] 返回值类型 方法名 (形参列表) {
方法体;
}
d) 对于构造方法来说,“返回值类型“不需要指定,并且也不能写void,只要写上void,那么这个方法就变成了普通方法
e) 对于构造方法来说,构造方法的方法名必须和类名保持一致
f) 构造方法的作用:
构造方法存在的意义是:通过构造方法的调用,可以创建对象。
g) 构造方法应该怎么调用:
- 普通方法是这样调用的:
方法修饰符中有static的时候:类名.方法名(实参列表)
没有static的时候:引用.方法名(实参列表)
- New 构造方法名(实参列表)
h) 构造方法调用执行之后有返回值吗?
每一个构造方法执行结束之后都有返回值,但是“return 值;”这样的语句不需要写。构造方法结束的时候java程序自动返回值。
并且返回值类型是构造方法所在类的类型。
i) 当一个类中没有定义任何构造方法的话,系统默认给该类提供一个无参数的构造方法,这个构造方法被称为缺省构造器。
j) 当一个类显示的将构造方法定义出来了,那么系统则不再默认为这个类提供缺省构造器
k) 构造方法支持重载机制,在一个类当中编写多个构造方法,这多个构造方法显然已经构成方法重载机制。
l) 构造方法的作用
i. 创建对象
ii. 创建对象的同时。初始化实例变量的内存空间。【给实例变量赋值】
iii. 成员变量之实例变量,属于对象级别的变量,这种变量必须先有对象才能有实例变量。
iv. 实例变量没有手动赋值的时候,系统默认赋值。那么这个系统默认赋值时在什么时候完成的呢?是在类加载的时候吗?
不是,因为类加载的时候只加载了代码片段,还没来得及创建对象。所以此时实例变量并没有初始化。
实际上,实例变量的内存空间是在构造方法执行过程当中完成开辟的,完成初始化的。
系统在默认赋值的时候,也是在构造方法执行过程当中完成的赋值。
实例变量是存储在堆内存Java对象的内部。
- 查看访问的是哪个属性,哪个方法?
按ctrl键,鼠标移动到查看的元素上,出现下划线的时候单击
- 在一个类当中元素过多,想快速查看,在当前类中使用ctrl + o快捷键,然后输入要查找的元素名称,该名称不一定输入全名称。
1. 对象和引用的概念
a) 对象:目前在使用new运算符在堆内存中开辟的内存空间称为对象。
b) 引用:是一个变量,不一定是局部变量,还可能是成员变量,引用保存了内存地址,指向了堆内存当中的对象。
c) 所有访问实例相关的数据,都需要通过”引用.”的方式访问,因为只有通过引用才能找到对象。
d) 只有一个空的引用,访问对象的实例和相关的数据会出现空指针异常。
2. 参数的传递
主要研究和学习的是方法在调用的时候,涉及到参数传递的问题,到底是怎么传递数据的呢?
a) 方法调用时涉及到的参数传递,实际上传递的是变量中保存的具体值
b) 最终结论:
方法调用的时候涉及到参数传递的问题,传递的时候,java只遵循一种语法机制,就是将变量中保存的值传递过去了,只不过有的时候这个值是一个字面值,有的时候这个值时另一个java对象的内存地址
this关键字
- This是一个关键字,翻译为:这个
- This是一个引用,this是一个变量,this变量中保存了内存地址指向了自身,this存储在JVM堆内存java对象内部
- 每一个对象都有this
- This可以出现在实例方法当中,this指向当前正在执行这个动作的对象。
- This不能在带有static的方法中使用
重点:没有static关键字的方法被称为“实例方法”,通过“引用.”访问
重点:没有static关键字的变量被称为:实例变量
注意:但一个行为执行的过程当中是需要对象参与的,那么这个方法一定要定义为“实例方法”,不要带static关键字
最终结论:
在带有static的方法当中不能“直接”访问实例变量和实例方法
因为实例变量和实例方法都需要对象的存在
而static的方法当中是没有this的,也就是说当前对象是不存在的。
自然也是无法访问当前对象的实例变量和实例方法
This什么时候不能省略
- 用来区分局部变量和实例变量的时候
This可以用在哪里
- 可以用在实例方法当中,代表当前对象【语法格式:this.】
- 可以使用在构造方法当中,通过当前的构造方法调用其他的构造方法【语法格式:this(实参);】
重点:this()这种语法只能出现在构造方法的第一行。
带有static的方法,其实既可以采用类名的方式访问,也可以采用引用的方式访问
但是即使采用引用的方式访问,实际上执行的时候和引用指向的对象无关。
带有static的方法建议采用类名.方法的方式访问。
静态变量,静态变量在类加载的时候初始化,不需要创建对象,内存就开辟了
静态变量存储在方法区的内存中
什么时候成员变量声明为实例变量?
什么时候成员变量声明为静态变量?
静态变量在类加载的时候初始化,内存在方法区中开辟,访问的时候不需要创建对象,直接使用“类名.静态变量名”的方式访问。
1. package com.OOProjectnode;
2.
3. public class Chinese {
4. private String id;
5. private String name;
6. private static String Country = "中国";
7.
8. public String getId() {
9. return id;
10. }
11.
12. public void setId(String id) {
13. this.id = id;
14. }
15.
16. public String getName() {
17. return name;
18. }
19.
20. public void setName(String name) {
21. this.name = name;
22. }
23.
24. public static String getCountry() {
25. return Country;
26. }
27.
28. public static void setCountry(String country) {
29. Country = country;
30. }
31.
32. public Chinese(String id, String name) {
33. this.id = id;
34. this.name = name;
35. }
36.
37. public Chinese() {
38. this.id = null;
39. this.name = null;
40. }
41. }
1. package com.OOProjectnode;
2.
3. public class ChineseTest {
4.
5. public static void main(String[] args){
6. Chinese zhangsan = new Chinese("1", "张三");
7. System.out.println(zhangsan.getId()+ ","+zhangsan.getName()+","+Chinese.getCountry());
8.
9. Chinese lisi = new Chinese("2", "李四");
10. System.out.println(lisi.getId()+ ","+lisi.getName()+","+Chinese.getCountry());
11.
12. }
13. }
Static英语单词翻译为静态的
Static修饰的方法是静态方法
Static修饰的变量是静态变量
所有static修饰的元素都称为是静态的,都可以使用类名.的方式访问(也可以使用引用.的方式访问,但不建议)
Static修饰的所有元素都是类级别的特征,和具体的对象无关
可以使用static关键字来定义静态代码块:
语法格式:
static{
Java语句;
}
静态代码块在类加载时执行,并且只执行一次
静态代码块在一个类中可以编写多个,并且遵循自上而下的顺序依次执行
静态代码块的作用是什么?怎么用?用在哪?什么时候用?
通常在静态代码块当中完成预备工作,先完成数据的准备工作,例如:初始化连接池。解析XML配置文件……
1. package com.selflearning.statictest010;
2.
3. /**
4. * 可以使用static关键字来定义静态代码块:
5. * 1.语法格式:
6. * static{
7. * java语句;
8. * }
9. *
10. * 2.静态代码块在类加时执行,并且只执行一次
11. * 3.
12. */
13. public class StaticTest010 {
14.
15. static {
16. System.out.println("类加载-->1");
17. }
18. static {
19. System.out.println("类加载-->2");
20. }
21. static {
22. System.out.println("类加载-->3");
23. }
24.
25. public static void main(String[] args){
26. System.out.println("main begin");
27. }
28. }
实例语句块/代码块【了解内容,使用的非常少】
- 实例代码块可以缩写多个,也是遵循自上而下的顺序依次执行
- 实例代码块在构造方法执行之前执行,构造方法执行一次,实例代码块对应执行一次
- 实例代码块也是java语言程序员必备的一个特殊的时机,这个特殊的时机被称为:对象初始化时机
1. package com.selflearning.statictest010;
2.
3. public class StaticTest011 {
4.
5. //构造函数
6. public StaticTest011(){
7. System.out.println("StaticTest011的缺省构造方法");
8. }
9.
10. //实例代码块
11. {
12. System.out.println(1);
13. }
14.
15. //实例代码块
16. {
17. System.out.println(2);
18. }
19.
20. //实例代码块
21. {
22. System.out.println(3);
23. }
24.
25. public static void main(String[] args){
26. System.out.println("main begin");
27. new StaticTest011();
28. }
29. }
30. /*-----------------运行结果-----------------
31. main begin
32. 1
33. 2
34. 3
35. StaticTest011的缺省构造方法
36. * */
方法什么时候定义为静态的?
- 方法描述的是动作,当所有对象执行这个动作的时候,最终产生影响的是一样的,那么这个动作已经不再属于某个对象动作了,可以将这个动作提升为类级别的动作,模板级别的动作。
- 静态方法中无法直接访问实例变量和实例方法
- 大多数方法都定义为实例方法,一般一个行为或者一个动作在发生的时候,都需要对象的参与。但是也有例外,例如:大多数“工具类”中的方法都是静态方法,因为工具类就是方便编程的,为了方便方法的调用,自然不需要new对象是最好的。
- 继承是面向对象三大特征之一【封装,继承,多态】
- 继承基本的作用:
- 代码复用
- 方法的覆盖
- 多态机制
- 继承的语法格式:
[修饰符列表] class 类名 extends 父类名{
类体 = 属性 + 方法
}
- Java语言当中的继承只支持单继承,一个类不能同时继承很多类,只能继承一个类,在C++中支持多继承。
- 关于继承的一些术语:
- B类继承A类,其中:
- A类称为:父类,基类,超类,superclass
- B类称为:子类,派生类,subclass
- 在java语言当中,子类继承父类,都继承哪些数据?
- 私有的不支持继承
- 构造方法不支持继承
- 其他数据都可以被继承
- 虽然java语言当中只支持单继承,但是一个类也可以间接继承其他类,例如:
C extends B{}
B extends A{}
A extends T{}
C类直接继承B类,但是C类间接继承T、A类
- Java语言中假设一个类没有显示的继承任何类,该类默认继承JavaSE库当中提供的java.lang.Object类
Java语言中任何一个类中都有Object类的特征
- 快捷键:
- Idea中查找类型: Ctrl + Shift + Alt + N
- Eclipse查找类型: Ctrl + Shift + T
1. package com.selflearning.c04_inherit;
2.
3. public class Account {
4. private String actno;
5. private double balance;
6.
7. public String getActno() {
8. return actno;
9. }
10.
11. public void setActno(String actno) {
12. this.actno = actno;
13. }
14.
15. public double getBalance() {
16. return balance;
17. }
18.
19. public void setBalance(double balance) {
20. this.balance = balance;
21. }
22.
23. public Account(String actno, double balance) {
24. this.actno = actno;
25. this.balance = balance;
26. }
27.
28. public Account() {
29. }
30. }
1. package com.selflearning.c04_inherit;
2.
3. //信用账户
4. public class CreditAccount extends Account{
5.
6. private double credit;
7.
8. public CreditAccount(){
9. super();
10. }
11.
12. public double getCredit() {
13. return credit;
14. }
15.
16. public void setCredit(double credit) {
17. this.credit = credit;
18. }
19. }
1. package com.selflearning.c04_inherit;
2.
3. public class ExtednsTest {
4. public static void main(String[] args) {
5. ExtednsTest et = new ExtednsTest();
6. String s = et.toString(); //这里编译通过了。这说明可以调用toString方法,
7. // ExetendsTest类中有toString方法,从Object类中继承过来的。
8. System.out.println(s); //com.selflearning.c04_inherit.ExtednsTest@10f87f48
9.
10. CreditAccount act = new CreditAccount();
11. act.setActno("act-001");
12. act.setBalance(-1000.0);
13. act.setCredit(0.99);
14.
15. System.out.println(act.getCredit() + " " + act.getBalance() + " " + act.getActno());
16. }
17. }
1. package com.selflearning.c04_inherit;
2.
3. public class ExtendsTest02 {
4. public static void main(String[] args) {
5. C c = new C();
6. c.doSome(); //这里调用的doSome方法是从B类中继承过来的doSome方法
7.
8. }
9. }
10.
11. class A{
12. public void doSome(){
13. System.out.println("do some!");
14. }
15. }
16.
17. class B extends A{
18.
19. }
20.
21. class C extends B{
22.
23. }
1. package com.selflearning.C05_methodCoverage;
2.
3. public class Animal {
4.
5. public void move(){
6. System.out.println("动物在移动");
7. }
8. }
1. package com.selflearning.C05_methodCoverage;
2.
3. public class Cat extends Animal{
4. public void move(){
5. System.out.println("猫在走猫步");
6. }
7. }
1. package com.selflearning.C05_methodCoverage;
2.
3. public class Bird extends Animal {
4. public void move(){
5. System.out.println("鸟儿在飞翔");
6. }
7. }
1. package com.selflearning.C05_methodCoverage;
2.
3. public class YingWu extends Bird{
4.
5. //这里的move()方法,覆盖的是Bird当中的move()方法
6. @Override
7. public void move() {
8. System.out.println("鹦鹉飞不起来");
9. }
10. }
1. package com.selflearning.C05_methodCoverage;
2.
3. /*
4. * 回顾java语言当中方法的重载:
5. * 1.方法重载又称为Overload
6. * 2.方法重载什么时候使用?
7. * 当在同一个类当中,方法完成的功能是相似的,建议方法名相同,这样方便程序员的编程,就像在调用一个方法似的,代码美观
8. * 3.什么条件满足之后构成方法重载?
9. * - 在同一个类当中
10. * - 方法名相同
11. * - 参数列表不同:类型/顺序/个数
12. * 4.方法重载和什么无关?
13. * - 和方法的返回值类型无关
14. * - 和方法的修饰符列表无关
15. * */
16.
17. public class OverrideTest01 {
18. public static void main(String[] args) {
19. Animal a = new Animal();
20. a.move();
21.
22. Cat c = new Cat();
23. c.move();
24.
25. Bird b = new Bird();
26. b.move();
27.
28. YingWu y = new YingWu();
29. y.move();
30. }
31. }
32.
33. /**
34. * ----------------------运行结果----------------------
35. * 动物在移动
36. * 猫在走猫步
37. * 鸟儿在飞翔
38. * 鹦鹉飞不起来
39. * */
1. package com.selflearning.C06_Polymorphism;
2.
3. public class Animal {
4.
5. public void move(){
6. System.out.println("动物在移动");
7. }
8. }
1. package com.selflearning.C06_Polymorphism;
2.
3. public class Bird extends Animal {
4.
5. //重写从父类中继承过来的方法
6. public void move(){
7. System.out.println("鸟儿在飞翔");
8. }
9. }
1. package com.selflearning.C06_Polymorphism;
2.
3. public class Cat extends Animal {
4.
5. //重写父类中继承过来的方法
6. public void move(){
7. System.out.println("猫在走猫步");
8. }
9.
10. //不是从父类继承过来的方法
11. //这个方法是子类对象特有的行为【不是所有动物都能抓老鼠】
12. public void catchMouse(){
13. System.out.println("猫抓老鼠!");
14. }
15. }
1. package com.selflearning.C06_Polymorphism;
2.
3. public class Test01 {
4.
5. public static void main(String[] args) {
6.
7. Animal a1 = new Animal();
8. a1.move();
9.
10. Cat c1 = new Cat();
11. c1.catchMouse();
12. c1.move();
13.
14. Bird b1 = new Bird();
15. b1.move();
16.
17. //使用多态语法机制
18.
19. /**
20. * 1. Animal和Cat之间存在继承关系,Animal是父类,Cat是子类
21. *
22. * 2.new Cat()创建的对象的类型是Cat,a2这个引用的数据类型是Animal,可见它们进行了类型转换
23. * 子类型转换成父类型,称为向上转型/upcasting,或者称为自动类型转换
24. *
25. * 3.java中允许这种语法:父类型引用指向子类型对象
26. * */
27. Animal a2 = new Cat();
28.
29. /**
30. * 1.程序永远都分为编译阶段和运行阶段
31. *
32. * 2.先分析编译阶段,在分析运行阶段,编译无法通过,根本是无法运行的
33. *
34. * 3.编译阶段编译器检查a2这个引用的数据类型是Animal,
35. * 由于Animal.class字节码当中有move()方法,所以编译通过了。
36. * 这个过程我们称为静态绑定,编译阶段绑定。只有静态绑定成功之后才有后续运行。
37. *
38. * 4.在程序运行阶段,JVM堆内存当中真实创建的对象是Cat对象,
39. * 那么以下程序在运行阶段一定会调用Cat对象的move()方法,
40. * 此时发生了程序的动态绑定,运行阶段绑定。
41. *
42. * 5.无论是Cat类有没有重写move方法,运行阶段一定调用的是Cat对象的move方法,因为底层真实对象就是Cat对象
43. *
44. * 6.父类型引用指向子类型对象这种机制导致程序存在编译阶段绑定和运行阶段绑定两种不同的形态/状态
45. * 这种机制可以成为一种多态语法机制。
46. * */
47. a2.move(); //猫在走猫步
48.
49. /**
50. * 以下程序为什么不能调用?
51. * 因为编译阶段编译器检查到a2的类型是Animal类型,
52. * 从Animal.class字节码文件当中查找catchMouse()方法,
53. * 最终没有找到该方法,导致静态绑定失败,没有绑定成功
54. * 也就是说编译失败了,无法运行。
55. * */
56. //a2.catchMouse();
57.
58. /**
59. *
60. * */
61. }
62. }
63. /* ----------------- 运行结果 -----------------
64. 动物在移动
65. 猫抓老鼠!
66. 猫在走猫步
67. 鸟儿在飞翔
68. 猫在走猫步
69. * ----------------- 运行结果 -----------------*/
多态在实际开发中的作用
核心:面向抽象编程,尽量不要面向具体编程
1. package com.selflearning.C06_Polymorphism.test02;
2.
3. /**
4. * 1.分析:主人喂养宠物这个场景要实现需要进行类型的抽象:
5. * - 主人【类】
6. * - 主人可以喂养宠物,所以主人有喂养的动作
7. * - 宠物【类】
8. * - 宠物可以吃东西,所以宠物有吃东西的动作
9. *
10. * 2.定义好类,然后将类实例化为对象,给一个环境驱使以下,让各个对象之间协作起来形成一个系统
11. */
12.
13. public class Test01 {
14. public static void main(String[] args) {
15.
16. //创建主人对象
17. Master zhangsan = new Master();
18. /*
19. //创建猫对象
20. Cat tom = new Cat();
21. //主人喂养猫
22. zhangsan.feed(tom);
23.
24. Dog erHa = new Dog();
25. zhangsan.feed(erHa);
26.
27. */
28. zhangsan.feed(new Cat());
29. zhangsan.feed(new Dog());
30. Snake mangShe = new Snake();
31. zhangsan.feed(mangShe);
32.
33. }
34. }
35. /* ------------------- 运行结果 -------------------
36. 小猫正在吃鱼!
37. 小狗正在啃骨头!
38. 蛇吞象!
39. ------------------- 运行结果 ------------------- */
1. package com.selflearning.C06_Polymorphism.test02;
2.
3. //这种方式没有使用java语言当中的多态机制
4. // 存在缺点:Master的扩展力差,因为只要加一个新的宠物,Master类就需要添加新的方法。
5. /*
6. public class Master {
7.
8. public void feed(Cat c){
9. c.eat();
10. }
11.
12. public void feed(Dog d){
13. d.eat();
14. }
15. }
16. */
17.
18. //降低程序的耦合度【解耦合】,提高程序的扩展力【软件开发的一个很重要的目标】
19. public class Master{
20.
21. //Master著人类面向的是一个抽象的Pet,不再面向具体的宠物
22. //提倡:面向抽象编程,不要面向具体编程
23. //面向抽象编程的好处:耦合度低,扩展力强
24. public void feed(Pet pet){
25. pet.eat();
26. }
27.
28. }
1. package com.selflearning.C06_Polymorphism.test02;
2.
3. public class Pet {
4. public void eat(){}
5. }
1. package com.selflearning.C06_Polymorphism.test02;
2.
3. public class Cat extends Pet {
4. public void eat(){
5. System.out.println("小猫正在吃鱼!");
6. }
7. }
1. package com.selflearning.C06_Polymorphism.test02;
2.
3. public class Dog extends Pet {
4. public void eat(){
5. System.out.println("小狗正在啃骨头!");
6. }
7. }
1. package com.selflearning.C06_Polymorphism.test02;
2.
3. public class Snake extends Pet {
4. public void eat(){
5. System.out.println("蛇吞象!");
6. }
7. }
1. 关于java语言当中的包机制:
a) 包又称为package,java中引用package这种语法机制主要是为了方便程序的管理。不同功能的类被分门别类放到不同的软件包当中,查找比较方便,管理比较方便,易维护。
b) 如何定义package?
i. 在java源程序的第一行上编写package语句。
ii. Package只能编写一个语句。
iii. 语法结构:
1. Package 报名;
c) 包名的命名规范:
i. 公司的域名倒叙 + 项目名 + 模块名 + 功能名
ii. 主要采用这种方式,重名的机率较低,因为公司域名具有全球唯一性
iii. 例如:
1. com.bjpowernode.oa.user.service
2. org.apache.tomact.core;
d) 包名要求全部小写,包名也是标识符,必须遵守标识符的命名规则
e) 一个包将来对应的是一个目录
f) 使用了package之后如何编译运行?
i. 使用了package机制之后,类名不再是test03了,类名是:com.szkjdx.javase.packagestudy.test03
ii. 编译:javac java源文件路径 (在硬盘上生成一个class文件:test03.class)
iii. 手动方式创建目录,将test03.class字节码文件放到指定的目录下
iv. 运行:java com.szkjdx.javase.packagestudy.test03
v. 另一种方式:编译 + 运行
1. Javac -d 编译之后存放路径 java源文件的路径
2. 例如:将F:\Hello.java文件编译之后放到C:\目录下
Java -d c:\ F:\Hello.java
3. Java -d . *.java
将当前路径中*.java编译之后存放到当前目录下
4. 运行:JVM的类加载器ClassLoader默认从当前路径下加载
a) 保证DOS命令窗口的路径先切换到com所在的路径,执行:
Java com.szkjdx.javase.packagestudy.test01
b)
2. Import语句来完成导入其他类,同一个包下的类不需要导入,不在同一个包下需要手动导入。
a) Import语法格式:
Import 类名;
Import 包名.*;
b) Import语句需要编写在package语句之下,class语句之上
c) Java.lang.*不需要手动引入,系统自动引入。
Lang:language语言包,是java语言的核心类,不需要手动引入
d) 最终结论:
什么时候需要import?
不是java.lang包下,并且不在同一个包下的时候,需要使用import进行引入
e) Eclipse导入类的快捷键:Ctrl + Shift + O
访问控制权限修饰符:
名称 | 访问范围 |
Public | 表示公开的,在任何位置都可以访问 |
Protected | 同包下、子类中可以访问 |
缺省 | 同包下可以访问 |
Private | 表示私有的,只能在本类中访问 |
Private < 缺省 < protected < public
1. package com.sust.cst.javase.selflearning.c09_accessControlPermission.t01;
2.
3. public class Test01 {
4. public static void main(String[] args) {
5. User u = new User();
6. System.out.println(u.i);
7. System.out.println(u.j);
8. }
9. }
1. package com.sust.cst.javase.selflearning.c09_accessControlPermission.t01;
2.
3. public class User {
4.
5. //受保护的
6. protected int i = 10;
7.
8. //缺省的
9. int j = 20;
10. }
1. package com.sust.cst.javase.selflearning.c09_accessControlPermission.t02;
2.
3. import com.sust.cst.javase.selflearning.c09_accessControlPermission.t01.User;
4.
5. public class Driver extends User {
6. public void m(){
7. System.out.println(this.i);
8. //System.out.println(this.j);
9. }
10. }
1. package com.sust.cst.javase.selflearning.c09_accessControlPermission.t02;
2.
3. import com.sust.cst.javase.selflearning.c09_accessControlPermission.t01.User;
4.
5. public class UserTest {
6. public static void main(String[] args) {
7. User u = new User();
8. //System.out.println(u.i);
9. //System.out.println(u.j);
10. }
11. }
设计模式:可以重复利用的解决方案
单例模式是23种设计模式中最简单的一种设计模式
为了解决什么问题?
为了保证JVM中某一个类型的java对象永远只有一个。
为了节省内存的开销
实现单例模式三要素:
设计模式从结构上分为三类:创建型、结构性、行为型
单例模式为创建型设计模式
单例模式分为两种:
特点:在类加载阶段就创建了对象
特点:用到对象的时候才会创建对象
1. package com.sust.cst.javase.selflearning.c10_Singleton;
2.
3. public class User {
4. }
1. package com.sust.cst.javase.selflearning.c10_Singleton;
2. /*
3. 实现单例模式
4. * */
5. public class Singleton {
6.
7. //静态变量
8. private static Singleton s;
9.
10. //将构造方法私有化
11. private Singleton(){}
12.
13. //对外提供一个公开的获取Singleton对象的方法
14. public static Singleton getInstance(){
15.
16. if(s == null){
17. s = new Singleton();
18. }
19.
20. return s;
21. }
22. }
1. package com.sust.cst.javase.selflearning.c10_Singleton;
2.
3. /*
4. 饿汉式单例模式
5. */
6. public class Custormer {
7.
8. //类加载只执行一次
9. private static Custormer c = new Custormer();
10.
11. //构造方法私有化
12. private Custormer(){}
13.
14. //提供公开的方法
15. public static Custormer getInstance(){
16.
17. return c;
18. }
19. }
1. package com.sust.cst.javase.selflearning.c10_Singleton;
2.
3. /*
4. 单例模式是23种设计模式种最简单的一种设计模式
5. */
6. public class UserTest {
7. public static void main(String[] args) {
8. User u1 = new User();
9. User u2 = new User();
10.
11.
12. //==两边如果是基本数据类型,可以比较两个基本数据类型是否相等
13. //==两边如果是引用数据类型,则比较的是内存地址。
14. System.out.println(u1 == u2); //false
15.
16. Singleton s1 = Singleton.getInstance();
17. Singleton s2 = Singleton.getInstance();
18. System.out.println(s1 == s2); //true
19.
20. Custormer c1 = Custormer.getInstance();
21. Custormer c2 = Custormer.getInstance();
22. System.out.println(c1 == c2); //true
23. }
24. }
1. package com.sust.cst.javase.selflearning.c11_super;
2.
3. public class Employee {
4.
5. String name = "张三";
6. public void work(){
7. System.out.println("员工在工作");
8. }
9. }
1. package com.sust.cst.javase.selflearning.c11_super;
2.
3. public class Manager extends Employee {
4.
5. String name = "李四";
6.
7. //子类将父类中的work方法重写了
8. @Override
9. public void work() {
10. System.out.println("经理在工作");
11. }
12.
13. public void m1(){
14. //this.work();
15. work();
16. super.work();
17.
18. System.out.println(this.name);
19. System.out.println(super.name);
20. }
21.
22. //super和this相同,都不能用在静态上下文中
23. public static void m2(){
24. //System.out.println(super.name);
25. }
26. }
1. package com.sust.cst.javase.selflearning.c11_super;
2.
3. public class Test01 {
4. public static void main(String[] args) {
5. Manager m = new Manager();
6.
7. m.m1();
8. }
9. }
1. package com.sust.cst.javase.selflearning.c11_super;
2.
3. public class Account {
4. //
5. private String actno;
6. private double balance;
7.
8. public String getActno() {
9. return actno;
10. }
11.
12. public void setActno(String actno) {
13. this.actno = actno;
14. }
15.
16. public double getBalance() {
17. return balance;
18. }
19.
20. public void setBalance(double balance) {
21. this.balance = balance;
22. }
23.
24. public Account(String actno, double balance) {
25. this.actno = actno;
26. this.balance = balance;
27. }
28.
29. public Account() {
30. System.out.println("Account的无参数构造方法执行!");
31. }
32. }
1. package com.sust.cst.javase.selflearning.c11_super;
2.
3. public class DebitAccount extends Account {
4.
5. private double debit;
6.
7. public DebitAccount(String actno, double balance, double debit) {
8.
9. //通过子类的构造方法去调用父类的构造方法,作用是:给当前子类对象中的父类型特征赋值
10. super(actno, balance);
11. this.debit = debit;
12. }
13.
14. public DebitAccount() {
15. //super();
16. //super("001", 1000.1);
17. }
18.
19. public double getDebit() {
20. return debit;
21. }
22.
23. public void setDebit(double debit) {
24. this.debit = debit;
25. }
26. }
1. package com.sust.cst.javase.selflearning.c11_super;
2.
3. public class Test02 {
4. public static void main(String[] args) {
5. DebitAccount da = new DebitAccount();
6. }
7. }
class关键字前加abstract
抽象方法的语法:在方法的修饰符列表中加abstract关键字,并且抽象方法应该以“;”来结束,不能带有“{}“
例:public abstract void m1();
1. package com.sust.cst.javase.selflearning.c12_abstract;
2.
3. public abstract class A {
4.
5. A(){
6. System.out.println("A...");
7. }
8.
9. public abstract void m1();
10.
11. public static void main(String[] args) {
12.
13. A a = new B();
14.
15. //抽象类无法创建对象
16. //A a = new A();
17. }
18. }
19.
20. class B extends A{
21. B(){
22. super(); //父类的构造方法虽然调用了,但是没有创建父类对象
23. System.out.println("B...");
24. }
25.
26. @Override
27. public void m1() {
28.
29. }
30. }
接口也是一种引用类型,可以等同看作类
[修饰符] interface 接口名{}
1. package com.sust.cst.javase.selflearning.c13_interface;
2.
3. public interface A {
4.
5. //常量(必须用public static final修饰)
6. public static final String SUCCESS = "success";
7. public static final double PI = 3.1415926;
8.
9. //public static final 是可以省略的
10. byte MAX_VALUE = 120;
11.
12. //抽象方法 接口中所有的抽象方法都是public abstract
13. public abstract void m1();
14.
15. //public abstract 是可以省略的
16. void m2();
17. }
18.
19. interface B {
20. void m1();
21. }
22.
23. interface C {
24. void m2();
25. }
26.
27. interface D {
28. void m3();
29. }
30.
31. interface E extends B,C,D{
32. void m4();
33. }
34.
35. //implements是实现的意思,是以恶搞关键字
36. //implements和extends意义相同
37. class MyClass implements B,C{
38.
39. @Override
40. public void m1() {
41.
42. }
43.
44. @Override
45. public void m2() {
46.
47. }
48. }
49.
50. class F implements E{
51.
52. @Override
53. public void m1() {
54.
55. }
56.
57. @Override
58. public void m2() {
59.
60. }
61.
62. @Override
63. public void m3() {
64.
65. }
66.
67. @Override
68. public void m4() {
69.
70. }
71. }
- 接口的作用
- 可以使项目分层,所有层都面向接口开发,开发效率提高了
- 可以使代码和代码之间的耦合度降低,使项目变得可插拔,可以随意切换
- 如何选择接口还是抽象类?
- 如果抽象类和接口都能实现功能,则优先选择接口
- 接口可以多实现,多继承
- 一个类除了实现接口外,还可以去继承其他类(保留了类的继承)
- 接口可以多继承,一个类可以实现多个接口,抽象类的类和类之间只能实现单继承
- 抽象类可以半抽象,接口完全抽象
- 最好面向抽象编程,可以使项目的可扩展能力增强
1. package com.sust.cst.javase.selflearning.c13_interface.Car;
2.
3. /*
4. 汽车和发动机之间的接口
5. 生产汽车的厂家面向接口生产
6. 生产发动机的厂家面向接口生产
7. */
8.
9. public interface Engine {
10. void start();
11. }
1. package com.sust.cst.javase.selflearning.c13_interface.Car;
2.
3. public class Car {
4.
5. //引擎
6. //面向接口编程
7. Engine e;
8.
9. //Constructor
10. Car(Engine e){
11. this.e = e;
12. }
13.
14. //汽车能够测试引擎
15. public void testEngine(){
16. e.start();//面向接口调用
17. }
18. }
1. package com.sust.cst.javase.selflearning.c13_interface.Car;
2.
3. public class HONDA implements Engine{
4.
5. @Override
6. public void start() {
7. System.out.println("HONDA启动");
8. }
9. }
1. package com.sust.cst.javase.selflearning.c13_interface.Car;
2.
3. public class YAMAHA implements Engine{
4. @Override
5. public void start() {
6. System.out.println("YAMAHA 启动");
7. }
8. }
1. package com.sust.cst.javase.selflearning.c13_interface.Car;
2.
3. public class Test {
4. public static void main(String[] args) {
5. //1.生产引擎
6. Engine e1 = new YAMAHA();
7. //2.生产汽车
9. Car c1 = new Car(e1);
10.
11. //3.测试引擎
12. c1.testEngine();
13.
14. //换HONDA
15. c1.e = new HONDA();
16. c1.testEngine();
17. }
18. }
toString(); *
SUN在Object类中设计toString方法的目的:返回java对象的字符串表示形式
在现实的开发过程中,Object里边的toString方法已经不够用了,因为Object的toString方法实现的结果不满意
Object中的toSting方法就是要被重写的
SUN实现的toString方法
1. public String toString() { 2. return getClass().getName() + "@" + Integer.toHexString(hashCode()); 3. }
Object中的toString方法返回:类名@java对象在内存中的地址经过哈希算法的出的int类型值再转换成十六进制。
这个输出结果可以等同看作java对象在堆中的内存地址
public boolean equals(Object obj); *
Object中的equals方法:
public boolean equals(Object obj) { return (this == obj); }
o1.equals(o2); o1是this,o2是obj
== 两边如果是引用类型,则比较内存地址,地址相同是true,反之则false
Object中的equals方法比较的是两个引用的内存地址
java对象中的equals方法的设计目的,是判断两个对象是否一样。
在java中比较两个字符串是否一致,不能用“==”
只能用String类的equals方法
1. package com.sust.cst.javase.selflearning.c14_Object.t02_equals; 2. 3. public class Test01 { 4. public static void main(String[] args) { 5. Object o1 = new Object(); 6. Object o2 = new Object(); 7. 8. boolean b1 = o1.equals(o2); 9. 10. System.out.println(b1); //false 11. 12. Star s1 = new Star("aaaa", 100); 13. Star s2 = new Star("aaaa", 100); 14. Star s3 = new Star("aaaa", 110); 15. 16. System.out.println(s1.equals(s2)); //true 17. System.out.println(s2.equals(s3)); //false 18. } 19. } 20. 21. class Star{ 22. String name; 23. int id; 24. 25. public Star(String name, int id) { 26. this.name = name; 27. this.id = id; 28. } 29. 30. //Object中的equals方法比较的是内存地址, 31. //在现实的业务逻辑当中不应该比较内存地址,应该比较内容 32. //所以Object中的equals方法也需要重写 33. //根据需求规定重写equals方法,需求规定:如果身份证号一致,并且名字也一致,则代表同一个人 34. //s1.equals(s2); 35. @Override 36. public boolean equals(Object obj) { 37. 38. if(this == obj) 39. return true; 40. 41. if(obj instanceof Star) { 42. Star s = (Star) obj; 43. 44. if (this.id == s.id) { 45. if (this.name.equals(s.name)) 46. return true; 47. } 48. } 49. return false; 50. } 51. }
1. package com.sust.cst.javase.selflearning.c14_Object.t02_equals; 2. 3. public class Test02 { 4. public static void main(String[] args) { 5. String s1 = new String("ABC"); 6. String s2 = new String("ABC"); 7. 8. System.out.println(s1 == s2); //false 9. 10. //String已经重写了equals 11. System.out.println(s1.equals(s2)); //true 12. } 13. }
finalize();
垃圾回收器(GC,Garbage Collection)
finalize方法什么时候调用?
- finalize方法每个java对象都有
- finalize方法不需要程序员去调用,由系统自动调用
- java对象如果没有更多的引用指向它,则该java对象成为垃圾数据,等待垃圾回收器的回收,垃圾回收器在回收这个java对象之前会自动调用该对象的finalize方法
finalize方法是该对象马上就要被回收了,例如:需要释放资源,则可以在该方法中释放
1. package com.sust.cst.javase.selflearning.c14_Object.t03_finalize; 2. 3. public class Test01 { 4. public static void main(String[] args) { 5. Person p1 = new Person(); 6. p1 = null;//没有引用再指向它,等待回收 7. 8. //程序员只能“建议”垃圾回收器回收垃圾 9. System.gc();//运行垃圾回收器 10. } 11. 12. static class Person{ 13. 14. //重写Object中的finalize方法 15. @Override 16. public void finalize() throws Throwable { 17. System.out.println(this + "马上就要被回收了!"); 18. //让一个引用再次重新指向这个对象,该对象不是垃圾数据,不会被垃圾回收器回收 19. Person p = this;//挽救这个对象 20. } 21. } 22. }
public native int hashCode();
1. package com.sust.cst.javase.selflearning.c14_Object.t04_hashCode; 2. 3. public class Test01 { 4. public static void main(String[] args) { 5. 6. //hashCode方法返回的是该对象的哈希码值 7. //java对象的内存地址经过哈希算法得出的int类型的数值 8. Test01 t = new Test01(); 9. 10. System.out.println(t.hashCode()); //284720968 11. } 12. }
clone();
创建并返回一个对象的副本,为了保证原数据的结构不被破坏
内部类的重要作用:可以访问外部类中的私有数据
1. package com.sust.cst.javase.selflearning.c15_internalClass.t01_staticInnerClass;
2.
3. public class OuterClass {
4.
5. //静态变量
6. static String s1 = "A";
7.
8. //成员变量
9. private String s2 = "B";
10.
11. //静态方法
12. private static void m1(){
13. System.out.println("static m1 method excute!");
14. }
15.
16. //成员方法
17. private void m2(){
18. System.out.println("m2 method excute!");
19. }
20.
21. //静态内部类
22. //可以用访问控制权限的修饰符修饰
23. //public protected private 缺省
24. static class InnerClass{
25.
26. //定义静态方法
27. public static void m3(){
28. System.out.println(s1);
29. m1();
30.
31. //System.out.println(s2);
32. //m2();
33. }
34.
35. //成员方法
36. public void m4(){
37. System.out.println(s1);
38. m1();
39.
40. //System.out.println(s2);
41. //m2();
42. }
43. }
44.
45. public static void main(String[] args) {
46.
47. //执行m3
48. OuterClass.InnerClass.m3();
49.
50. //执行m4
51. InnerClass innerClass = new OuterClass.InnerClass();
52. innerClass.m4();
53. }
54. }
1. package com.sust.cst.javase.selflearning.c15_internalClass.t02_memberInnerClass;
2.
3. public class OuterClass {
4.
5. //静态变量
6. static String s1 = "A";
7.
8. //成员变量
9. private String s2 = "B";
10.
11. //静态方法
12. private static void m1(){
13. System.out.println("static m1 method excute!");
14. }
15.
16. //成员方法
17. private void m2(){
18. System.out.println("m2 method excute!");
19. }
20.
21. //成员内部类
22. //可以用访问控制权限的修饰符修饰
23. //public protected private 缺省
24. class InnerClass{
25.
26. //不能定义静态方法
27. //public static void m3(){}
28.
29. //成员方法
30. public void m4(){
31. System.out.println(s1);
32. m1();
33.
34. //System.out.println(s2);
35. //m2();
36. }
37. }
38.
39. public static void main(String[] args) {
40.
41. //创建外部类对象
42. OuterClass outerClass = new OuterClass();
43.
44. InnerClass innerClass = outerClass.new InnerClass();
45.
46. innerClass.m4();
47. }
48. }
局部内部类 *
局部内部类等同于局部变量
重点:局部内部类再访问局部变量的时候,局部变量必须使用final修饰
1. package com.sust.cst.javase.selflearning.c15_internalClass.t03_localInnerClass;
2.
3. public class OuterClass {
4.
5. //方法
6. public void m1(){
7. //局部变量
8. final int i = 10;
9.
10. //局部内部类
11. //局部内部类不能用访问控制权限修饰符修饰
12. class InnerClass{
13.
14. //局部内部类中不能有静态声明
15. //public static void m1(){}
16.
17. //成员方法
18. public void m2(){
19. System.out.println(i); //10
20. }
21. }
22.
23. //m1方法执行 ...--> 10
24. //如果不加final,则不能更改i,否则会输出其他结果
25.
26. //只能在m1方法中调用m2
27. InnerClass innerClass = new InnerClass();
28. innerClass.m2();
29. }
30.
31. public static void main(String[] args) {
32. //InnerClass无法在外部创建对象
33.
34. OuterClass outerClass = new OuterClass();
35. outerClass.m1();
36. }
37. }
匿名内部类 *
指的是类没有名字
优点:少定义一个类
缺点:无法重复使用
1. package com.sust.cst.javase.selflearning.c15_internalClass.t04_anonymousInnerClass;
2.
3. public class Test01 {
4.
5. //静态方法
6. public static void test(CustomerService customerService){
7. customerService.logout();
8. }
9.
10. public static void main(String[] args) {
11.
12. //调用test方法
13. //方法1
14. // test(new CustomerServiceImpl());
15.
16. //方法2 使用匿名内部类的方式执行test方法
17. //整个"new CustomerService() {...}"就是一个匿名内部类
18. test(new CustomerService() {
19. @Override
20. public void logout() {
21. System.out.println("系统已经安全退出!");
22. }
23. });
24.
25. }
26.
27.
28. }
29.
30. //接口
31. interface CustomerService{
32.
33. //退出系统
34. void logout();
35. }
36.
37. //方法1:编写一个类实现CustomerService接口
38. /*class CustomerServiceImpl implements CustomerService{
39. public void logout(){
40. System.out.println("系统已经安全退出!");
41. }
42. }*/
泛化关系
类和类之间的继承关系以及接口与接口之间的继承关系
1. package com.sust.cst.javase.selflearning.c16_relationshipBetweenClassesAndClasses.t01_generalizationRelationship;
2.
3. public class A {
4. }
1. package com.sust.cst.javase.selflearning.c16_relationshipBetweenClassesAndClasses.t01_generalizationRelationship;
2.
3. //B继承A,A和B之间的关系称为泛化关系
4. public class B extends A {
5. }
1. package com.sust.cst.javase.selflearning.c16_relationshipBetweenClassesAndClasses.t01_generalizationRelationship;
2.
3. public interface C {
4. }
1. package com.sust.cst.javase.selflearning.c16_relationshipBetweenClassesAndClasses.t01_generalizationRelationship;
2.
3. //D和C两个接口之间继承也属于泛化关系
4. public interface D extends C {
5. }
类对接口的实现
1. package com.sust.cst.javase.selflearning.c16_relationshipBetweenClassesAndClasses.t02_realizeRelationship;
2.
3. public interface A {
4. void m1();
5. }
1. package com.sust.cst.javase.selflearning.c16_relationshipBetweenClassesAndClasses.t02_realizeRelationship;
2.
3. //B类实现了A接口,它们之间属于实现关系
4. public class B implements A{
5.
6. @Override
7. public void m1() {
8. System.out.println("实现关系");
9. }
10. }
类与类之间的连接,一个类可以知道另一个类的属性和方法,在java语言中使用成员变量体现
1. package com.sust.cst.javase.selflearning.c16_relationshipBetweenClassesAndClasses.t03_connectionRelation;
2.
3. public class Self {
4.
5. //Field
6. String name;
7.
8. //在当前类中含有其他类的引用
9. //在当前对象中含有指向其他对象的引用
10. //朋友
11. Friend f; //Self和Friend就是关联关系
12.
13. public Self(Friend f) {
14. this.f = f;
15. }
16. }
1. package com.sust.cst.javase.selflearning.c16_relationshipBetweenClassesAndClasses.t03_connectionRelation;
2.
3. public class Friend {
4.
5. String name;
6. String addr;
7. String tel;
8.
9. public Friend(String addr) {
10. this.addr = addr;
11. }
12. }
1. package com.sust.cst.javase.selflearning.c16_relationshipBetweenClassesAndClasses.t03_connectionRelation;
2.
3. import com.sust.cst.javase.selflearning.c11_super.Servlet;
4.
5. public class Test01 {
6. public static void main(String[] args) {
7. Friend f = new Friend("北京朝阳");
8.
9. //建立关联关系
10. Self me = new Self(f);
11.
12. //通过m可以获取朋友的住址
13. System.out.println(me.f.addr);
14. }
15. }
是关联关系的一种,是较强的关联关系,是整体和部分的关系,如: 汽车和轮胎,它与关联关系不同,关联关系的类处在同一个层次上,而聚合关系的类处在不平等的层次上,一个代表整体,一个代表部分,在java语言中使用实例变量体现。
整体不依赖部分,部分也不会依赖整体。
整体无法决定部分的生命周期。
1. package com.sust.cst.javase.selflearning.c16_relationshipBetweenClassesAndClasses.t04_aggregationRelationship;
2.
3. public class Student {
4. }
1. package com.sust.cst.javase.selflearning.c16_relationshipBetweenClassesAndClasses.t04_aggregationRelationship;
2.
3. import java.util.List;
4.
5. //Classroom就是整体,student就是部分
6. public class Classroom {
7.
8. //Classroom和List集合属于关联关系,在同一个层级上
9. //Classroom和Student属于聚合关系,一个是整体,一个是部分
10. List studentList;//studentList就是部分
11. }
12.
13. //集合:容器
比聚合关系强的关联关系,如:人和四肢,整体对象决定部分对象的生命周期,部分对象每一时刻只与一个对象发生合成关系,在java语言中使用实例变量体现。
1. package com.sust.cst.javase.selflearning.c16_relationshipBetweenClassesAndClasses.t05_syntheticRelationship;
2.
3. public class Limbs {
4. }
1. package com.sust.cst.javase.selflearning.c16_relationshipBetweenClassesAndClasses.t05_syntheticRelationship;
2.
3. import java.util.List;
4.
5. public class Human {
6.
7. //人和List是关联关系
8. //人和四肢是合成关系,人是整体,四肢是部分
9. //合成关系和聚合关系是相似的,
10. // 区别的地方在整体和部分是紧密相连的,整体生命周期决定部分的生命周期。
11. List limbsList;
12.
13. }
是比关联关系弱的关系,在java语言中体现为返回值,参数,局部变量和静态方法调用。
1. package com.sust.cst.javase.selflearning.c16_relationshipBetweenClassesAndClasses.t06_dependency;
2.
3. public class Test {
4.
5. public void m1() {
6. //局部变量
7. User u = new User();//依赖关系
8. }
9. }
10.
11. class User{}
is-a is-like-a has-a
- is-a
继承
- is-like-a
类和接口之间的实现关系
- has-a
关联关系
异常是什么?
NullPointerException e;
e是引用类型,e中保存的内存地址指向堆中的对象
这个对象一定是NullPointerException类型
这个对象就表示真实存在的异常事件
NullPointerException是一类异常
“抢劫”就是一类异常, à 类
张三被抢劫就是一个异常事件 à 对象
异常机制的作用
程序发生异常事件之后,为我们输出了详细的信息,程序员通过这个信息可以堆程序进行一些处理,使程序更加健壮
1. package com.sust.cst.javase.selflearning.c17_Exception;
2.
3. public class Test01 {
4. public static void main(String[] args) {
5. int a = 10;
6. int b = 0;
7. int c = a/b;
8.
9. /*
10. 以上程序编译通过了,但是运行时出现了异常,表示发生某个异常事件
11. JVM控制台输出如下信息:
12. Exception in thread "main" java.lang.ArithmeticException: / by zero
13. at com.sust.cst.javase.selflearning.c17_Exception.ExceptionTest01.main(ExceptionTest01.java:7)
14.
15. 本质:程序执行过程中发生了算数异常,JVM为我们创建了一个ArithmeticException类型的对象。
16. 并且这个对象中包含了详细的异常信息,并且JVM将这个对象中的信息输出到了控制台。
17. * */
18.
19. //上面的代码出现了异常,没有处理,下面的代码不会执行,直接退出JVM
20. System.out.println("hello world!");
21. }
22. }
1. package com.sust.cst.javase.selflearning.c17_Exception;
2.
3. public class Test02 {
4.
5. public static void main(String[] args) {
6. int a = 10;
7. int b = 0;
8.
9. if(b != 0) {
10. int c = a / b;
11. System.out.println(a + "/" + b + "=" + c);
12. }
13. else
14. System.out.println("除数不能为0");
15. }
16. }
处理异常有两种方式:
1. package com.sust.cst.javase.selflearning.c17_Exception;
2.
3. import java.io.*;
4.
5. //声明抛出
6. //在方法声明的位置上使用throws关键字向上抛出异常
7. public class Test03 {
8. //public static void main(String[] args) throws FileNotFoundException{
9. //public static void main(String[] args) throws IOException {
10. public static void main(String[] args) throws Exception{
11. /*
12. FileInputStream 输入流
13. 在java.io类中
14. 用于读取在硬盘中的文件
15. */
16.
17. //创建文件输入流,读取文件
18. //思考:java编译器使如何知道以下的代码执行过程中可能出现异常,
19. // java编译器使如何知道这个异常发生的机率比较高呢?
20. //java编译器不是那么智能,因为FileInputStream这个构造方法在声明的位置上使用了throws FileNotFoundException
21. FileInputStream fileInputStream = new FileInputStream("c:/ab.txt");
22.
23. /*以上程序编译不通过
24. Error:(16, 43) java: 未报告的异常错误java.io.FileNotFoundException; 必须对其进行捕获或声明以便抛出
25. */
26. }
27. }
1. package com.sust.cst.javase.selflearning.c17_Exception;
2.
3. import java.io.*;
4.
5. //深入throws
6. public class Test04 {
7. public static void main(String[] args) {
8.
9. //m1();
10.
11. //使用throws处理异常不是真正的处理异常而是推卸责任
12. //谁调用的就会抛给谁
13. //上面的m1方法如果出现了异常,因为采用的是上抛,给了JVM,JVM遇到了这个异常就会退出JVM,下面的代码不会执行
14. //System.out.println("hello world!");
15.
16. //真正处理
17. try {
18. m1();
19. } catch (Exception e) {
20. }
21.
22. System.out.println("hello world!");
23. }
24.
25. public static void m1() throws Exception {
26. m2();
27. }
28.
29. public static void m2() throws Exception {
30. m3();
31. }
32.
33. public static void m3() throws Exception {
34. new FileInputStream("c:/ab.txt");//FileInputStream构造方法声明位置上使用了throws
35. }
36. }
37.
38. //在程序运行过程中发生了FileNotFoundException类型的异常
39. //JVM为我们创建了一个FileNotFoundException类型的对象
40. //该对象中携带以下信息:
41. //JVM负责将该对象的信息打印到控制台
42. //并且JVM停掉了程序的运行。
43. /*
44. Exception in thread "main" java.io.FileNotFoundException: c:\ab.txt (系统找不到指定的文件。)
45. at java.base/java.io.FileInputStream.open0(Native Method)
46. at java.base/java.io.FileInputStream.open(FileInputStream.java:213)
47. at java.base/java.io.FileInputStream.(FileInputStream.java:155)
48. at java.base/java.io.FileInputStream.(FileInputStream.java:110)
49. at com.sust.cst.javase.selflearning.c17_Exception.Test04.m3(Test04.java:26)
50. at com.sust.cst.javase.selflearning.c17_Exception.Test04.m2(Test04.java:22)
51. at com.sust.cst.javase.selflearning.c17_Exception.Test04.m1(Test04.java:18)
52. at com.sust.cst.javase.selflearning.c17_Exception.Test04.main(Test04.java:9)
53. */
语法:
try{
可能出现异常的代码
}catch(异常类型1 异常变量){
处理异常的代码
}catch(异常类型2 变量){
处理异常的代码
}……
1. package com.sust.cst.javase.selflearning.c17_Exception;
2.
3. /*
4. 处理异常的第二种方式:捕捉
5. try...catch...
6. */
7.
8. import java.io.*;
9.
10. public class Test05 {
11. public static void main(String[] args) {
12.
13. //以下代码编译无法通过,因为FileNotFoundException没有被处理
14. /*try{
15. //FileNotFoundException
16. FileInputStream fileInputStream = new FileInputStream("c:/ab.txt");
17. }catch (ArithmeticException e){ //捕获的算数异常
18. }*/
19.
20. //编译通过
21. /*
22. try{
23. //FileNotFoundException
24. FileInputStream fileInputStream = new FileInputStream("c:/ab.txt");
25. }catch (FileNotFoundException e){
26. }
27. */
28. //以下程序编译无法通过
29. //因为还有更多的IOException没有处理
30. /*try{
31. //FileNotFoundException
32. FileInputStream fileInputStream = new FileInputStream("c:/ab.txt");
33. fileInputStream.read();
34. }catch (FileNotFoundException e){
35.
36. }*/
37.
38. //编译通过
39. try{
40. //FileNotFoundException
41. FileInputStream fileInputStream = new FileInputStream("c:/ab.txt");
42. fileInputStream.read();
43. }catch (FileNotFoundException e){
44.
45. }catch(IOException e){
46.
47. }
48.
49. //编译通过
50. //相对于上一种方法,这种方式处理异常比较模糊
51. /* try{
52. //FileNotFoundException
53. FileInputStream fileInputStream = new FileInputStream("c:/ab.txt");
54. fileInputStream.read();
55. }catch (IOException e){
56.
57. }
58. */
59. //编译无法通过
60. //catch可以写多个,但必须从上到下,从小到大
61. /*try{
62. //FileNotFoundException
63. FileInputStream fileInputStream = new FileInputStream("c:/ab.txt");
64. fileInputStream.read();
65. }catch (IOException e){
66.
67. }catch (FileNotFoundException e){
68.
69. }*/
70. }
71. }
1. package com.sust.cst.javase.selflearning.c17_Exception;
2.
3. import java.io.FileInputStream;
4. import java.io.FileNotFoundException;
5. import java.io.IOException;
6.
7. public class Test06 {
8. //编译无法通过
9. //IOException没有处理
10. /*public static void main(String[] args) throws FileNotFoundException {
11.
12. FileInputStream fileInputStream = new FileInputStream("abc");
13. fileInputStream.read();
14. }*/
15.
16. //通过
17. /*public static void main(String[] args) throws FileNotFoundException, IOException {
18. FileInputStream fileInputStream = new FileInputStream("abc");
19. fileInputStream.read();
20. }*/
21.
22. //通过
23. /*public static void main(String[] args) throws IOException {
24. FileInputStream fileInputStream = new FileInputStream("abc");
25. fileInputStream.read();
26. }
27. */
28.
29. public static void main(String[] args) {
30. try{
31. //程序执行到此处发生了FileNotFoundException类型的异常
32. //JVM会自动创建一个FileNotFoundException类型的对象,将该对象的内存地址赋值给catch语句块中的e变量
33. FileInputStream fileInputStream = new FileInputStream("abc");
34.
35. //上面的代码出现了异常,try语句块的代码不再继续执行,直接进入catch语句块中执行
36. System.out.println("Test");
37.
38. fileInputStream.read();
39. }catch (FileNotFoundException e){ //e内存地址指向堆中的那个对象是“FileNotFoundException”类型的事件
40. System.out.println("读取的文件不存在!");
41.
42. //FileNotFoundException将Object中的toString方法重写了
43. System.out.println(e);//java.io.FileNotFoundException: abc (系统找不到指定的文件。)
44. }catch (IOException e){
45. System.out.println(" 其他IO异常");
46. }
47.
48. System.out.println("ABC");
49.
50. }
51. }
1. package com.sust.cst.javase.selflearning.c17_Exception;
2.
3. import java.io.*;
4.
5. public class Test07 {
6. public static void main(String[] args) {
7. try{
8. FileInputStream fileInputStream = new FileInputStream("c:/abc.txt");
9.
10. //JVM为我们执行了以下代码
11. //FileNotFoundException e = new FileNotFoundException("c:\\abc.txt (系统找不到指定的文件。)");
12.
13. }catch (FileNotFoundException e){
14. //打印异常堆栈信息
15. //一般情况下都会使用该方式去调试程序
16. //该方法用的较多
17. //e.printStackTrace();
18.
19. /*
20. java.io.FileNotFoundException: c:\abc.txt (系统找不到指定的文件。)
21. at java.base/java.io.FileInputStream.open0(Native Method)
22. at java.base/java.io.FileInputStream.open(FileInputStream.java:213)
23. at java.base/java.io.FileInputStream.(FileInputStream.java:155)
24. at java.base/java.io.FileInputStream.(FileInputStream.java:110)
25. at com.sust.cst.javase.selflearning.c17_Exception.Test07.main(Test07.java:8)
26. */
27.
28. //这种方法用的较少,因为返回的信息太少
29. String msg = e.getMessage();
30. System.out.println(msg); //c:\abc.txt (系统找不到指定的文件。)
31. }
32.
33. //这段代码会执行
34. System.out.println("ABC");
35. }
36. }
1. package com.sust.cst.javase.selflearning.c17_Exception;
2.
3. import java.io.*;
4.
5. public class Test08 {
6.
7. public static void main(String[] args) throws Exception {
8.
9. /*try{
10. System.out.println("ABC");
11. return;
12. }finally {
13. System.out.println("Test finally");
14. }*/
15.
16. /*try{
17. FileInputStream fileInputStream = new FileInputStream("acv");
18.
19. //不会执行
20. System.out.println("tttt");
21. }finally {
22.
23. //会执行
24. System.out.println("Test finally 02");
25. }*/
26.
27. //只要在执行finally语句块之前退出了jvm,则finally语句块不会执行
28. try{
29. //退出JVM
30. System.exit(0);
31. }finally {
32.
33. //不会执行
34. System.out.println("Test finally 03");
35. }
36. }
37. }
1. package com.sust.cst.javase.selflearning.c17_Exception;
2.
3. public class Test09 {
4. public static void main(String[] args) {
5. int i = m1();
6. System.out.println(i); //10
7. }
8.
9. public static int m1(){
10.
11. int i = 10;
12.
13. try{
14. i = 10;
15. return i;
16. }finally {
17. i++;
18. System.out.println("m1()的i = " + i); //11
19. }
20.
21. //以上代码的执行原理
22. /*try{
23. int temp = i;
24. return temp;
25. }finally {
26. i++;
27. System.out.println("m1()的i = " + i);
28. }*/
29. }
30. }
1. package com.sust.cst.javase.selflearning.c17_Exception;
2.
3. import java.io.FileInputStream;
4. import java.io.FileNotFoundException;
5. import java.io.IOException;
6.
7. public class Test10 {
8.
9. public static void main(String[] args) {
10.
11. //必须在外部声明
12. FileInputStream fileInputStream = null;
13.
14. try{
15. fileInputStream = new FileInputStream("avb");
16. }catch(FileNotFoundException e){
17. e.printStackTrace();
18. }finally {
19.
20. //为了保证资源一定释放
21. if(fileInputStream != null){
22. try{
23. fileInputStream.close();
24. }catch(IOException e){
25. e.printStackTrace();
26. }
27. }
28. }
29.
30. }
31. }
如何手动抛出异常以及如何自定义异常
1. package com.sust.cst.javase.selflearning.c17_Exception.t03_customException;
2.
3. /*
4. 自定义无效名字异常
5. 1.编译时异常,直接继承Exception
6. 2.运行时异常,直接继承RuntimeException
7. */
8.
9. //public class IllegalNameException extends RuntimeException{ //运行时异常
10. public class IllegalNameException extends Exception{ //编译时异常
11.
12. //定义异常一般提供两个构造方法
13. public IllegalNameException(){}
14.
15. public IllegalNameException(String msg){
16. super(msg);
17. }
18. }
1. package com.sust.cst.javase.selflearning.c17_Exception.t03_customException;
2.
3. //客户相关的业务
4. public class CustomerService {
5.
6. //对外提供注册的方法
7. public void register(String name) throws IllegalNameException{
8.
9. //完成注册
10. if(name.length() < 6){
11. //异常
12. //创建异常对象
13. //IllegalNameException e = new IllegalNameException("用户名长度不能少于6位!");
14.
15. //手动抛出异常
16. //throw e;
17.
18. throw new IllegalNameException("用户名长度不能少于6位");
19. }
20.
21. //如果代码能执行到此处,说明用户名是合法的
22. System.out.println("注册成功");
23. }
24. }
1. package com.sust.cst.javase.selflearning.c17_Exception.t03_customException;
2.
3. /*
4. 模拟注册
5. */
6. public class Test01 {
7. public static void main(String[] args) throws IllegalNameException {
8.
9. //假如用户提供的用户名如下
10. String username = "aaaaaaa";
11.
12. //注册
13. CustomerService customerService = new CustomerService();
14.
15. try {
16. customerService.register(username);
17. } catch (IllegalNameException e) {
18. System.out.println(e.getMessage());
19. }
20. }
21. }
重写方法不能比被重写的方法抛出更宽泛的异常
1. package com.sust.cst.javase.selflearning.c17_Exception.t04_methodCoverageAndException;
2.
3. /*
4. 重写的方法不能比被重写的方法抛出更宽泛的异常
5. */
6.
7. import java.io.FileNotFoundException;
8. import java.io.IOException;
9.
10. public class Test11 {
11. }
12.
13. /*class A {
14. public void m1() {
15. }
16. }
17.
18. //子类永远无法抛出比父类更多的异常
19. class B extends A {
20. public void m1() throws Exception {
21. }
22. }*/
23.
24. class A{
25. //public void m1() throws FileNotFoundException{}
26. public void m1() throws IOException{}
27. }
28.
29. class B extends A{
30. //public void m1() throws IOException{}
31. public void m1() throws FileNotFoundException{}
32. }
数组是可以存储任意数据类型的元素
1. package com.sust.cst.javase.selflearning.c18_array;
2.
3. public class Test01 {
4. public static void main(String[] args) {
5. //声明一个一维数组,用来存储int类型
6. int[] a1 = {100, 200, 150, 3030}; //静态初始化一维数组
7.
8. //boolean类型的数组
9. boolean[] b1= {true, false};
10. //String类型数组
11. String[] str1 = {"ab", "cd", "ed"};
12.
13. char[] c1 = {'a', 'b', 'c'};
14.
15. //Object数组
16. Object o1 = new Object();
17. Object o2 = new Object();
18. Object o3 = new Object();
19.
20. Object[] objs = {o1, o2, o3};
21.
22. }
23. }
- 数组中存储元素的类型是统一的,每个元素在内存中所占空间大小是相同的,直到数组的首元素的内存地址,要查找的元素只要知道下标就可以快速计算出偏移量,通过内存地址快速定位该元素,所以数组查找元素的效率较高。
- 随机的对数组进行增删元素,当增加元素的时候,为了保证数组中元素在空间存储上是有序的,所以被添加元素位置后面的所有元素都要向后移动,删除元素也是,后面所有元素要向前移动,所以数组的增删元素的效率很低。
1. package com.sust.cst.javase.selflearning.c18_array;
2.
3. public class Test02 {
4. public static void main(String[] args) {
5. //静态初始化一个int类型的一维数组
6. int[] a1 = {1, 2, 3};
7.
8. //取得第一个元素
9. System.out.println("第一个元素" + a1[0]);
10. //取得最后一个元素
11. System.out.println("最后一个元素" + a1[a1.length-1]);
12.
13. //取得个数
14. System.out.println("数组中元素的个数:" + a1.length);
15.
16. //遍历一维数组
17. for(int i = 0; i < a1.length; i++){
18. System.out.println(a1[i]);
19. }
20.
21. //将第二个元素修改为100
22. a1[1] = 100;
23. System.out.println("------------------------------");
24. //遍历一维数组
25. for(int i = 0; i < a1.length; i++){
26. System.out.println(a1[i]);
27. }
28. }
29. }
动态初始化一维数组,会先在堆内存中分配这个数组,并且数组中每一个元素都采用默认值。
float,double 0.0
byte,short,int,long 0
boolean false
char \u0000
引用 null
1. package com.sust.cst.javase.selflearning.c18_array;
2.
3. public class Test03 {
4. public static void main(String[] args) {
5. //动态初始化一维数组
6.
7. //动态声明一个int类型的数组,最多可以存储4个元素
8. int[] a1 = new int[4];
9.
10. //遍历
11. for(int i = 0; i < a1.length; i++)
12. System.out.println(a1[i]);
13.
14. //赋值
15. a1[0] = 2;
16. a1[1] = 21;
17. a1[2] = 22;
18. a1[3] = 23;
19.
20. //遍历
21. for(int i = 0; i < a1.length; i++)
22. System.out.println(a1[i]);
23.
24. //引用类型的数组
25. Object[] objs = new Object[3];
26.
27. for(int i = 0; i < objs.length; i++){
28. Object o = objs[i];
29. //o.toString(); 注意空指针异常,因为引用类型的数组默认值是null
30. System.out.println(o);//null
31. }
32. }
33. }
34.
35. /* --------------- 运行结果 ---------------
36. 0
37. 0
38. 0
39. 0
40. 2
41. 21
42. 22
43. 23
44. null
45. null
46. null
47. --------------- 运行结果 --------------- */
48.
49. /*
50. public void println(Object x) {
51. String s = String.valueOf(x);
52. synchronized (this) {
53. print(s);
54. newLine();
55. }
56. }
57.
58. public static String valueOf(Object obj) {
59. return (obj == null) ? "null" : obj.toString();
60. }
61. */
1. package com.sust.cst.javase.selflearning.c18_array;
2. /*
3. 什么时候使用动态初始化,什么时候使用静态初始化?
4.
5. */
6. public class Test04 {
7. public static void main(String[] args) {
8. //以下两种方式都是可以的
9. int[] a1 = {1,2,3};
10. int a2[] = {2,3,5};
11.
12. int a3[] = new int[4];
13. }
14. }
1. package com.sust.cst.javase.selflearning.c18_array;
2.
3. import com.sust.cst.javase.selflearning.c07_final.finalTest01.A;
4.
5. /*
6. 深入一维数组
7. */
8. public class Test05 {
9. public static void main(String[] args) {
10.
11. //创建一个数组,这个数组既可以存储Dog也能存储Cat
12. Animal[] as = new Animal[4];
13.
14. //给数组每个元素赋值
15. Dog d1 = new Dog();
16. Dog d2 = new Dog();
17. Cat c1 = new Cat();
18. Cat c2 = new Cat();
19.
20. as[0] = d1;
21. as[1] = d2;
22. as[2] = c1;
23. as[3] = c2;
24.
25. //需求:遍历数组,取出每个对象,如果是Cat执行move方法;如果是Dog执行eat方法
26. for(int i = 0; i < as.length; i++){
27. Animal a = as[i];
28.
29. System.out.println(a);
30. //强制类型转换(向下转换)
31. if(a instanceof Cat){
32. Cat c = (Cat)a;
33. c.move();
34.
35. }else if(a instanceof Dog){
36. Dog d = (Dog)a;
37. d.eat();
38. }
39. }
40. }
41. }
42.
43. class Animal{}
44.
45. class Dog extends Animal{
46. public void eat(){
47. System.out.println("dog eat");
48. }
49.
50. @Override
51. public String toString() {
52. return "this is a dog";
53. }
54. }
55.
56. class Cat extends Animal{
57. public void move(){
58. System.out.println("cat move");
59. }
60.
61. @Override
62. public String toString() {
63. return "this is a cat";
64. }
65. }
66.
67. /* -------------------- 运行结果 --------------------
68. this is a dog
69. dog eat
70. this is a dog
71. dog eat
72. this is a cat
73. cat move
74. this is a cat
75. cat move
76. -------------------- 运行结果 -------------------- */
1. package com.sust.cst.javase.selflearning.c18_array;
2.
3. /*
4. 方法调用的时候也可以这样传递一个数组
5. */
6. public class Test06 {
7. public static void main(String[] args) {
8.
9. //第一种方式
10. int[] a = {12,3,3425,4,234};
11. m1(a);
12.
13. System.out.println();
14. System.out.println("------------------");
15. System.out.println();
16.
17. //*第二种方式*
18. m1(new int[]{21,3,2412,4,21,324,1});
19. }
20.
21. public static void m1(int[] a) {
22. for (int i = 0; i < a.length; i++)
23. System.out.println(a[i]);
24. }
25. }
26. /* ------------------ 运行结果 ------------------
27. 12
28. 3
29. 3425
30. 4
31. 234
32.
33. ------------------
34.
35. 21
36. 3
37. 2412
38. 4
39. 21
40. 324
41. 1
42.
43. ------------------ 运行结果 ------------------ */
JVM在调用Test07类的main方法之前,先将” abc cde fdaf”这个字符串以空格的方式分割,然后存储在String数组中
1. package com.sust.cst.javase.selflearning.c18_array;
2.
3. public class Test07 {
4.
5. //main方法中的String[]数组的设计主要是用来接收命令行的参数的
6. public static void main(String[] args) {
7. /*System.out.println("String类型的数组中元素的个数是:" + args.length);
8.
9. //遍历
10. for(int i = 0; i < args.length; i++)
11. System.out.println(args[i]);*/
12.
13. //需求:运行该软件的时候,必须提供用户名和密码
14. //格式:java Test07 username password
15. //如果用户没有提供足够的参数,则退出系统
16.
17. if(args.length != 2){
18. System.out.println("要想使用该系统,必须这样输入:");
19. System.out.println("java Test07 username password");
20. return;
21. }
22. //参数提供正确,如果用户名是admin,密码是123则登录成功
23. String usrname = args[0];
24. String pasword = args[1];
25.
26. //java中比较字符串是否相等,必须使用equals方法
27. //String类型是SUN提供,已经将equals方法重写了,比较的是内容
28. //if(usrname.equals("admin") && pasword.equals("123"))
29. if("admin".equals(usrname) && "123".equals(pasword)){//这种方式可以避免空指针异常
30. System.out.println("登录成功,欢迎" + usrname + "回来");
31. }else{
32. System.out.println("登录失败,用户名" + usrname + "不存在,或密码错误!");
33. }
34.
35. }
36. }
37.
38. /*
39. 在idea中,如何给main方法的参数args赋值?
40. 1.顶边栏选择 Run
41. 2.选择 Edit Confgurations
42. 3.找到 Program arguments,输入所需参数即可。
43. 注意:输入多个参数时,要用空格隔开参数
44. 4.参数配置完成,直接运行即可
45. */
46.
47. /* ------------ 运行结果 ------------
48. 登录成功,欢迎admin回来
49. ------------ 运行结果 ------------ */
1. package com.sust.cst.javase.selflearning.c18_array;
2.
3. public class Test08 {
4. public static void main(String[] args) {
5. //public static native void arraycopy(Object src, int srcPos,
6. // Object dest, int destPos,
7. // int length);
8. //System.arraycopy(源数组,源数组的开始下标,目标数组,目标数组的开始下标,拷贝的长度);
9.
10. int[] src = {2, 3, 4, 5, 6, 7, 8};
11. int[] dest = {10, 325, 432, 4, 34, 543};
12.
13. /*//把src中的4,5,6拷贝到dest数组中,从4开始
14. System.arraycopy(src, 2, dest, 3, 3);
15.
16. //遍历
17. for (int i = 0; i < dest.length; i++)
18. System.out.println(dest[i]);*/
19.
20. Test08 test08 = new Test08();
21.
22.
23. test08.arrayCopy(test08.a, 2, test08.b, 3, 3);
24. for (int i = 0; i < dest.length; i++)
25. System.out.println(test08.b[i]);
26. }
27.
28. public int[] a = {2, 3, 4, 5, 6, 7, 8};
29. public int[] b = {10, 325, 432, 4, 34, 543};
30.
31. public void arrayCopy(int[] a, int na, int[] b, int nb, int length) {
32. for (int i = nb, j = na; i < nb + length && j < na + length; i++, j++) {
33. b[i] = a[j];
34. }
35. }
36. }
37. /* -------------- 运行结果 --------------
38. 10
39. 325
40. 432
41. 4
42. 5
43. 6
44. -------------- 运行结果 -------------- */
1. package com.sust.cst.javase.selflearning.c18_array.t04_myStack;
2.
3. public class MyStack {
4. //使用数组存储数据
5. //栈可以存储多个引用类型的元素
6. private Object[] elements;
7.
8. //指向栈顶元素上方的一个帧
9. private int curlen;
10.
11. //栈默认的初始化容量是10
12. //Constructor
13.
14.
15. public MyStack() {
16. this(5);
17. }
18.
19. public MyStack(int max) {
20. elements = new Object[max];
21. curlen = 0;
22. }
23.
24. //栈应该对外提供压栈的方法
25. public void myPush(Object element) throws MyStackOperationException {
26. /*elements[curlen] = element;
27. curlen++;*/
28. if(curlen == elements.length){
29. //异常
30. throw new MyStackOperationException("栈已满");
31. }
32. elements[curlen++] = element;
33. }
34.
35. //栈应该对外提供弹栈的方法
36. public Object myPop() throws MyStackOperationException { //栈顶的元素往外弹
37. /* curlen--;
38. return elements[curlen];*/
39. if(curlen == 0){
40. throw new MyStackOperationException("栈已空");
41. }
42.
43. return elements[--curlen];
44. }
45. }
1. package com.sust.cst.javase.selflearning.c18_array.t04_myStack;
2.
3. public class MyStackOperationException extends Exception {
4. public MyStackOperationException(String message) {
5. super(message);
6. }
7.
8. public MyStackOperationException() {
9. }
10. }
1. package com.sust.cst.javase.selflearning.c18_array.t04_myStack;
2.
3. public class Test {
4. public static void main(String[] args) throws MyStackOperationException {
5. MyStack myStack = new MyStack();
6. User u1 = new User("Jack", 20);
7. User u2 = new User("Jbck", 21);
8. User u3 = new User("Jcck", 22);
9. User u4 = new User("Jdck", 23);
10. User u5 = new User("Jeck", 24);
11.
12. try{
13. myStack.myPush(u1);
14. myStack.myPush(u2);
15. myStack.myPush(u3);
16. myStack.myPush(u4);
17. myStack.myPush(u5);
18.
19. myStack.myPush(u5);
20. }catch (MyStackOperationException e){
21. e.printStackTrace();
22. }
23.
24. try{
25. //弹栈
26. for (int i = 0; i < 5; i++)
27. System.out.println(myStack.myPop());
28.
29. System.out.println(myStack.myPop());
30. }catch (MyStackOperationException e){
31. e.printStackTrace();
32. }
33. }
34. }
35.
36. class User {
37. String name;
38. int age;
39.
40. public User(String name, int age) {
41. this.name = name;
42. this.age = age;
43. }
44.
45. @Override
46. public String toString() {
47. return "User{" +
48. "name='" + name + '\'' +
49. ", age=" + age +
50. '}';
51. }
52. }
53.
54. /* ------------------------------ 运行结果 ------------------------------
55. com.sust.cst.javase.selflearning.c18_array.t04_myStack.MyStackOperationException: 栈已满
56. at com.sust.cst.javase.selflearning.c18_array.t04_myStack.MyStack.myPush(MyStack.java:30)
57. at com.sust.cst.javase.selflearning.c18_array.t04_myStack.Test.main(Test.java:18)
58. User{name='Jeck', age=24}
59. User{name='Jdck', age=23}
60. User{name='Jcck', age=22}
61. User{name='Jbck', age=21}
62. User{name='Jack', age=20}
63. com.sust.cst.javase.selflearning.c18_array.t04_myStack.MyStackOperationException: 栈已空
64. at com.sust.cst.javase.selflearning.c18_array.t04_myStack.MyStack.myPop(MyStack.java:40)
65. at com.sust.cst.javase.selflearning.c18_array.t04_myStack.Test.main(Test.java:27)
66. ------------------------------ 运行结果 ------------------------------ */
1. package com.sust.cst.javase.selflearning.c18_array.t03_TwoDimensionalArray;
2.
3. public class Test09 {
4.
5. public static void main(String[] args) {
6. //静态初始化二维数组
7. int[][] a = {
8. {1, 2, 3, 4},
9. {2, 34, 23, 532},
10. {3, 4, 54, 23, 523},
11. {332, 242, 676, 6867, 546, 98}
12. };
13.
14. //以上这个数组中有多少个一维数组?
15. System.out.println(a.length + "个一维数组");
16.
17. System.out.println("\n----------------------\n");
18.
19. //获取第一个一维数组
20. int[] a0 = a[0];
21.
22. //获取第一个一维数组中的第一个元素
23. int a00 = a0[0];
24. System.out.println(a00);
25. System.out.println(a[0][0]);
26.
27. System.out.println("\n----------------------\n");
28.
29. //获取最后一个一维数组中最后一个元素
30. System.out.println(a[3][5]);
31. System.out.println(a[a.length - 1][a[a.length - 1].length - 1]);
32.
33. System.out.println("\n----------------------\n");
34.
35. //遍历二维数组
36. for(int i= 0; i< a.length; i++){
37. for(int j = 0; j < a[i].length;j++)
38. System.out.print(a[i][j] + " ");
39. System.out.println();
40. }
41. }
42. }
43.
44. /* ---------------------- 运行结果 ----------------------
45. 4个一维数组
46.
47. ----------------------
48.
49. 1
50. 1
51.
52. ----------------------
53.
54. 98
55. 98
56.
57. ----------------------
58.
59. 1 2 3 4
60. 2 34 23 532
61. 3 4 54 23 523
62. 332 242 676 6867 546 98
63. ---------------------- 运行结果 ---------------------- */
1. package com.sust.cst.javase.selflearning.c18_array.t03_TwoDimensionalArray;
2.
3. public class Test10 {
4. public static void main(String[] args) {
5.
6. //3个一维数组
7. //每个一维数组中有4个元素
8. int[][] a = new int[3][4];
9.
10. //遍历
11. for(int i = 0; i< a.length;i++) {
12. for (int j = 0; j < a[i].length; j++)
13. System.out.print(a[i][j] + " ");
14.
15. System.out.println();
16. }
17.
18. System.out.println("\n----------------\n");
19.
20. //赋值
21. a[1][2] = 100;
22.
23. //遍历
24. for(int i = 0; i< a.length;i++) {
25. for (int j = 0; j < a[i].length; j++)
26. System.out.print(a[i][j] + " ");
27.
28. System.out.println();
29. }
30. }
31. }
32.
33. /* ---------------- 运行结果 ----------------
34. 0 0 0 0
35. 0 0 0 0
36. 0 0 0 0
37.
38. ----------------
39.
40. 0 0 0 0
41. 0 0 100 0
42. 0 0 0 0
43. ---------------- 运行结果 ---------------- */
1. package com.sust.cst.javase.selflearning.c18_array.t03_TwoDimensionalArray;
2.
3. public class Test11 {
4. public static void main(String[] args) {
5. m1(new int[][]{{1,23,4},{5,6,7,8},{10,9}});
6. }
7.
8. public static void m1(int[][] a){
9. for(int i = 0; i< a.length; i++){
10. for(int j = 0; j < a[i].length;j++)
11. System.out.print(a[i][j] + " ");
12. System.out.println();
13. }
14. }
15. }
16.
17. /* --------- 运行结果 ---------
18. 1 23 4
19. 5 6 7 8
20. 10 9
21. --------- 运行结果 --------- */
1. package com.sust.cst.javase.selflearning.c18_array.t04_sortAndFind;
2.
3. public class BubbleSort {
4. public static void main(String[] args) {
5. int[] a = {3, 1, 6, 2, 5};
6.
7. System.out.println("原始数组:");
8. display(a);
9. bubbleSort(a);
10. System.out.println("排序后的数组:");
11. display(a);
12. }
13.
14. public static int[] bubbleSort(int[] a){
15. for (int i = a.length - 1; i > 0; i--) {
16. for (int j = 0; j < i; j++) {
17. if (a[j] > a[j + 1]) {
18. int temp = a[j];
19. a[j] = a[j + 1];
20. a[j + 1] = temp;
21. }
22. }
23. }
24.
25. return a;
26. }
27.
28. public static void display(int[] a){
29. for (int i = 0; i < a.length; i++)
30. System.out.print(a[i] + " ");
31. System.out.println();
32. }
33. }
34.
35. /* -------------- 运行结果 --------------
36. 原始数组:
37. 3 1 6 2 5
38. 排序后的数组:
39. 1 2 3 5 6
40. -------------- 运行结果 --------------
找出最小值,然后这个最小值和最前面的数据交换位置
1. package com.sust.cst.javase.selflearning.c18_array.t04_sortAndFind;
2.
3. public class SelectSort {
4. public static void main(String[] args) {
5. int[] a = {3, 1, 6, 2, 5};
6.
7. System.out.println("原始数据为:");
8. display(a);
9. System.out.println("排序后的数据为:");
10. selectSort(a);
11. display(a);
12. }
13.
14. public static void selectSort(int[] a) {
15. for (int i = 0; i < a.length - 1; i++) {
16.
17. //假设第一个数据是最小值
18. //记录最小值元素的下标
19. int min = i;
20.
21. for (int j = i; j < a.length - 1; j++)
22. if (a[min] > a[j + 1])
23. min = j + 1;
24.
25. if (min != i) {
26. int temp = a[i];
27. a[i] = a[min];
28. a[min] = temp;
29. }
30. }
31.
32. }
33.
34. public static void display(int[] a) {
35. for (int i = 0; i < a.length; i++) {
36. System.out.print(a[i] + " ");
37. }
38. System.out.println();
39. }
40. }
41.
42. /* ------------- 运行结果 -------------
43. 原始数据为:
44. 3 1 6 2 5
45. 排序后的数据为:
46. 1 2 3 5 6
47. ------------- 运行结果 ------------- */
二分法查找
二分法查找是建立在已经排序的基础之上的
1. package com.sust.cst.javase.selflearning.c18_array.t04_sortAndFind;
2.
3. import java.util.Scanner;
4.
5. public class DichotomySearch {
6. public static void main(String[] args) {
7.
8. Scanner scanner = new Scanner(System.in);
9. int[] a = {1, 3, 4, 5, 7, 8, 9, 10, 23, 25, 36};
10. System.out.println("请输入要查找的数据:");
11. int destElement = scanner.nextInt();
12.
13. //要求从a数组中查找10这个元素的下标
14. int index = dichotomySearch(a, destElement);//如果找到则返回元素的下标,如果找不到,统一返回-1
15. String searchResult = (index != -1) ? (destElement + "在数组中的下标是:" + index) : ("这个元素不存在");
16.
17. System.out.println(searchResult);
18. }
19.
20. //折半查找
21. public static int dichotomySearch(int[] a, int x) {
22.
23. int index = -1;
24. int begin = 0;
25. int end = a.length - 1;
26.
27. while (begin <= end) {
28.
29. int mid = (begin + end) / 2;
30.
31. if (a[mid] == x) {
32. index = mid;
33. break;
34. }
35. else if (a[mid] > x) {
36. end = mid - 1;
37. } else if (a[mid] < x) {
38. begin = mid + 1;
39. }
40. }
41.
42. return index;
43. }
44. }
45.
46. /* --------------- 运行结果 ---------------
47. 输入数据:
48. 10
49. 运行结果:
50. 请输入要查找的数据:
51. 10
52. 10在数组中的下标是:7
53. 输入数据:
54. 100
55. 运行结果:
56. 请输入要查找的数据:
57. 100
58. 这个元素不存在
59. --------------- 运行结果 --------------- */
java.util.Arrays
1. package com.sust.cst.javase.selflearning.c18_array.t04_sortAndFind;
2.
3. import java.util.Arrays;
4. import java.util.List;
5.
6. public class ArraysTest01 {
7. public static void main(String[] args) {
8.
9. int[] a = {3, 1, 6, 4, 7, 5, 3, 2, 8, 10, 123, 43, 5, 34};
10. int[] b = {3, 1, 6, 4, 7, 6, 3, 2, 8, 10, 123};
11.
12. System.out.println("a[] = " + Arrays.toString(a));
13. System.out.println("b[] = " + Arrays.toString(b));
14.
15. int compareIndex = Arrays.compare(a, b);
16. System.out.println(compareIndex);
17.
18. //复制指定的数组,截断或填充零(如果需要),以便副本具有指定的长度。
19. int[] c = Arrays.copyOf(a, 20);
20. System.out.println("c[] = " + Arrays.toString(c));
21. c = Arrays.copyOf(a, 5);
22. System.out.println("c[] = " + Arrays.toString(c));
23.
24. //找到并返回两个数组中第一个不一样的数据的下标
25. int mismatchIndex = Arrays.mismatch(a, b);
26. System.out.println("两个数组中第一个不一样的数据的下标为:" + mismatchIndex);
27.
28. //排序
29. Arrays.sort(a);
30. System.out.println("a[] = " + Arrays.toString(a));
31.
32. //二分法查找
33. System.out.println();
34. int index = Arrays.binarySearch(a, 2);
35. System.out.println(2+"的下标为:"+index);
36.
37. //将第3位开始,第4位除外的数据改写为99
38. System.out.println();
39. Arrays.fill(a, 3,4,99);
40. System.out.println("a[] = " + Arrays.toString(a));
41. }
42. }
43.
44. /* ------------------------------ 运行结果 ------------------------------
45. a[] = [3, 1, 6, 4, 7, 5, 3, 2, 8, 10, 123, 43, 5, 34]
46. b[] = [3, 1, 6, 4, 7, 6, 3, 2, 8, 10, 123]
47. -1
48. c[] = [3, 1, 6, 4, 7, 5, 3, 2, 8, 10, 123, 43, 5, 34, 0, 0, 0, 0, 0, 0]
49. c[] = [3, 1, 6, 4, 7]
50. 两个数组中第一个不一样的数据的下标为:5
51. a[] = [1, 2, 3, 3, 4, 5, 5, 6, 7, 8, 10, 34, 43, 123]
52.
53. 2的下标为:1
54.
55. a[] = [1, 2, 3, 99, 4, 5, 5, 6, 7, 8, 10, 34, 43, 123]
56. ------------------------------ 运行结果 ------------------------------ */
String类是不可变类,也就是说String对象声明后,将不可修改。
java.lang.String;是字符串类型
1. package com.sust.cst.javase.selflearning.c19_commonclass.t01_String;
2.
3. public class Test01 {
4. public static void main(String[] args) {
5.
6. //创建一个"abc"字符串对象,该对象的内存地址,让s1变量保存
7. //s1是一个引用,s1指向"abc"对象
8. String s1 = "abc";
9.
10. //可以让s1重新指向吗?
11. //可以,s1是局部变量,s1前边没有final,所以s1可以重新指向
12. //但是"def"字符串本身不可变
13. s1 = "def";
14.
15. String s2 = "hello";//在字符串常量池中新建一个"hello"字符串对象,该对象不可变
16. String s3 = "hello";//从字符串常量池中直接拿来用
17. System.out.println(s2 == s3); //true
18.
19. //比较两个字符串是否相等,不能用"=="
20. String s4 = new String("abc");
21. String s5 = new String("abc");
22.
23. //new 关键字一定是在堆中开辟空间,所以两个字符串的内存地址不相等
24. System.out.println(s4 == s5); //false
25.
26. //比较两个字符串是否一致,必须使用String类提供的equals方法
27. System.out.println(s4.equals(s5)); //true
28.
29. //以下程序执行,会在字符串常量池中创建3个字符串对象
30. //"aaa" "bbb" "aaabbb"
31. String s6 = "aaa";
32. String s7 = "bbb";
33. String s8 = s6 + s7;
34. }
35. }
36. /* ------------ 运行结果 ------------
37. true
38. false
39. true
40. ------------ 运行结果 ------------ */
1. package com.sust.cst.javase.selflearning.c19_commonclass.t01_String;
2.
3. /*
4. 分析以下程序创建字符串对象的区别
5. 1.String s1 = "abc"; 只会在字符串常量池中创建一个"abc"字符串对象
6.
7. 2.String s2 = new String("hello"); 会在字符串常量池中创建一个"hello"字符串对象,并且会在堆中再创建一个字符串对象
8.
9. 第二种方式比较浪费内存,常用的是第一种方式
10. */
11.
12. public class Test02 {
13. public static void main(String[] args) {
14.
15. //推荐使用这种方式
16. String s1 = "abc";
17.
18. //不推荐使用这种方式,它不仅会在字符串常量池中创建对象,还会在堆中创建对象,比较浪费空间
19. String s2 = new String("abc");
20. }
21. }
使用String的时候我们应该注意的问题,尽量不要做字符串频繁的拼接操作。因为字符串一旦创建不可改变,只要频繁拼接,就会在字符串常量池中创建大量的字符串对象,给垃圾回收带来问题。
1. package com.sust.cst.javase.selflearning.c19_commonclass.t01_String;
2.
3. public class Test03 {
4. public static void main(String[] args) {
5.
6. //判断以下程序创建了几个对象?
7. //堆中2个
8. //方法区中字符串常量池中1个
9. String s1 = new String("hello");
10. String s2 = new String("hello");
11. }
12. }
1. package com.sust.cst.javase.selflearning.c19_commonclass.t01_String;
2.
3. public class Test04 {
4. public static void main(String[] args) {
5.
6. String[] ins = {"sport", "music", "food", "sleep"};
7.
8. //要求将上面的兴趣爱好凭借成一个字符串"sport,music,food,sleep"
9. String temp = "";
10.
11. //不太推荐以下方式,这种方式频繁的拼接字符串,会对垃圾回收产生一些问题
12. for (int i = 0; i < ins.length; i++) {
13. temp += ins[i];
14.
15. if (i < ins.length - 1)
16. temp += ",";
17. }
18.
19. System.out.println(temp);
20. }
21. }
22. /* ----------- 运行结果 -----------
23. sport,music,food,sleep
24. ----------- 运行结果 ----------- */
关于字符串常用构造方法
1. package com.sust.cst.javase.selflearning.c19_commonclass.t01_String;
2.
3. public class Test05 {
4. public static void main(String[] args) {
5.
6. //1.
7. String s1 = "abc";
8.
9. //2.
10. String s2 = new String("abc");
11.
12. //3.
13. byte[] bytes = {97, 98, 99, 100};
14. String s3 = new String(bytes);
15. System.out.println(s3);//abcd String已经重写了Object中的String
16.
17. //4.
18. String s4 = new String(bytes, 1, 2);
19. System.out.println(s4);//bc
20.
21. //5.
22. char[] c1 = {'我','是','中','国','人'};
23. String s5 = new String(c1);
24. System.out.println(s5);//我是中国人
25.
26. //6.
27. String s6 = new String(c1,2,2);
28. System.out.println(s6);//中国
29. }
30. }
31. /* ---------- 运行结果 ----------
32. abcd
33. bc
34. 我是中国人
35. 中国
36. ---------- 运行结果 ---------- */
1. package com.sust.cst.javase.selflearning.c19_commonclass.t01_String;
2.
3. public class Test06 {
4. public static void main(String[] args) {
5.
6. //1. char charAt(int index); 返回指定索引处的char值
7. String s1 = "我是xx,是xx";
8. char c1 = s1.charAt(2);
9. System.out.println(c1);//王
10.
11. //2. boolean endsWith(String suffix); 测试此字符串是否以指定的后缀结束
12. System.out.println("helloWorld.java".endsWith("java"));//true
13. System.out.println("helloWorld.java".endsWith(".java"));//true
14. System.out.println("helloWorld.java".endsWith("helloWorld.java"));//true
15.
16. System.out.println("helloWorld.java".endsWith("helloWorld.txt"));//false
17. System.out.println("helloWorld.java".endsWith("java "));//false
18.
19. //3. boolean equalsIgnoreCase(String anotherString); 将此String与另一个String比较,不考虑大小写
20. System.out.println("abc".equalsIgnoreCase("aBC"));//true
21.
22. //4. byte[] getBytes(); 使用平台默认字符集将此String编码到byte序列,并将结果存储到新的byte数组
23. byte[] bytes = "abc".getBytes();
24. for (int i = 0; i < bytes.length; i++) {
25. System.out.print(bytes[i] + " ");// 97 98 99
26. }
27. System.out.println();
28.
29. //5. int indexOf(String str) 返回指定字符串在此字符串中第一次出现出的索引
30. System.out.println("http://192.168.1.100.8080/oa/login.action?username=jack&pwd=123".indexOf("/oa"));//25
31.
32. //6. int indexOf(String str, int fromIndex) 返回指定子字符串在此字符串中第一次出现处的索引,从指定索引开始
33. System.out.println("javaoraclec++javavb".indexOf("java", 1));//13
34.
35. //7. int lastIndexOf(String str) 返回指定字符串中最右边出现处的索引
36. System.out.println("javaoraclec++javavb".lastIndexOf("java"));//13
37.
38. //8. int lastIndexOf(String str, int fromIndex) 返回指定子字符串在此字符串中最后依次出现处的索引,从指定的索引开始反向搜索
39. System.out.println("javaoraclec++javavb".lastIndexOf("java", 14));//13
40.
41. //9. int length(); 返回字符串长度
42. System.out.println("abc".length());//3 数组是length属性,String是length()方法
43.
44. //10. String replaceAll(String regex, String replacement)
45. //使用指定的字面值替换序列替换此字符串所有匹配给定的正则表达式的子字符串
46. System.out.println("javaoraclec++javavb".replaceAll("java", "mysql"));//这个程序是4个字符串
47. //
48.
49. //11. String[] split(String regex)
50. //根据给定正则表达式的匹配拆分此字符串
51. String myTime = "2008,08,08";
52. String[] ymd = myTime.split(",");
53. for (int i = 0; i < ymd.length; i++) {
54. System.out.print(ymd[i]);
55. }
56. System.out.println();
57.
58. //12.boolean startWith(String s); 判断字符串以s字符串开始
59. System.out.println("/system/login.action".startsWith("/"));//true
60.
61. //13.String substring(int begin); 从begin开始截取字符串
62. System.out.println("/oa/login.action".substring(3));// /login.action
63.
64. //14. String substring(int beginIndex, int endIndex) 从beginIndex到endIndex(包含bginIndex,不包括endIndex)截取字符串
65. System.out.println("/oa/login.action".substring(4, 9));// login
66.
67. //15. char[] toCharArray(); 将字符串转换成char数组
68. char[] c2 = "我是刘洋".toCharArray();
69. for(int i = 0; i
例如:正则表达式”^a{2}$”表示2个a字符,等同于”aa”
\d 数字
\D 非数字
\w 英文字母
\W 非英文字母
1. package com.sust.cst.javase.selflearning.c19_commonclass.t01_String;
2.
3. /*
4. 正则表达式
5. */
6. public class Test07 {
7. public static void main(String[] args) {
8.
9. System.out.println("aa".matches("a{2}$"));//true
10. System.out.println("ab".matches("a{2}$"));//false
11.
12. String s1 = "asdd33dfsdaf33ddsd55fdd3dssf434sdf455ddsdddh565gggh55ddhg";
13.
14. //将dd替换为"中"
15. System.out.println(s1.replaceAll("dd","中"));
16.
17. //将dd替换为"中"
18. System.out.println(s1.replaceAll("d{2}","中"));
19.
20. //将数字替换为"中"
21. System.out.println(s1.replaceAll("\\d", "中"));
22.
23. //将非数字替换为"中"
24. System.out.println(s1.replaceAll("\\D", "中"));
25. }
26. }
27. /* ---------------------------------- 运行结果 ----------------------------------
28. true
29. as中33dfsdaf33中sd55f中3dssf434sdf455中s中dh565gggh55中hg
30. as中33dfsdaf33中sd55f中3dssf434sdf455中s中dh565gggh55中hg
31. asdd中中dfsdaf中中ddsd中中fdd中dssf中中中sdf中中中ddsdddh中中中gggh中中ddhg
32. 中中中中33中中中中中中33中中中中55中中中3中中中中434中中中455中中中中中中中565中中中中55中中中中
33. ---------------------------------- 运行结果 ---------------------------------- */
是一个字符串缓冲区,
预先在内存中申请一块空间,以容纳字符序列
如果预留的空间不够用,则进行自动扩容,以容纳更多的字符序列。
String是不可变的字符序列,存储在字符串常量池中;
StringBuffer是一个char数组,但是该char数组是可变的,并且可以自动扩容。
StringBuffer和StringBuilder的默认初始化容量是16
最好在创建StringBuffer之前,预测StringBuffer的存储字符数量。然后在创建StringBuffer的时候采用指定初始化榕江的方式创建StringBuffer.为了减少底层数组的拷贝,提高效率。
1. package com.sust.cst.javase.selflearning.c19_commonclass.t02_StringBufferAndStringbuilder;
2.
3. /*
4. java.lang.StringBuffer;
5. java.lang.StringBuilder;
6. */
7.
8. public class Test01 {
9. public static void main(String[] args) {
10.
11.
12. //创建字符串缓冲区对象
13. StringBuffer sb = new StringBuffer();//默认初始化值为16
14.
15. //可以向StringBuffer中追加字符串
16. String[] ins = {"体育", "音乐", "睡觉", "旅游"};
17.
18. //推荐字符串频繁拼接使用StringBuffer或StringBuilder
19. for(int i =0 ; i < ins.length;i++){
20. sb.append(ins[i]);
21.
22. if(i < ins.length-1)
23. sb.append(",");
24. }
25.
26. System.out.println(sb);
27. }
28. }
29. /* ------------- 运行结果 -------------
30. 体育,音乐,睡觉,旅游
31. ------------- 运行结果 ------------- */
StringBuffer是线程安全的,可以在多线程的环境下使用不会出现问题
StringBuidler是非线程安全的,在多线程环境下使用可能出现问题
基本数据类型 |
包装类型 |
byte |
java.lang.Byte; |
short |
java.lang.Short; |
int |
java.lang.Integer; |
long |
java.lang.Long; |
float |
java.lang.Float; |
double |
java.lang.Double; |
boolean |
java.lang.Boolean; |
char |
java.lang.Character; |
思考:java中提供的8种数据类型不够用吗?为什么java中还需要提供对应的包装类呢?
方便
1. package com.sust.cst.javase.selflearning.c19_commonclass.t03_thePackageTypeOfTheBasicDataType.m01_Integer;
2.
3. public class Test01 {
4. //需求:规定m1方法可以接收java中任何一种数据类型
5. //m1方法如果想接收byte类型的数据,可以将byte类型先包装成java.lang.Byte;再传递参数
6. public static void m1(Object o){
7. System.out.println(o);
8. }
9.
10. public static void main(String[] args) {
11. byte b = 10;
12.
13. Byte b1 = new Byte(b);
14.
15. m1(b1);//10 Byte已经将Object中的toString方法重写
16. }
17. }
18. /* --------- 运行结果 ---------
19. 10
20. --------- 运行结果 --------- */
1. package com.sust.cst.javase.selflearning.c19_commonclass.t03_thePackageTypeOfTheBasicDataType.m01_Integer;
2.
3. /*
4. 以java.lang.Integer;类型为例,讲解8种类型
5. */
6. public class Test02 {
7. public static void main(String[] args) {
8.
9. //获取int类型的最大值和最小值
10. System.out.println("int 类型最小值:" + Integer.MIN_VALUE);
11. System.out.println("int 类型最大值:" + Integer.MAX_VALUE);
12.
13. //获取byte类型的最大值和最小值
14. System.out.println("byte 类型最小值:" + Byte.MIN_VALUE);
15. System.out.println("byte 类型最大值:" + Byte.MAX_VALUE);
16.
17. //创建Integer类型的对象
18. Integer x1 = new Integer(10);
19. Integer x2 = new Integer("123");
20. System.out.println(x1); //10
21. System.out.println(x2); //123
22.
23. //以下程序编译可以通过
24. //但是运行的时候会报异常,数字格式化异常 NumberFormatException
25. //虽然可以将字符串转换为Integer类型,但是该字符串也必须是"数字字符串"
26. //Integer x3 = new Integer("abc"); //NumberFormatException
27. }
28. }
29. /* ----------------------------- 运行结果 -----------------------------
30. int 类型最小值:-2147483648
31. int 类型最大值:2147483647
32. byte 类型最小值:-128
33. byte 类型最大值:127
34. 10
35. 123
36. Exception in thread "main" java.lang.NumberFormatException: For input string: "abc"
37. at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
38. at java.base/java.lang.Integer.parseInt(Integer.java:658)
39. at java.base/java.lang.Integer.(Integer.java:1117)
40. at com.sust.cst.javase.selflearning.c19_commonclass.t03_thePackageTypeOfTheBasicDataType.m01_Integer.Test02.main(Test02.java:24)
41. ----------------------------- 运行结果 ----------------------------- */
1. package com.sust.cst.javase.selflearning.c19_commonclass.t03_thePackageTypeOfTheBasicDataType.m01_Integer;
2.
3. /*
4. 关于Integer中常用的方法
5. */
6.
7. public class Test03 {
8. public static void main(String[] args) {
9.
10. //int --> Integer
11. //基本数据类型 --> 引用数据类型
12. Integer i1 = new Integer(10);
13.
14. //int intValue() 以int类型返回该Integer的值
15. //Integer --> int
16. //引用类型 --> 基本数据类型
17. int i2 = i1.intValue();
18.
19. System.out.println(i2 + 1);//11
20.
21. //重要!!!static int parseInt(String a) 将字符串参数作为有符号的十进制整数进行解析
22. //字符串转换为整形数字
23. int age = Integer.parseInt("26");
24. System.out.println(age+1);//27
25.
26. //"abc"字符串必须是数字字符串才行
27. //NumberFormatException
28. //int price = Integer.parseInt("abc");
29.
30. //重要!!!static double parseDouble(String a)
31. //字符串转换为double数字
32. double price = Double.parseDouble("3.12");
33. System.out.println(price+1.0);//4.12
34.
35. //static String toBinaryString(int i) 十进制转换为二进制
36. String s1 = Integer.toBinaryString(10);
37. System.out.println(s1);//1010
38.
39. //static String toHexString(int i) 十进制转换为十六进制
40. String s2 = Integer.toHexString(10);
41. System.out.println(s2);//a
42. //static String toOctalString(int i) 十进制转换为八进制
43. String s3 = Integer.toOctalString(10);
44. System.out.println(s3);//12
45.
46. //static Integer valueOf(int i) 将int 类型转换成Integer
47. Integer x1 = Integer.valueOf(10);
48. //static Integer valueOf(String s) 将String 类型转换成Integer
49. Integer x2 = Integer.valueOf("10");
50. }
51. }
52. /* ---------------------------- 运行结果 ----------------------------
53. 11
54. 27
55. 4.12
56. 1010
57. a
58. 12
59. ---------------------------- 运行结果 ---------------------------- */
1. package com.sust.cst.javase.selflearning.c19_commonclass.t03_thePackageTypeOfTheBasicDataType.m01_Integer;
2.
3. /*
4. Integer
5. int
6. String
7. 三种类型相互转换
8. */
9. public class Test04 {
10. public static void main(String[] args) {
11. //1.int --> Integer
12. Integer i1 = Integer.valueOf(10);
13.
14. //2.Integer --> int
15. int i2 = i1.intValue();
16.
17. //3.String --> Integer
18. Integer i3 = Integer.valueOf("10");
19.
20. //4.Integer --> String
21. String s1 = i3.toString();
22.
23. //5.String --> int
24. int i = Integer.parseInt("123");
25.
26. //6.int --> String
27. String s2 = 10 + "";
28. }
29. }
以下的特性适合JDK1.5之后的,包括1.5
JDK1.4,包括1.4在内,所有之前的版本不能使用以下特性
1. package com.sust.cst.javase.selflearning.c19_commonclass.t03_thePackageTypeOfTheBasicDataType.m01_Integer;
2.
3. public class Test05 {
4. public static void main(String[] args) {
5. //JDK5.0之前的
6. //int --> Integer(装箱)
7. Integer i1 = new Integer(10);
8.
9. //Integer --> int (拆箱)
10. int i2 = i1.intValue();
11.
12. //JDK5.0之后
13. Integer i3 = 10;//自动装箱
14. int i4 = i3;//自动拆箱
15.
16. System.out.println(i3);//"10"
17. System.out.println(i4+1);//11
18.
19. m1(10);//自动装箱
20.
21. System.out.println(m2(10, 5) + 1);//自动装箱
22. }
23.
24. public static void m1(Object o){
25. System.out.println(o);
26. }
27.
28. public static int m2(Integer i1, Integer i2){
29. return i1 - i2; //自动拆箱
30. }
31. }
32. /* ----------------- 运行结果 -----------------
33. 10
34. 11
35. 10
36. 6
37. ----------------- 运行结果 ----------------- */
深入自动装箱和自动拆箱
1. package com.sust.cst.javase.selflearning.c19_commonclass.t03_thePackageTypeOfTheBasicDataType;
2.
3. /*
4. 深入自动装箱和自动拆箱
5. */
6. public class Test06 {
7. public static void main(String[] args) {
8.
9. Integer i1 = new Integer(10);
10. Integer i2 = new Integer(10);
11.
12. //这里不会有自动拆箱
13. System.out.println(i1 == i2); //fasle 这里比较的是i1和i2的内存地址
14.
15. //比较2个Integer类型的数据是否相等,不能用"=="
16. //Integer已经重写了Object中的equals方法
17. System.out.println(i1.equals(i2)); //true
18.
19. //重点:
20. Integer i3 = 128;
21. Integer i4 = 128;
22.
23. //上面等同于
24. //Integer i3 = new Integer(128);
25. //Integer i4 = new Integer(128);
26.
27. System.out.println(i3 == i4);//false
28.
29. //注意以下程序
30. //如果x∈[-128 - 127],java中引入了一个"整型常量池",在方法区中
31. //该整型常量池值存储[-128,127]中的数据
32.
33. Integer i5 = 127; //这个程序不会在堆中创建对象,会直接从整型常量池中拿
34. Integer i6 = 127;
35.
36. System.out.println(i5 == i6);//true
37.
38. Integer i7 = -128;
39. Integer i8 = -128;
40. System.out.println(i7 == i8);//true
41.
42. Integer i9 = -129;
43. Integer i10 = -129;
44. System.out.println(i9 == i10);//false
45. }
46. }
47. /* ---------------------- 运行结果 ----------------------
48. false
49. true
50. false
51. true
52. true
53. false
54. ---------------------- 运行结果 ---------------------- */
获取自1970年1月1日 00时00分00秒 000毫秒 到当前的毫秒数
获取系统当前时间
格式化日期
1. package com.sust.cst.javase.selflearning.c19_commonclass.t04_Data;
2.
3. import java.text.SimpleDateFormat;
4. import java.util.Date;
5.
6. public class Test01 {
7. public static void main(String[] args) {
8.
9. /*
10. 获取自1970年1月1日 00时00分00秒 000毫秒 到当前的毫秒数
11.
12. 1000毫秒 == 1秒
13. */
14.
15. long now = System.currentTimeMillis();
16. System.out.println(now);//1573180904328
17.
18. /*
19. 获取系统当前时间
20. */
21. Date nowTime = new Date();
22. System.out.println(nowTime);//Fri Nov 08 10:45:20 CST 2019
23.
24. //以上程序说明java.util.Date已经重写了Object中的toString方法
25. //只不过重写的结果对中国人而言不太容易理解
26.
27. //所以引入格式化日期
28. //java.util.Date; --> String
29.
30. /*
31. 日期格式:
32. y 年
33. M 月
34. d 日
35. H 小时
36. m 分
37. s 秒
38. S 毫秒
39. */
40. //1.创建日期格式化对象
41. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SSS");
42. //2.开始格式化(Date --> String)
43. String strTime = simpleDateFormat.format(nowTime);
44.
45. System.out.println(strTime); //2019年11月08日 10:59:00 774
46. }
47. }
48. /* --------------------- 运行结果 ---------------------
49. 1573182073362
50. Fri Nov 08 11:01:13 CST 2019
51. 2019年11月08日 11:01:13 363
52. --------------------- 运行结果 --------------------- */
String => Date
1. package com.sust.cst.javase.selflearning.c19_commonclass.t04_Data;
2.
3. /*
4. 获取特定日期
5. */
6.
7. import java.text.ParseException;
8. import java.util.Date;
9.
10. import java.text.SimpleDateFormat;
11. public class Test02 {
12. public static void main(String[] args) throws ParseException {
13.
14. String strTime = "2008年08月08日 08:08:08 888";
15.
16. //将String日期转换冲鞥日期类型Date
17. //String --> Date
18.
19. //1.创建日期格式化对象
20. //格式不饿能随便写,应该设上面的字符串格式相同
21. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SSS");
22.
23. //2.将字符串转换成日期类型
24. Date time = simpleDateFormat.parse(strTime);
25.
26. System.out.println(time); //Fri Aug 08 08:08:08 CST 2008
27. }
28. }
29. /* -------------- 运行结果 --------------
30. Fri Aug 08 08:08:08 CST 2008
31. -------------- 运行结果 -------------- */
1. package com.sust.cst.javase.selflearning.c19_commonclass.t04_Data;
2.
3. import java.text.SimpleDateFormat;
4. import java.util.Date;
5.
6. /*
7. Date t = Date(long date)
8. */
9. public class Test03 {
10. public static void main(String[] args) {
11. Date date = new Date(1000);
12.
13. //date --> String
14. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy,MM,dd HH:mm:ss SSS");
15.
16. //北京东八区
17. //1970年1月1日 08时00分01秒 000
18. System.out.println(simpleDateFormat.format(date));//1970,01,01 08:00:01 000
19.
20. //获取当前系统时间的前十分钟时间
21. Date date2 = new Date((System.currentTimeMillis() - 10 * 60 * 1000));
22. System.out.println(simpleDateFormat.format(date2));
23. System.out.println(simpleDateFormat.format(new Date()));
24. }
25. }
26. /* ---------------------- 运行结果 ----------------------
27. 1970,01,01 08:00:01 000
28. 2019,11,15 10:00:47 272
29. 2019,11,15 10:10:47 272
30. ---------------------- 运行结果 ---------------------- */
1. package com.sust.cst.javase.selflearning.c19_commonclass.t04_Data;
2. import java.text.ParseException;
3. import java.text.SimpleDateFormat;
4. import java.util.Calendar;
5. import java.util.Date;
6. /*
7. 日历 Calendar
8. */
9. public class Test04 {
10. public static void main(String[] args) throws ParseException {
11. //获取系统当前日历 Calendar
12. //static Claendar getInstance() 使用默认时区和语言环境获得一个日历
13. Calendar calendar = Calendar.getInstance();
14. //查看当前日历的“星期几”
15. //int get(int field) 返回给定日历字段的值
16. int x = calendar.get(Calendar.DAY_OF_WEEK);
17. /*
18. public static final int DAY_OF_MONTH = 5;
19. public static final int DAY_OF_YEAR = 6;
20. public static final int DAY_OF_WEEK = 7;
21. */
22. System.out.println(x);//6(星期日为第一天)
23. System.out.println(calendar.get(Calendar.DAY_OF_MONTH));//15
24.
25. //获取2008年8月8日是星期几
26. //1.获取2008年8月8日的日历
27. String strTime = "2008,08,08";
28. Date date = new SimpleDateFormat("yyyy,MM,dd").parse(strTime);
29. calendar.setTime(date);
30. //2.获取星期几
31. System.out.println(calendar.get(Calendar.DAY_OF_WEEK));//6 星期五
32. }
33. }
34. /* ------- 运行结果 -------
35. 6
36. 15
37. 6
38. ------- 运行结果 ------- */
数字格式元素:
1. package com.sust.cst.javase.selflearning.c19_commonclass.t05_num;
2.
3. import java.text.DecimalFormat;
4.
5. /*
6. 关于数字格式化 java.text.DecimalFormat;
7. */
8. public class Test01 {
9. public static void main(String[] args) {
10.
11. //1.创建数字格式化对象
12. //需求:加入千分位。
13. DecimalFormat decimalFormat = new DecimalFormat("###,###");
14.
15. //2.开始格式化
16. //Number-->String
17. System.out.println(decimalFormat.format(1234567));//"1,234,567"
18.
19. //加入千分位,保留2位小数
20. decimalFormat = new DecimalFormat("###,###.##");
21. System.out.println(decimalFormat.format(1234567.128));//"1,234,567.13"
22.
23. //加入千分位,保留4位小数,不够补0
24. decimalFormat = new DecimalFormat("###,###.0000");
25. System.out.println(decimalFormat.format(1234567.128));//"1,234,567.1280"
26. }
27. }
28. /* ---------------- 运行结果 ----------------
29. 1,234,567
30. 1,234,567.13
31. 1,234,567.1280
32. ---------------- 运行结果 ---------------- */
该类型数据精确度极高,适合做财务软件
财务软件中double类型精确度太低
1. package com.sust.cst.javase.selflearning.c19_commonclass.t05_num;
2.
3. import java.math.BigDecimal;
4.
5. /*
6. java.math.BigDecimal;
7. */
8. public class Test02 {
9. public static void main(String[] args) {
10.
11. //创建大数据
12. BigDecimal b1 = new BigDecimal(10);
13. BigDecimal b2 = new BigDecimal(20);
14.
15. //做加法运算
16. //b1 + b2//错误:两个引用类型不能做加法运算
17.
18. //必须调用方法
19. //BigDecimal add(BigDecimal augend)
20. //返回一个BigDecimal,其值为(this + augend),其标度为max(this.scale(), augend.scale())
21. BigDecimal b3 = b1.add(b2);
22. System.out.println(b3);
23. }
24. }
25. /* ------------ 运行结果 ------------
26. 30
27. ------------ 运行结果 ------------ */
1. package com.sust.cst.javase.selflearning.c19_commonclass.t06_random;
2.
3. import java.util.Random;
4.
5. /*
6. 生成随机数
7. */
8. public class Test01 {
9. public static void main(String[] args) {
10. //创建一个新的随机数生成器
11. Random random = new Random();
12.
13. //生成int 类型的随机数
14. //int nextInt(int n)
15. // 返回一个伪随机数,
16. // 它是取自随机数生成器序列的,在0(包括)和指定值(不包括)之间均匀分布的int值
17. int x = random.nextInt(101);//0-100之间的随机数
18. System.out.println(x);
19.
20. //循环生成5个0-100之间的随机数
21. for (int i = 0; i < 5; i++) {
22. System.out.print(random.nextInt(101) + " ");
23. }
24. System.out.println();
25.
26. //生成5个不重复的随机数
27. int[] temp = new int[5];
28. int i = 0;
29. while (i < 5) {
30. temp[i] = random.nextInt(101);
31. for (int j = 0; j < i; j++) {
32. if (temp[i] == temp[j]) {
33. i--;
34. break;
35. }
36. }
37. i++;
38. }
39.
40. for (i = 0; i < temp.length; i++)
41. System.out.print(temp[i] + " ");
42. System.out.println();
43. }
44. }
45. /* ----------------- 运行结果 -----------------
46. 100
47. 81 54 79 84 55
48. 68 96 67 77 8
49. ----------------- 运行结果 ----------------- */
枚举 Enum
不使用枚举会造成问题
1. package com.sust.cst.javase.selflearning.c19_commonclass.t07_enum;
2. /*
3. 定义一个方法,该方法的作用是计算两个int类型的商
4. 如果计算成功,则该方法返回1;如果执行失败,则该方法返回0
5. */
6. public class Test01 {
7. public static void main(String[] args) {
8. int a = 10;
9. int b = 0;
10. System.out.println("计算" + a + " \\ " + b + "的商:");
11. int retValue = divide(a, b);
12.
13. if(retValue == 0)
14. System.out.println("失败");
15. else if(retValue == 1)
16. System.out.println("成功");
17. }
18.
19. //程序执行成功,但是该程序存在风险
20. //程序中的问题能在编译阶段解决的绝对不会放在运行期解决
21. //所以以下程序可以引入枚举类型enum
22. public static int divide(int a, int b){
23. int result = 1;
24.
25. try{
26. int c = a/b;
27. }catch (Exception e){
28. result = 10;
29. }
30.
31. return result;
32. }
33. }
34. /* ------- 运行结果 -------
35. 计算10 \ 0的商:
36. 无输出,程序编写错误
37. ------- 运行结果 ------- */
使用枚举带来的好处
1. package com.sust.cst.javase.selflearning.c19_commonclass.t07_enum;
2.
3. public class Test02 {
4. public static void main(String[] args) {
5. int a = 10;
6. int b = 0;
7. System.out.println("计算" + a + " \\ " + b + "的商:");
8. Result retValue = divide(a, b);
9.
10. if (retValue == Result.FAIL)
11. System.out.println("失败");
12. else if (retValue == Result.SUCCESS)
13. System.out.println("成功");
14. }
15.
16. //程序执行成功,但是该程序存在风险
17. //程序中的问题能在编译阶段解决的绝对不会放在运行期解决
18. //所以以下程序可以引入枚举类型enum
19. public static Result divide(int a, int b) {
20. Result result = Result.SUCCESS;
21.
22. try {
23. int c = a / b;
24. } catch (Exception e) {
25. result = Result.FAIL;
26. }
27.
28. return result;
29. }
30. }
31.
32. //定义一个枚举类型
33. enum Result {
34. //规范要求:大写
35. SUCCESS, FAIL //有限的
36. }
37.
38. //四季
39. enum Season {
40. SPRING, SUMMER, AUTUMN, WINTER
41. }
42.
43. /* -------- 运行结果 --------
44. 计算10 \ 0的商:
45. 失败
46. -------- 运行结果 -------- */
集合继承结构图
UML图例:
boolean add(Object), void clear(), boolean isEmpty()
boolean add(Object element); 向集合中添加元素
void clear(); 清空集合
boolean isEmpty(); 判断集合中是否有元素
int size(); 获取集合中元素的个数
1. package com.sust.cst.javase.selflearning.c20_Collection.t01_Collection;
2.
3. import java.util.ArrayList;
4. import java.util.Collection;
5.
6. /*
7. boolean add(Object element); 向集合中添加元素
8. void clear(); 清空集合
9. boolean contains(Object element); 判断集合中是否包含某个元素
10. boolean isEmpty(); 判断集合中是否有元素
11. Iterator iterator(); 获取集合所依赖的迭代器对象
12. boolean remove(Object o); 删除集合中某个元素
13. int size(); 获取集合中元素的个数
14. Object[] toArray(); 将集合转换为数组
15. */
16. public class Test01 {
17. public static void main(String[] args) {
18. //1.创建集合
19. Collection c = new ArrayList();//多态
20.
21. //2.添加元素
22. c.add(1);//自动装箱
23. c.add(new Integer(100));
24.
25. Object o = new Object();
26. c.add(o);//Collection集合只用单个存储元素,并且只能存储引用类型
27. Customer cus = new Customer("Jack", 20);
28. c.add(cus);
29.
30. //3.获取元素个数
31. System.out.println(c.size());//4
32. System.out.println(c.isEmpty());//false
33.
34. //4.将集合转换为Object类型的数组
35. Object[] objcets = c.toArray();
36.
37. for (int i = 0; i < objcets.length; i++) {
38. System.out.print(objcets[i] + "\t");
39. }
40. System.out.println();
41.
42. //5.清空
43. c.clear();
44. System.out.println(c.size());//0
45. System.out.println(c.isEmpty());//true
46. }
47. }
48.
49. class Customer {
50. private String name;
51. private int age;
52.
53. Customer(String name, int age) {
54. this.name = name;
55. this.age = age;
56. }
57.
58. public String getName() {
59. return name;
60. }
61.
62. public void setName(String name) {
63. this.name = name;
64. }
65.
66. public int getAge() {
67. return age;
68. }
69.
70. public void setAge(int age) {
71. this.age = age;
72. }
73.
74. @Override
75. public String toString() {
76. return "Customer{" +
77. "name='" + name + '\'' +
78. ", age=" + age +
79. '}';
80. }
81. }
82. /* -------------- 运行结果 --------------
83. 4
84. false
85. 1 100 java.lang.Object@506e1b77 Customer{name='Jack', age=20}
86. 0
87. true
88. -------------- 运行结果 -------------- */
Iterator iterator(); 获取集合所依赖的迭代器对象
通过迭代器中方法完成集合的迭代(遍历)
1. package com.sust.cst.javase.selflearning.c20_Collection.t01_Collection;
2.
3. import java.util.Collection;
4. import java.util.Iterator;
5. import java.util.LinkedList;
6.
7. /*
8. Iterator iterator(); 获取集合所依赖的迭代器对象
9. 通过迭代器中方法完成集合的迭代(遍历)
10.
11. 注意:这种方式是所有集合通用的遍历方式
12. */
13. public class Test02 {
14. public static void main(String[] args) {
15. //1.创建集合对象
16. Collection c = new LinkedList();
17.
18. //添加元素
19. c.add(100);
20. c.add(3.14);
21. c.add(false);
22.
23. //迭代(遍历)
24. //1.获取迭代器对象
25. //不需要关心底层集合的具体类型,所有集合依赖的迭代器都实现了java.util.Iterator接口
26. Iterator iterator = c.iterator();//迭代器是面向接口编程
27. // it是一个引用,保存内存地址,指向堆中的“迭代器”对象
28.
29. //java.util.Linkedlist$ListItr 类是LinkedList集合所依赖的迭代器
30. //java.util.Arraylist$Itr 类是ArrayList集合所依赖的迭代器
31. System.out.println(iterator);
32.
33. //2.调用方法,完成遍历(迭代)
34. //while循环
35.
36. //boolean b = iterator.hasNext(); 判断是否有更多的元素,如果有返回true
37. while(iterator.hasNext()){
38. //Object o = it.next(); 将迭代器向下移动一位,并且取出指向的元素
39. Object element = iterator.next();
40. System.out.print(element + " ");
41. }
42. System.out.println();
43.
44. /*
45. 原则:调用it.next();之前,必须调用it.hasNext()
46. */
47.
48. //for循环
49. for(iterator = c.iterator();iterator.hasNext();){
50. Object o = iterator.next();
51. System.out.print(o + " ");
52. }
53. System.out.println();
54. }
55. }
56. /* -------------- 运行结果 --------------
57. java.util.LinkedList$ListItr@b4c966a
58. 100 3.14 false
59. 100 3.14 false
60. -------------- 运行结果 -------------- */
boolean contains(Object element); 判断集合中是否包含某个元素
1. package com.sust.cst.javase.selflearning.c20_Collection.t01_Collection;
2.
3. import java.util.ArrayList;
4. import java.util.Collection;
5.
6. /*
7. boolean contains(Object element); 判断集合中是否包含某个元素
8.
9. 存储在集合中的元素应该重写equals方法
10. */
11. public class Test03 {
12. public static void main(String[] args) {
13. //创建集合
14. Collection c = new ArrayList();
15.
16. //创建1个Integer类型的对象
17. Integer i1 = new Integer(10);
18.
19. //添加元素
20. c.add(2);
21. c.add(4);
22. c.add(6);
23. c.add(8);
24. c.add(i1);
25.
26. //判断集合中是否包含i1
27. System.out.println(c.contains(i1));//true
28.
29. //创建1个Integer类型的对象
30. Integer i2 = new Integer(10);
31.
32. //contains方法底层调用的是equals方法,如果equals返回true,就是包含
33. System.out.println(c.contains(i2));//true
34.
35. /*
36. public boolean contains(Object o) {
37. return indexOf(o) >= 0;
38. }
39. public int indexOf(Object o) {
40. return indexOfRange(o, 0, size);
41. }
42.
43. int indexOfRange(Object o, int start, int end) {
44. Object[] es = elementData;
45. if (o == null) {
46. for (int i = start; i < end; i++) {
47. if (es[i] == null) {
48. return i;
49. }
50. }
51. } else {
52. for (int i = start; i < end; i++) {
53. if (o.equals(es[i])) {
54. return i;
55. }
56. }
57. }
58. return -1;
59. }
60. */
61.
62. Manager m1 = new Manager(100,"Jack");
63. c.add(m1);
64. System.out.println(c.contains(m1));//true
65.
66. Manager m2 = new Manager(100,"Jack");
67. //重写equals方法之前
68. //System.out.println(c.contains(m2));//false
69.
70. //重写equals方法之后,比较内容
71. System.out.println(c.contains(m2));//true
72. }
73. }
74.
75. class Manager{
76. int no;
77. String name;
78.
79. public Manager(int no, String name) {
80. this.no = no;
81. this.name = name;
82. }
83.
84. @Override
85. public String toString() {
86. return "Manager{" +
87. "no=" + no +
88. ", name='" + name + '\'' +
89. '}';
90. }
91.
92. //重写Manager的equals方法
93. //需求规定:如果姓名和编号都相同,则表示一个Manager
94. public boolean equals(Object o){
95. boolean retBool = false;
96.
97. if(this == o)
98. retBool = true;
99. if(o instanceof Manager){
100. Manager m = (Manager)o;
101. if(m.no == this.no && m.name.equals(this.name))
102. retBool = true;
103. }
104.
105. return retBool;
106. }
107. }
108. /* ------ 运行结果 ------
109. true
110. true
111. true
112. true
113. ------ 运行结果 ------ */
boolean remove(Object o); 删除集合中某个元素
remove和contains方法都需要集合中的元素重写equals方法,因为Object中的equals方法比较内存地址,在显示的业务逻辑当中不能比较内存地址,该比较内容。
1. package com.sust.cst.javase.selflearning.c20_Collection.t01_Collection;
2.
3. import java.util.ArrayList;
4. import java.util.Collection;
5.
6. /*
7. boolean remove(Object o); 删除集合中某个元素
8.
9. remove和contains方法都需要集合中的元素重写equals方法,
10. 因为Object中的equals方法比较内存地址,在显示的业务逻辑当中
11. 不能比较内存地址,该比较内容
12. */
13. public class Test04 {
14. public static void main(String[] args) {
15.
16. //创建集合对象
17. Collection c = new ArrayList();
18.
19. Integer i1 = new Integer(10);
20.
21. //添加元素
22. c.add(i1);
23.
24. //删除
25. Integer i2 = new Integer(10);
26. c.remove(i2);
27.
28. System.out.println(c.size());//0
29.
30. Manager m1 = new Manager(100,"Smith");
31. c.add(m1);
32.
33. Manager m2 = new Manager(100,"Smith");
34. c.remove(m2);
35.
36. System.out.println(c.size());//0
37. }
38. }
39. /* -------- 运行结果 --------
40. 0
41. 0
42. -------- 运行结果 -------- */
迭代器的remove方法和集合自身带的remove方法的区别:
c集合自身删除一个元素之后,整体就改变了,需要重新获取迭代器才能接续往下执行。
1. package com.sust.cst.javase.selflearning.c20_Collection.t01_Collection;
2.
3. import java.util.ArrayList;
4. import java.util.Collection;
5. import java.util.Iterator;
6.
7. /*
8. 深入remove方法
9. 1.迭代器的remove方法
10. 2.集合自身带的remove方法
11. */
12. public class Test05 {
13. public static void main(String[] args) {
14.
15. Collection c = new ArrayList();
16.
17. c.add(1);
18. c.add(2);
19. c.add(3);
20.
21. //遍历
22. Iterator it = c.iterator();
23.
24. while(it.hasNext()){
25. //推荐使用迭代器自身带的remove方法删除元素
26. it.next();
27. //删除
28. it.remove();//通过迭代器删除
29.
30. /* //使用集合自身所带的remove方法
31. Object element = it.next();
32.
33. //删除
34. c.remove(element);*/
35.
36. /*
37. Exception in thread "main" java.util.ConcurrentModificationException
38. at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1042)
39. at java.base/java.util.ArrayList$Itr.next(ArrayList.java:996)
40. at com.sust.cst.javase.selflearning.c20_Collection.t01_Collection.Test05.main(Test05.java:30)
41. */
42. }
43.
44. System.out.println(c.size());//0
45. }
46. }
47. /* -------- 运行结果 --------
48. 0
49. -------- 运行结果 -------- */
1. package com.sust.cst.javase.selflearning.c20_Collection.t02_List;
2.
3. import java.util.ArrayList;
4. import java.util.Iterator;
5. import java.util.List;
6.
7. /*
8. List集合存储元素的特点
9. */
10. public class Test01 {
11. public static void main(String[] args) {
12.
13. //创建一个List集合
14. List l = new ArrayList();
15.
16. l.add(1123);
17. l.add(2);
18. l.add(12);
19. l.add(1290);
20. l.add(1534);
21.
22. //遍历
23. Iterator it = l.iterator();
24.
25. while(it.hasNext()){
26. System.out.println(it.next());
27. }
28. }
29. }
30. /* -------- 运行结果 --------
31. 1123
32. 2
33. 12
34. 1290
35. 1534
36. -------- 运行结果 -------- */
ArrayList集合底层是数组,数组是有下表的,因此他有许多自己的特性。
ArrayList集合底层默认初始化容量是 10 ,扩大之后的容量是原容量的 1.5 倍。
Vetor集合底层默认初始化容量也是10,扩大之后的容量是原容量的2倍。
如何优化ArrayList和Vetor?
尽量减少扩容操作,因为扩容需要数组拷贝,很耗内存。
一般推荐在创建集合的时候指定初始化容量。
1. package com.sust.cst.javase.selflearning.c20_Collection.t02_List;
2.
3. import java.util.ArrayList;
4. import java.util.Iterator;
5. import java.util.LinkedList;
6. import java.util.List;
7.
8. /*
9. 深入List集合
10. */
11. public class Test02 {
12. public static void main(String[] args) {
13. //创建List集合
14. //List l = new ArrayList();
15. List l = new LinkedList();
16.
17. //添加元素
18. l.add(123);
19. l.add(234);
20. l.add(69);
21. //在下标为1的位置上添加555
22. l.add(1,555);
23.
24. //取得第一个元素
25. System.out.println(l.get(0));//123
26. System.out.println("-------------------");
27. //遍历(List集合特有的遍历方式)
28. for(int i = 0; i< l.size();i++){
29. Object element = l.get(i);
30. System.out.print(element + " ");
31. }
32. System.out.println();
33. System.out.println("-------------------");
34.
35. //迭代器
36. Iterator it = l.iterator();
37. while (it.hasNext()){
38. System.out.print(it.next() + " ");
39. }
40. }
41. }
42. /* ----------- 运行结果 -----------
43. 123
44. -------------------
45. 123 555 234 69
46. -------------------
47. 123 555 234 69
48. ----------- 运行结果 ----------- */
1. package com.sust.cst.javase.selflearning.c20_Collection.t03_Set.m01_HashSet;
2.
3. import java.util.HashSet;
4. import java.util.Iterator;
5. import java.util.Set;
6.
7. public class Test01 {
8. public static void main(String[] args) {
9. //创建set集合
10. Set s = new HashSet();
11. //无需不可重复
12. s.add(1);
13. s.add(1);
14.
15. s.add(100);
16. s.add(88);
17. s.add(89);
18. s.add(8394);
19. s.add(1293);
20. s.add(23);
21. s.add(45);
22.
23. //遍历
24. Iterator it = s.iterator();
25. while(it.hasNext()){
26. System.out.println(it.next());
27. }
28. }
29. }
30. /* -------- 运行结果 --------
31. 1
32. 100
33. 23
34. 88
35. 89
36. 8394
37. 1293
38. 45
39. -------- 运行结果 -------- */
关于往Set集合中存储的元素,该元素的hashCode和equals方法
HashMap中有一个put方法,put(key, value),key是无序不可重复的
结论:存储在HashSet集合或者HashMap集合key部分的元素,需要同时重写equals和hashCode方法
1. package com.sust.cst.javase.selflearning.c20_Collection.t03_Set.m01_HashSet;
2.
3. import java.util.HashSet;
4. import java.util.Iterator;
5. import java.util.Set;
6.
7. /*
8. 关于往Set集合中存储的元素,该元素的HashCode和equals方法
9. HashMap中有一个put方法,put(key, value) key是无序不可重复的
10.
11. 结论:存储在HashSet集合或者HashMap集合Key部分的元素,需要同时重写equals和hashCode方法
12. */
13. public class Test02 {
14. public static void main(String[] args) {
15. //创建集合
16. Set es = new HashSet();
17. Employee[] employees = new Employee[6];
18. String[] names = {"Jack", "Jack", "Scott", "Sun", "Jim", "Cook"};
19. String[] nos = {"1000", "1000", "1000", "2001", "3000", "3001"};
20.
21. System.out.println(employees.length);
22.
23. for (int i = 0; i < employees.length; i++) {
24. employees[i] = new Employee(nos[i], names[i]);
25. }
26.
27. for (int i = 0; i < employees.length; i++) {
28. System.out.println("employees[" + i + "].hashCode() = " +
29. employees[i].hashCode());
30. }
31.
32. //添加元素
33. for (int i = 0; i < employees.length; i++) {
34. es.add(employees[i]);
35. }
36.
37. //产看集合元素个数
38. System.out.println(es.size());
39.
40. Iterator it = es.iterator();
41. while (it.hasNext()) {
42. System.out.println(it.next());
43. }
44.
45. // while(es.iterator().hasNext()){
46. // System.out.println(es.iterator().next());
47. // }
48. }
49. }
50.
51. class Employee {
52. //编号
53. private String no;
54. private String name;
55.
56. public Employee(String no, String name) {
57. this.no = no;
58. this.name = name;
59. }
60.
61. public Employee() {
62. this(null, null);
63. }
64.
65. public String getNo() {
66. return no;
67. }
68.
69. public void setNo(String no) {
70. this.no = no;
71. }
72.
73. public String getName() {
74. return name;
75. }
76.
77. public void setName(String name) {
78. this.name = name;
79. }
80.
81. //重写equals方法
82. @Override
83. public boolean equals(Object o) {
84. if (this == o) return true;
85. if (!(o instanceof Employee)) return false;
86. Employee employee = (Employee) o;
87. return no.equals(employee.no) &&
88. name.equals(employee.name);
89. }
90.
91.
92. //重写hashCode方法
93. @Override
94. public int hashCode() {
95. //以员工编号分组
96. return this.no.hashCode();
97. }
98.
99. @Override
100. public String toString() {
101. return "Employee{" +
102. "no='" + no + '\'' +
103. ", name='" + name + '\'' +
104. '}';
105. }
106. }
1. package com.sust.cst.javase.selflearning.c20_Collection.t03_Set.m02_SortedSetAndTreeSet;
2.
3. import java.text.ParseException;
4. import java.text.SimpleDateFormat;
5. import java.util.Date;
6. import java.util.Iterator;
7. import java.lang.Object;
8. import java.util.SortedSet;
9. import java.util.TreeSet;
10.
11. /*
12. java.util.Set;
13. java.util.SortedSet; 无序不可重复,但是存进去的元素可以按照元素大小顺序自动排列
14. java.util.TreeSet;
15. */
16. public class Test01 {
17. public static void main(String[] args) throws ParseException {
18.
19. //创建集合
20. SortedSet sortedSet = new TreeSet();
21.
22. //添加元素
23. for (int i = 0; i < 6; i++) {
24. sortedSet.add((int) (Math.random() * 1000) % 100);
25. }
26.
27. //遍历
28. Iterator it = sortedSet.iterator();
29. while (it.hasNext()) {
30. System.out.print(it.next() + " ");
31. }
32. System.out.println();
33.
34. //String
35. SortedSet strSet = new TreeSet();
36.
37. String[] strings = {"Jack", "Sun", "Kook", "Lucy", "King"};
38.
39. for (int i = 0; i < strings.length; i++) {
40. strSet.add(strings[i]);
41. }
42.
43. //遍历
44. it = strSet.iterator();
45. while (it.hasNext()) {
46. System.out.print(it.next() + " ");
47. }
48. System.out.println();
49. System.out.println();
50.
51. //日期
52. String[] stime = { "2008-08-08",
53. "2009-08-08",
54. "2010-06-08",
55. "2010-04-23",
56. "2012-08-08" };
57.
58. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
59. Date[] t = new Date[5];
60. for (int i = 0; i < t.length; i++) {
61. t[i] = sdf.parse(stime[i]);
62. }
63.
64. SortedSet times = new TreeSet();
65. for (int i = 0; i < t.length; i++) {
66. times.add(t[i]);
67. }
68.
69. it = times.iterator();
70. while (it.hasNext()) {
71. Object element = it.next();
72. if (element instanceof Date) {
73. Date d = (Date) element;
74. System.out.println(sdf.format(d));
75. }
76. }
77. }
78. }
79. /* ----------- 运行结果 -----------
80. 0 1 3 19 26 61
81. Jack King Kook Lucy Sun
82.
83. 2008-08-08
84. 2009-08-08
85. 2010-04-23
86. 2010-06-08
87. 2012-08-08
88. ----------- 运行结果 ----------- */
因为被存储的元素实现了Comparable接口,SUN编写TreeSet集合在添加元素的时候,会调用CompareTo方法完成比较。
1. package com.sust.cst.javase.selflearning.c20_Collection.t03_Set.m02_SortedSetAndTreeSet;
2.
3. import java.util.Iterator;
4. import java.util.SortedSet;
5. import java.util.TreeSet;
6.
7. /*
8. SortedSet集合存储元素为什么可以自动排序?
9. */
10. public class Test02 {
11. public static void main(String[] args) {
12. SortedSet users = new TreeSet();
13.
14. User[] u = new User[5];
15. for (int i = 0; i < u.length; i++) {
16. u[i] = new User((int) (Math.random() * 100) % 20);
17. }
18.
19. //添加元素
20. for (int i = 0; i < u.length; i++) {
21. users.add(u[i]);
22. }
23. /* User类未实现Comparable接口时发生的错误
24. Exception in thread "main" java.lang.ClassCastException: class com.sust.cst.javase.selflearning.c20_Collection.t03_Set.m02_SortedSetAndTreeSet.User cannot be cast to class java.lang.Comparable (com.sust.cst.javase.selflearning.c20_Collection.t03_Set.m02_SortedSetAndTreeSet.User is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')
25. at java.base/java.util.TreeMap.compare(TreeMap.java:1291)
26. at java.base/java.util.TreeMap.put(TreeMap.java:536)
27. at java.base/java.util.TreeSet.add(TreeSet.java:255)
28. at com.sust.cst.javase.selflearning.c20_Collection.t03_Set.m02_SortedSetAndTreeSet.Test02.main(Test02.java:21)
29. */
30.
31. Iterator it = users.iterator();
32. while (it.hasNext()) {
33. System.out.println(it.next());
34. }
35. }
36. }
37.
38. class User implements Comparable {
39. int age;
40. String name;
41.
42. public User(int age) {
43. this.age = age;
44. }
45.
46. @Override
47. public String toString() {
48. return "User{" +
49. "age=" + age +
50. '}';
51. }
52.
53. //该方法程序员负责实现,SUN提供的程序已经调用了该方法
54. //需求:按照User的age排序
55. @Override
56. public int compareTo(Object o) {
57. //编写比较规则
58. int age1 = this.age;
59. int age2 = ((User) o).age;
60.
61. //return this.name.compareTo(((User) o).name);
62. return age1 - age2;
63. }
64. }
65. /* ---------- 运行结果 ----------
66. User{age=3}
67. User{age=5}
68. User{age=10}
69. User{age=16}
70. User{age=19}
71. ---------- 运行结果 ---------- */
让SortedSet集合做到排序还有另一种方式:java.util.Comparator;
单独写一个比较器
第一种方式,设计的程序和程序之间关联程度比较强,耦合度较高
第二种方式,单独写一个比较器,对原先写出的类的影响比较小,所以推荐使用"单独写一个比较器"的方式.
1. package com.sust.cst.javase.selflearning.c20_Collection.t04_Map;
2.
3. import java.util.*;
4.
5. /*
6. 关于Map中常用的方法
7.
8. void clear(); 清空Map
9. boolean containsKey(Object Key); 判断Map中是否包含这样的Key
10. boolean containsValue(Object Value); 判断Map中是否包含这样的value
11. Set
1. package com.sust.cst.javase.selflearning.c20_Collection.t04_Map;
2.
3. import java.util.Properties;
4.
5. /*
6. Hashtable默认初始化容量是 11 ,默认加载因子是 0.75
7.
8. java.util.Properties; 也是由key和value组成,但是key和value都是字符串类型
9. */
10. public class Test02 {
11. public static void main(String[] args) {
12. //创建属性类对象
13. Properties p = new Properties();
14.
15. //setProperty 存
16. p.setProperty("driver","oracle.jdbc.driver.OracleDriver");
17. p.setProperty("username","scott");
18.
19. //注意:key不能重复,如果重复则value会被覆盖
20. p.setProperty("username","aaaa");
21. p.setProperty("password","tiger");
22. p.setProperty("url","jdbc:oracle:thin:@192.168.1.100.1521:bjpowernode");
23.
24. //getProperty 取,通过key获取value
25. String v1 = p.getProperty("driver");
26. String v2 = p.getProperty("username");
27. String v3 = p.getProperty("password");
28. String v4 = p.getProperty("url");
29.
30. System.out.println(v1);
31. System.out.println(v2);
32. System.out.println(v3);
33. System.out.println(v4);
34. }
35. }
36. /* --------------------- 运行结果 ---------------------
37. oracle.jdbc.driver.OracleDriver
38. aaaa
39. tiger
40. jdbc:oracle:thin:@192.168.1.100.1521:bjpowernode
41. --------------------- 运行结果 --------------------- */
SortedMap中的key特点:无序不可重复,但是存储的元素可以按照大小自动排列。
如果想自动排序,key部分的元素需要:
1.实现Comparable接口
2.单独写一个比较器
1. package com.sust.cst.javase.selflearning.c20_Collection.t04_Map;
2.
3. import java.util.*;
4.
5. /*
6. SortedMap中的key特点:无序不可重复,但是存储的元素可以按照大小自动排列。
7. 如果想自动排序,key部分的元素需要:
8. 1.实现Comparable接口
9. 2.单独写一个比较器
10. */
11. public class Test03 {
12. public static void main(String[] args) {
13.
14. //Map,key存储商品,value存储个数
15. //SortedMap products = new TreeMap();
16.
17. //匿名内部类单独写一个比较器
18. SortedMap products = new TreeMap(new Comparator() {
19. @Override
20. public int compare(Object o1, Object o2) {
21. double price1 = ((Product)o1).getPrice();
22. double price2 = ((Product)o2).getPrice();
23. int retvalue = 0;
24.
25. if(price1 > price2){
26. retvalue = 1;
27. }else if(price1 < price2){
28. retvalue = -1;
29. }
30.
31. return retvalue;
32. }
33. });
34.
35. //准备对象
36. Product[] p = new Product[4];
37. String[] names = {"西瓜", "苹果", "桃子", "香蕉"};
38. double[] prices = {1.0, 4.0, 5.0, 3.0};
39.
40. for (int i = 0; i < p.length; i++) {
41. String proName = names[i];
42. double proPrice = prices[i];
43.
44. p[i] = new Product(proName, proPrice);
45. }
46.
47. //添加
48. double[] weight = {8.0, 3.0, 4.0, 10.0};
49.
50. for(int i = 0; i < p.length;i++){
51. products.put(p[i],weight[i]);
52. }
53.
54. //遍历
55. Set keys = products.keySet();
56. Iterator it = keys.iterator();
57. while(it.hasNext()){
58. Object k = it.next();
59. Object v = products.get(k);
60. System.out.println(k + "-->" + v + "kg");
61. }
62. }
63. }
64.
65. //实现comparable接口
66. class Product {//implements Comparable {
67. private String name;
68. private double price;
69.
70. public Product(String name, double price) {
71. this.name = name;
72. this.price = price;
73. }
74.
75. public String getName() {
76. return name;
77. }
78.
79. public void setName(String name) {
80. this.name = name;
81. }
82.
83. public double getPrice() {
84. return price;
85. }
86.
87. public void setPrice(double price) {
88. this.price = price;
89. }
90.
91. @Override
92. public String toString() {
93. return "Product{" +
94. "name='" + name + '\'' +
95. ", price=" + price +
96. "元" +
97. '}';
98. }
99.
100. /* //需求:按照商品价格排序
101. @Override
102. public int compareTo(Object o) {
103. double price1 = this.price;
104. double price2 = ((Product) o).price;
105. int rtnValue = 0;
106.
107. if (price1 < price2) {
108. rtnValue = -1;
109. } else if (price1 > price2) {
110. rtnValue = 1;
111. }
112.
113. return rtnValue;
114. }*/
115. }
116. /* ---------------- 运行结果 ----------------
117. Product{name='西瓜', price=1.0元}-->8.0kg
118. Product{name='香蕉', price=3.0元}-->10.0kg
119. Product{name='苹果', price=4.0元}-->3.0kg
120. Product{name='桃子', price=5.0元}-->4.0kg
121. ---------------- 运行结果 ---------------- */
1. package com.sust.cst.javase.selflearning.c20_Collection.t05_Collections;
2.
3. import java.util.*;
4.
5. /*
6. 关于集合工具类 java.util.Collections;
7.
8. java.util.Collections; 是一个类
9. java.util.Collection; 是集合接口
10. */
11. public class Test01 {
12. public static void main(String[] args) {
13.
14. //使用Collections工具完成集合的排序
15. List l = new ArrayList();
16.
17. //添加元素
18. l.add(10);
19. l.add(5);
20. l.add(7);
21. l.add(123);
22. l.add(3425);
23.
24. //遍历
25. System.out.println("---------- List集合排序前 ----------");
26. for (int i = 0; i < l.size(); i++) {
27. System.out.print(l.get(i) + " ");
28. }
29. System.out.println();
30.
31. Iterator it = l.iterator();
32. while (it.hasNext()) {
33. System.out.print(it.next() + " ");
34. }
35. System.out.println();
36.
37. for (it = l.iterator(); it.hasNext(); ) {
38. System.out.print(it.next() + " ");
39. }
40. System.out.println();
41. System.out.println("---------- List集合排序后 ----------");
42.
43. //排序
44. Collections.sort(l);
45.
46. //遍历
47. it = l.iterator();
48. while (it.hasNext()) {
49. System.out.print(it.next() + " ");
50. }
51. System.out.println();
52.
53. System.out.println("---------- Set集合排序前 ----------");
54.
55. //给定Set集合
56. Set s = new HashSet();
57. s.add(1);
58. s.add(3);
59. s.add(1234);
60. s.add(325);
61. s.add(1123);
62. it = s.iterator();
63. while (it.hasNext()) {
64. System.out.print(it.next() + " ");
65. }
66. System.out.println();
67.
68. //对Set集合排序
69. //Collections.sort(s);
70. /*
71. Error:(61, 20) java: 对于sort(java.util.Set), 找不到合适的方法
72. 方法 java.util.Collections.sort(java.util.List)不适用
73. (无法推断类型变量 T
74. (参数不匹配; java.util.Set无法转换为java.util.List))
75. 方法 java.util.Collections.sort(java.util.List,java.util.Comparator super T>)不适用
76. (无法推断类型变量 T
77. (实际参数列表和形式参数列表长度不同))
78. */
79.
80. //将Set集合转换成List集合
81. List listS = new ArrayList(s);
82. Collections.sort(listS);
83.
84. //遍历
85. System.out.println("---------- Set集合转换为ArrayList集合排序后 ----------");
86. for (int i = 0; i < listS.size(); i++) {
87. System.out.print(listS.get(i) + " ");
88. }
89.
90. //创建list集合,List集合中存储Person类型,是否可以排序?
91. //Collections工具类可以对List集合中的元素排序,但是集合中的元素必须是“可比较的”,实现Comparable接口
92. /*List persons = new ArrayList();
93. persons.add(new Person());
94. persons.add(new Person());
95. persons.add(new Person());
96. persons.add(new Person());
97.
98. Collections.sort(persons);*/
99. /*
100. class
101. com.sust.cst.javase.selflearning.c20_Collection.t05_Collections.Person
102. cannot be cast to
103. class
104. java.lang.Comparable
105. */
106.
107. //将ArrayList集合转换成线程安全的
108. List myList = new ArrayList();
109. Collections.synchronizedList(myList);
110. }
111. }
112.
113. class Person {
114.
115. }
116. /* -------------------- 运行结果 --------------------
117. ---------- List集合排序前 ----------
118. 10 5 7 123 3425
119. 10 5 7 123 3425
120. 10 5 7 123 3425
121. ---------- List集合排序后 ----------
122. 5 7 10 123 3425
123. ---------- Set集合排序前 ----------
124. 1 1234 3 1123 325
125. ---------- Set集合转换为ArrayList集合排序后 ----------
126. 1 3 325 1123 1234
127. -------------------- 运行结果 -------------------- */
泛型JDK5.0新特性 编译期感念
优点:统一类型,减少强制转换。
缺点:只能存储一种类型。
1. package com.sust.cst.javase.selflearning.c20_Collection.t06_Generics;
2.
3. import java.util.HashSet;
4. import java.util.Iterator;
5. import java.util.Set;
6.
7. /*
8. 以下程序不适用泛型的缺点?
9. 如果集合不适用泛型,则集合中的元素类型就不统一。
10. 在遍历集合的时候只能拿出来Object类型,需要做大量的强制类型转换,很麻烦。
11. */
12. public class Test01 {
13. public static void main(String[] args) {
14. //创建一个集合,存储ABC
15. Set s = new HashSet();
16.
17. A a = new A();
18. B b = new B();
19. C c = new C();
20.
21. s.add(a);
22. s.add(b);
23. s.add(c);
24.
25. //
26. Iterator it = s.iterator();
27. while(it.hasNext()){
28. Object o = it.next();
29. //只能做大量的强制类型转换
30. if(o instanceof A){
31. A sA = (A)o;
32. sA.m1();
33. }else if(o instanceof B){
34. B sB = (B)o;
35. sB.m2();
36. }else if(o instanceof C){
37. C sC = (C)o;
38. sC.m3();
39. }
40. }
41. }
42. }
43.
44. class A{
45. public void m1(){
46. System.out.println("A ---> m1");
47. }
48. }
49. class B{
50. public void m2(){
51. System.out.println("B ---> m2");
52. }
53. }
54. class C{
55. public void m3(){
56. System.out.println("C ---> m3");
57. }
58. }
59. /* ------- 运行结果 -------
60. B ---> m2
61. A ---> m1
62. C ---> m3
63. ------- 运行结果 ------- */
泛型是一个编译阶段的语法,在编译阶段统一集合中的类型。
1. package com.sust.cst.javase.selflearning.c20_Collection.t06_Generics;
2.
3. import com.sun.source.util.Trees;
4.
5. import java.util.*;
6.
7. /*
8. 泛型如何实现?
9. */
10. public class Test02 {
11. public static void main(String[] args) {
12. //创建一个List集合,只能存储字符串类型
13. System.out.println("\n-------- List使用泛型 --------");
14. List strs = new ArrayList();
15.
16. //添加元素
17. //strs.add(1);
18. //Error:(15, 18) java: 不兼容的类型: int无法转换为java.lang.String
19.
20. strs.add("Jack");
21. strs.add("Sun");
22. strs.add("Lucy");
23. strs.add("Sim");
24. strs.add("Lyon");
25.
26. Iterator it = strs.iterator();
27. while (it.hasNext()) {
28. String s = it.next();
29. System.out.print(s + " ");
30. }
31. System.out.println();
32.
33. /*
34. Map使用泛型
35. */
36. System.out.println("\n-------- Map使用泛型 --------");
37. Map maps = new HashMap();
38. //存
39. maps.put("西瓜", 10);
40. maps.put("苹果", 30);
41. maps.put("菠萝", 8);
42. maps.put("榴莲", 23);
43.
44. //遍历
45. Set keys = maps.keySet();
46. Iterator it2 = keys.iterator();
47. while (it2.hasNext()) {
48. String k = it2.next();
49. Integer v = maps.get(k);
50. System.out.println(k + "----->" + v);
51. }
52.
53. /*
54. SortedSet集合使用泛型
55. */
56. System.out.println("\n-------- SortedSet集合使用泛型 --------");
57. SortedSet ss = new TreeSet();
58.
59. //添加元素
60. Manager[] managers = new Manager[5];
61.
62. double[] sals = {100.0, 2200.0, 3500.0, 2453.5, 1334.0};
63. for(int i = 0; i < managers.length;i++){
64. managers[i] = new Manager(sals[i]);
65. }
66.
67. for(int i = 0; i < managers.length;i++){
68. ss.add(managers[i]);
69. }
70.
71. //遍历
72. Iterator it3 = ss.iterator();
73. while(it3.hasNext()){
74. Manager m = it3.next();
75. m.work();
76. System.out.println(m);
77. }
78.
79. }
80. }
81.
82. class Manager implements Comparable{
83. double sal;
84.
85. public Manager(double sal) {
86. this.sal = sal;
87. }
88.
89. public void work(){
90. System.out.println("在工作,一个月" + sal + "元");
91. }
92.
93. @Override
94. public String toString() {
95. return "Manager{" +
96. "sal=" + sal +
97. '}';
98. }
99.
100. @Override
101. public int compareTo(Manager o) {
102. double sal1 = this.sal;
103. double sal2 = o.sal; //此处不需要强制类型转换了
104. int retval = 0;
105.
106. if(sal1 > sal2){
107. retval = -1;
108. }else if(sal1 < sal2){
109. retval = 1;
110. }
111.
112. return retval;
113. }
114. }
115. /* ---------------- 运行结果 ----------------
116. -------- List使用泛型 --------
117. Jack Sun Lucy Sim Lyon
118.
119. -------- Map使用泛型 --------
120. 苹果----->30
121. 榴莲----->23
122. 西瓜----->10
123. 菠萝----->8
124.
125. -------- SortedSet集合使用泛型 --------
126. 在工作,一个月3500.0元
127. Manager{sal=3500.0}
128. 在工作,一个月2453.5元
129. Manager{sal=2453.5}
130. 在工作,一个月2200.0元
131. Manager{sal=2200.0}
132. 在工作,一个月1334.0元
133. Manager{sal=1334.0}
134. 在工作,一个月100.0元
135. Manager{sal=100.0}
136. ---------------- 运行结果 ---------------- */
自定义泛型
1. package com.sust.cst.javase.selflearning.c20_Collection.t06_Generics;
2. /*
3. 自定义泛型
4. */
5. public class Test03 {
6. public static void main(String[] args) {
7. MyClass mc = new MyClass();
8.
9. //泛型就是编译期检查类型
10. //Error
11. //mc.m1(100);
12. //Error:(8, 15) java: 不兼容的类型: int无法转换为java.lang.String
13.
14. mc.m1("Jack");
15. }
16. }
17.
18. //自定义泛型
19. class MyClass{//T --> Type E --> Element
20. public void m1(T t){
21. System.out.println(t);
22. }
23. }
24. /* --- 运行结果 ---
25. Jack
26. --- 运行结果 --- */
语法:
for(类型 变量:数组名/集合名){}
集合要想使用增强for循环这种语法,集合需要使用泛型
如果不使用泛型,需要用Object类型来定义集合中的元素
1. package com.sust.cst.javase.selflearning.c20_Collection.t07_foreach;
2.
3. import java.util.ArrayList;
4. import java.util.HashSet;
5. import java.util.List;
6. import java.util.Set;
7.
8. /*
9. 关于增强for循环
10. */
11. public class Test01 {
12. public static void main(String[] args) {
13. int[] a = {1,2,3,4};
14.
15. //遍历
16. System.out.println("\n* 数组使用普通方式遍历 -------------");
17. for( int i = 0; i < a.length;i++){
18. System.out.print(a[i] + " ");
19. }
20. System.out.println();
21.
22. //foreach
23. System.out.println("\n* 数组使用foreach方式遍历 ----------");
24. for(int x:a){//int x代表的是集合或者数组中的某个元素
25. System.out.print(x + " ");
26. }
27. System.out.println();
28.
29. //集合
30. Set strs = new HashSet();
31. strs.add("Jack");
32. strs.add("Lucy");
33. strs.add("Lyon");
34. strs.add("Max");
35.
36. //遍历
37. System.out.println("\n* 集合使用foreach方式遍历 ----------");
38. for(String name:strs){
39. System.out.print(name + " ");
40. }
41. System.out.println();
42.
43. //集合不使用泛型
44. System.out.println("\n* 集合使用泛型遍历 -----------------");
45. List l = new ArrayList();
46. l.add(1);
47. l.add(2);
48. l.add(3);
49. l.add(4);
50.
51. //如果集合不使用泛型,该集合在使用增强for循环的时候应该用Object类型定义
52. for(Object element:l){
53. System.out.print(element + " ");
54. }
55. System.out.println();
56. }
57. }
58. /* ---------------- 运行结果 ----------------
59. * 数组使用普通方式遍历 -------------
60. 1 2 3 4
61.
62. * 数组使用foreach方式遍历 ----------
63. 1 2 3 4
64.
65. * 集合使用foreach方式遍历 ----------
66. Max Lyon Lucy Jack
67.
68. * 集合使用泛型遍历 -----------------
69. 1 2 3 4
70. ---------------- 运行结果 ---------------- */
增强for循环的缺点:没有下标
1. package com.sust.cst.javase.selflearning.c20_Collection.t07_foreach;
2. /*
3. 关于增强for的缺点:没有下标
4. */
5. public class Test02 {
6. public static void main(String[] args) {
7. String[] ins = {"运动","音乐","旅游","美食"};
8.
9. System.out.println("\n* 使用for循环-------------");
10. StringBuffer sb1 =new StringBuffer();
11. for(int i = 0; i < ins.length;i++){
12. if(i == ins.length-1)
13. sb1.append(ins[i]);
14. else{
15. sb1.append(ins[i]);
16. sb1.append(",");
17. }
18. }
19. System.out.println(sb1);
20.
21. //以上的循环就不适合使用增强for
22. System.out.println("\n* 使用增强for循环---------");
23. StringBuffer sb2 =new StringBuffer();
24. for(String s:ins){
25. sb2.append(s);
26. sb2.append(",");
27. }
28. //截取掉最后的","
29. System.out.println(sb2.substring(0,sb2.length()-1));
30. }
31. }
32. /* ------- 运行结果 -------
33. * 使用for循环-------------
34. 运动,音乐,旅游,美食
35.
36. * 使用增强for循环---------
37. 运动,音乐,旅游,美食
38. ------- 运行结果 ------- */