JAVA基础

最基础的Java知识,必须掌握的Java基础

环境变量配置

JAVA_HOME:配置的是jdk的根目录
path:配置bin目录(%JAVA_HOME%\bin)

基本格式

类名必须和文件名保持一致

1
2
3
4
5
6
7
public class 类名{
// 类名每个单词首字母大写
public static void main(String[] args) {

}
}

java工具包

jdk:java开发工具包(java development kit),代码编写依赖jdk
jre:java运行环境(java runtime environment),提供javav程序运行的环境
jvm:java虚拟机(java virtual machine),确切说程序是在jvm里面运行的(只认识class字节码文件)

常用cmd命令

dir:显示当前路径下的目录
cd:路径操作
cls:清除当前屏幕
javadoc 程序名.java:生成Doc文档

cmd运行步骤

先写程序
编译:javac 程序名.java
执行:java 程序名

注释

单行注释://注释内容 快捷键Ctrl+/
多行注释:/*注释类容*/ 快捷键Ctrl+Shift+/
文档注释:/**注释内容*/(对类和文档进行解释)

1
2
3
4
5
6
7
8
9
10
11
12
13
/*
多行注释 一般写在类的开头
写出
1. 类的功能
2. 类的实现步骤
*/
public class name{
// main是程序的主方法 固定格式 程序的入口
public static void main(String[] args) {
System.out.println("HelloWorld");

}
}

目录文件夹

src文件夹:源文件夹 里面存放(包package)java文件

bin文件夹:存放编译之后的(包package)class文件

Class–>Package规范:公司域名后缀名+公司名称+其他

com/cn/edu.java.other

设置相关

字体大小调节

1
Window->Preferences->Appearance->Colors and Fonts->Basic->Text Font

设置统一编码格式为UTF-8

1
Window->Preferences->workspace->Text file encoding

设置注释格式

1
windows-->preference-->Java-->Code Style-->Code Templates-->code-->new Java files

变量的定义和注意事项

变量定义后,不赋值不能使用
变量有自己的作用范围,变量的有效范围定义在一对大括号内
变量不允许重复定义

数据类型

基本数据类型(四类八种)

Java默认数据类型是int

整数默认类型是int,小数默认类型是double

整数:byte/short/int/long

byte:1个字节 -128~127
short:2个字节
**int(默认):4个字节
long:8个字节(过大的数后面加上**L
)

小数:float/double(默认)

float:4个字节
double:8个字节

布尔:boolean(默认false)

boolean:1个字节

单个字符:char(默认是’’)

char:2个字节

引用数据类型

String:字符串类(默认是null)
String + 基本类型:字面量数据类型
数组:数据类型[] 数组变量名 = new 数据类型[长度]
任意引用数据类型都存在堆里面

数据类型转换

自动类型转换:**范围小(byte)的可以直接转换为范围大(int)**的

byte -> short -> int -> long -> float -> double

1
2
3
4
5
6
7
8
9
10
public class DateVonvert {
public static void main(String[] args) {
double b = 1000; // 出现了类型的自动转换,int自动转换为double
System.out.println(b);

byte b = 111;
int j = b; // byte转换为int
System.out.println(j);
}
}

强制类型转换被转后的数据类型 变量名 = (被转后的数据类型)要被转的数据

1
2
3
4
5
6
7
8
9
10
11
public class DateVonvert {
public static void main(String[] args) {
double dd = 3.14;
// 被转后的数据类型 变量名 = (被转后的数据类型)要被转的数据
int ii = (int) dd;
System.out.println(ii);

byte bb = (byte) 200;
System.out.println(bb); // 丢数据
}
}

运算符

算术运算符

+ 加法,连接
- 减法
* 乘法
/ 除法
**%**取模,取余数
++ 自增1
自减1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Operator {
public static void main(String[] args) {
// + 连接作用,将一个字符串和其他数据连接起来
// + 任何类型只要和字符串+,所有的数据都变成了字符串
// + 遇到字符串,变成连接符号"5+5=55"
System.out.println("5+5="+5+5);

// ++ 写在变量前面和后面的区别
int i = 5;
int j = i++;
// j = i++ ++后算,先把i赋值给j,i自己再++
System.out.println(i); // 6
System.out.println(j); // 5

int m = 5;
int n = ++m;
// n = ++m ++先算,再把m++赋值给n
System.out.println(m); // 6
System.out.println(n); // 6
}

}

赋值运算符

= / += / -= / /= / %=

1
2
3
4
5
6
7
8
9
10
11
public class Operator {
public static void main(String[] args) {
byte b = 1;
b = (byte)(b + 1); // 必须转换 不然报错
System.out.println(b);

byte b1 = 1;
b1 += 1; // 等同于(byte)(b + 1)
System.out.println(b);
}
}

比较运算符

== / != / <** / **> / <=** / **>=

结果只有 true 或者 false
比较字符串是否一致:名称1.equals(名称2)

逻辑运算符

对两个boolean类型数据之间进行计算结果也是boolean类型

& 与:一个false,结果就是false
| 或:一个true,结果就是true
^ 异或:两边相同为false,不相同为true
取反:**!true为false !false为true**
&& 短路与:一边是false,另一边不运行
|| 短路或:一边是true,另一边不运行

三元运算符

公式:布尔表达式?结果1:结果2
结果1和结果2数据类型保持一致

布尔表达式是true,三元运算符结果就是–>结果1

布尔表达式是false,三元运算符结果就是–>结果2

1
2
3
4
5
6
public class Operator {
public static void main(String[] args) {
System.out.println(3>2?99:88); // 99
System.out.println(3>5?99:88); // 88
}
}

循环控制语句

If Else

1
2
3
4
5
6
7
8
if(表达式){
//表达式成立执行这里面的语句
//语句
}else if(表达式2){

}else{
//不满足执行这里的语句
}

While/Do While

两者区别:
while 先判断是否满足条件 满足就执行循环体
do while 无论满不满足循环体都先执行一次

1
2
3
4
5
6
7
while(判断条件){
// 成立执行这里的语句
}

do{
//执行一次
}while(判断条件);

Switch Case

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// switch后表达式满足的数据类型有
// int byte char String(1.7版本) enum(枚举) short
switch(表达式){
// case后的数据类型要和switch表达式的数据类型保持一致
case 表达式1:
代码逻辑;
break;
case 表达式2:
代码逻辑;
break;
case 表达式n:
代码逻辑;
break;
// 前面所有的表达式都不满足执行default语句后的代码
default:
代码逻辑;
break;
}

For

1
2
3
4
5
6
7
8
for(表达式1;表达式2;表达式3){
// 代码逻辑
}

// 增强for循环
for(数组元素数据类型 变量名称:数组变量名){
// 循环体
}

Break,Continue,Return

Break:直接终止整个循环体,不能单独使用在if
Continue:结束本次循环体,开始下个循环
Return:结束整个方法

Scanner使用

**Scanner input = new Scanner(System.in);**,定义输入
**int a = input.nextInt();**,接收用户输入
**input.close()**,关闭流

断点调试

先双击行首数字出
F6程序往下走一步
F8走到下一个断点处

数组

一维数组

语法

1
2
3
数据类型[] 变量名 = new 数据类型[长度]
数据类型[] 变量名 = {值1,值2,值3,值n}
**获取数组长度**:数组名.length;

二维数组

语法

1
2
3
4
5
6
7
8
9
10
数据类型[][] 变量名 = 数据类型[m][n]
数据类型[][] 变量名 = 数据类型[m][]
数据类型[][] 变量名 = \{\{元素1\},\{元素2\},\{元素3\}\};

// 3表示二维数组的长度是3(存放3个一维数组)
// 4表示每个一维数组里面可以存放4个元素
String[][] strArr = new String[3][4];
System.out.println(strArr.length); // 打印二维数组的长度
System.out.println(strArr[0].length); // 打印一维数组长度

Arrays工具类

1
2
3
4
5
Arrays.toString(arr); // 将数组内容转成字符串输出
Arrays.sort(arr); // 默认从小到大排序
Arrays.copyof(源数组,新数组长度); // 拷贝数组
Arrays.equals(数组1,数组2); // 判断两个数组是否一致
Arrays.binarySearch(数组名, 要查找的元素); // 查找元素在数组中的索引,找不到返回(-插入点-1),数组必须有序才能查找

排序(Sort)

冒泡排序

效率最慢

Screenshot_1.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int[] arr = {23,2,44,1};

// 控制排序的轮数
for(int i = 0; i<arr.length-1; i++) {
// 控制元素与相邻元素相比
for (int j = 0; j < arr.length-1-i; j++) {
// 判断两个相邻的元素
if(arr[j]>arr[j+1]) { // arr[j]位置交换
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}

选择排序

Screenshot_1.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
for(int i = 0; i<arr.length-1; i++) {
int min = arr[i]; // 定义一个最小值
int minindex = i; // 获得最小值的索引

// 判断遍历数组出最小值
for (int j = i+1; j < arr.length; j++) {
if (min>arr[j]) {
min = arr[j];
minindex = j;
}
}

// 交换位置
int temp2 = arr[i];
arr[i] = arr[minindex];
arr[minindex] = temp2;
}

插入排序

效率最快

Screenshot_2.png

1
2
3
4
5
6
7
8
9
10
11
for (int i = 1; i < arr.length; i++) {
int temp = arr[i]; // 数组的第二位
int leftindex = i-1; // 左侧索引
// arr[leftindex] 后移
while (leftindex >= 0 && arr[leftindex] > temp) {
arr[leftindex + 1] = arr[leftindex];
leftindex--;
}
// 空位
arr[leftindex + 1] = temp;
}

类和对象

类的创建

1
2
3
4
5
6
7
public class 类名{
// static表示静态的
// 下面都是类的属性
static String name; // 姓名
static String gender; //性别
static int age;
}

类的方法

  1. 权限修饰符:public static(公共的),protected(受保护的),private(私有的),默认(default)
  2. 方法返回值:数据类型,void(无返回值数据类型)
  3. 方法名():规范:首字母小写,第二个单词字母大写,名字不能重复
  4. 方法的参数:形式参数,形参 所有数据类型都可以充当形参
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//1.无参无返回值
public static void method1() {
System.out.println("无参无返回值");
}
//2.无参有返回值:必须加return语句,返回要返回的数据(数据类型必须是返回值的数据类型)
public static String method2() {
System.out.println("无参有返回值");
String str = "hello";
return str; // 结束当前方法
}
//3.有参无返回值(参数的个数>=1)
public static void method3(int[] arr,int num,int...obj) {
System.out.println("有参无返回值");
System.out.println(arr);
}
//4.有参有返回值
public static int method4(String str,int i) {
System.out.println("有参有返回值");
return i; // 必须返回和参数相同的数据类型
}

可变参数数据类型…参数名字,可变参数本质上是一个数组
可变参数注意事项:

  1. 一个方法中,可变参数只能有一个
  2. 可变参数必须写在参数列表的最后一位

创建对象

语法:类名 对象名 = new 类名();

1
2
Person zhangSan = new Person();
System.out.println(zhangSan); // 输出内存地址

调用类的属性和方法

1
2
3
4
zhangSan.name = "张三";
zhangSan.gender = "男";
zhangSan.age = 20;
System.out.println(zhangSan.name); // 输出name

调用方法

语法:方法名();

1
2
3
4
5
public static void method1() {
System.out.println("无参无返回值");
}

method1() // 调用method1方法

方法重载

  1. 方法名相同
  2. 参数数据类型,参数顺序不一样
  3. 不考虑返回值和权限修饰符
1
2
3
4
5
6
7
8
public Animal() {
// 初始化一些变量数据
}

// 构造方法重载
public Animal(String name1) {
name = name1;
}

成员变量和局部变量

  1. 存在位置不一样:成员变量在类里面,局部变量在方法里面
  2. 作用范围不一样:成员变量在类里任何地方都可以访问,局部变量只可以在方法里面使用
  3. 内存储存位置不一样:成员变量在堆里,局部变量在栈里
  4. 初始值不一样:成员变量有初始值,不需要初始化,局部变量没有初始值,必须初始化

枚举类

  1. 定义语法:

    1
    2
    3
    public enum Test(){
    '这是枚举类'
    }
  2. 注意:

    • 枚举类必须先定义对象(实例),再定义成员变量和成员方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public enum Test(){
    '对象(实例),多个对象中间用逗号隔开'
    MONDAY, '默认基于无参构造创建的对象'
    TUESDAY,
    WEDNESDAT,
    THURSDAY("周四"); '使用有参构造创建对象'
    '想获得对象中的参数值,通过调用对象的get方法获得'
    '成员变量'
    private String name;
    public Integer id;
    '枚举类中的所有构造方法都必须是私有的'
    private Week(){}
    private Week(String name){}
    }
    • 枚举类中的对象值一般不允许修改,所以一般只给get方法

面向对象三大特性

封装

对私有属性提供对外的公开访问方法:使用**setter()和getter()**方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private int age; // 年龄赋值的时候 要进行判断 private修饰成员只能在本类中调用
String tname;
public void setAge(int age1) {
if (age1 < 22) {
System.out.println("年龄不合法!");
System.out.println("年龄默认设置为22岁!");
age1 = 22;
}
age = age1;
}

public int getAge() {
return age;
}
lombok使用教程

Screenshot_1.png

this关键字
  1. 当成员变量与局部变量重名的时候,可以使用this来辨别,this指代的是当前对象
  2. this充当实参
  3. this可以调用构造函数this(),必须在代码的第一行
  4. this可以访问属性
  5. this不能在static所修饰的方法中运用
static关键字
  1. 静态方法里面不能访问非静态成员
  2. 如果是static修饰的成员变量,最好初始化
  3. 静态方法中不能使用this
  4. 可以和任何权限修饰符一起使用:public/private/protected/final
  5. 数据是让所有对象共享

静态代码块

1
2
3
4
5
6
7
8
9
static {
初始化数据,不管创不创建对象都走
只运行一次
System.out.println("静态代码块");
}
{
只有在创建对象的时候才会走这句话
System.out.println("普通代码块");
}

继承(extends)

语法:public class 类1 extends 类2{}一个类只能继承一个类
子类对象创建时会默认先执行父类的无参构造

Screenshot_1.png

super
  1. 访问父类构造方法(super())
  2. 访问父类的成员变量和成员方法(super.父类变量名/方法名)
方法重写(override)

前提条件:必须要有层级关系

  1. 方法重写出现在子类里面
  2. 方法名,形式参数必须和父类保持一致
  3. 子类访问权限修饰符 >= 父类的
  4. 子类返回值类型 <= 父类的
  5. 重写父类方法前面加上:**@Override**
权限修饰符
  1. public:可以修饰类和成员变量,在整个项目中都是友好的
  2. protected:可以修饰成员变量,在整个包内和子类中友好
  3. 默认不写:可以修饰类和成员变量,在包内友好
  4. private:可以修饰成员变量,在本类中友好
  5. final:可以修饰常量,被修饰的方法中不能被重写,在继承中不被继承

Screenshot_1.png

多态

发生多态条件:

  1. 父类对象指向任何一个子类的实例(对象)
  2. 编译时数据类型(=左边)与运行时数据类型(=右边)不一致时
  3. 子类对象转成父类实例向上转型
  4. 创建对象发生多态:父类对象 名称 = new 子类对象();
  5. 父类对象转成子类实例(强制转换),向下转型,要配合instanceof一起使用
  6. 访问成员变量看**=左边的数据,访问成员方法=右边**
    弊端:无法访问子类特有的成员(变量、方法)
instanceof

使用:父类实例 instanceof 子类对象

Screenshot_1.png

抽象类和接口

抽象类

使用条件:当所有子类都需要重新父类的逻辑时,父类方法体就变得没有意义,就把父类方法声明成抽象的方法
使用方法访问权限修饰符 abstract 返回值类型 方法名();
注意:抽象类不能创建对象,体现在多态上,抽象类的构造方法主要是满足子类对象的创建

Screenshot_3.png
Screenshot_4.png

接口(interface)

创建接口

1
2
3
public interface 接口名{

}

项目命名规范

  1. ****Dao/DAO.javaUserDao.java
  2. ****Service.javaUserService.java

接口中的内容
常量必须为public static final修饰,常量名字必须都是大写
抽象方法必须为publice abstract修饰
JDK1.8之后有普通方法,但必须使用default static修饰
访问父类的普通方法使用super.方法名()

接口的作用

  1. 接口可以通过implements实现多调用,一个类可以实现多个接口
  2. 主要用于多态的使用
  3. 接口和接口之间可以实现多继承

接口和抽象类的区别

共同点:都不能实例化,都用于多态
不同点:接口只有常量和抽象方法和default/static所修饰的功能方法,抽象类有成员变量,成员方法,抽象方法,构造方法,静态代码块

异常

异常Exception(类) —> 可以处理
错误Error(类) —> JVM抛出,程序直接终止
它们有共同的父类:Throwable
Screenshot_2.png

异常可以分为两大类:

  1. 可检测到的异常checkedException:PasreException,SQLException,ClassNotFoundException,IOException
  2. 运行时的异常RuntimeException:NPE,ClassCastException

捕获异常的方法

**String getMessage()**:获得详细的异常信息字符串内容
**void printStackTrace()**:将详细异常信息通过流打印(输出)至控制台

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

出现多个异常的情况下,只走其中一个异常,就是说catch只走一次!

try{
可能会出现异常的代码

}catch(异常类 变量名 ){ 捕获具体的异常类的
//处理异常信息
//避免捕获不处理异常信息

1.后端开发(服务器端开发)--->java项目运行在Linux服务器
异常日志记录异常信息(将异常信息写入异常日志文件) slf4j log4j

2.异常信息传递 (throw) 将异常信息从底层到顶层全部输出。
将当前异常类对象 封装到 级别高的异常对象里面

3.异常工具类返回的错误信息

return ServerResponse.error("msg","code");

}catch(异常类 变量名 ){
处理异常信息的方式

System.out.println(exception.getMessage());

exception.printStackTrace();
}
finally{

释放资源

不管是否有异常出现 都会执行的
}

Screenshot_1.png

抛出异常 throws

throw 声明抛出一个具体的异常对象

  1. 异常信息传递 (throw)
  2. 结束程序
  3. 与自定义异常结合使用
1
2
3
4
5
6
7
8
9
10
11
12
public static  void a() throws ArithmeticException{

将异常类抛出给上级(调用者);
System.out.println("异常之前");
}

public static int calMoney(String boorowTime, String returnTime)
if(boorowTime == null || returnTime == null){
抛出一个异常信息
throw new NullPointerException("参数数据不能为null")
遇见throw程序直接结束
}

将String时间数据转换为Data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
String pattren  = "yyyy-MM-dd HH-mm-ss"; // 创建一个格式
SimpleDataFormat dateFormat = new SimpleDataFormat(pattren);

// 格式化数据(解析) 将字符串解析为data类型的数据
// 有一个可检测的异常
try{
Data borrowData = dateFormat.parse(boorowTime);
Data returnData = dateFormat.parse(returnTime);

// 计算两个日期的间隔
// 将Date类型的数据转换成数值型的数据
long borrow = borrowData.gettimr(); // data代表的是时间的毫秒数
long return1 = returnData.gettimr();

int hour = (int)((return1 - borrow)/1000/3600); // 转换成int类型的时间
} catch(ParseException e){
e.printStackTrace();
}

lang包常用类

Screenshot_1.png

Integer

包装类分为四类八种
Byte,Shory,Integer,Long,Float,Double,Character,Boolean
成员变量的数据类型使用包装类

Integer介绍:

  1. final所修饰的类
  2. 继承于Number
  3. 实现了一个**Comparable<Integer>**接口
  4. 赋值只能给数字类型和数字类型的字符串

基本类型的数据转换成了一个包装类 —> 自动装箱操作

1
2
// 底层实现:Integer num = Integer.valueOf(100);
Integer num = 100;

包装类的对象转换成基本类型的数据 —> 自动拆箱操作

1
2
3
4
5
6
7
8
9
10
11
12
13
// 底层实现:int num1 = num.intValue();
int num1 = num;

Integer num2 = new Integer(100);
Integer num3 = new Integer("100");

int num4 = 100;
Integer num5 = 100;
Integer num6 = 100;
Integer num7 = 200;
int num8 = 200;

System.out.println(num2=num2); false

这里实现了包装类的拆箱操作

1
2
3
4
System.out.println(num2=num4); true
System.out.println(num4=num5); true

System.out.println(num1=num4); false

整数缓存池:数组 Short[] Integer[] Long[],范围在-128~127之间,
两个数比较在这之间为True,否则为False

1
2
3
4
5
6
Integer num5 = 100;
Integer num6 = 100;
Integer num7 = 200;
int num8 = 200;
System.out.println(num5=num6); true
System.out.println(num7=num8); false
Integer功能方法

比较数据类型是否一致

1
2
3
4
5
6
7
8
//equals方法从Object继承 是Integer重写父类的euqals
System.out.println(num1.equals(num2));
//返回值只有0 -1 1
System.out.println(Integer.compare(num1, num2));
//从Comparable实现过来的
System.out.println(num1.compareTo(num2));
// Objectes JDK1.7后有的
System.out.println(Objects.equals(num1, num2));

String 和 Integer转换

1
2
3
4
5
String strNum = "100";
int num = new Integer(strNum); //第一个方法
Integer num2 = Integer.valueOf(strNum); //第二个方法
Integer num3 = Integer.parseInt(strNum); //第三个方法
Integer num4 = Integer.parseInt(strNum,2); //2代表进制数,输出结果都是10进制为主

Integer 转换成 String

1
2
3
4
Integer in = 100;
String str = in.toString(); // 转换成字符串
int i = 10;
String j = i + ""; // int转换为String

Character

Character功能方法

将字符串转换为指定进制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
System.out.println(Character.MAX_RADIX); //最大进制 36
System.out.println(Character.MIN_RADIX); //最小进制 2
String str = "110";
char[] chs = str.toCharArray();
// 将第一位转换为10进制的数
System.out.println(Character.digi(chs[0], 10));

Character ch1 = '我';

if(Character.isLetter(ch1)){
判断是否为大小写字母
Character.toLowerCase(ch1); //小写
Character.toUpperCase(ch1); // 大写
}else if(Character.is.Digit(ch1)){
判断是否为数字
}else if(Character.isWhitesace(' ')){
判断是否为空字符串
}

Math

获得随机数

1
Math.random();  // 范围是0.0-1.0  包头不包尾

求几次幂

1
Math.pow(2,2); // 求2的2次幂

四舍五入

1
Math.round(4.6);  // 结果是5

求一个数的平方根

1
Math.sqrt(4.0);  // 结果是2.0

最大值最小值

1
2
Math.max(10,1)
Math.min(10,1)

获取绝对值

1
Math.abs(-10); // 变成10

Object(基类/超类)

获得对象的哈希码值(返回值是int)

1
hashCode()

equals——hashcode.png

获得一个对象(类/接口字节码文件)

1
getClass();

判断元素是否为空

1
Objects.requireNonNull(元素名);

在另外一个线程里面唤醒另外一个正在wait的线程

1
2
notify();
notifyAll();

线程等待

1
2
3
wait();
wait(long timeout);
wait(long timeout, int nanos);

创建(克隆)对象,获得一个对象的副本

1
2
3
4
clone();
浅克隆: 对于包装类,String-->克隆的是数据
其它引用类型-->克隆的是地址
深克隆:其它引用类型-->重新开辟内存

Class

表示正在运行的类或者接口(获得正在运行的类或者接口的class文件)
反射最基本的一个类–>获得类/接口的所有内容
一般用于底层的封装和框架的开源

获得Class类的对象的方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
创建一个Class类的实例
Person person = new Person();
Class clazz = person.getClass(); // clazz就是Person类的字节码文件
clazz.getName(); // 获得类或者接口的全限定名称--->包名+类名
clazz.getSimpleName(); // 拿到类名

创建一个Class类的实例
Class clazz = Person.class; // clazz就是Person类的字节码文件

创建一个Class类的实例
try{
Class.forName("给类或者接口的全限定名称");
Object obj = clazz.newInstance(); // 创建对象 默认执行无参构造
}catch(ClassNotFoundException e){
e.printStackTrace();
}

返回到类的类加载器(bin目录)

1
clazz.getClassLoader();

查找具有给定名称的资源

1
clazz.getResourceAsStream("资源文件路径");

获得类的属性 对属性赋值(Field类)

1
2
Field[] fields = clazz.getFields();  // 只能获得public所修饰的属性
fields = clazz.getDeclaredFields(); // 获得类的所有属性

String

实现了java.io.Serializable, Comparable<String>, CharSequence接口

创建字符串

1
2
3
4
5
6
7
构造
String str1 = new String();

String str2 = new String("hello");

byte[] bytes = {78,98,99}
String str3 = new String(bytes); //将字节数组转为字符串内容

获得字符串的字节内容

1
2
3
4
5
6
7
8
9
10
11
注意编码和解码格式统一
//使用默认的编码格式解析成字节数组
System.out.println("哈哈哈哈".getBytes());
// 将字节数组使用指定的格式进行编码处理
System.out.println("哈哈哈哈".getBytes("GBK").length);
// 将字节数组使用指定的编码格式进行解码处理
System.out.println("哈哈哈哈".getBytes(),"UTF-8");

Charset代表具体的编码格式
// 查看当前工作空间默认编码格式
System.out.println(Charset.defaultCharset());

将字符数组转换为字符串内容

1
2
char[] ch = {23,'a','家','好'};
String str4 = new String(ch);

toCharArray字符数组转换为字符串内容操作

1
String str4 = new String("啊啊啊啊".toCharArray());
String功能方法

获得字符串指定索引的字符内容(返回值是char类型)

1
2
3
4
5
6
7
str.charAt(1);  // 不能超过字符串的总长度

字符串之间的比较(返回值是int类型)
str.compareTo("abc"); //ASII码值相减
str.compareToIgnoreCase("ABC"); // 不区分大小写进行比较
str.equals("abc"); // 返回值是boolean类型
str.equalsIgnoreCase("ABC"); // 不区分大小写进行比较,返回值是boolean类型

将指定的字符串内容追加到字符串的末尾(返回值是String类型)

1
str.concat("_123"); // abc_123,返回的是一个新的字符串内容,str不会发生改动

判断字符串中是否包含指定字符序列内容(返回值是boolean类型)

1
str.contains("a");  // 判断str中是否包含a

将任意类型的数据转换为字符串(返回值是String类型)

1
String.valueOf(1);

判断字符串中是否以某个类型开头和结尾(返回值是boolean类型)

1
2
3
4
5
str.endsWith("a"); // 判断是否是a结尾
str.startsWith("b"); // 判断是否是b开头

返回字符串的哈希吗值
str.hashCode();

获得指定字符串第一次出现的索引位置(返回值是int类型)

1
2
3
找不到指定的字符串内容返回值是-1
str.indexOf("a");
str.indexOf("a",1) // 从第二个元素开始查找

获得指定字符串最后一次出现的索引位置(返回值是int类型)

1
2
3
找不到指定的字符串内容返回值是-1
str.lastIndexOf("a");
str.lastIndexOf("a",1); // 从第一个开始查到最后一次出现的位置

获得当前字符串的副本(返回值是String类型)

1
str.intern(); //返回是一个常量池的数据(地址)

判断字符串是否是空(返回值是boolean类型)

1
str.isEmpty();

使用分隔符连接字符串内容(返回值是String类型)

1
String.join("_","a","b","c"); // a_b_c  后面可以写多个数据

判断字符串是否匹配正则的要求(返回值是boolean类型)

1
str.matches("abc"); // abc就是正则

使用指定字符串替换字符串内容(返回值是String类型)

1
2
3
4
str.replace('a','b'); // 将所有a替换成b
str.replace("a","abc"); // 将所有a替换成abc
str.replaceAll("支持正则", "abc"); // 可以支持正则表达式
str.replaceFirst("a","abc"); // 只替换第一个出现的a,支持正则

将字符串使用指定的正则表达式进行分割(返回值是String[]类型)

1
2
str.split("a"); // 通过a把字符串分隔开 支持正则
str.split("a",2) // 将字符串分为2个,通过a分割

截取部分字符串内容(返回值是String类型)

1
2
3
// 从第一个索引开始截取到第三个索引,包头不包尾
str.substring(1,3);
str.substring(str.indexOf("xxx"),str.lastIndexOf("xxx")); // 从第一次出现的字符串截取到最后一次出现字符串的位置

转换为大小写(返回值是String类型)

1
2
str.toUpperCase(); //转换为大写
str.toLowerCase(); //转换为小写

去掉字符串左右两边空格(返回值是String类型)

1
str.trim();

去掉中间空格

1
2
str.trim.replace(" ","");
str.trim.replaceAll(" ","");

StringBuffer/StringBuilder(字符串变量类)

  • StringBuffer:

值可以改变。线程安全(StringBuffer所有的方法都是同步的synchronized) 效率慢

  • StringBuilder:

值可以改变 线程不安全(不同步的),效率最快,(绝对不能作为成员变量进行使用)

  • 创建初始化对象
    1
    StringBuffer buffer = new StringBuffer("hello");

追加字符串

1
2
buffer.append("123"); // 始终是同一对象,不会浪费内存
buffer.insert(索引值,"追加的内容");

删除字符串

1
2
buffer.delete(开始索引, 结束索引); // 包头不包尾	
buffer.deleteCharAt(删除指定索引位置); // 删除给出的索引位置的字符

反转字符串

1
buffer.reverse();

修改某个索引字符内容

1
buffer.setCharAt(索引位置,'要修改的内容');

StringBuilder功能方法
创建初始化对象

1
2
StringBuilder builder = new StringBuilder();
StringBuilder builder = new StringBuilder("hello");

String/StringBuffer/StringBuilder区别

  • 从数据:
    String: 数据不可变
    StringBuffer/StringBuilder:值可以改变
  • 从内容
    String: 浪费内存
    StringBuffer/StringBuilder;始终都是同一个对象
  • 从线程安全
    String/StringBuffer 线程安全(同步)
    StringBuilder 线程不安全(不同步)
  • 效率
    StringBuilder最快,其次是String,最后是StringBuffer

System

System类不能手动创建对象,因为构造方法被private修饰
方法:

1
2
3
4
5
6
获取系统当前毫秒值,可以测试程序执行时间
long start = System.currentTimeMillis();
for(int i = 0; i < 1000; i++){
}
long end = System.currentTimeMillis();
System.out.println(end - start); // 获取到执行for循环的时间
1
2
退出虚拟机,所有程序停止
System.exit(0);
1
2
收取对象的垃圾
System.gc();
1
2
获取当前系统的属性
System.getProperties();
1
2
复制数组
System.arraycopy(源数组,源数组的起始索引,目标数组,目标数组的起始索引,复制的个数);

util包常用类

Date

Date类对象用来表示时间和日期
该类提供一系列操纵日期和时间各组成部分的方法
构造方法重载
Screenshot_1.png

Calendar

Calendar类也是用来操作日期和时间的类,但它可以以整
数形式检索类似于年、月、日之类的信息

Calendar类是抽象类,无法实例化,要得到该类对象只能
通过调用getInstance方法来获得

Insatnt

JDK8的应用,推荐使用 Instant 代替 Date,LocalDateTime 代替 Calendar

LocalDate/LocalTime/LocalDateTime

LocalDate 获得当前系统的时间 2007-12-03
LocalTime 获得当前系统的时间 10:15:30
LocalDateTime 获得当前系统的时间 2007-12-03T10:15:30
此类也是不可变且线程安全

DateFormat

1
2
3
4
5
6
//时间转换成字符串
public static String formatDate(Date now,String pattern){
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
String result = sdf.format(now);
return result;
}
1
2
3
4
5
6
//字符串转换成时间
public static Date formateString(String str, String pattern){
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
Date date = sdf.parse(str);
return date;
}

数字的格式化

1
2
3
4
5
//#.## 保留两位小数
//#.##% 自动百分比计数并保留两位小数
//,### 每三位以逗号分隔
DecimalFormat df = new DecimalFormat("#.##");
String result = df.format(3.1415926);

Random(伪随机数类)

在多线程中是不安全的
创建实例

1
2
Random random = new Random();
Random random = new Random(10);

取一个随机整数值

1
2
random.nextInt();    // 随机生成整数
random.nextInt(10); //生成一个0-10的整数,包头不包尾
ThreadLocalRandom(随机数类)

在多线程中是安全的

1
2
ThreadLocalRandom localRandom =ThreadLocalRandom.current();
System.out.println(localRandom.nextInt(40, 100));//从40到99选一个随机数

加密解密

Base64

jdk1.8可正常使用
Base64.Encoder(加密),Base64.Decoder(解密)
该类使用RFC 4648和RFC 2045中规定的Base64编码方案来实现用于解码字节数据的解(编)码器。

1
2
3
4
5
6
7
8
9
'加密'
String pass = "1234";
Encoder encoder = Base64.getEncoder();// 获得编码器
String encodePass = encoder.encodeToString(pass.getBytes());

'解密'
Decoder decoder = Base64.getDecoder();// 获得解码器
byte[] by = decoder.decode(encodePass);
String str = new String(by);
MessageDigest

MessageDigest类为应用程序提供消息摘要算法的
功能,如SHA-1或SHA-256或MD5。 消息摘要是采用
任意大小的数据并输出固定长度散列值的安全单向
散列函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// MD5加密 信息摘要算法的一种
try {
// 1.获得messageDigest对象
MessageDigest messageDigest =
MessageDigest.getInstance("MD5");
// 2.传输需要加密数据
messageDigest.update(pass.getBytes());
// 3.加密
byte[] encodeBy = messageDigest.digest();
System.out.println(Arrays.toString(encodeBy));
// 将字节数组转换成BigInteger实例
BigInteger bigInteger = new BigInteger(1,
encodeBy);
String pass1 = bigInteger.toString(16);
System.out.println(pass1);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}

泛型

意义:与形式参数作用一样,限定数据类型

作用:隐式帮助进行类型转换

功能:

  1. 修饰类–>泛型类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    '泛型类的字母常用:E,T,K,V'
    public class Hello<E>{
    '泛型可以充当数据类型,也可以有setter和getter方法'
    private E e;
    '泛型充当形式参数'
    public void a(E e1){
    System.out.println(e1);
    }
    '泛型充当返回值,加上<E>代表这个方法是一个泛型方法'
    public <E> E b(){
    System.out.println(b);
    }
    }
  2. 修饰接口–>泛型接口
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public interface World<E,T>{
    // 接口内都是抽象方法 public abstract
    '泛型充当形参'
    void add(E e);
    '泛型充当返回值'
    T delete(int id);
    '泛型修饰方法'
    <T> T test();
    }
  3. 泛型擦除概念:泛型是在编译的时候起作用,但在代码运行期间是没有作用的
  4. 泛型上限
    • 让泛型继承一个类
      1
      2
      3
      public class Test<E extends Number>{
      '传入的参数只能是Number中的数据类型'
      }
  5. 泛型通配符:**?**
    1
    2
    3
    4
    5
    public class test<E,T>{
    public void add(Hello<?,?> hello){
    '?统配任意数据类型,不需要和类中的E和T保持一致'
    }
    }

集合

集合作用和数组作用一致,用于存储多个元素数据
理论上可以存储任意引用数据类型的数据(开发中都存储相同类型的数据–>避免出现类型准换问题)

在类/接口中出现 <A>这个,代表这个类为泛型的标志–>参数化类型(形参)

代表集合里面只能存储泛型所规定的的类型的数据(限定集合元素数据类型)

?代表的是泛型的通配符

? extends 父类,限制父类,不限制子类

? super 子类,限制子类,不限制父类

集合的接口
集合.png

Collection(是List和Set的父类)

特征

  1. 用于存放单值元素
  2. 元素是无序的(没有索引位置)
  3. 元素是否可以重复要看使用的是哪个类实现的

创建集合对象

1
Collection<指定泛型的变量> collection = new ArrayList<指定泛型的变量>();

增加元素

1
2
collection.add(E e);  // 将指定元素添加到集合中
collection.addAll(Collection<? extends E> c); // 将指定集合中的所有元素添加到此集合

删除元素

1
2
3
4
5
collection.remove(Object o); // 删除指定元素
collection.removeAll(Collection<?> c); // 删除指定集合中包含的所有此集合的元素
collection.removeIf(Predicate<? super E> filter) // 删除满足给定谓词的此集合的所有元素。
使用(迭代器)Iteator<T>中的 iterator()删除
remove();

查询元素

1
collection.size();  // 返回此集合中的元素个数

清除集合中所有的元素

1
collection.clear();  // 清空集合所有元素

判断元素是否存在

1
2
collection.clear();  // 清空集合所有元素contains(object o); // 如果此集合包含指定的元素,则返回 true 
collection.clear(); // 清空集合所有元素isEmpty(); // 如果此集合不包含元素,则返回 true

lambda语法:**(参数类型 参数名,参数类型 参数名)->{需要进行的操作}**
遍历集合元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
foreach方法
for(Object obj:collection) {
//假如元素数据为hello的时候 就删除
System.out.println(obj);
}

迭代器
Iterator it = collection.iterator();//获得集合元素的迭代器 (将集合的所有元素存储到迭代器对象里面)
while(it.hasNext()) { // it.hasNext判断集合中是否还有课迭代对象
Object obj = it.next(); // it.next表示迭代对象
if(obj.equals("hello")) {
it.remove();
}
}

jdk1.8 forEach+lambda新方法

collection.forEach(obj->{
System.out.println(obj);
});

集合中存储任意类型的对象

1
2
Collection coll = new ArrayList();  // 不指定存储的数据类型 可以存储任意类型的对象
coll.add("aa"); // 存储后是Object类型

迭代器

1
2
3
4
5
Iterator it = coll.iterator();
while(it.hasNext()){
Object obj = it.next(); // it.next()获取的Object类型
String i = (String)obj; // 强制转换为String类型
}

集合转数组

1
2
3
4
5
6
第一种方法
Object[] objs = collection.toArray();

第二种方法 (推荐使用)
Object[] objects = new Object[collection.size()];
collection.toArray(objects);
List<T>

特征

  1. 存储单值元素
  2. 元素有序的(有索引位置)
  3. 元素可以重复的

包括三个子类:ArrayList<E>(重要),LinkedList<E>,Vector
E代表的是:Element 元素,实际就是一个变量

三者之间的区别:

  1. 底层的数据结构
    ArrayList/Vector 是由动态数组进行维护。
    LinkedList 是由双向链表进行维护。
  2. 添加 删除 查询效率
    ArrayList查询最快
    LinkedList添加删除最快 查询较慢
    Vector: 都慢
  3. 线程安全
    ArrayList/LinkedList 都是线程不安全
    Vector 线程安全

ArrayList

1
2
初始化容量10
List<Integer> list = new ArrayList<>();
1
2
获取
list.get(list.size()-1) // 获取最后一个元素
1
2
3
删除
list.remove(1); //1为索引值,删除索引为1的值并且返回被删除的索引
list.remove(new Integer(1)); // 删除一个值为1的数
1
2
修改
list.set(0, 1000); // 把第一个元素改为1000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
遍历
1.
for(int index = 0,size = list.size();index<size;index++) {
System.out.println(list.get(index));
}

2.
for(Integer num:list) {
System.out.println(num);
}

3.
Iterator<Integer> it = list.iterator();
while(it.hasNext()) {
Integer num1 = it.next();
System.out.println(num1);
it.remove();
}

4.
ListIterator<Integer> listIt = list.listIterator(); // 迭代器
while(listIt.hasNext() ){
System.out.println(listIt.next());
}

5.
list.forEach(num->{
System.out.println(num);
});

linkedList

1
2
初始化对象
LinkedList<String> linkedList = new LinkedList<>();
1
2
3
4
添加元素
linkedList.add(0, "abc"); // 根据索引添加
linkedList.addFirst("a"); // 在集合第一个元素添加
linkedList.addLast("d") // 在集合最后一个元素添加
1
2
3
4
5
6
7
8
获取元素
linkedList.get(0); // 获取第一个元素
linkedList.getFirst(); // 获取第一个元素
linkedList.getLast(); // 获取最后一个元素

linkedList.peek(); // 获取第一个元素
linkedList.peekFirst(); // 获取第一个元素 列表为空,则返回 null
linkedList.peekLast();// 获取最后一个元素 列表为空,则返回 null
1
2
3
4
5
6
7
8
9
删除元素
linkedList.remove();//删除第一个元素
linkedList.removeFirst(); //删除第一个元素
linkedList.removeLast(); //删除最后一个元素
linkedList.remove("hello"); // 删除“hello”元素

linkedList.poll(); // 获取并删除第一个元素
linkedList.pollFirst();// 获取并删除第一个元素 列表为空,则返回 null
linkedList.pollLast();// 获取并删除最后一个元素 列表为空,则返回 null
Set

特征

  1. 存储单值元素
  2. 元素无序(没有索引位置)
  3. 元素不可以重复的,值必须唯一(前提: 一定要重写 equals和hashcode),默认初始容量16
    包含三个子类:HashSet<T>,LinkedHashSet<T>,TreeSet<T>
    区别:
  4. 底层的数据结构
    HashSet哈希表(哈希算法)维护,存储取出快,元素无序
    LinkedHashSet 是由哈希表+双向链表维护,继承HashSet,元素是有序的 (插入顺序和 输出顺序是一致的)
    TreeSet 是由二叉树(红黑树)进行维护 元素是有序的(按照自然顺序进行排列 要求集合元素数据类型必须有比较器 (实现 Comparable))
  5. 元素是否可以为null
    HashSet/LinkedHashSet 元素可以为null
    TreeSet 元素不允许为null
  6. 线程是否安全
    HashSet<T>/LinkedHashSet<T>/TreeSet<T> 都不安全

哈希表存储对象的依据是对象的哈希值和equals方法
实现方法和Collection一致

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
初始化对象
Set<Integer> set = new HashSet<>();

添加元素
set.add(10);

Set<User> userSet = new HashSet<>();
userSet.add(new User()); // 可以传一个对象引用,
userSet.add(new User()); // 前提: 一定要重写 equals和hashcode方法
userSet.add(new User());

遍历集合元素
set.forEach(num->{
if(num==10) {
System.out.println(num);
}
});

Map

存储的是一组元素数据,有key和value
Map中的key是不能重复的,value可以重复
实现类和子类:HashMap<K,V>(元素无序),LinkedHashMap<K,V>(元素有序),TreeMap<K,V>,HashTable<K,V>,CouncurrentHashMap<K,V>
区别:

  1. 从底层数据结构
    HashMap/HashTable 哈希表维护
    LinkedHashMap 哈希表和链表维护,是HashMap的子类
    TreeMap 红黑树维护,元素有序的,会按照key的自然顺序进行排序
    CouncurrentHashMap CAS(比较并交换) 乐观锁 + Redis
  2. 线程安全
    HashMap/LinkedHashMap/TreeMap 线程不安全
    HashTable/CouncurrentHashMap 线程安全
  3. key和value是否可以为null
    HashMap/LinkedHashMap key/value都可以为null
    TreeMap key不能为null value是可以为null
    HashTable/CouncurrentHashMap key/value都不能为null

HashMap,TreeMap,HashTable,LinkedHashMap

1
2
3
4
5
创建对象
Map<String, Integer> map = new HashMap<>();
ConcurrentHashMap<User, Integer> userMap = new ConcurrentHashMap<>();
TreeMap<User, Integer> userMap = new TreeMap<>();
Map<Integer, Integer> map = new LinkedHashMap<>(16); //需要指定容量
1
2
新增元素
map.put("key",value); // put的返回值一般情况是null,当有重复键时返回的是之前键的value值
1
2
3
4
查询元素
map.get("key"); // 返回的是value值
map.containsKey("key");
map.containsValue(value);
1
2
3
删除元素
map.remove("key"); // 返回的是移除之前的value值
map.remove("key", value);
1
2
3
替换元素
map.replace("key", value);
map.replace("key", value, 替换的value);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
遍历集合元素
map.forEach((key,value)->{
System.out.println("key:"+key+"----value:"+value);
});

JDK8的新方法
Set<Entry<String, Integer>> entrySet = map.entrySet();
entrySet.forEach((Entry<String, Integer> entry)->{
//map集合的所有的元素内容 都在entry对象
System.out.println("key:"+entry.getKey()+"----value:"+entry.getValue());
});

增强for循环
for(Map.Entry<String, Integer> entry:map.entrySet()){
System.out.println("key:"+entry.getKey()+"----value:"+entry.getValue());
}

迭代器
Iterator<Entry<String, Integer>> it = entrySet.iterator();
while(it.hasNext()) {
Entry<String, Integer> entry = it.next();
System.out.println("key:"+entry.getKey()+"----value:"+entry.getValue());
}

Collections

集合操作工具类

1
2
3
对 List集合 进行二分搜索,参数传递 List集合 和 被查找的元素,集合必须是有序的
Collections.binarySearch(list,5); // 查找5出现在集合的哪个索引
找不到指定的元素内容返回值是 插入点-1
1
2
对 List集合 随机排列
Collections.shuffle(list);
1
2
3
List本身是线程不安全,用这个可以让它变成线程安全类
List<Integer> list = new ArrayList<>();
list = Collections.synchronizedList(list);
1
2
3
4
5
6
7
8
9
使用sort()方法对 list集合 进行升序排列,lambad替换 接口/抽象类
Collections.sort(list);
重写
Collections.sort(stuList, new Comparator<Student>() {
@Override
public int compare(Student stu1, Student stu2) {//排序规则
return stu1.getScore().compareTo(stu2.getScore());
}
});

IO

File操作

file方法.png
File类构造方法

1
2
3
4
// windows路径下不区分大小写
File file = new File("文件路径"); // 将路径封装成File类型对象
File file = new File("父路径","子路径"); // 可以单独操作父路径和子路径
File file = new File(File类型的路径, "子路径"); // 父路径单独分开,是一个File类型

显示与系统有关的路径分隔符

1
2
String separator = File.pathSeparator;  // 是一个静态变量
打印是一个分号,在Linux下打印是一个冒号

显示与系统有关的名称分隔符

1
2
String separator = File.separator;  // 静态变量
打印一个向右的斜线 \ Linux下是左斜线 /
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
"判断路径中是否有这个文件" + file.exists();
"判断路径中是否是一个文件夹" + file.isDirectory();
"判断路径中是否是一个文件" + file.isFile();
"判断文件是否可读:" + file.canWrite();

"创建一个文件" + file.createNewFile();
"创建一个一级目录文件夹" + file.mkdir();
"创建多级目录文件夹" + file.mkdirs();
"删除文件" + file.delete();
"剪切/重命名文件" + file.renameTo(路径,"重命名");

"获得文件最后部分的名字:" + file.getName();
"获得文件大小字节数:" + file.length();
"获得目录名:" + file.getName();
"获取文件的绝对路径:" + file.getAbsolutePath(); //返回String对象
"获取文件的绝对路径:" + file.getAbsoluteFile(); //返回File对象
"获取文件的相对路径:" + file.getPath();
"获取路径中文件和文件夹名" + file.list(); // 返回值是String[],相当于遍历
"获取路径中文件和文件夹名" + file.listFiles(); //返回值是File[],返回的是目录和文件的全路径
"获取修改的时间:" + file.lastModified();// 毫秒数
递归

注意事项:

  1. 递归一定要有出口
  2. 递归次数不能过多
  3. 构造方法禁止递归
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public static void main(String[] args) {
File dir = new File("d:\\eclipse");
getAllDir(dir);
}

定义方法,实现目录的全遍历
public static void getAllDir(File dir){
System.out.println(dir);
//调用方法listFiles()对目录,dir进行遍历
File[] fileArr = dir.listFiles();
for(File f : fileArr){
//判断变量f表示的路径是不是文件夹
if(f.isDirectory()){
//是一个目录,就要去遍历这个目录
//本方法,getAllDir,就是给个目录去遍历
//继续调用getAllDir,传递他目录
getAllDir(f);
}else{
System.out.println(f);
}
}
}

计算斐波那契数列
public static int getFBNQ(int month){
if( month == 1)
return 1;
if( month == 2)
return 1;
return getFBNQ(month-1)+getFBNQ(month-2);
}

字节操作

字节输入流.png
fileInputStream构造方法.png
fileInputStream方法.png
字节输出流.png
fileOutputStream构造方法.png
fileOutputStream方法.png

fileInputStream
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public static void test2(File file) {

jdk1.7 提供一种更加优雅的方式 去关闭流对象 try(流对象)...catch...resources

try (InputStream inputStream = new FileInputStream(file);)
{
//2.读取文件内容
byte[] by = new byte[(int)file.length()];// 1024的整数倍
int result = inputStream.read(by);//将输入流对象的数据写入到字节数组里面 返回值(读取的有效字节数)
int num = inputStream.read(); //一次读取一个字节 如果是读到文件末尾返回-1
"off 从字节数组的第几个元素开始写入 ,len: 写入多少个元素到字节数组"
int result = inputStream.read(by, 0, 4);
//将文件内容读入到字节数组
System.out.println(Arrays.toString(by));
//转换成字符串进行操作
for(byte b:by) {
System.out.print((char)b);
}
//字节数组转换成字符串
System.out.println(new String(by));

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

}
fileOutputStream
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void test1(File file) {

try (
// 1.创建输出流对象
"文件不存在可以自定去创建,后面为true表示追加文件后面写,不会删除文件之前已经有的内容"
OutputStream outputStream = new FileOutputStream(file,true);
) {
outputStream.write('\n'); "换行"
outputStream.write('c');"一次写一个字节内容"

byte[] by = {97,97,97,'a'};
outputStream.write(by); "依次写入byte中的字节"

outputStream.write("单价".getBytes()); "在文件中写中文"

outputStream.write(by, 0, by.length);"off从第几个元素开始写入文件 len:写多少个"
outputStream

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

字符操作

字符输入流.png
FileReader构造方法.png
FileReader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void test3(File file) {
try (Reader reader = new FileReader(file);
) {
int result = 0;
char[] ch = new char[10];
while ((result = reader.read(ch, 0, ch.length)) != -1) {// result有效的字符数
System.out.print(new String(ch));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

字符输出流.png
FileWriter构造方法.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void test1(File file) {
try (
// 1.创建字符输出流对象
Writer writer = new FileWriter(file);) {
writer.write('我');
writer.write("我们".toCharArray());
writer.write("abc".toCharArray(), 0, 2);
writer.write("\n");
writer.append('a');

writer.flush(); "必须要刷新,不刷新就没有文件,有close()就不用刷新"

} catch (IOException e) {
e.printStackTrace();
}
}

BufferedReader构造方法.png
BufferedReader方法.png
BufferedWriter构造方法.png
BufferedWriter方法.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static void testCopy3(File sourceFile, File targetFile) {
System.out.println("COPY文件");
long start = System.currentTimeMillis(); // 计算开始copy的时间
try (
创建高效的字节输入流对象
BufferedInputStream bufferedInputStream = new BufferedInputStream(
new FileInputStream(sourceFile));
创建高效输出流对象
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
new FileOutputStream(targetFile));) {

int len = 0;
byte[] by = new byte[1024];
while ((len = bufferedInputStream.read(by)) != -1) {
bufferedOutputStream.write(by, 0, len);
}
long end = System.currentTimeMillis(); // 计算结束copy的时间
System.out.println("copy结束。。。。。。。。。。。"+(end-start));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

输入输出流

DataInputStream/DataOutputStream
实现了一个DataInput接口,一般配合Socket使用
必须先写入文件,才能读取文件
读的顺序要和写的顺序一致

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
"先Write"
public static void test1(File file) {
// 用户登录
// 用户名 密码
// 保存用户名 密码内容
try (DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(file));

) {
dataOutputStream.writeUTF("jim"); "写入用户名"
dataOutputStream.writeInt(1234); "写入密码"
dataOutputStream.writeByte(20); "写入年龄"

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}


"再Read"
public static void test(File file) {

try (DataInputStream dataInput = new DataInputStream(new FileInputStream(file));) {

// 读取文件内容
String name = dataInput.readUTF(); "读取UTF内容"
int id = dataInput.readInt(); "读取Int内容"
byte age = dataInput.readByte(); "读取字节内容"

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

}

Properties

特点:

  1. 存储**键值对(一组数据)*属性名—>属性值*
  2. 读取配置文件内容,*properties
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
"构造方法"
Properties properties = new Properties();

"存储元素"
properties.put("key","value");
properties.setProperty("key","value"); // 建议用这个

"字节输入流对象的创建的两种方法"
InputStream inStream = PropertiesDemo.class.getResourceAsStream("user.properties");//资源文件名称
InputStream inStream = PropertiesDemo.class.getClassLoader().getResourceAsStream("com/javasm/io/user.properties");

"以.properties结尾的文件书写格式中间不能有空格!"
name=zhangSan
age=20

"流对象读取文件中的键值对,保存到集合"
properties.load(inStream);

"重写往文件里写入"
properties.store(文件写入器,"原因"); // 原因不能写中文

"获取元素"
String trueName = properties.getProperty("key");
"转成ISO8859-1读取,再转成utf-8输出"
trueName = new String(trueName.getBytes("ISO8859-1"), "utf-8");

"遍历"
Set<Entry<Object, Object>> set = properties.entrySet();
set.forEach(entry->{
System.out.println(entry.getKey()+"--------"+entry.getValue());
});

序列化

ObjectOutputStream 序列化流 写入
ObjectInputStream 反序列化流 读取
必须先写入文件,才能读取文件,类必须要实现Serializable接口
静态的成员变量不能序列化
transient(瞬态)修饰的成员变量不能被序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
"构造方法"
ObjectInput objectInput = new ObjectInputStream(ObjectInputDemo.class.getClassLoader().getResourceAsStream("bin目录下配置文件名称"))
ObjectOutput objectOutput = new ObjectOutputStream(new FileOutputStream(new File("配置文件路径")))

"将指定的对象写入到文件中"
objectOutput.writeObject(user);
"从ObjectInputStream读取一个对象"
objectInput.readObject();

"字节转字符的桥" : InputStreamReader();
"字符转字节的桥" : OutputStreamWriter();

"接收用户输入的字符,并指定的编码格式"
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
"将用户的输入写入到文件中"
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(new File("src/b.txt")));

"指定读取的文件"
BufferedReader bufferedReader = new BufferedReader(new FileReader(new File("src/IO.txt")));
"将读取到文件的内容输出"
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(System.out));

"写入固定的序列号"private static final long serialVersionUID = 1L
"一次读取一行" :bufferedReader.readLine();
"写一个换行" :bufferedWriter.newLine();
"将缓冲区的内容刷新到文件" :bufferedWriter.flush();
"将内容输出/输入":bufferedWriter.write(content);

相关文章

JDBC

JAVA多线程

JUC