JAVA最基础的教程

微信公众号:《极客小祥》

永远相信美好的事情即将发生

环境变量配置

JAVA_HOME:配置的是jdk的根目录

path:配置bin目录(%JAVA_HOME%\bin)

基本格式

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

public class 类名{
	// 类名每个单词首字母大写
	public static void main(String[] args) {
		
	}
}

1、java工具包

jdk:java开发工具包(java development kit),代码编写依赖jdk

jre:java运行环境(java runtime environment),提供javav程序运行的环境

jvm:java虚拟机(java virtual machine),确切说程序是在jvm里面运行的(只认识class字节码文件)

2、常用cmd命令

dir:显示当前路径下的目录

cd:路径操作

cls:清除当前屏幕

javadoc 程序名.java:生成Doc文档

3、cmd运行步骤

先写程序

编译:javac 程序名.java

执行:java 程序名

4、注释

单行注释://注释内容 快捷键Ctrl+/

多行注释:/*注释类容*/ 快捷键Ctrl+Shift+/

文档注释:/**注释内容*/(对类和文档进行解释)

/*
	多行注释 一般写在类的开头
	写出
		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

设置相关

字体大小调节Window->Preferences->Appearance->Colors and Fonts->Basic->Text Font

设置统一编码格式为UTF-8Window->Preferences->workspace->Text file encoding

设置注释格式:windows–>preference–>Java–>Code Style–>Code Templates–>code–>new Java files

变量的定义和注意事项

变量定义后,不赋值不能使用

变量有自己的作用范围,变量的有效范围定义在一对大括号内

变量不允许重复定义

数据类型

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

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个字节

2、引用数据类型

String:字符串类(默认是null)

String + 基本类型:字面量数据类型

数组:数据类型[] 数组变量名 = new 数据类型[长度]

任意引用数据类型都存在堆里面

3、数据类型转换

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

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

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);
	}
}

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

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

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
	}

}

2、赋值运算符

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

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);
	}
}
3、比较运算符

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

结果只有 true 或者 false

比较字符串是否一致:名称1.equals(名称2)

4、逻辑运算符

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

& 与:一个false,结果就是false

| 或:一个true,结果就是true

^ 异或:两边相同为false,不相同为true

取反:!true为false !false为true

&& 短路与:一边是false,另一边不运行

|| 短路或:一边是true,另一边不运行

5、三元运算符

公式:布尔表达式?结果1:结果2

结果1和结果2数据类型保持一致

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

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

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
	}
}

循环控制语句

1、If Else
if(表达式){
	//表达式成立执行这里面的语句
	//语句
}else if(表达式2){

}else{
	//不满足执行这里的语句
}
2、While/Do While

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

while(判断条件){
	// 成立执行这里的语句
}

do{
	//执行一次
}while(判断条件);
3、Switch Case
// switch后表达式满足的数据类型有
// int byte char String(1.7版本) enum(枚举) short
switch(表达式){
// case后的数据类型要和switch表达式的数据类型保持一致
case 表达式1:
	代码逻辑;
	break;
case 表达式2:
	代码逻辑;
	break;
case 表达式n:
	代码逻辑;
	break;
// 前面所有的表达式都不满足执行default语句后的代码
default:
	代码逻辑;
	break;
}
4、For
for(表达式1;表达式2;表达式3){
	// 代码逻辑
}

// 增强for循环
for(数组元素数据类型 变量名称:数组变量名){
	// 循环体
}
5、Break,Continue,Return

Break:直接终止整个循环体,不能单独使用在if

Continue:结束本次循环体,开始下个循环

Return:结束整个方法

6、Scanner使用

Scanner input = new Scanner(System.in);,定义输入

int a = input.nextInt();,接收用户输入
input.close(),关闭流

7、断点调试

先双击行首数字出

F6程序往下走一步

F8走到下一个断点处

数组

1、一维数组

语法

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

语法

数据类型[][] 变量名 = 数据类型[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);  // 打印一维数组长度

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

排序(Sort)

1、冒泡排序

效率最慢

Screenshot_1.png

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;
		}
	}
}
2、选择排序

Screenshot_1.png

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;
}
3、插入排序

效率最快

Screenshot_2.png

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、类的创建
public class 类名{
	// static表示静态的
	// 下面都是类的属性
	static String name; // 姓名
	static String gender; //性别
	static int age;
}
2、类的方法
  1. 权限修饰符:public static(公共的),protected(受保护的),private(私有的),默认(default)
  2. 方法返回值:数据类型,void(无返回值数据类型)
  3. 方法名():规范:首字母小写,第二个单词字母大写,名字不能重复
  4. 方法的参数:形式参数,形参 所有数据类型都可以充当形参
//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. 可变参数必须写在参数列表的最后一位
3、创建对象

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

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

调用类的属性和方法

zhangSan.name = "张三";
zhangSan.gender = "男";
zhangSan.age = 20;
System.out.println(zhangSan.name);  // 输出name
4、调用方法

语法:方法名();

public static void method1() {
	System.out.println("无参无返回值");
}

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

// 构造方法重载
public Animal(String name1) {
	name = name1;
}
6、成员变量和局部变量
  1. 存在位置不一样:成员变量在类里面,局部变量在方法里面
  2. 作用范围不一样:成员变量在类里任何地方都可以访问,局部变量只可以在方法里面使用
  3. 内存储存位置不一样:成员变量在堆里,局部变量在栈里
  4. 初始值不一样:成员变量有初始值,不需要初始化,局部变量没有初始值,必须初始化

枚举类

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

面向对象三大特性

1、封装

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

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. 数据是让所有对象共享

静态代码块

static {
	初始化数据,不管创不创建对象都走
	只运行一次
	System.out.println("静态代码块");
}
{
	只有在创建对象的时候才会走这句话
	System.out.println("普通代码块");
}
2、继承(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

3、多态

发生多态条件:

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

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

Screenshot_1.png

抽象类和接口

1、抽象类

使用条件:当所有子类都需要重新父类的逻辑时,父类方法体就变得没有意义,就把父类方法声明成抽象的方法

使用方法访问权限修饰符 abstract 返回值类型 方法名();

注意:抽象类不能创建对象,体现在多态上,抽象类的构造方法主要是满足子类对象的创建

Screenshot_3.png
Screenshot_4.png

2、接口(interface)

创建接口

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. 接口和接口之间可以实现多继承
3、接口和抽象类的区别

共同点:都不能实例化,都用于多态

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

异常

异常Exception(类) —> 可以处理

错误Error(类) —> JVM抛出,程序直接终止

它们有共同的父类:Throwable

Screenshot_2.png

异常可以分为两大类:

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

String getMessage():获得详细的异常信息字符串内容

void printStackTrace():将详细异常信息通过流打印(输出)至控制台


出现多个异常的情况下,只走其中一个异常,就是说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

2、抛出异常 throws

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

  1. 异常信息传递 (throw)
  2. 结束程序
  3. 与自定义异常结合使用
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

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

1、Integer

包装类分为四类八种

Byte,Shory,Integer,Long,Float,Double,Character,Boolean

成员变量的数据类型使用包装类

Integer介绍:

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

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

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

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

// 底层实现: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

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

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

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功能方法

比较数据类型是否一致

//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转换

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

Integer in = 100;
String str = in.toString(); // 转换成字符串
int i = 10;
String j = i + ""; // int转换为String
2、Character
Character功能方法

将字符串转换为指定进制

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(' ')){
	判断是否为空字符串
}
3、Math

获得随机数

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

求几次幂

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

四舍五入

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

求一个数的平方根

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

最大值最小值

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

获取绝对值

Math.abs(-10); // 变成10
4、Object(基类/超类)

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

hashCode()

equals——hashcode.png

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

getClass();

判断元素是否为空

Objects.requireNonNull(元素名);

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

notify();
notifyAll();

线程等待

wait();
wait(long timeout);
wait(long timeout, int nanos);

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

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

表示正在运行的类或者接口(获得正在运行的类或者接口的class文件)

反射最基本的一个类–>获得类/接口的所有内容

一般用于底层的封装和框架的开源

获得Class类的对象的方式
1、创建一个Class类的实例
Person person = new Person();
Class clazz = person.getClass();  // clazz就是Person类的字节码文件
clazz.getName(); // 获得类或者接口的全限定名称--->包名+类名
clazz.getSimpleName(); // 拿到类名

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

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

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

clazz.getClassLoader();

查找具有给定名称的资源

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

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

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

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

创建字符串

构造
String str1 = new String();

String str2 = new String("hello");

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

获得字符串的字节内容

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

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

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

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

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

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

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

str.charAt(1);  // 不能超过字符串的总长度

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

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

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

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

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

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

String.valueOf(1);

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

str.endsWith("a"); // 判断是否是a结尾
str.startsWith("b"); // 判断是否是b开头

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

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

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

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

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

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

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

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

str.isEmpty();

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

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

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

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

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

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

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

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

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

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

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

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

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

str.trim();

去掉中间空格

str.trim.replace(" ","");
str.trim.replaceAll(" ","");
7、StringBuffer/StringBuilder(字符串变量类)

StringBuffer:

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

StringBuilder:

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

StringBuffer功能方法

创建初始化对象

StringBuffer buffer = new StringBuffer("hello");

追加字符串

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

删除字符串

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

反转字符串

buffer.reverse();

修改某个索引字符内容

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

StringBuilder功能方法

创建初始化对象

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

String/StringBuffer/StringBuilder区别

  1. 从数据:

    String: 数据不可变

    StringBuffer/StringBuilder:值可以改变
  2. 从内容

    String: 浪费内存

    StringBuffer/StringBuilder;始终都是同一个对象
  3. 从线程安全

    String/StringBuffer 线程安全(同步)

    StringBuilder 线程不安全(不同步)
  4. 效率

    StringBuilder最快,其次是String,最后是StringBuffer
8、System

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

方法:

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

util包常用类

1、Date

Date类对象用来表示时间和日期

该类提供一系列操纵日期和时间各组成部分的方法

构造方法重载
Screenshot_1.png

2、Calendar

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


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

3、Insatnt

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

4、LocalDate/LocalTime/LocalDateTime

LocalDate 获得当前系统的时间 2007-12-03

LocalTime 获得当前系统的时间 10:15:30

LocalDateTime 获得当前系统的时间 2007-12-03T10:15:30

此类也是不可变且线程安全

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

数字的格式化

//#.## 保留两位小数
//#.##% 自动百分比计数并保留两位小数
//,### 每三位以逗号分隔
DecimalFormat df = new DecimalFormat("#.##");
String result = df.format(3.1415926);
6、Random(伪随机数类)

在多线程中是不安全的

创建实例

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

取一个随机整数值

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

在多线程中是安全的

ThreadLocalRandom localRandom =ThreadLocalRandom.current();
System.out.println(localRandom.nextInt(40, 100));//从40到99选一个随机数
7、加密解密
Base64

jdk1.8可正常使用

Base64.Encoder(加密),Base64.Decoder(解密)

该类使用RFC 4648和RFC 2045中规定的Base64编码方案来实现用于解码字节数据的解(编)码器。

'加密'
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。 消息摘要是采用
任意大小的数据并输出固定长度散列值的安全单向
散列函数

// 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、意义:与形式参数作用一样,限定数据类型
2、作用:隐式帮助进行类型转换
3、功能:
  1. 修饰类–>泛型类
    '泛型类的字母常用: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. 修饰接口–>泛型接口
    public interface World<E,T>{
    	// 接口内都是抽象方法 public abstract
    	'泛型充当形参'
    	void add(E e);
    	'泛型充当返回值'
    	T delete(int id);
    	'泛型修饰方法'
    	<T> T test();
    }
    
  3. 泛型擦除概念:泛型是在编译的时候起作用,但在代码运行期间是没有作用的
  4. 泛型上限
    • 让泛型继承一个类
    public class Test<E extends Number>{
    	'传入的参数只能是Number中的数据类型'
    }
    
  5. 泛型通配符:?
    public class test<E,T>{
    	public void add(Hello<?,?> hello){
    		'?统配任意数据类型,不需要和类中的E和T保持一致'
    	}
    }
    

集合

集合作用和数组作用一致,用于存储多个元素数据

理论上可以存储任意引用数据类型的数据(开发中都存储相同类型的数据–>避免出现类型准换问题)

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

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

?代表的是泛型的通配符

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

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

集合的接口
集合.png

1、Collection(是List和Set的父类)

特征

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

创建集合对象

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

增加元素

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

删除元素

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

查询元素

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

清除集合中所有的元素

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

判断元素是否存在

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

lambda语法:(参数类型 参数名,参数类型 参数名)->{需要进行的操作}

遍历集合元素

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);
});

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

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

迭代器

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

集合转数组

第一种方法
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

初始化容量10
List<Integer> list = new ArrayList<>();
获取
list.get(list.size()-1) // 获取最后一个元素
删除
list.remove(1); //1为索引值,删除索引为1的值并且返回被删除的索引
list.remove(new Integer(1)); // 删除一个值为1的数
修改
list.set(0, 1000); // 把第一个元素改为1000
遍历
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

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

linkedList.peek(); // 获取第一个元素
linkedList.peekFirst(); // 获取第一个元素	 列表为空,则返回 null 
linkedList.peekLast();// 获取最后一个元素 列表为空,则返回 null 
删除元素
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一致

初始化对象
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);
	}
});
2、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

创建对象
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); //需要指定容量
新增元素
map.put("key",value); // put的返回值一般情况是null,当有重复键时返回的是之前键的value值
查询元素
map.get("key");  // 返回的是value值
map.containsKey("key");
map.containsValue(value);
删除元素
map.remove("key");  // 返回的是移除之前的value值
map.remove("key", value);
替换元素
map.replace("key", value);
map.replace("key", value, 替换的value);
遍历集合元素
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());
}
3、Collections

集合操作工具类

对 List集合 进行二分搜索,参数传递 List集合 和 被查找的元素,集合必须是有序的
Collections.binarySearch(list,5); // 查找5出现在集合的哪个索引
找不到指定的元素内容返回值是 插入点-1
对 List集合 随机排列
Collections.shuffle(list);
List本身是线程不安全,用这个可以让它变成线程安全类
List<Integer> list = new ArrayList<>();
list = Collections.synchronizedList(list);
使用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

1、File操作

file方法.png
File类构造方法

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

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

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

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

String separator = File.separator;  // 静态变量
打印一个向右的斜线 \   Linux下是左斜线 /
"判断路径中是否有这个文件" + 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. 构造方法禁止递归
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);
}
2、字节操作

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

fileInputStream
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
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();
	}
}
3、字符操作

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

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

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

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();
}
	}

4、输入输出流

DataInputStream/DataOutputStream

实现了一个DataInput接口,一般配合Socket使用

必须先写入文件,才能读取文件

读的顺序要和写的顺序一致

"先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();
	}

}
5、Properties

特点:

  1. 存储键值对(一组数据)属性名—>属性值
  2. 读取配置文件内容,*properties
"构造方法"
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());
});
6、序列化

ObjectOutputStream 序列化流 写入

ObjectInputStream 反序列化流 读取

必须先写入文件,才能读取文件,类必须要实现Serializable接口

静态的成员变量不能序列化

transient(瞬态)修饰的成员变量不能被序列化

"构造方法"
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);
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值