目录
前言
java语言的概述
1、1995年由sun公司开发的编程语言,目前被Oracle(甲骨文)公司收购,编程语言-用来编写软件
2、B/S:互联网应用软件
C/S:桌面应用软件
移动端应用软件
3、JAVASE:标准板
JAVAEE:企业版
4、JDK:在计算中能运行java的条件
jdk:开发环境
jre:运行环境
bin/javac.exe 编译命令
bin/java.exe 运行命令
常用的DOS命令
win+R cmd
盘符: 切换盘符 d:
dir 列出当前目录下所有的文件以及文件夹
cd 文件夹名 进入某个文件夹
cd\ 返回根目录
cd.. 返回上一级目录
cls 清屏
ipconfig 查看本机的网络配置
跨平台
java程序在任意的操作系统上都可以运行,一次编译到处运行
java虚拟机JVM来实现跨平台
编写步骤
1、创建文本文件,文件名改为.java文件
2、编写代码
```
public class 类名{// 定义类
public static void main(String[] args){ //定义main方法(主程序入口)
System.out.println("HelloWorld");//输出语句(带换行)
}
}
```
类名和文件名必须保持一致(包括大小写)
java代码执行过程
1、源文件:编写java代码,扩展名为.java
2、编译:通过javac.exe,将源代码编译成字节码文件,扩展名为.class
3、运行:最后使用java.exe,将字节码文件进行运行
注释
用来解释说明程序的文字,注释是不会被执行的
单行注释: //注释内容
多行注释: /* 注释内容 */
文档注释: /** 注释内容 */
注意:文档注释可以通过Javadoc命令把文档注释中的内容生成文档,并输出到HTML文件中,方便记录程序信息,非常方便
关键字
一些带有特殊含义的单词,具有专门用途的,字母全部是小写
public class static void等
标识符
就是自定义字符序列,类,接口,方法,变量等等取名的规则
英文大小写字母、数字、 _ $
数字不能开头、不可以使用关键字、严格区分大小写、没有长度限制、见名之意
变量、方法:小驼峰命名法 addStudent
类名、接口:大驼峰命名法 HelloWorld
常量:均为大写
包名:全为小写 aaa.bbb.ccc
数据类型
8bit=1b
1024b=1kb
1024kb=1MB
1024MB=1GB
1024GB=1TB
1024TB=1PB
基本数据类型(4类8种)
整数
byte
8bit
-128~127
short
16位
-32768~32767
int
32位
默认类型
long 64位
小数(浮点)
float
double
默认类型
字符
char
布尔 boolean
true
false
引用数据类型
数组、类、接口、枚举
常量
不可变的数据量
变量
可变的数据量,是一个内存中的小盒子,用来存放数据和取出数据
数据类型 变量名=值;
变量的注意事项:
1、变量不赋值不能使用(在使用之前必须赋值)
2、在一个作用域中变量名不能重复定义
3、变量使用的时候是有作用域概念的
数据类型转换
自动类型转换:小类型转大类型,会自动转换
强制类型转换:大类型转小类型
范围小的数据类型 变量名=(范围小的数据类型)范围大的数据类型;
运算符
算术运算符
+ - * / % ++ --
+在字符串中是"连接符"
/是取商、%是取余
++、--在自身运算时前后没有任何区别,在参与运算时,在前先进行自增,后运算,在后先运算,后自增
赋值运算符
= += -+ *= /= %=
int i=10; i+=10; i=i+10
比较运算符
== != < > <= >=
结果必须是boolean类型
逻辑运算符
&(与) |(或) !(非) &&(短路与) ||(短路或)
与、或、短路与、短路或左右两侧必须是boolean类型,结果也必须是boolean类型
**&**:左右两侧有一侧为false,那么结果就为false
**|**:左右两侧有一侧为true,那么结果就为true
**&&**:左右两侧有一侧为false,那么结果就为false,如果第一个结果为false,那么后面不会进行计算,效率更高
**||**:左右两侧有一侧为true,那么结果就为true,如果第一个结果为true,那么后面不会进行计算,效率更高
**!**:取反
三元运算符
**(条件表达式)?表达式1:表达式2;**
条件表达式:boolean类型的内容
表达式1:如果条件表达式结果为true,执行的内容
表达式2:如果条件表达式结果为false,执行的内容
引用数据类型_Scanner类
接受用户键盘输入的类
1、导包 import java.util.Scanner;
2、创建变量 Scanner sc=new Scanner(System.in);
3、使用功能 变量名.nextInt();
nextInt():接受用户输入的整数
nextDouble():接受用户输入的小数
next():接受用户输入的字符串
if语句
做程序判断的,如果if条件为true,那么执行if体,否则不执行(执行else体)
```
if(条件表达式){
if体;
}
```
```
if(条件表达式){
if体;
}else{
else体;
}
```
```
if(条件表达式){
if体;
}else if(条件表达式){
else体;
}else if(条件表达式){
else体;
}...
else{
}
```
循环语句
循环的必要条件:初始化变量、判断条件、自增量```
while循环
```
while(条件表达式){
循环体;
}
```
do while循环
```
do{
循环体;
}while(条件表达式);
```
for循环
```
for(初始化变量;判断条件;自增量){
循环体;
}
```
手动死循环
while(1==1){
}
for(;true;){
}
```
break:跳出所在的循环体
continue:提前结束本次循环,继续下次循环
```
嵌套循环
for(){
for(){
}
}
```
引用数据类型_Random类
程序产生随机数
1、导包 import java.util.Random;
2、创建变量 Random rd=new Random();
3、使用功能 变量名.nextInt(范围);
switch
针对某个表达式的值做出匹配,从而决定执行哪一段代码
```
switch(表达式){
case 常量1:
执行的语句;
break;
case 常量2:
执行的语句;
break;
case 常量3:
执行的语句;
break;
default:
执行的语句;
break;
}
```
switch中表达式可以接受的数据类型:byte、short、int、char、enum、String
switch具有穿透性
数组
数据的容器,用来存放数据的,**是一个引用数据类型**
数据类型[] 数组名=new 数据类型[长度];
数据类型[] 数组名=new 数据类型[]{值1,值2,值3...};
数据类型[] 数组名={值1,值2,值3...};
**数组创建的注意事项**:确定数组的数据类型、[]必须写、长度必须确定
**数组取值**:数组名[索引]; 索引是从0开始的
**数组赋值**:数组名[索引]=值;
**数组的长度**:数组名.length
数组中常见异常:NullPointerException空指针异常
ArrayIndexOutOfBoundsException:数组索引越界异常
方法
就是解决问题的办法,提高代码的复用性
方法定义的格式
修饰符 返回值类型 方法名(参数类型 参数名,参数类型 参数名...){
方法体;
[return 返回值;]
}
修饰符:public static
返回值类型:方法运行结果的数据类型。
方法名:符合标识符命名规则,按照小驼峰命名法进行命名。
参数类型、参数名:方法运行时是否有未知数。
方法体:就是方法的具体实现。
return:返回方法的结果;
结束方法。
方法的调用
方法在定义完之后不会自动执行的,需要手动"调用"
直接写方法名就是调用方法
方法定义和使用的注意事项
1、方法不能定义在另一个方法里面
2、方法名字写对
3、写对方法的参数列表
4、方法如果没有返回值,定义时写void,在方法中可以省略return关键字,return下面不能有代码
5、方法返回值的数据类型和return后面的数据类型必须匹配
6、方法名不能重复定义(除非使用方法的重载)
方法的重载
在一个类中,方法名相同,参数列表不同(数量、数据类型、顺序)
方法的重载和返回值无关
方法的重载和修饰符无关
方法的重载和形参无关
重载只需要关注方法名和参数列表即可
方法的参数是基本数据类型时,传递的是 值
方法的参数是引用数据类型,传递的是 内存地址
引用数据类型——类
自定义类和java提供的类
现实事物的抽象表述形式,可以通过java的类来实现
事物由属性和功能两部分组成
属性:这个事物具备的特性
功能(方法):这个事物具备的功能
```
public class 类名{
定义属性
修饰符 数据类型 变量名;
方法定义
修饰符 返回值类型 方法名(参数列表){
}
}
```
使用:
1、导包 类在同一文件夹下,不需要导包
2、创建对象(变量)
3、使用功能(变量)
面向对象和面向过程
是一种编写程序的思维方式
面向过程是遇到一件事时,思考"我该怎么做",然后一步步实现的过程
面向对象是遇到一件事时,思考"我该让谁来做",而"谁"就是对象,用对象来完成这件事情
面向对象的好处
符合人类思考的习惯
更多体现的是指挥者
将复杂的问题简单化
面向对象的三大特点
封装、继承、多态
成员变量和局部变量的区别
1、定义的位置不同
成员变量定义在类中
局部变量定义在方法或者{}中
2、在内存的位置不同
成员变量在堆内存中存储
局部变量跟随方法在栈内存中存储
3、生命周期不同
成员变量随着方法出现在堆中,随着对象的消失从堆中消失
局部变量随着方法运行在栈中,随着方法的弹栈而消失
4、初始化不同
成员变量在堆中,有默认的初始值
局部变量没有默认初始值,必须手动赋值才可以使用
封装
方法就是一个最基本的封装体
类其实也是一个封装体
封装的好处
提高了代码的复用性
隐藏了实现的细节,还要对外提供可以访问的方式,便于调用者使用
提高了安全性
getxxx和setxxx方法
在案例中,发现Person类的age属性如果直接赋值的话,可能会有安全问题,所以通过判断可以解决此问题。但是复用性得不到解决,所以我们将判断的语句封装成方法写到自定义类中,对成员变量进行私有化(private),对外提供访问的setxxx()和getxxx()方法。通过这两个方法,对成员变量进行赋值和取值操作。建议自定义类中,对所有的成员变量进行封装。
继承
概念:描述事物之间所属的关系(类和类),通过继承可以使多种事物之间形成一种关系
特点:子类会自动拥有父类"让你拥有的"属性和方法
父类private修饰的属性和方法,子类也不能使用
继承格式
class 子类 extends 父类{}
继承的好处
1、继承的出现提高了代码的**复用性**,提高了软件开发的效率
2、继承的出现让类于类之间产生关系,为多态提供了前提
继承的注意事项
1、在Java中,类只支持单继承,一个类只能有一个直接父类(因为在调用的时候分不清哪个父类方法)
2、在java中,是支持多重继承的,a extends b b extends c
继承的体系
每个事务具有共性进行向上抽取,形成父类
父类:具有所有子类的共性内容
子类:不但具有父类的内容还具有自身的特点
分析的时候,由下向上分析
实现的时候,由上往下实现
继承之后子类成员变量的特点
1、子类的对象调用成员变量的时候,子类自己有,使用自己的,子类没有则调用父类的
2、子类和父类拥有相同名字的成员变量,在子类中,默认调用子类的成员变量(this.成员变量),如果想调用父类的变量,则加super.成员变量调用
继承之后成员方法的特点
1、子类对象调用方法的时候,子类自己有,使用自己的,子类没有调用父类的
2、如果子类父类方法名相同,那么子类会自动**重写**父类的方法
方法的重写
在继承关系中,子类和父类的方法完全相同,子类就会自动覆盖重写父类的方法
重写的注意事项
子类方法覆盖重写父类方法,必须保证权限大于等于父类权限
public>默认>protected>private
重写要注意参数列表一致
方法重写的返回值如果是基本数据类型,子类和父类返回值必须相同
方法重写的返回值如果是引用数据类型,子类的重写方法返回值可以与父类相同或者是父类返回值的子类
**完全一致即可**
抽象类
抽象类的产生
在分析事物的时候,发现了共性内容,进行向上抽取。但是,有一些共性抽取出来的方法,声明相同,但是方法的主体不同,所以此方法没法进行具体化实施,所以这个方法就是一个 抽象方法。
只要类中含有抽象方法,那么这个类就必须是**抽象类**,抽象类中既可以拥有抽象方法也可以拥有普通方法。
```
public abstract class 类名{
public abstract 返回值类型 方法名(参数列表);
}
```
子类继承父类,如果该父类是**抽象类**,那么子类必须覆盖重写父类中所有的抽象方法
抽象类的特点
·抽象类能不能创建对象?
不能。因为抽象创建对象没有意义
·为甚么子类必须覆盖重写父类抽象方法?
因为子类是要创建对象的,因为有继承关系,所以直接调用父类抽象方法没意义,所以必须重写,只有覆盖重写了抽象类中所有的抽象方法,其子类才能创建对象,否则该子类还是一个抽象类
之所以使用抽象类,更多的体现在思想,是对共性内容的简单化操作
抽象类一定是父类: √
抽象类中可不可以没有抽象方法: 可以
关键字abstract和哪些关键字不能共存?
private final static
接口
就是多个类的公共规范
是一个引用数据类型,最重要的内容是抽象方法
换成关键字interface之后,编译成的字节码文件依然是 .java->.class
jdk7:常量、抽象方法
public static final 变量名=值;
public abstract 返回值类型 方法名();
jdk8:常量、抽象方法、默认方法、静态方法
public default 返回值类型 方法名(){} 一般用于接口升级,不要求 强制重写,但是可以重写,也可以直接使用
public static 返回值类型 方法名(){} 直接通过接口名.进行使用
jdk9:常量、抽象方法、默认方法、静态方法、私有方法
private 返回值类型 方法名(){} 一般用于接口方法内部使用
接口的使用步骤
接口不能直接创建对象,必须要有实现类来实现接口
```
public class 实现类名称Impl implements 接口名称{
重写接口中的抽象方法
}
```
接口的实现类必须覆盖重写接口中所有的抽象方法,如果实现类并没有覆盖重写完接口中所有的抽象方法,那么这个实现类必须是抽象类。
接口的注意事项
1、类与接口之间是多实现的,一个类可以实现多个接口
2、接口和接口之间是多继承
3、多个父接口中的默认方法如果重复,那么实现类必须进行默认方法的覆盖重写
4、多个父接口中的默认方法如果重复,那么子接口必须进行默认方法的覆盖重写(必须带default)
5、接口是没有静态代码块或者构造方法的
6、如果实现类所实现的多个接口中,存在重复的抽象方法,那么只需要覆盖重写一次即可
7、一个类可以继承一个直接父类,同时实现多个接口,如果接口中的默认方法和父类的普通方法相同, 那么优先使用父类的
多态
多种形态,指同一行为,具有不同的表现形式
父new子,父类引用指向子类对象
```
父类的类型 变量名=new 子类对象();
接口类型 变量名=new 实现类对象();
```
**通过多态直接访问成员变量:**看等于号左边是谁,优先使用谁,没有则向上找
**通过多态间接访问成员变量:**看等于号左边方法属于谁,优先使用。但是,子类重写之后,则属于等于号右边
**通过多态访问方法的规则:**如果在子类重写父类的情况下,看new的是谁,就会优先使用谁,没有则向上找
成员变量:编译看左边,运行看左边
成员方法:编译看左边,运行看右边
多态的好处
无论右边new的时候换成那个子类对象,等于号左边调用的方法都不会发生变化
多态的转型
·向上转型:一定安全,右侧创建一个子类对象,把它当做是父类进行看待
父类名称 对象名=new 子类名称();
小范围转向的大范围 double d=100;
·向下转型:一个还原操作,将父类对象,还原成子类本来的对象
子类类型 对象名=(子类类型)父类对象名;
int i=(int)3.14; 相对有一定的风险,转换失败会抛出异常ClassCastException
·如何才能知道一个父类引用对象,本来是什么类型?
```
对象 instanceof 类名称
```
会得到一个boolean值的结果,来判断原本是什么类型
final关键字
最终关键字
final关键字可以修饰变量: 就会变成常量,不能重新赋值,全部大写
final关键字可以修饰方法: 此方法不能被重写
final关键字可以修饰类: 太监类,不能被继承
final关键字可以修饰对象: 锁定对象内存地址
权限修饰符
public 公开的
protected 受保护的
default(不能写) 默认的
private 私有的
private | public | protected | default | |
同一类中 | √ | √ | √ | √ |
同一包中(子类与无关类) | × | √ | √ | √ |
不同包的子类 | × | √ | √ | × |
不同包的无关类 | × | √ | × | × |
成员变量建议使用private,隐藏细节,提高安全性
方法建议使用public,方便调用
构造方法建议使用public,方便创建对象
内部类
一个类中定义另外一个类,里面的类就称之为内部类,外面的类称之为外部类
```
成员内部类:定义在类中方法外的类
class 外部类{
class 内部类{
}
}
```
```
外部类名.内部类名 对象名=new 外部类类型().new 内部类类型();
```
内部类可以直接访问外部类的成员,包括私有成员
外部类要访问内部类成员,必须创建内部类对象
```
局部内部类:在一个类的方法中定义一个类
class 外部类{
public void 方法名(){
class 内部类{
}
}
}
```
匿名内部类
匿名对象:在调用方法的时候,只能调用唯一的一次,如果希望同一对象调用多次方法,那么必须给这个对象起名字
匿名内部类:如果接口的实现类(或者父类的子类)只需要使用唯一的一次,那么这种情况下就可以省略掉该类的定义,改为使用匿名内部类
```
接口名称 对象名=new 接口名称(){
重写接口中所有的抽象方法
}
new:代表创建对象的动作
接口名称():是代表要实现哪个接口
{}:里面的内容就是重写的内容
```
构造方法
作用: 在new对象的同时给成员变量赋值,给对象属性进行初始化值
构造方法的格式
```
修饰符 构造方法名(参数列表){
}
```
构造方法的体现
1、构造方法没有返回值类型,也不需要写返回值,void都不能写
2、构造方法名称必须和类名保持一致
3、每一个类都必须有一个构造方法,构造方法不写也有
当编译器javac编译类的时候,会自动检查有没有构造方法,如果没有,编译器会自动创建一个空的构造方法
如果检查的时候有构造方法,那么编译器将不会自动创建构造方法
构造方法执行几次:每创建一个对象,构造方法就会执行一次
什么时候执行:创建对象的时候会自动执行
构造方法之间的调用
this(参数列表);
this. 本类调用 this() 本类构造方法调用
super(参数列表);
super. 父类成员调用 super()父类构造方法调用
注:this()和super()都必须在代码的第一行编写
构造方法和一般方法的区别
1、格式不同
2、作用不同 构造方法一般用来给成员变量初始化
3、调用方式不同 构造方法创建对象的时候调用,或者this()、super()调用
普通方法需要的时候通过对象或者静态调用
4、执行不同 构造方法在创建对象的时候只执行一次
普通方法可以使用对象多次调用
String类
字符串,是属于类的引用数据类型
在API中,我们发现几个重要的特点:
1、字符串内容永不可变
2、正是因为字符串不可变,所以字符串是可以**共享**的
3、字符串效果上相当于char[],但是底层是byte[]
创建字符串的3+1方式:
`String()` 初始化新创建的 `String`对象,使其表示空字符序列。
String(char[] value)` 分配一个新的 `String` ,以便它表示当前包含在字符数组参数中的字符序列。
String(byte[] bytes)` 通过使用平台的默认字符集解码指定的字节数组来构造新的 `String` 。
String str="abc"; **直接写上双引号,就是字符串对象**
==对于基本数据类型来说,比较的是值是否相同
==对于引用数据类型来说,比较的是内存地址是否相同
String常用方法
boolean equals(Object obj):比较字符串值是否相同
boolean equalsIgnoreCase(String str):比较字符串值是否相同,忽略大小写
int length():获取字符串个数
String concat(String str):连接字符串
char charAt(int index):获取指定索引的单个字符
int indexOf(String str):查找参数字符串在本字符串中首次出现的索引 ,没有返回-1
String subString(int index):截取字符串,从参数的位置一直到字符串的末尾,返回一个新的字符串
String subString(int beginindex,int endindex):截取字符串,从参数的beginindex开始,到endindex结束,返回一个新的字符串(包头不包尾)
char[] toCHarArray():将字符串拆分成字符数组
byte[] getBytes():将字符串转为底层字节数组
String replace(String str,String str1):替换字符串
String[] split(String str):通过参数规则,将字符串切分成若干份
static静态关键字
可以通过类名、接口名直接访问静态修饰的方法和变量
如果一个成员变量使用了static关键字,那么这个变量将**不属于"对象"**,**属于所在的"类"**,多个对象可以**共享**同一份数据
静态不能访问非静态: 因为静态出现的时间要早,而非静态晚一些。
静态方法中能否使用关键字this? 不能,因为this代表的是本类对象,而静态方法出现的时间要比this早
静态代码块
```
public class 类名{
static{
静态代码块内容
}
}
```
当第一次使用到类的时候,静态代码块就会执行唯一的一次
静态内容总是优先于非静态,所以静态代码块比构造方法先执行
用来一次性对静态成员变量赋值
Object
java.lang.Object类是java语言中的根类,是所有类的父类,其中所有的方法子类都可以使用
public String toString():返回对象的字符串表述形式(默认输出内存地址)
将对象名直接输出实际上就是默认调用此方法
通过String类的理解,发现输出内存地址没有意义,所以我们自定义类需要重写此方法来提高作用。将自定义类中的成员变量进行输出
public boolean equals(Onject obj):默认比较内存地址是否相同。和==号的作用是一样的
自定义方法需要重写此方法来比较成员变量是否相同
先判断是否为null,在判断是否是自己,最后强转,进行成员变量比较
在自定义类中需要添加的内容:成员变量封装、空参有参构造方法、重写的toString和equals方法
BigDecimal
在java.math包中提供的对超过16位有效位数的数字进行精确的运算
构造方法:
`BigDecimal(String val)` :将字符串转为大的十进制数字
通用方法:
static BigDecimal valueOf(double d):将浮点数转为BigDecimal
BigDecimal add(BigDecimal b):相加
BigDecimal subtract(BigDecimal b):相减
BigDecimal multiply(BigDecimal b):相乘
BigDecimal divide(BigDecimal b):相除。如果不能整除,有余数,会出现ArithmeticException
BigDecimal divide(BigDecimal b,保留的小数位,舍入的模式)
BigDecimal setScale(保留的小数位,舍入模式)
Date类
表示特定的瞬间,精确到毫秒 1秒=1000毫秒
构造方法:
Date():获取当前时间,以特定格式输出
Date(Long date):通过参数传递的毫秒值,得出时间
格林威治时间,时间原点 1970年1月1日 00:00:00 东八区 1970年1月1日 08:00:00
long getTime():获取时间的毫秒数
DateFormat类
日期,时间格式化的抽象类,不能直接使用,需要通过子类SimpleDateFormat进行实现
构造方法:
SimpleDateFormat(格式):通过参数将日期格式化
String format(Date d):通过参数中的日期进行格式化 **将日期转文本**
Date parse():将文本转为日期
Calendar日历类
封装了所有可能用到的时间相关信息,替换掉了Date类的许多方法
Calendar为抽象类,不能直接使用,可以通过静态方法getInstance()来获取日历
int get(int field):返回给定日历字段的值
void set(int field,int value):给日历中的字段设置值
void add(int field,int value):通过日历中的字段进行偏移量的增加或减少,正数为增加,负数为减少
Date getTime():返回Date类型的时间值
System类
是一个与系统相关的类,里面有大量的静态方法
```
System.currentTimeMillis():获取当前时间,以毫秒数计算
```
```
System.arraycopy():复制数组
```
StringBuilder和StringBuffer
字符串缓冲区,执行速度要比String快
默认16个字符空间,自动扩充
StringBuilder append():添加任意数据类型的字符串形式,返回当前对象本身,可以使用链式编程的方式
StringBuffer线程安全(速度慢),StringBuilder线程不安全(速度快)
包装类
基本数据类型与对应的包装类之间,来回转换的过程称之为装箱和拆箱
·装箱:从基本数据类型转为对应的包装类对象**
1、通过构造方法进行装箱
2、valueOf()进行转化
·拆箱:从包装类对象转换为对应的基本数据类型**
intValue()
·自动装箱和自动拆箱**
·基本数据类型和字符串的转化**
1、+”“
2、String.valueOf()
·字符串和基本数据类型的转化**
所有包装类都有自己的parsexxx(String str)方法,可以将字符串转为想要的基本数据类型
异常
java代码中在运行时期发生的问题就是异常
Throwable:是所有错误和异常的祖宗类
Error:错误
Exception:异常 编译期异常,在java程序编译的时候出现的问题
RuntimeException:运行期异常,java程序在运行过程中出现的问题
异常分为两大类:运行时异常和编译时异常
·运行时异常:编译器检查不出来,一般指编程时代的逻辑错误,是程序员应该避免出现的异常。java.lang.RuntimeException类及它的子类都是运行时异常;对于运行时异常,可以不作处理,因为这类异常很普通,若处理可能对程序的可读性和运行效率产生影响。
·编译时异常:是编译器要求必须处置的异常。
Throw关键字:指定方法中抛出指定的异常
在方法中写入throw new xxxException("异常产生原因");
Throw关键注意事项:
1、必须写在方法的内部
2、throw关键字后边new的对象必须是Exception或者是Exception的子类对象
3、抛出的异常我们需要处理
如果是运行期异常,那么我们可以不强制进行处理,由JVM处理也可以
如果是编译期异常,那么我们必须手动处理throws,try...catch
常见的运行时异常:
1、NullPointerException 空指针异常
2、ArithmeticException 数学运算异常
3、ArrayIndexOutOfBoundsException 数组下标越界异常
4、ClassCastException 类型转换异常
5、NUmberFormatException 数字格式不正确异常
常见的编译时异常:
1、SQLException 操作数据库时,查询表可能发生异常
2、IOException 操作文件时发生的异常
3、FIleNOtFoundException 当操作一个不存在文件时发生的异常
4、ClassNOtFoundException 加载类而类不存在时发生的异常
5、EOFException 操作文件,到文件末尾发生的异常
异常处理的方式
1、try...catch...finally 程序员在代码中捕获发生的异常,自行处理
2、throws 将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者是JVM
throws关键字
Throws关键字:异常处理的一种办法,交给别人处理
当方法的内部抛出异常对象的时候,那么我们就必须处理这个异常对象
可以使用throws关键字处理异常对象
注意事项:
1、必须写在方法声明处
2、后边的异常必须是Exception或者是Exception的子类对象
3、方法内部如果抛出多个异常对象,那么throws后边也必须声明多个异常,如果多个异常对象存在继承关系,那么抛出父类异常就可以
try...catch...finally...
基本语法:
try{
可疑代码,将异常生成对应的异常对象,传递给catch块
}catch{
对异常的处理
}//没有finally,语法上也可以通过
注意事项:
1、如果异常发生,异常发生后面的代码不会执行,直接进入catch块
2、如果异常没有发生,顺序执行try的代码块,不会进入catch块
3、如果希望不管异常是否发生,都执行代码,就用finally
4、可以有多个catch语句,捕获不同的异常,要求父类异常在后,子类异常在前
自定义异常
定义: 当程序中出现了某种“错误”但该错误信息并没有在Throwable子类中描述处理,这个时候可以自己设计异常类,用于描述该错误信息。
步骤:
1、定义类:自定义异常类名 继承Exception或RuntimeException
2、如果继承Exception,属于编译异常
3、如果继承RuntimeException,属于运行异常
集合
·如果继承Exception,属于编译异常
·提供了一系列方法,方便操作对象
集合和数组:
1、长度:数组不可变;集合可变。
2、内容:数组可以是基本数据类型,也可以是引用数据类型;集合只能是引用数据类型。
Collection
Collection集合的方法
package com.hxzy;
import java.util.ArrayList;
import java.util.List;
public class text {
@SuppressWarnings({"all"})
public static void main(String[] args){
List list = new ArrayList();
//add 添加
list.add("jack"); //add 添加
list.add(10); //list.add(new Integer(10))
list.add(true);
System.out.println("list="+list);
//remove 删除
list.remove(0); //索引并删除第一个元素
list.remove(true); //指定删除某个元素
System.out.println("list="+list);
//contains 查找元素是否存在
System.out.println(list.contains("jack"));
//size 获取元素个数
System.out.println(list.size());
//isEmpty 判断是否为空
System.out.println(list.isEmpty());
//clear 清空
list.clear();
System.out.println("list="+list);
//addAll 添加多个元素
ArrayList list1 = new ArrayList();
list1.add("红楼梦");
list1.add("三国演义");
list.addAll(list1);
System.out.println("list="+list);
//containsAll 查找多个元素是否存在
System.out.println(list.containsAll(list1));
//removeAll 删除多个元素
list.add("聊斋");
list.removeAll(list1);
System.out.println("list="+list);
}
}
Collection接口遍历元素的方式
1、迭代器Iterator
(1)Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。
(2)所有实现了Collection接口的集合类都有一个Iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器。
(3)Iterator仅用于遍历集合,Iterator本身并不存放对象。
Iterator iterator = collection.iterator();
// hasNext() 判断是否还有下一个元素
while(iterator.hasNext()){
//next() 作用:1、下移 2、将下移以后集合位置上的元素返回
System.out.println(iterator.next());
}
package com.hxzy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Objects;
public class text {
@SuppressWarnings({"all"})
public static void main(String[] args){
Collection collection = new ArrayList();
collection.add(new Book("三国演义","罗贯中",10.1));
collection.add(new Book("小李飞刀","古龙",5.1));
collection.add(new Book("红楼梦","曹雪芹",34.6));
System.out.println(collection);
//遍历集合 1、先得到对应的迭代器
Iterator iterator = collection.iterator();
// 2、使用while循环遍历
while (iterator.hasNext()){ //判断是否还有数据
//返回下一个元素,类型是Object
Object obj = iterator.next();
System.out.println(obj);
}
// 3、当退出while后,这时Iterator迭代器,指向最后的元素 iterator.next(); //NotSuchElementException
// 4、如果希望再次遍历,需要重置迭代器
iterator = collection.iterator();
System.out.println("第二次遍历");
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
}
}
class Book {
private String name;
private String author;
private double price;
public Book(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
public String getName() {
return name;
}
public String getAuthor() {
return author;
}
public double getPrice() {
return price;
}
public void setName(String name) {
this.name = name;
}
public void setAuthor(String author) {
this.author = author;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
}
2、for循环增强
增强for循环就是简化版的Iterator,本质相同,只能用来遍历数组或集合。
基本语法:
for(元素类型 元素名 :数组名或集合名)
{
访问元素
}
package com.hxzy;
import java.awt.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class text {
@SuppressWarnings({"all"})
public static void main(String[] args){
//1、创建3个Dog{name,age}对象,放入到Arraylist中,赋给List引用
//2、用迭代器和增强for循环两种方式来遍历
//3、重写Dog的toString方法,输出name和age
List list = new ArrayList<>();
list.add(new Dog("小黄",10));
list.add(new Dog("大壮",12));
list.add(new Dog("狗子",3));
//利用for增强
for (Object Dog:list){
System.out.println(Dog);
}
//使用迭代器
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object dog = iterator.next();
System.out.println(dog);
}
}
public static class Dog{
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
}
List
List接口
List接口是Collection接口的子接口
(1)List集合类中元素有序(添加顺序与取出顺序一致)、可重复添加。
(2)List容器中的元素都对应一个整数型的序号记载其在容器内的位置,可根据序号存取容器中的元素。
package com.hxzy;
import java.util.ArrayList;
import java.util.List;
public class text {
@SuppressWarnings({"all"})
public static void main(String[] args){
List list = new ArrayList<>();
list.add("jack");
list.add("tom");
list.add("mary");
list.add("java");
System.out.println(list);
System.out.println(list.get(3));
}
}
List接口的常用方法
package com.hxzy;
import java.util.ArrayList;
import java.util.List;
public class text {
@SuppressWarnings({"all"})
public static void main(String[] args){
List list = new ArrayList<>();
list.add("张三丰");
list.add("贾宝玉");
// void add(int index,Object ele); 在index位置插入ele元素
list.add(1,"李四");
System.out.println(list);
// boolean addAll(int index,Collection eles); 从index位置开始将eles中的所有元素添加进来
List list1 = new ArrayList();
list1.add("张三");
list1.add("王五");
list.addAll(1,list1);
System.out.println(list1);
// Object get(int index); 获取指定index位置的元素
// int indexOf(Object obj); 返回obj在集合中首次登场的位置
System.out.println(list.indexOf("张三丰"));
// int lastIndexOf(Object obj); 返回obj在当前集合中末次出现的位置
list.add("张三丰");
System.out.println(list);
System.out.println(list.lastIndexOf("张三丰"));
// Object remove(int index); 移除指定index位置的元素,并返回此元素
list.remove(0);
System.out.println(list);
// Object set(int index,Object ele); 设置指定index位置的元素为ele,相当于替换
list.set(1,"tom");
System.out.println(list);
// List subList(int fromIndex,inttoIndex); 返回从fromIndex到toIndex位置的子集合
List returnlist = list.subList(0,2); // 返回的子集合 fromIndex <= sublist < toIndex
System.out.println(returnlist);
}
}
List接口的三种遍历方式
1、Iterator迭代器
2、增强for循环
3、普通for循环
ArrayList
用于存放数据的,比数组的可扩展性高
1、导包 import java.util.ArrayList;
2、创建对象(变量) ArrayList<数据类型> 变量名=new ArrayList<>();
3、使用功能(变量)
add(数据类型 变量名):通过参数将值存储到集合中
数据类型 get(索引):通过索引取值
int size():返回集合的长度
remove(int index):通过索引删除集合中的元素
clear():清空集合中所有的元素
set(int index,修改之后的值):
ArrayList中只能存储引用数据类型,所以java提供了8中基本数据类型的引用数据类型
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
Vector
底层:对象数组
线程是同步的,即线程安全(在开发中,需要线程同步安全时,考虑使用Vector)
Arraylist 不安全,效率高
Vector 安全,效率不高
LinkedList
1、LinkedList底层实现了双向链表和双端队列特点
2、可添加任何元素(元素可重复),包括null
3、线程不安全,没有实现同步
底层操作机制
1、LinkedList底层维护了一个双向链表
2、LinkedList中维护了两个属性first和last分别指向首节点和尾节点
3、每个节点(Node对象)里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点,最终实现双向链表
4、LinkedList中对元素的删除和添加,不是通过数组完成的,相对来说效率较高
注:Node是一个自定义的节点类,用于构建数据结构(链表、二叉树等)。Node一般包含两个主要属性:数据(value)和指向下一个节点的引用(next)。
public class text {
public static void main(String[] args) {
Node jack = new Node("jack");
Node tom = new Node("tom");
Node jon = new Node("jon");
jack.next = tom;
tom.next = jon;
jon.pre = tom;
tom.pre = jack;
Node first = jack;
Node last = jon;
while (true){
if(first == null){
break;
}
System.out.println(first);
first = first.next;
}
while (true){
if (last == null){
break;
}
System.out.println(last);
last = last.pre;
}
}
}
class Node{ //定义一个Node类,Node对象表示双向链表的一个节点
public Object item; //真正存放数据
public Node next; //后一个节点
public Node pre; // 前一个节点
public Node(Object name){
this.item = name;
}
@Override
public String toString() {
return "Node name="+item;
}
}
LinkedList的增删改查案例
package com.sxny;
import java.util.LinkedList;
public class text {
public static void main(String[] args) {
LinkedList<Object> objects = new LinkedList<>();
objects.add(1);
objects.add(2);
objects.add(3);
System.out.println(objects);
objects.remove(); // 默认删除第一个节点
System.out.println(objects);
// Object.remove(2); 异常
objects.remove(1);
System.out.println(objects);
//修改某个节点对象
objects.set(0,333);
System.out.println(objects);
// 得到某个节点对象
Object o = objects.get(0);
System.out.println(o);
}
}
Arraylist 可变数组 增删 效率较低 数组扩容 改查 效率较高
LinkedList 双向列表 增删 效率较高 通过链表追加 改查 效率较低
(一般来说,在程序中,大多是查询,因此选择Arraylist较多)
Set接口和常用方法
特点: 1、无序(添加和取出顺序不一致,没有索引)
2、不允许添加重复元素,只能有一个null
3、实现类有 HashSet、 TreeSet
常用方法: Set接口是Collection的子接口,常用方法与Collection接口一样
遍历方式: 1、迭代器 2、增强for循环
注:不能使用索引的方式获取,无序
Set常用方法举例:
import java.util.HashSet;
public class text {
public static void main(String[] args) {
HashSet<Object> objects = new HashSet<>();
for (int i=0;i<10;i++){
objects.add(i);
}
objects.add(null);
// objects.add(1); 重复元素
// 增强for循环遍历
for (Object o:objects){
System.out.print(" "+o);
}
objects.remove(1);
System.out.println(objects);
}
一、Set接口实现类 HashSet
import java.util.HashSet;
public class text {
public static void main(String[] args) {
HashSet hashSet = new HashSet();
// 在执行add方法后,会返回一个boolean值,成功返回true,失败返回false
System.out.println(hashSet.add("john"));
System.out.println(hashSet.add("tom"));
System.out.println(hashSet.add("jack"));
System.out.println(hashSet.add("rose"));
hashSet.add("mike");
// 通过remove指定删除某个对象
hashSet.remove("john");
System.out.println(hashSet);
hashSet = new HashSet<>();
System.out.println(hashSet); // 空
hashSet.add("lucy");
hashSet.add("lucy"); // 只能存在一个
hashSet.add(new Dog("小黑"));
hashSet.add(new Dog("小黑")); // 相当于创建了两个对象,因此可以添加成功
System.out.println(hashSet);
hashSet.add(new String("hsp"));
hashSet.add(new String("hsp")); // ??? 不清楚String为啥不能添加
System.out.println(hashSet);
}
}
class Dog{
private String name;
public Dog(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
'}';
}
}
HashSet底层机制 ???
练习
定义一个Employee类,该类包含 name ,age 要求:
创建3个Employee对象放入HashSet中,name和age的值相同时,认为相同员工,不能添加到HashSet集合中
import java.util.HashSet;
import java.util.Objects;
public class text {
public static void main(String[] args) {
// 定义一个Employee类,该类包含 name ,age
// 创建3个Employee对象放入HashSet中,name和age的值相同时,认为相同员工,不能添加到HashSet集合中
HashSet hashSet = new HashSet();
hashSet.add(new Employee("张三",13));
hashSet.add(new Employee("李四",22));
hashSet.add(new Employee("王五",20));
hashSet.add(new Employee("张三",13));
System.out.println(hashSet);
}
}
class Employee{
private final String name;
private final int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) { // 判断
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Employee employee = (Employee) o;
return age == employee.age && Objects.equals(name, employee.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
二、Set接口实现类 LinkedHashSet
不允许添加重复元素
import java.util.LinkedHashSet;
import java.util.Objects;
public class text {
public static void main(String[] args) {
LinkedHashSet linkedHashSet = new LinkedHashSet();
linkedHashSet.add(new Car("奥迪",1000));
linkedHashSet.add(new Car("奥拓",500000));
linkedHashSet.add(new Car("法拉利",10000000));
linkedHashSet.add(new Car("奥迪",1000));
System.out.println(linkedHashSet);
}
}
class Car{
private final String name;
private final int age;
public Car(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Car car = (Car) o;
return age == car.age && Objects.equals(name, car.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "Car{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Map接口和常用方法
1、Map与Collection并列存在,用于保存具有映射关系的数据:Key - Value2、Map中的Key和Value可以使任何引用类型的数据
3、Map中的Key不可重复,Value可以重复,Key和Value都可为null,但是Key只能有一个,Value可以有多个
4、常用String类作为Map的Key
5、Key和Value之间存在单向的一对一关系,即通过指定的Key总能找到对应的value
遍历方式
import java.util.*;
public class text {
public static void main(String[] args) {
Map map = new HashMap();
map.put(1,"张三");
map.put(2,"李四");
map.put(3,"王五");
map.put(null,"空");
// 一、遍历Key,通过Key取出对应的value
Set keyset = map.keySet();
System.out.println("通过增强for循环");
for (Object key:keyset){
System.out.println(key+"-"+map.get(key));
}
System.out.println("通过迭代器");
Iterator iterator = keyset.iterator();
while (iterator.hasNext()){
Object key = iterator.next();
System.out.println(key+"-"+map.get(key));
}
// 二、取出Value
Collection value = map.values();
System.out.println("增强for循环");
for (Object v:value){
System.out.println(v);
}
System.out.println("迭代器");
Iterator iterator1 = value.iterator();
while (iterator1.hasNext()){
Object v = iterator1.next();
System.out.println(v);
}
}
}
练习
使用HashMap添加三个员工对象,Key:员工id Value:员工对象,并遍历显示
工资 > 18000的员工
员工类:姓名,ID,工资
package com.sxny;
import java.util.*;
public class text {
public static void main(String[] args) {
Map map = new HashMap<>();
map.put(1,new Manager("张三",1,10000));
map.put(2,new Manager("李四",2,12000));
map.put(3,new Manager("王五",3,30000));
Collection keySet = map.keySet();
for (Object key:keySet){
System.out.println(key+"-"+map.get(key));
Manager manager = (Manager) map.get(key); // 获取指定类型(Manager)的Key
if (manager.getPrice()>18000){
System.out.println("工资大于18000的员工:"+manager);
}
}
}
}
class Manager{
private final String name;
private final int id;
private final int price;
public Manager(String name, int id, int price) {
this.name = name;
this.id = id;
this.price = price;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public int getPrice() {
return price;
}
@Override
public String toString() {
return "Manager{" +
"name='" + name + '\'' +
", id=" + id +
", price=" + price +
'}';
}
}
Map接口实现类 HashMap
1、Map接口的常用实现类:HashMap、Hashtable、Properties2、HashMap是Map接口使用频率最高的实现类
3、HashMap是以key-val的方式存储数据
4、key不能重复,但是val可以重复,允许使用null键和null值
5、如果添加相同的Key,则会覆盖原来的,相当于修改
6、与HashSet一样,不保证顺序,因为底层是Hash表的方式来存储
7、HashMap没有实现同步,因此线程是不安全的
HashMap底层机制 ???
Map接口实习类 Hashtable
1、通过k-v存储
2、hashtable的Key和Value都不能是null,否则会抛出NullPointerException
3、Hashtable的使用方法和HashMap基本相同
4、Hashtable的线程是安全的,HashMap不安全
HashMap 线程不安全 效率高 允许null键和值
Hashtable 线程安全 效率较低 不允许null键和值
Map接口实现类 Properties
1、通过key-val存储2、使用特点与Hashtable类似
3、Properties可用于从后缀为properties文件中,加载数据到Properties类对象,进行读取和 修改
总结
在开发时,对于实现类的选择:
1、先判断存储类型(一组对象(单列)或一组键值对(双列))
2、一组对象(单列) : Collection接口
允许重复: List
增删多:LinkedList(底层维护了一个双向列表)
改查多:Arraylist(底层维护了OBject类型的可变数组)
不允许重复:Set
无序:HashSet(底层是HashMap,维护了一个哈希表,即(数组+链表+红黑树))
排序:TreeSet
插入和取出顺序相同:LinkedHashSet(维护数组+双向链表)
3、一组键值对(双列) : Map
键无序:HashMap(底层哈希表)
键排序:TreeMap
键插入和取出顺序一致:LinkedHashMap
读取文件:Properties
Collection工具类
Collection是操作Set、List、Map等集合的工具类,提供了一系列静态的方法对集合元素进行排序、查询和修改等操作
- ·reverse(List): 反转List中元素的顺序
- ·shuffle(List): 对List集合元素进行随机排序
- ·sort(List): 根据元素的自然顺序对指定List集合元素按升序排序
- ·sort(List,Comparator): 根据Comparator产生的顺序对List集合进行排序 ??? 用法不懂
- ·swap(List,int,int): 将指定List集合中的i处元素与j处元素进行交换
package com.sxny;
import java.util.*;
public class text {
public static void main(String[] args) {
List objects = new ArrayList<>();
objects.add("tom");
objects.add("jon");
objects.add("mike");
objects.add("king");
System.out.println(objects);
Collections.reverse(objects); // 反转
System.out.println(objects);
Collections.shuffle(objects);
System.out.println(objects); // 随机排序
Collections.sort(objects);
System.out.println(objects); // 升序
Collections.swap(objects,0,1);
System.out.println(objects);
}
}
泛型
泛型语法
Arraylist<引用数据类型> arraylist = new arraylist<引用数据类型>();
注: 1、指定数据类型后,可以传入该数据类型或其子类数据类型。
2、不指定数据类型,默认为Object
举例
·传统方法 利用集合arraylist收纳,遍历输出内容
1、不能对加入集合中的数据类型进行约束(不安全)
2、遍历时需要进行数据类型转换(异常ClassCastException)
package com.sxny;
import java.util.ArrayList;
public class text {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add(new Dog("张三",12));
arrayList.add(new Dog("李四",14));
arrayList.add(new Dog("王五",16));
arrayList.add(new Cat("奶盖",3));
for (Object object:arrayList){ //增强for循环
Dog dog = (Dog)object;
System.out.println(dog.getName()+" "+dog.getAge());
}
}
}
class Dog{
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Cat{
private String name;
private int age;
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
·利用泛型
package com.sxny;
import java.util.ArrayList;
public class text {
public static void main(String[] args) {
ArrayList<Dog> arrayList = new ArrayList<Dog>();
arrayList.add(new Dog("张三",12));
arrayList.add(new Dog("李四",14));
arrayList.add(new Dog("王五",16));
//arrayList.add(new Cat("奶盖",3)); 报错
for (Object object:arrayList){ //增强for循环
Dog dog = (Dog)object;
System.out.println(dog.getName()+" "+dog.getAge());
}
}
}
class Dog{
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Cat{
private String name;
private int age;
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
自定义泛型
class 类名<T,R......>{//......表示可以有多个泛型
成员
}
注:(1)普通成员可以使用泛型
(2)使用泛型的数组,不能初始化
(3)静态方法中不能使用类的泛型
(4)泛型类的类型,是创建对象时确定的(因为创建对象时,需要指定确定的类型)
(5)如果在创建对象时,没有指定类型,默认为Object
package com.sxny;
import java.util.ArrayList;
public class text {
public static void main(String[] args) {
ArrayList<Student> students = new ArrayList<>();
students.add(new Student("jack",12));
students.add(new Student("pop",14));
students.add(new Student("mike",17));
for (Student student:students){
System.out.println(student);
}
}
}
class Student{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
自定义泛型接口 ???
自定义泛型方法 ???
泛型的继承和通配符???
JUnit
1、JUnit是一个Java语言的单元测试框架
2、多数Java的开发环境都已经集成了JUnit作为单元测试的工具
多线程基础
- ·进程:程序的一次执行过程,或是正在运行的一个程序,是动态过程,有它自身的产生、存在和消亡的过程
- ·线程:由进程创建的,是进程的一个实体,一个进程可以有多个线程
- ·单线程: 同一时刻,只允许执行一个线程
- ·多线程: 同一时刻,可以执行多个线程(一个QQ进程,可以同时打开多个聊天窗口)
- ·并发: 同一时刻,多个任务交替执行,单核CPU实现的多任务就是并发
- ·并行: 同一时刻,多个任务同时执行,多核cpu可以实现并行
使用方式: 1、继承Thread类,重写run方法
2、实现Runnable接口,重写run方法
package com.sxny;
public class text {
public static void main(String[] args) throws InterruptedException{
Cat cat = new Cat();
cat.start();
System.out.println(Thread.currentThread().getName());
for (int i=0;i<60;i++){
System.out.println(i);
Thread.sleep(1000);
}
}
}
class Cat extends Thread{
int times = 0;
@Override
public void run() {
while(true) {
System.out.println("hello" +(++times)+ "线程名:" + Thread.currentThread().getName());
try {
Thread.sleep(1000); //休眠1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
if (times == 80) {
break;
}
}
}
}
IO流
常见的文件操作
相关方法
创建文件
- new File(String pathname) 根据路径构建一个File对象
- new File(File parent,String child) 根据父目录文件+子路径构建
- new File(String parent,String child) 根据父目录+子路径构建
获取信息
- getName: 文件名
- getAbsolutePath: 文件绝对路径
- getparent: 文件父类目录
- length: 文件大小(字节)
- exists: 判断文件是否存在
- isFile: 判断是否为一个文件
- isDirectory: 判断是否为一个目录
目录操作和文件删除
- mkdir: 创建一级目录
- mkdirs: 创建多级目录
- delete: 删除空目录或文件
package com.sxny;
import org.w3c.dom.Text;
import java.io.File;
import java.io.IOException;
public class text {
public static void main(String[] args) throws InterruptedException{
text text = new text();
text.create1();
text.create2();
text.create3();
File file = new File("d:\\news4.txt");
System.out.println(file.getName());
System.out.println(file.getAbsoluteFile());
System.out.println(file.getParent());
System.out.println(file.length());
System.out.println(file.exists());
System.out.println(file.isFile());
System.out.println(file.isDirectory());
}
// 通过路径构建
public void create1(){
String filePath = "d:\\news1.txt" ;
File file = new File(filePath);
try{
file.createNewFile();
System.out.println("文件创建成功");
}catch (IOException e){
e.printStackTrace(); // 在命令打印异常信息在程序中出现的原因及位置
}
}
// 通过父目录文件 + 子路径构建
public void create2(){
File parentFile = new File("d:\\");
String fileName = "new2.txt";
File file = new File(parentFile,fileName);
try{
file.createNewFile();
System.out.println("创建成功");
}catch(IOException e){
e.printStackTrace();
}
}
// 根据父目录 + 子路径构建
public void create3(){
String parentFile = "d:\\";
String fileName = "new3.txt";
File file = new File(parentFile,fileName);
try{
file.createNewFile();
System.out.println("文件创建成功");
}catch(IOException e){
e.printStackTrace();
}
}
}
FileInputStream
字节流输入——单个字符的读取,效率较低
package com;
import java.io.FileInputStream;
public class text {
public static void main(String[] args){
String filePath = "D:\\IDEA\\Java-project\\demo-JSON\\src\\com\\project\\text";
int readData = 0;
FileInputStream fileInputStream = null;
try{
fileInputStream = new FileInputStream(filePath);
while ((readData = fileInputStream.read()) != -1){
System.out.print((char) readData);
}
}catch (Exception e){
e.printStackTrace(); //在命令行打印异常信息在程序中出错的位置及原因
}finally {
try {
fileInputStream.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
字节流输入——使用read(byte[ ] b)读取文件,提高效率(缓冲区)
package com;
import java.io.FileInputStream;
public class text {
public static void main(String[] args){
String filePath = "D:\\IDEA\\Java-project\\demo-JSON\\src\\com\\project\\text";
byte[] buf = new byte[8]; //一次读取8个字节
int readData = 0;
FileInputStream fileInputStream = null;
try{
fileInputStream = new FileInputStream(filePath);
try {
while ((readData = fileInputStream.read()) != -1){
System.out.print(new String(buf,0,readData));
}
}catch (StringIndexOutOfBoundsException e){
e.printStackTrace();
}
}catch (Exception e){
e.printStackTrace(); //在命令行打印异常信息在程序中出错的位置及原因
}finally {
try {
fileInputStream.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
FileOutputStream
在文件中写入“hello world”(如果文件不存在,会创建文件,前提目录存在)