JavaSE

1、数据类型、命名法

8种基本数据类型

4种整数类型(byte、short、int、long);

2种浮点类型(float、double);

1种字符类型char

1种布尔类型boolean

++自增

++a先自增1再参与代码执行

a++先参与代码执行后自增1

int b=9;
		System.out.println(b++);
		System.out.println(b);
		
		//输出结果:
		9
		10

比较运算

大于>、等于=、小于<、小于等于<=、大于等于>=、不等于!=

赋值运算

等于、加(减乘除)等于、取余等于

浮点型强制转换为整形,舍弃小数部分,只保留整数部分

什么是跨平台

平台一般指的是,操作系统。跨平台就是一次编写开发,可以在任何操作系统运行。

Java的jdk、jre以及jvm

jdk :Java开发工具包,提供Java开发和编译(javac)、执行等相关支持

jre :Java运行环境,提供Java程序运行的支持(提供jar包)

jvm :虚拟机,运行编译之后的字节码文件

基本语法规范

  • 严格大小写
  • 类名首字母大写,遵循驼峰命名法,如UserInfo
  • 方法名首字母小写,方法名遵循驼峰命名法,如userInfo
  • 源文件名必须和类名相同,后缀是Java,编译文件后缀是class

命名法

  • 驼峰命名法:若干个单词组成,每个首字母大写,如UserName
  • 下划线命名法: 单词小写,每个单词之间同下划线链接,如user_name
  • 匈牙利命名法:首字母用变量的数据类型缩写,后面遵循驼峰命名法 如:String UserName

基本数据类型的取值范围

  1. byte [-27,27-1]
  2. short [-215,215-1]
  3. int [-231,231-1]
  4. long [-263,263-1]
  5. float 32bit
  6. double 64bit
  7. char 16bit
  8. boolean 表示1位的信息 1bit

2、数据类型简单了解、运算符

2.1、数据类型

package zlx;

public class text {
	public static void main(String[] args) {
		
		//基本数据类型
		//1.byte字节 比特bit  1bit = 1二进制位
        //占用内存空间    1byte = 8bit
        //byte的取值范围是[-128,127]  也就是[-2^7,2^7-1]
        //默认值为0
        
		/*    
		 2short
		  占用内存空间 1short = 16bit
		  取值范围[-2^15,2^15-1	]
		  默认值0
	      */
		
		
		/*3 int
		 * 占用空间 1int = 32bit 
		 * 取值范围[-2^31,2^31-1]
		 * 默认值为0
		 * 
		 * !!!int类型是一个数字的默认数据类型
		 * 没有声明的整数都是int类型
		 * 
		 * */
		System.out.println(12);
		/*
		 * 4 long
		 * 占用空间 1long = 64bit
		 * 取值范围[-2^63,2^63-1]
		 * 默认值0L
		 * 小写L不好区分所以用大写
		 * */
		long a3 = 123;
		long a4 = 123456L;//小写L不好区分所以用大写
		
		
		//浮点型
		/*
		 * 5 float单精度浮点数
		 * float = 32bit
		 * 精度可以理解为,表示数值的精确程度
		 * 默认值0.0f
		*/
		float f = 3.154652F;
		float f1 = 3.154652F;
		
		
		/*
		 *  6 double 
		 *  double = 64bit
		 *  默认值0.0d
		 * 
		 * */
		double d = 3.2; 
		double d1 = 3.2;
		
		
		/*
		 * 7 char字符型
		 * char类型是一个单一的16位 Unicode字符
		 * char = 16bit
		 * 
		 * 最小值 '\u0000' 0
		 * 最大值'\uFFFF' 65535
		 * char类型可以存储任何单一字符
		 * 1)char类型的值必须用英文单引号括起来
		 * 2)char类型的值只能是单个字符
		 */
		char a = '菜';


		/*
		 * 8 boolean 类型
		 * 数据表示1位的信息
		 * boolean = bit  两家公司对于boolean类型占位数不一样
		 * 只有true跟false两个取值
		 * 默认值位false
		 * 
		 * */
		boolean b;
		
	}
}


public static void main(String[] args) {
		// TODO Auto-generated method stub
		/*
		 * 根据精度由低到高排序为
		 * byte->short,char->int->long->float->double
		 * 1.自动数据类型转换:根据上有顺序,低精度转为高精度,可以自动转换为高精度的变量
		 * 
		 * 2.强制类型转换
		 * 
		 * 高精度转换为低精度时,必须使用强制类型转换,但是会发生溢出或者损失精度
		 * 
		 * 
		 *数据转换规则,不能对Boolean类型进行类型转换
		 *高精度转换为低精度时,必须使用强制类型转换,但是会发生溢出或者损失精度
		 *浮点数转整数是直接舍弃小数部分,而不是四舍五入
		 * */
		double d = 3.14d;
		int i = (int)d;
		System.out.println(i);
	}

2.2、运算符

1.算术运算符:

​ + - * / % ++ –
加 减 乘 除 取余 自增 自减
自增:++在变量后,变量先参与代码的执行,后自增
++在变量前,变量先自增,后参与代码的执行

2.逻辑运算符

​ && || !
与 或 非
短路与运算,当【与&&】运算符左边的表达式为false时,根据运算规则已经可以判断出整个表达式的结果,不会继续判断右边的表达式。

​ 短路或运算,当【或||】运算符左边的表达式为true时,根据运算规则 已经可以判断出整个表达式的结果,不会继续判断右边的表达式

非运算  表达式的布尔值取反  

3.比较运算符

​ 运算结果为布尔值

4.赋值运算符:

= += -= *= /= %=

5.位运算符

1) 二进制的转换
2)原码 反码 补码

​ 1.正数的原码=反码=补码
2.负数反码=原码按位取反
补码=反码+1

3)在计算机世界里。所有的数据都是以补码的形式存在于计算机中的(都是以补码运算)
4)

& 按位与 如果都是1 返回1 否则返回0
} 按位或 如果都是0返回0 否则返回1
^ 异或 对应位相同返回0 否则返回1
~ 非运算 按位取反运算符,二进制的补码按位取反(包括符号位)0->1,1->0

int a = 2;
  2 = 0010
  取反符号位取反
  0 0010
  1 1101 补码
  1 1100 反码
  1 0011 原码
  -3
System.out.println(~a);

​ << 左移运算符
>>>无符号右移

位运算符的优势:

运算速度更快
 应用场景:加密

三元运算符

​ int a = 0;
boolean t =false;
三元运算符 也叫选择表达式

​ a = t ? 2 :3;
t成立,2给a,反过来 不成立 3给a

3、选择分支与循环

3.1、选择分支

1、if分支

		boolean t = true;
		if (t) {
			System.out.println("ttt!true");
		}else {
			System.out.println("ttt!false");
		}
		
		//当判断条件可能出现的情况大于两种时,用if else if
		if (1 == 1) {
			
		}else if (2 == 2) {
			
		}
		
		//当判断条件只有一种情况需要特殊处理,直接if
		if (t) {
			System.out.println("!!!!");
		}

2、switch分支

int a = 5;
		switch (a) {
		case 1:
			System.out.println("a==1");
			break;
		case 2:
			System.out.println("a==2");
			break;

		default:
			System.out.println("上边都没有");
			break;
		}
		

3.2、循环

1、while循环

while(condition){

}

condition 判断是否执行的条件

boolean t = true;
		int count = 0;
		while (t) {
			count++;
			if (count == 10) {
				t =false;
			}
		}

2、do while循环

do{} while{condition} 循环结构里的代码,至少执行一次

boolean t = false;
		int count = 0;
		do {
			count++;System.out.println(count);
		} while (t);

3、for循环

for(index;condition;i++){
    //循环语句
}

第一次循环: index - condition - 循环语句 - step
第二次循环:condition - 循环语句 - step
index:循环的初始值,只在第一次循环的时候完成变量初始化以及赋值
step:每次循环,初始值的增长量,在每次循环结构中的代码执行完毕后执行

3、break和continue

​ break 跳出循环,循环终止
continue 结束当前循环,进入下次循环,本次循环continue后的代码不再执行

​ 死循环:

​ for(;😉 {
System.out.println(1);
}

4、嵌套循环

public class Test {
	public static void main(String[] args) {
		//嵌套循环,至多嵌套不超过3层
		for (int i = 0; i < 5; i++) {//父循环,外层循环
			System.out.println("---------"+i+"---------");
			for (int j = 0; j < 3; j++) {//子循环,内层循环
				System.out.println("j");
			}
		}
	}
}

//输出结果
---------0---------
j
j
j
---------1---------
j
j
j
---------2---------
j
j
j
---------3---------
j
j
j
---------4---------
j
j
j

5、嵌套循环中在子循环中跳出父循环

fa:for(int i = 0 ;i < 5; i++){//外层循环取名fa
    System.out.println("-----------"+i+"------------");
    for(int j = 0; j < 5 ; j++){
        if(j == 3) break fa;//满足条件终止此循环以及外层循环
    }
}

4、数组

//1.声明一个数组
		//数组的长度,指的是数组中可以存储的元素个数
		int[] array = new int[5];
		
		int[] array2 = {1,2,4,5,9,7};//声明一个int类型的数组,同时初始化数组的元素
		//其他语言的写法,也不会报错
		int array3[] = new int[4];
		
		//2.数组的赋值
		array[0] = 6;
		
		//3.查看指定位置的值
		int a = array[2];
		
		//4.查看数组长度.length方法
		int t = array.length;
		
		//5.遍历数组
		for (int i : array) {
			System.out.println(i);
		}

5、String - 字符串常量

1、用法

  • .equals()比较两个字符串是否相等(String s = null)s.equals会报错!!
  • instanceof 判断前者是否为后面类型
  • .length 返回字符串的长度
  • .trim()消除开头和结尾的空格
  • .replace() 替换字符串 (旧字符串,新字符串)
  • .concat() 拼接字符串
  • 大小写转换:
    • 全大写 toUpperCase
    • 全小写 toLowerCase
  • .split()字符串切分
  • .contains判断字符串是否包含指定字符
  • .substring截取字符串
    • 从指定下标到结束 只给出开始下标
    • 从指定下标到指定下标,但不包括最后一个(左闭右开)
  • .indexOf 根据字符获取下标
  • .charAt 根据下标获取字符
  • .isEmpty 判断是否为空 为null时报错
  • .toCharArray 转换为字符数组
  • String.valueOf变量转为String类型
//		String s1 = null;
//		String s2 = new String("asd");
//		String s3 = " a d s g ";
//		String s4 = "A d S g";
		
//		1、 equals() 比较两个值是否相等
//		s2.equals(s1);
		
//		2、判断一个变量(或对象) 是否是后面的数据类型
//		System.out.println(s1 instanceof String);
		
//		3、返回字符串的长度
//		System.out.println(s2.length());
		
//		4、trim() 去除字符串两端的空格
		
//		System.out.println(s3.trim());
		
//		5、replace 替换字符串
//		System.out.println(s3.replace(" ", "!"));
		
//		6、拼接字符串 concat
//		System.out.println(s3.concat("444"));
		
//		7、字符串大小写转换
//		全转小写
//		System.out.println(s4.toLowerCase());
//		全转大写
//		System.out.println(s4.toUpperCase());
		
//		8、字符串切分
//		String s5 = "aabbccdd";
//		String[] arr = s5.split("");
//		System.out.println(Arrays.toString(arr));
		
//		9、 判断字符串中是否包含指定字符
//		System.out.println(s4.contains("d"));
		
//		10、 截取字符串
//		String s6 = "123456";
//		从指定下标截取到结束
//		System.out.println(s6.substring(1));
//		从开始下标截取到结束下标,但不包括结束下标
//		System.out.println(s6.substring(1, 4));
		
//		11、根据下标获取字符
//		System.out.println(s5.indexOf("c"));;
		
//		12、根据下标获取字符
//		System.out.println(s5.charAt(3));
		
//		13、判断字符串是否为空
//		String s13 = "";
//		String s13a = null;
//		String s13b = "11";
//		System.out.println(s13.isEmpty());
//		System.out.println(s13a.isEmpty());
//		System.out.println(s13b.isEmpty());
		
//		14、将字符串转换为字符数组
//		String s14 = "!@#ASFD";
//		char[] arr2 = s14.toCharArray();
//		System.out.println(Arrays.toString(arr2));
		
//		15、将变量转为String类型
//		int a = 2;
//		String s15 = String.valueOf(a);
//		System.out.println(s15);
//		System.out.println(s15 instanceof String);

2、相等性原则

1)==比较的是基本数据类型,比较的是 值 是否相等
2)==比较引用类型,比较的是 内存地址 是否相等

3)Object类的equals()比较的是 内存地址 是否相同
4)String类的equals()比较的是 值 是否相同

Object类是Java类的顶级父类,所有类默认继承它

3、String/StringBuffer/StringBuilder的区别

  • StringBuffer/Stringbuilder 类的对象能够被多次修改,并且不产生新的对象,即内存地址不变
  • 修改String对象的值,内存地址会发生变化
  • StringBuffer是线程安全的,StringBuilder是不安全的
  • 线程安全会带来额外的开销,所以StringBuilder的执行效率会比StringBuffer高
//		1、声明一个StringBuffer变量
//		StringBuffer sb = new StringBuffer("aaa");
		//hashCode()  返回一个hash值,在一定程度上这个hash可以表示内存地址
//		System.out.println(sb.hashCode());
		//2.拼接字符串
//		sb.append("bbb");
//		System.out.println(sb.hashCode());
		//3.reverse方法,将字符串反转输出
//		System.out.println(sb.reverse());
		//4.删除字符串中指定下标范围的字符
//		System.out.println(sb.delete(3, 6));
		//5.在指定下标位置插入指定字符
//		System.out.println(sb.insert(1, "!!!"));
		//6.替换指定索引区间的字符串
//		System.out.println(sb.replace(1, 3, "!@#$%^&"));
		//7.长度
//		System.out.println(sb.length());
		//8.容量长度,StringBuffer对象最多可以存储的字符个数,超过该数量自动扩容
//		System.out.println(sb.capacity());
		
		/*
		 容量长度:capacity()
		 默认为16,在声名StringBuffer时给出初始值。那就是n+16
		 在addend超出容量后,自动扩容
		 左移一位+2。

6、构造方法与方法的重载

6.1、构造方法的作用:

用于类在创建对象的时候,完成类对象相关的初始化操作

6.2、构造方法特点:

  • 构造方法的方法名必须与类名一致
  • 构造方法没有返回值
  • 如果一个类没有显示的声明一个构造方法,则Java虚拟机会默认给他添加一个无参的构造方法
        //1.成员变量
		String name;
		int age;
		//3.构造方法
		/*
		 作用:
		 用于类在创建对象的时候,完成类对象相关的初始化操作
		 
		 
		 构造方法特点:
		 1构造方法的方法名必须与类名一致
		 2构造方法没有返回值
		 3如果一个类没有显示的声明一个构造方法,则Java虚拟机会默认给他添加一个无参的构造方法
		 4用于完成创建对象后的初始化操作
		 */
		
		public test2() {}
		
		public test2(String name1,int age1) {//()里面的部分称为参数列表,也叫形参(形式参数)
			this.age = age;
			this.name = name;
		}
		//2.方法
		public void speak() {
			
		}
		public static void main(String[] args) {
			test2 t = new test2();
			t.age = 15;
			
			test2 t2 = new test2("张三",52);
			
		}

6.3、访问权限修饰符

访问权限修饰符

  1. private (私有的) 本类
  2. 默认的 本类,同包
  3. pretected(受保护的) 本类 同包 不同包子类
  4. public (公共的) 本类 同包 不同包子类 不同包的其他类

缺省值 == 默认值

鲁棒性 == 健壮性

返回值
void 无返回值关键字

有返回值,需要在方法签名中声明要返回的数据类型

6.4、重载

重写重载的区别

重写重载
发生位置子父类中同一类中
改变的位置访问控制修饰符不同,方法体不同参数列表不同、方法体不同
不变的位置方法名、参数列表、返回值类型都不同方法名不变

方法的载重

判断载重的一句:重载的是方法的参数列表

特点:

  1. 放在同一个类中
  2. 方法名相同
  3. 参数列表不同(个数,类型,顺序)注意:参数列表不同跟变量名没关系
  4. 返回值的类型是否改变,跟方法是否重载没关系,不能作为重载的依据

7、面向对象三要素

  • 封装
  • 继承
  • 多态

1.封装

定义:成员变量私有化,提供公共的set和get方法

public class Test2 {

	private String name;
	private int age;
	
	//给变量赋值set
	public void setName(String name) {
		//This关键字表示的是调用该方法的当前对象
		this.name = name;
	}
	//get获取变量的值
	public String getName() {
		return name;
	}
}
class T3{
	public static void main(String[] args) {
		test2 t = new test2();
		t.setName("小明");
		System.out.println(t.getName());
	}
}


同文档中只能有一个类是public的

快速生成set和get方法

类文件空白位置,点击鼠标右键——source——Generate Getters and Setters

2.继承

定义:子类可以不需要声明,直接调用父类的资源(成员变量与方法)

继承的特点:

  1. 所有类都有父类,即所有类都派生于Object类
  2. 只能单亲继承,即每一个子类只能有一个父类
  3. 子类只能继承父类的非私有方法和变量
    • 子类不能继承父类的私有属性
    • 如果子类中共有的方法影响到了父亲私有属性,那么私有属性是能够被子类使用的(即通过父类的公有方法访问到父类的私有变量)
  4. 子类可以直接使用继承的变量和方法,不需要再在子类中声明或写出

重写

  • 重写发生在子父类中
  • 重写的方法名相同,参数列表相同
  • 重写的方法体不同
  • 子类重写的方法,权限不能缩小

3.多态

没有继承就没有多态,生成的对象,在调用父类方法时,如果方法被子类重写,则调用的是子类重写的方法。

代码当中体现多态性,其实就是一句话:父类引用指向子类对象

格式:父类 对象名 = new 子类();

再Java中,有两种形式可以实现多态:继承和接口

方法的重载实现的是编译时的多态性(也成为前绑定),而方法的重写实现的是运行时的多态性(也成为后绑定)。

super关键字

表示当前类的父类对象,可以使用super关键字对父类变量和方法的访问

子类方法中无论写不写super(),Java都默认使用super()调用父类的构造方法

特点:

  1. 用在子类构造方法中
  2. 无论写不写super(),Java都会默认使用super()调用父类的构造方法
  3. 只能通过super()调用父类的构造方法一次
  4. 通过super()调用父类的构造方法,必须放在子类构造方法的第一行
public class Father {
	protected String name;
	
	public void test() {
		System.out.println("父类方法");
	}
}

/*
 *面向对象 类为单位
 *面向过程 方法为单位
 * */
 




/*
 * 重写的特点
 * 重写发生在子父类中
 * 重写的方法名相同,参数列表相同
 * 重写的方法体不同
 * 子类重写的方法,权限不能缩小
 * */
public class Son extends Father{

	@Override
	public void test() {
		// TODO Auto-generated method stub
		System.out.println("子类方法");
	}

	public static void main(String[] args) {
		Father son = new Son();
		son.test();
	}

	
}

JVM类加载的顺序(static)

静态代码块>new>代码块>构造方法

public class Son extends Father{
	static {
		System.out.println("静态代码块");
	}
	{
		System.out.println("代码块");
	}
	public Son() {
		System.out.println("构造方法");
	}
	public static void main(String[] args) {
		new Son();
	}
}

特点

  1. static生命的资源只能被初始化一次
  2. 修饰变量称为静态变量,局部变量不能被static修饰,因为static有全局的意思
  3. 修饰方法,称为静态方法,静态方法只能调用其他静态资源,不能调用非静态变量,不能被this和super,因为静态资源的加载先于实例化
  4. static修饰的变量或者方法独立于任何类,他不依赖类的特定对象,该类被所有对象共享
  5. 修饰内部类,外部类不需要实例化,可以直接通过外部类名直接调用

面向对象 类为单位
面向过程 方法为单位

final关键字

  1. 修饰类,类不能被继承
  2. 修饰方法,方法不能被重写
  3. 修饰变量,称为常量,常量的值不能被修改;常量名必须大写,且声明常量的时候就得给常量赋值
  4. 修饰基本数据类型,变量的值不能被改变
  5. 修饰引用类型(对象),该对象的引用(内存地址)不能被改变
final int NO = 12;
final String NAME = "abc";

8、抽象类

定义:抽象类不能实例化,它的作用是提供给其它类进行继承

抽象类特点:

  1. 修饰类,类为抽象类,不能被实例化
  2. 修饰对象,方法为抽象方法,只有方法的签名,没有方法体

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AIdeB291-1666355976917)(C:\Users\19912\AppData\Local\Temp\1665459012674.png)]

public class GrandFather {

	public GrandFather(String name) {
		
	}
}




/*抽象类
 * 定义:抽象类不能实例化,它的作用是提供给其它类进行继承
 * 
 * 抽象关键字abstract
 * 特点:
 * 1 修饰类,类为抽象类,不能被实例化
 * 2 修饰对象,方法为抽象方法,只有方法的签名,没有方法体
 * */
public abstract class Father extends GrandFather{
	public Father(String name) {
		super(name);
	}
	//方法的签名
	public abstract void run();
}



public class Son extends Father{

	public Son(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		
	}

}

9、接口

Java遵循:

单继承多实现

先继承后实现

接口的特点:

  1. 接口只有方法的签名和静态常量
  2. 接口变量默认public final static修饰
  3. 接口的签名方法,会默认用public abstract修饰
  4. 接口不能自身实例化,接口的实现类可以实例化
  5. 子类实现接口,必须重写就扣的所有签名方法
  6. 接口可以实现多个,而父类只有一个
  7. 遵循 单继承多实现,先继承后实现

接口的优点:

  1. 解决Java开发的单继承问题
  2. 接口可以实现并行开发
  3. 便于重构
/*
 * implements实现接口关键字
 * 
 *继承与实现的规则
 * java中遵循
 * 单继承多实现
 * 先继承后实现
 * 
 * 接口的特点:
 * 
 * */

public class Tom implements IPerson,IPlayer{

	@Override
	public void speak() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public String fun1() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int fun2() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		
	}

}

9.1、向上转型、向下转型

1、向上转型:子类对象向父类转型

父类类型–>父类引用–>子类对象

  1. 将一个【父类的引用】指向一个子类对象,称为向上转型,此时自动进行类型转换(即可以理解为创建了一个父类类型的子类对象)
  2. 通过父类的引用调用的方法是子类重写或继承父类的方法,而不是父类原本的方法,更不是子类特有的方法
  3. 通过父类的引用无法调用子类特有的方法,即向上转型的子类对象只能调用继承自父类的方法,而不能调用子类独有的方法,方法数量缩小,安全

2、向下转型:父类对象向子类转型

子类类型–>子类引用–>父类对象

父类对象向子类转换需要强制类型转换

  1. 将一个父类对象赋给一个子类类型的引用称为向下转型
  2. 只有Object有向下转型的可能

10、常用工具类

10.1、日期类

java.util.Date;日期

java.time.LocalDate;

java.time.LocalDateTime;Java8后的日期

java.lang.Math 数学运算

java.util.Arrays 数组工具类

package d12;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
import java.util.Date;

public class D12 {
	public static void main(String[] args) {
		
		//java.time.LocalDateTime  Java8后新增的日期类
		//获取当前日期时间
		LocalDateTime localDateTime = LocalDateTime.now();
		System.out.println(localDateTime);
		
		System.out.println(localDateTime.getYear());//获取年份
		System.out.println(localDateTime.getMonthValue());//获取月份
		System.out.println(localDateTime.getMonth());//获取月的名字
		System.out.println(localDateTime.getDayOfMonth());//或租所在月的第几天
		System.out.println(localDateTime.getDayOfWeek());//获取所在周的第几天
		System.out.println(localDateTime.getHour());//获取小时
		System.out.println(localDateTime.getMinute());//获取分钟
		System.out.println(localDateTime.getSecond());//获取秒
		
		
		//自定义一个日期
		LocalDate date2 = LocalDate.of(2014, Month.JULY, 20);
		System.out.println(date2);

//		//java.util.Date 日期
//		
//		
//		Date date = new Date();//创建一个日期对象
//		System.out.println(date);
//		
//		//java.text.Sim
//		//new SimpleDateFormat(日期格式模板)  创建一个日期格式化工具类
//		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
//		String dateString = sf.format(date);
//		System.out.println(dateString);
		
		
		
		
		
	
//				//java.lang.Math  数学运算 
//				byte a = 2;
//				short b = 4;
//				//加法
//				int h = Math.addExact(a,b);
//				System.out.println(h);
//				
//				//减法
//				int j = Math.subtractExact(a, b);
//				
//				//乘法
//				int c = Math.multiplyExact(a, b);
//				
//				//除法
//				int chu = Math.floorDiv(a, b);
//				
//				System.out.println("----------------------");
//				
//				//求最大值
//				int max = Math.max(12, 3);
//				System.out.println(max);
//				//最小
//				int min = Math.min(2, 3);
//				System.out.println(min);
//				
//				//绝对值
//		
//				double ab = Math.abs(-3.14);
//				//圆周率
//				System.out.println(Math.PI);
//				//pow(a,b)a的b次方
//				double r1 = Math.pow(2, 10);
//				System.out.println(r1);
				
		
	}
}


10.2、包装类

10.2.1、8个基本数据类型分别对应的包装类

byte Byte

short Short

int Integer

long Long

float Float

double Double

char Character

boolean Boolean

10.2.2、数组工具类

package d12;

import java.util.Arrays;

public class D12 {
	public static void main(String[] args) {
		//java.util.Arrays  数组工具类
		int[] a = {2,1,3,4,5};
		//1.打印数组
		System.out.println(Arrays.toString(a));
		
		//2.数组赋值
		Arrays.fill(a, 0);//给数组所有元素赋值为0
		
		//fill(数组,开始下标,结束下标,替换值)
		//从开始下标(包括开始下标)到结束下标(不包括结束下标)范围内的所有元素都替换为11
//		Arrays.fill(a, 1, 3, 11);
		
		//3.数组排序
//		Arrays.sort(a);
		
		//4.二分查找 前提:数组排好序
//		int index = Arrays.binarySearch(a, 3);
//		System.out.println(index);
		
		//5.数组扩容   copyOf(原数组,新数组长度)
		int[] b = Arrays.copyOf(a, 12);
		System.out.println(Arrays.toString(b));
		
		//6.比较数组中的元素以及顺序是否相同
		int[] c = {2,1,3,4,5};
		boolean tar = Arrays.equals(a, c);
		System.out.println(tar);
	}
}

package d12;

import java.util.Arrays;

public class D12 {
				
	public static void main(String[] args) {
		int a = 12;
		Integer b = a;
		Integer b2 = 20;
		
		String str = "110";
		//valueOf()将其他类型,转换为整数类型
		Integer b3 = Integer.valueOf(str);
		
		//取值范围
		int max = Integer.MAX_VALUE;
		int min = Integer.MIN_VALUE;
		System.out.println();
		/*
		 * valueOf的原理
		 * Integer会缓存[-128,127]这个范围内的数,当传入的参数在这个范围内时,会直接返回缓存中的数字
		 * 否则超出这个范围才创建新的Integer对象
		 * */
		//1.比较两个数的大小
		int res = Integer.compare(2, 4);//compare(a,b)返回1表示a>b返回-1表示a<b返回0表示a=b
		//2.数字转字符串
		String s = Integer.toString(res);
	}
}

11、集合

Collection接口又有3种子类型,List、Set和Queue,在下面是一些抽象类,最下面具体实现类

Collection的实现类只能存储引用类型,所以对于基本数据类型,Collection的实现类只能存储他们的包装类(位于java.lang包)

1、List

有序,可重复

ArrayList是实现了基于动态数组的数据结构,在未声明长度的情况下,默认长度是10,数据填满会自动扩充原长度的一半

public static void main(String[] args) {
		//创建一个List集合
		List<String> list = new ArrayList<>();
		
		//添加元素
		list.add("AAA");
		//指定下标添加元素
		list.add(1,"CCC");
		
		//获取元素的值
//		System.out.println(list.get(1));
		
		//集合的长度
//		System.out.println(list.size());
		
		//遍历集合
		
		for (String s : list) {
			System.out.println(s);
		}
		//List是有序的,允许重复的
		list.add("BBB");
		list.add("BBB");
	}

2、Set

特点:
1.集合中的元素无序,不可重复

public static void main(String[] args) {
		//创建一个set集合
		Set<Integer> set = new HashSet<Integer>(); 
		
		//添加元素
		set.add(1);
		set.add(2);
		
		//获取集合的长度size
		
		//遍历元素
		
		//判断是否存在指定元素
		boolean tar = set.contains(1);
		
		//移除元素
		set.remove(2);
		
		//清空集合
		set.clear();
	}

3、Queue

队列:先进先出

栈:后进先出

package d12;


import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;


/*
 
 队列Queue
 */

public class D13 {
				
	public static void main(String[] args) {
		//创建一个set集合
		Queue<Integer> queue = new LinkedList<Integer>();
		
		//添加元素
		queue.add(12);
		queue.add(4);
		
		//获取队列长度size()
		
		//1.获取队列头部元素,但不删除,队列为空,引发异常
//		int firstEle = queue.element();
		
		//2获取队列头部元素,不删除,队列为空返回null
//		Integer fristEle2 = queue.peek();
		
		//3.获取并删除头部元素,队列为空,返回null
		
//		Integer fristEle3 = queue.poll();
//		System.out.println(fristEle3);
//		
//		System.out.println(queue.poll());
		
		//4.在不超过容量长度的情况下,可以立即插入一个元素到队列尾
		//当插入元素超出容量长度时(插入失败),add()方法会报异常,而offer()方法会返回布尔值false
		
		queue.offer(7);
		
		//5.遍历队列
		Integer ele = null;
		while ((ele = queue.poll()) != null) {
			System.out.println(ele);
		}
	}
}

4、vector

允许重复

1.基于动态数组的数据结构
2.是线程同步(线程安全),执行效率慢
3.数据填满时会自动扩容原长度的一倍,因此ArrayList更节省空间

package d12;

import java.util.List;
import java.util.Vector;

/*
 Vector
 1.基于动态数组的数据结构
 2.是线程同步(线程安全),执行效率慢
 3.数据填满时会自动扩容原长度的一倍,因此ArrayList更节省空间

 */

public class D13 {
				
	public static void main(String[] args) {
		List<Integer> vector = new Vector<Integer>();
		
		//添加
		vector.add(1);
		vector.add(1);
		vector.add(2);
		vector.add(3);
		
		//集合长度
		System.out.println(vector.size());
		
		//获取指定下标的元素
		Integer ele = vector.get(3);
		System.out.println(ele);
		
		for (Integer integer : vector) {
			System.out.println(integer);
		}
	}
}

5、Map

特点:

  1. 存储的是键值对
  2. k和v只能存储引用类型
  3. map的key不允许重复,多次给一个key赋值,后面的会把前面的赋值覆盖Map
Map实现类KeyValue
HashMap允许为null允许为null
TreeMap不允许为null允许为null
ConcurrentMap不允许为null不允许为null
HashTable不允许为null不允许为null
package d12;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/*
 Map
 */

public class D13 {
				
	public static void main(String[] args) {
		//创建一个Map集合,map中存储的元素,k-v键值对
		Map<String, Integer> map = new HashMap<String, Integer>(); 
		
		//添加元素
		map.put("name", 12);//k-v键值对  key键,value值
		
		//获取值,根据键名
		Integer v = map.get("name");
		System.out.println(v);
		
		map.put("name", 24);//map中的键名是唯一的,多次对同一个键赋值,后面的值会覆盖前面的值
		System.out.println(map.get("name"));
		
		//集合长度
		int len = map.size();
		
		//获取集合中所有键的Set集合
		Set<String> kSet = map.keySet();
		for (String k : kSet) {
			System.out.println(map.get(k));
		}
		
		//清空
//		map.clear();
		
		//是否包含指定键
		boolean hasK = map.containsKey("name");
		
		//是否包含指定值
		boolean hasV = map.containsValue(24);
		System.out.println(hasV);
		
		//获取所有键值对的Set集合
		Set<Entry<String, Integer>> eSet = map.entrySet();
		for (Entry<String, Integer> entry : eSet) {
			System.out.println(entry.getKey()+entry.getValue());
		}
		
		//判断是否为空集合
		boolean t = map.isEmpty(); 
		
		//根据键删除键值对
//		System.out.println(map);
//		map.remove("name");
//		System.out.println(map);
		
		//替换
		map.replace("name", 100);
		System.out.println(map);
	}
}

HashMap的实现原理

  1. HashMap底层原理是数组加链表的结构,在java8后又增加了红黑树
  2. 当添加一个元素key-value时,首先计算键值对的Key的hash值,以此来确定插入到数组的位置
  3. 如果根据Hash值确定的数组位置已经存在元素,就添加到同一个Hash值的元素的后面,于是形成了链表
  4. 当链表长度大于8,并且数组中元素k-v键值对个数超过64时,链表就转成红黑树,这样就提高了查找的速率
  5. 当红黑树中的节点数个数小于6时,红黑树又重新转换为链表

12、枚举

特点

  1. 应enum关键字定义枚举类

  2. 枚举类默认继承java.util.Enum类

  3. 枚举类的构造方法只能使用private修饰符,如果构造方法省略修饰符,则默认使用private

  4. 枚举类的所有对象(实例)必须在枚举中显式列出,否则这个枚举类将永远不能创建实例对象

  5. 枚举类的所有对象,系统会自动添加public static final修饰符

    final的作用是内存地址不变,枚举类中对象的常量可以用get/set方法修改

package d14;
/*
	枚举
	特点:
	1.应enum关键字定义枚举类
	2.枚举类默认继承java.util.Enum类
	3.枚举类的构造方法只能使用private修饰符,如果构造方法省略修饰符,则默认使用private
	4.枚举类的所有对象(实例)必须在枚举中显式列出,否则这个枚举类将永远不能创建实例对象
	5.枚举类的所有对象,系统会自动添加public static final修饰符
	final的作用是内存地址不变,枚举类中对象的常量可以用get/set方法修改
	
	作用/使用场景:
	存储固定不变的账户、IP地址、密钥等信息
	不经常换的,但是需要与第三方对接

 */
public enum User {
	//定义对象
	u1(),u2("张三","abc123",100.00);
	
	private String name;
	private String pass;
	private double money;
	
	private User() {
		
	}

	private User(String name, String pass, double money) {
		this.name = name;
		this.pass = pass;
		this.money = money;
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPass() {
		return pass;
	}

	public void setPass(String pass) {
		this.pass = pass;
	}

	public double getMoney() {
		return money;
	}

	public void setMoney(double money) {
		this.money = money;
	}

	
}
	

13、单例模式

设计模式:软件开发规范
单例模式 一个类,有且只能有一个对象
单例模式的写法:

  1. 枚举
  2. 懒汉式
  3. 饿汉式

懒汉式例子

public static Person p;
	private Person(){
		
	}
	public static Person getInstance(){
		if (p == null) {
			p = new Person();
		}
		return p;
	}

饿汉式例子

//饿汉式:在类初始化时,已经自行实例化(在程序执行之前,先完成实例化,在程序执行过程中直接返回创建好的实例化对象)
	private static final Person P = new Person();
	private Person() {
		
	}
	public static Person geInstance() {
		return P;
	}

14、异常

package d14;

//执行顺序ctr/catch>finally>return
public class TestExpe {
	public static void main(String[] args) {

	}
	public static int showException() {
	try {//可能出现的异常用try包括
		int[] a = new int[5];
		System.out.println(a[4]);
		return 1;
	} catch (Exception e) {捕获异常
		//打印异常信息
		e.printStackTrace();
		System.out.println("出现异常");
		return 2;
	}finally {
		//无论出不出现异常,这里边的代码都会执行
        //如果try中有return返回值,则先执行完finally中的代码,在返回数据
		System.out.println("666666666");
	}
	
}
}

15、多线程

多线程示例:

一家公司账户有100元,这天两个会计同时操作了公司的银行账户,会计A取50,会计B存100,可能会发生以下几种情况:

  1. 账户余额变成50(A和B同时读到了账户余额等于100,A最后更改了账户)
  2. 账户余额变成200(A和B同时读到了账户余额等于100,B最后更改了账户)
  3. 账户余额变成150 (A和B顺序读取到账户余额)

1、进程

  1. 是执行中的应用程序
  2. 一个进程可以包含一个或多个线程
  3. 一个进程至少要包含一个线程(比如Java中运行main方法的主线程)

比如:B站看视频的同时,还可以点赞收藏等等,这些操作都是Bilibili这个应用程序的子任务,也就是这个进程的子任务

2、线程

  1. 线程本身依靠进程(程序)运行
  2. 线程是程序中的顺序控制流,只能使用分配给程序(进程)的资源和环境

解释:运行一个Java程序的实质是启动一个Java虚拟机进程,也就是说一个运行的Java程序就是一个Java虚拟机进程。

线程是进程中可独立执行的最小执行单元,一个进程中有多个进程,同一线程中的线程共享该进程的资源(内存、空间、变量、方法)

2.1、单线程

程序中只存在一个主线程,实际上主方法(main)就是一个主线程

线程是进程中所要完成的一个计算过程,也被称为进程的任务

2.2、多线程

多线程是在一个进程中同时运行多个任务

多线程的目的:更好的使用cpu资源,提高程序的计算效率

2.3、串行、并行、并发

2.3.1 串行:一个人做一件件做所有任务
2.3.2 并发:一个人,交替的做多个任务

​ 即一个人先执行一个任务,在这个任务执行期间,有一段时间人是空闲的,他利用这段时间再去执行另一个任务,这样交替执行任务。

示例:蒸馒头的同时,馒头没熟之前,这段时间可以拖地、洗衣服等等

2.3.3 并行:多个人,同时做多个任务;总耗时取决于耗时最长的任务

3、创建线程的方式

  1. 继承Thread类,extends Thread
  2. 实现Runable接口,implement Runable
  3. 通过Collection接口和FutureTask对象创建线程
  4. 通过线程创建对象

创建线程

//方法1
package d17thread;

public class Demo {
	public static void main(String[] args) {
		CrThr c = new CrThr();
		c.start();
	}
}

class CrThr extends Thread{
	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("创建线程");
	}
	
}
//方法2
package d17thread;

public class Demo {
	public static void main(String[] args) {
		CrThr c = new CrThr();
		Thread t = new Thread(c);
		t.start();
	}
}

class CrThr implements Runnable{
	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("创建线程");
	}
	
}

package d17thread;

/*创建线程类的方式
 * 1.继承Thread类,extends Thread
 * 2.实现runable接口,implements Runable
 * 3.通过Callable接和FutureTask对象创建线程
 * 4.通过创建线程池创建对象
 */
public class Test {
	public static void main(String[] args) {
		//创建线程对象
		Worker w = new Worker();
		w.setName("tt1");
		//启动线程类
		w.start();
		/*
		 * 调用start()方法不是立即调用run()
		 * 而是先去争用cpu时间片,一旦获取cpu时间片,才会去调用run()方法
		 */
		
		Worker2 w2 = new Worker2();
		Thread t = new Thread(w2,"t1");
		t.start();
	}
}



class Worker extends Thread{

	@Override
	public void run() {
		// TODO Auto-generated method stub
		/*
		 * sleep()属于Thread类,wait()类属于Object类
		 * sleep()方法表示线程休眠指定的时间,休眠时间结束,线程继续执行
		 * wait()方法表示线程等待,此时线程会让出cpu资源,知道其他线程通过nodify()/nodifyAll()方法唤醒该线程
		 * 
		 */
		try {
			sleep(1000);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		try {
			wait();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("线程开始执行");
	}
	
}
class Worker2 implements Runnable{
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 10; i++) {
			
			
			System.out.println(i);
		}
		System.out.println("重写Runable接口");
	}
}


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FT8AyC0a-1666355976928)(C:\Users\19912\AppData\Local\Temp\1665997650707.png)]

3.1、线程的一生

新建、就绪、运行、阻塞、死亡

  1. 新建:创建线程对象后,即进入阻塞状态

  2. 就绪:当调用线程对象的start()方法,线程进入就绪状态,处于就绪状态的线程,只是说明该线程已经做好了准备,随时等待cpu调度执行,并不是说执行了start()方法线程就会立即执行

  3. 运行:当cpu开始调度处于就绪状态的线程时,此时线程才开始执行(执行run()方法),即进入运行状态,注意,就绪状态是进入到运行状态的唯一入口,也就是说,线程想要进入运行状态执行,首先必须处于就绪状态种

  4. 阻塞:处于运行状态中的线程由于某种原因,暂时放弃对cpu的使用权,停止执行,此时进入阻塞状态,直到其重新进入到就绪状态

    根据阻塞产生的原因不同,阻塞状态又分为三种

    1. 等待阻塞:运行状态中的线程执行Object.wait()方法
    2. 同步阻塞:线程在获取synchronized内部锁失败(因为所被其他线程占用)
    3. 其他阻塞:通过调用线程的Thread.sleeo()、join()方法或发出I/O请求时,线程会进入到阻塞状态,当sleep()状态超时(sleep休眠结束)、join()方法等待线程终止或超时,或者I/O处理完毕时,线程重新进入就绪状态
  5. 死亡:线程执行完毕或者因为异常推出了run()方法,该线程结束生命周期,线程销毁

4、线程的同步机制

同步机制:多个线程按照一定顺序执行的方案

4.1 同步锁 synchronized

  • Java 中的任何一个对象,都有唯一一个与之相关联的锁
  • 这种锁被称为监听器(monitor)或内部锁(Intrinsic Lock)
  • 内部锁是一种排它锁,即哪个线程拿到锁,该线程才能电泳同步方法,其他线程阻塞状态
  • 内部锁是通过synchronized关键字实现的
  • synchronized关键字可以用来修饰方法以及代码块
package d17thread;

public class Th1 {
	/*
	 * 同步机制:多个线程按照一定顺序执行的方案
	 * 
	 * 同步锁 synchronized
	 * 
	 * Java 中的任何一个对象,都有唯一一个与之相关联的锁
	 * 这种锁被称为监听器(monitor)或内部锁(Intrinsic Lock)
	 * 内部锁是一种排它锁,即哪个线程拿到锁,该线程才能电泳同步方法,其他线程阻塞状态
	 * 内部锁是通过synchronized关键字实现的
	 * synchronized关键字可以用来修饰方法以及代码块
	 */
	
	
	public static void main(String[] args) {
		Thre t = new Thre();
		t.start();
		Thre t1 = new Thre();
		t1.start();
	}
	static int count;
	static synchronized void add() {
		for (int i = 0; i < 80000; i++) {
			count++;
			System.out.println(count);
		}
	}

}
class Thre extends Thread{

	@Override
	public void run() {
		// TODO Auto-generated method stub
		Th1.add();
	}
	
}
package d17thread;

public class Th1 {
	/*
	 * 同步机制:多个线程按照一定顺序执行的方案
	 * 
	 * 同步锁 synchronized
	 * 
	 * Java 中的任何一个对象,都有唯一一个与之相关联的锁
	 * 这种锁被称为监听器(monitor)或内部锁(Intrinsic Lock)
	 * 内部锁是一种排它锁,即哪个线程拿到锁,该线程才能电泳同步方法,其他线程阻塞状态
	 * 内部锁是通过synchronized关键字实现的
	 * synchronized关键字可以用来修饰方法以及代码块
	 */
	
	
	public static void main(String[] args) {
		Thre t = new Thre();
		t.start();
		Thre t1 = new Thre();
		t1.start();
	}
	static int count;
	static synchronized void add() {
		for (int i = 0; i < 80000; i++) {
			count++;
			System.out.println(count);
		}
	}

}
class Thre extends Thread{

	@Override
	public void run() {
		// TODO Auto-generated method stub
		Th1.add();
	}
	
}

16 、I/O流

1、定义

数据在两个设备之间的传输称为流,流是一组有顺序的

2、使用

2.1、字节

字节输入流
  1. 新建File类对象
  2. 创建字节输入流
  3. 返回接下来从此输入流读取的字节数
  4. 循环输出
字节输出流
  1. 新建File类对象
  2. 输入要输出的内容
  3. 创建字节输出流
  4. 写入内容的字节组到输出流

2.2、字符

字符输入流
  1. 新建File类对象
  2. 创建字节输入流文件
  3. 对字节输入流进行编码
  4. 创建字符流对象
  5. 关闭所有资源
字符输出流
  1. 新建File类对象
  2. 创建字节输出流文件
  3. 设置编码并返回字符输出流
  4. 创建字符输出流

3、File类常用方法

package d1018IO;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;

public class FileDemo {
	public static void main(String[] args) {
		File file = new File("C:\\Users\\19912\\Desktop\\不准删除.txt");
		//1 判断文件是否存在
		boolean has = file.exists();
		
		//2判断是否是一个文件
//		System.out.println(file.isFile());
		
		//3判断是否是一个文件夹(目录)
//		System.out.println(file.isDirectory());
		
		//4获取当前目录下的所有文件
//		String[] s = file.list();
//		System.out.println(Arrays.toString(s));
		
		//5获取当前目录下的所有文件对象
//		File[] files = file.listFiles();
//		System.out.println(Arrays.toString(files));
		
		//6删除文件或者文件夹
//		boolean tar = file.delete();
		
		//7当文件存在时删除文件或者文件夹
//		file.deleteOnExit();
		
		//8创建文件夹
//		boolean b = file.mkdir();
//		System.out.println(b);
		
		//9创建一个新文件
//		try {
//			file.createNewFile();
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		//10判断文件是否可读
		System.out.println(file.canRead());
		
		//11判断文件是否可写
		System.out.println(file.canWrite());
	}
}

复制大文件

package d1018IO;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class BigFile {
	public static void main(String[] args) throws IOException {
		InputStream in = new FileInputStream(new File("C:\\Users\\19912\\Desktop\\新建文本文档.txt"));
		
		OutputStream out = new FileOutputStream(new File("C:\\Users\\19912\\Desktop\\文本文档.txt"));
		
		//获取字节输入流的长度
		int size = in.available();
		System.out.println(size);
		for (int i = 0; i < size; i++) {
			out.write(in.read());
		}
		//效率提高1024倍
//		byte[] bt = new byte[1024];
//		int len = in.read(bt);//每次读指定数组长度的字节数,并将读到的字节传入大数组中返回读到的字节长度
//		while(len != -1) {
//			out.write(bt);//将字节数组中的字节写入到输出流中
//			len = in.read(bt);
//		}
		
		
		
		out.close();
		in.close();
	}
}

17、序列化与反序列化

序列化的两种主要用途:

  1. 把对象的字节序列永久的保存到硬盘上,通常存放在同一个文件中
  2. 在网络上传送对象的字节序列

包serizlizable

1、序列化id的作用

序列化ID起着关键的作用,Java的序列化机制是通过在运行时判断类的seriaVersionUID来验证版本一致性的

反序列化时,JVM会把传进来的字节流中的seriaVersionUID与本地实体类中的seriaVersionUID进行比较,如果相同则认为是一致的,便可以进行反序列化,否则就会报序列化版本不一致的异常

2、序列化

将 对象 转换成特定格式的字节文件叫做序列化

//序列化
		File file = new File("C:\\Users\\19912\\Desktop\\User.ser");
		OutputStream out;
		try {
			out = new FileOutputStream(file);
			ObjectOutputStream objOut = new ObjectOutputStream(out);
			
			objOut.writeObject(u);
			objOut.flush();
			objOut.close();
			out.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

3、反序列化

将特定的字节文件转换为对象叫做反序列化

//反序列化
		try {
			File file2 = new File("C:\\\\Users\\\\19912\\\\Desktop\\\\User.ser");
			InputStream in = new FileInputStream(file2);
			ObjectInputStream objIn = new ObjectInputStream(in);
			User user = (User) objIn.readObject();
			objIn.close();
			in.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 

18、计网

1、计算机网络五层模型-网络层次划分

  1. 应用
  2. 网络
  3. 传输
  4. 数据链路
  5. 物理层

2、TCP三次握手

seq: 我发送了x个数据过去

ack:返回并告诉我收到了x+1之前的数据

SYN:请求同步 SYN=1 ACK确认标志确认是否有效,一般置为1 成功后返回SYN=1,ACK=1,ack=x+1,seq=y

第一次握手(请求建立连接),客户端发送连接请求报文

第二次握手(回答),服务器接收连接请求后回复ACK确认报文,并为此次连接分配资源

第三次握手(建立连接),客户端接收到ACK报文后也给服务端发送ACK报文,并分配资源,发送完毕后,客户端、服务端进入TCP连接成功状态完成三次握手

3、TCP四次挥手

第一次握手(请求结束连接),客户端发送FIN = 1,发送seq = x

第二次握手(第一次回答),回答已收到请求,等待回答 ACK=1,ack= x+1,seq = y

第三次握手(第二次回答),回答可以结束连接,FIN=1,ACK=1,seq =z,ack = x+1

第四次握手(回答收到)ACK= 1,ack = z+1,seq = z+1

  1. Client端发起中断连接请求,也就是发送FIN报文;

  2. Serer端接收到FIN报文后,先发送ACK报文,确认接收到了Client端的请求,然后进入准备状态,此时Server端如果还有没发送完的数据,可以继续发送;

  3. Client端接收到Server端的ACK报文,进入FIN_WAIT状态,继续等待Server端的FIN报文;

  4. 当Server端确定数据已发送完成,则向Client端发送FIN报文;

  5. Client端接收到FIN报文后,再次发送ACK报文,然后进入TIME_WAIT状态,如果Server端没有接收到ACK报文可以重传;

  6. Server端收到ACK后,断开连接,Client端等待2MSL后依然没有收到回复,则证明Server端已正常关闭,Client端也可以关闭连接了。TCP连接就这样关闭了。

19、Socket编程

客户端

package d20;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

//客户端
public class ClientNode {
	
	public static void main(String[] args) {
		int serverPort = 8081;//服务端端口号
		String serverIp = "127.0.0.1";//服务端IP地址
		
		try {
			//1首先直接创建socket,端口号1~1023为系统保存,一般设在1023之外
			Socket socket = new Socket(serverIp, serverPort);
			
			InputStreamReader reader = new InputStreamReader(System.in);
			//2创建 获取键盘输入内容的 字符输入流
			BufferedReader systemIn = new BufferedReader(reader);
			//3创建 字符输出流,向服务端输出内容
			PrintWriter socketOut = new PrintWriter(socket.getOutputStream());
			
			//4创建字符输入流 接收客户端输入的内容
			BufferedReader socketIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			
			while(true){
				//输入流获取键盘输入内容
				String readline = systemIn.readLine();
				//输出流向服务端发送数据
				socketOut.println(readline);
				socketOut.flush();
				
				//读取服务端返回的数据
				String serverStr = socketIn.readLine();
				System.out.println("服务端:" + serverStr);
				if(readline.equals("bye")) {
					break;
				}
			}
			
			//关闭资源
	        systemIn.close();
	        socketIn.close();
	        socketOut.close();
	        socket.close();
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

服务端

package d20;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
//服务端
public class ServerNode {

	public static void main(String[] args) {
		int port = 8081;
		
        try {
        	//1 创建ServerSocket,监听端口8081
			ServerSocket serverSocket = new ServerSocket(port);
			
			//2 调用服务器的accept方法,接受来自客户端的连接请求。
			//在接收到客户端连接请求之前,此方法会进行阻塞(程序会在这等待),
			//当有申请连接时会建立连接并返回一个socket
	        Socket socket = serverSocket.accept();
	        
	        InputStreamReader reader = new InputStreamReader(socket.getInputStream());
	        //4 创建客户端输入流:获取客户端传输的数据
	        BufferedReader socketIn = new BufferedReader(reader);
	        
	        BufferedReader systemIn = new BufferedReader(new InputStreamReader(System.in));
	        //5 创建输出流:用于向客户端返回数据
	        PrintWriter socketOut = new PrintWriter(socket.getOutputStream());
	        
	        
	        while (true) {
	        	//读取客户端输入内容
		        String clientStr = socketIn.readLine();
		        System.out.println("客户端:" + clientStr);
		        if (clientStr.equals("bye")) {
		        	//服务端 向 客户端 输出内容
			        socketOut.println(systemIn.readLine());
			        socketOut.flush();
					break;
				}
		        
		        //服务端 向 客户端 输出内容
		        socketOut.println(systemIn.readLine());
		        socketOut.flush();
			}
	        systemIn.close();
	        socketIn.close();
	        socketOut.close();
	        socket.close();
	        serverSocket.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

20、反射

反射reflect定义:

  • Java的反射(reflection)机制是指在程序的运行状态中
  • 可以创建任意一个类的对象
  • 可以了解任意一个对象所属的类
  • 可以了解任意一个类的成员变量和方法
  • 可以调用任意一个对象的变量和方法
  • 这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制
  • 反射被视为动态语言的关键
package d1020反射;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/*
 * 反射reflect
 * 定义:
 * Java的反射(reflection)机制是指在程序的运行状态中
 * 可以创建任意一个类的对象
 * 可以了解任意一个对象所属的类
 * 可以了解任意一个类的成员变量和方法
 * 可以调用任意一个对象的变量和方法
 * 这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制
 * 反射被视为动态语言的关键
 * 
 * 1 Class
 * 
 * 2 Field
 * 
 * 3 Method
 */

public class Shop {
	public static void main(String[] args) {
		//Class类表示的是一个类的.class文件
		Class c = Man.class;
		try {
			//1创建该类的对象
			Man m = (Man) c.newInstance();
			
			//2获取类中的指定变量(包括私有变量)
			Field f = c.getDeclaredField("name");
			System.out.println(f.getName());
			
			//3获取类中的指定变量(不包括私有变量)
			c.getField("name");
			
			//4获取类中所有变量,返回Field类型的数组
			Field[] fs = c.getDeclaredFields();
			for (Field field : fs) {
				//f.getType()获取变量的数据类型
				System.out.println(f.getType());
			}
			
			//5 根据指定方法名和制定的参数列表数据类型,获得方法对象
			//getMethod(String name,Class...,parametersType)
			//name:方法名
			//parametersType:参数列表的数据类型
			Method mt = c.getMethod("speak", null);
			Method mt2 = c.getDeclaredMethod("speak", String.class,int.class);
			
			//6获取类的构造方法对象
			Constructor c1 = c.getConstructor(null);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

1、Class是什么

Java在将.class文件载入时,JVM将产生一个java.lang.Class对象代表该.class的字节码文件,从该Class对象中可以获得类的许多基本信息,这就是反射机制。

2、创建一个类对象有几种方式

  1. 通过new关键字创建对象
  2. 通过反射的Class类的newInstance方法创建对象

3、创建Class类对象的方法

  1. 通过类名调用.class
  2. 通过对象调用getClass()方法
  3. 给指定对象的该变量赋值

4、Field对象的机制与实现

  1. Java.lang.reflect.Field类是记录对象属性的类
  2. 可以操作类中私有、以及公有等全部属性和属性的信息

4.1、Field对象的常用方法

package d1020反射;

import java.lang.reflect.Field;

public class Demo {
	public static void main(String[] args) {
		//创建Class类对象的方法
		//1 通过类名调用.class
		
		Class cl = Man.class;
		Man mi = new Man();
		mi.name = "zzz";
		try {
			Field fi = cl.getDeclaredField("name");
			
			//1获取变量的数据类型
			System.out.println(fi.getType());
			
			//2取得obj对象中的这个属性的值
			String str = (String) fi.get(mi);
			System.out.println(str);
			
			//3给指定对象的该变量赋值
			fi.set(mi, "lll");
			
			Field fi2 = cl.getDeclaredField("age");
			fi2.setAccessible(true);//开启私有变量的访问权限
			fi2.set(mi, 12);
			System.out.println(mi.getAge());
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
		
//		//2 通过对象调用getClass()方法
//		Man ma = new Man();
//		Class cl2 = ma.getClass();
//		
//		//3根据完整包路径,获取Class对象
//		try {
//			Class cl3 = Class.forName("d1020反射.Man");
//		} catch (ClassNotFoundException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		//创建一个类对象有几种方式
//		//1 通过new关键字创建对象
//		//2 通过反射的Class类的newInstance方法创建对象
	}
}

21、正则表达式

1 、简介

正则表达式用于处理字符串,它通过约束字符的排列规则,可以:

  1. 验证字符串是否匹配正则规则;
  2. 检索符合规则的字符串;

完整的正则表达式包括:

  1. 特殊字符(或“元字符”)
  2. 文字(或“普通文本字符”)

2、元字符

2.1、

字符关键词解释
\d数字字符匹配一个数字字符,等价于[0,9]
\D匹配一个非数字字符
\n换行符匹配一个换行符
\r回车符匹配一个回车符
\s空白字符匹配任何空格字符,包括空格、制表符、换页符等,等价于[\f\n\r\t\v]
\S匹配任何非空白字符
\w单词字符匹配一个单词字符(包括下划线字符),等价于[A-Za-z0-9]
\W匹配任何非单词字符

2.2、

.匹配任意一个字符
\(反斜杠)转义字符,将特殊字符转义成普通字符

2.3、

()标记一个子表达式,一个子表达式可以匹配一段字符串
|意为’或’,|两边的子表达式称为多选分支

形如(子表达式a|子表达式b)这样的结构称为“多选结构”,|两边的子表达式称为“多选分支”。

2.4、限制符

?匹配前面的子表达式或字符0或1次至多1次
*****匹配至少0次[0,n]
+匹配至少1次[1,n]
{min,max}匹配至少min次,至多max次[min-max]
{n}匹配n次
{n,}至少匹配n次

注意:***** 和 + 限定符都是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个**?**就可以实现非贪婪或最小匹配。

贪婪匹配:贪婪模式会尽可能多的匹配

**非贪婪匹配:**非贪婪模式会尽可能少的匹配

当**?*紧跟在任何一个其他限制符、+、?、{n}、{n,}、{n,m}后面时,匹配模式都是非贪婪的。

2.5、

^匹配文本的开始位置,^称为脱字符
$匹配文本的结束位置

3、字符组

字符组用**[]表示,一个字符组匹配一个字符的位置**,且该位置可以匹配字符组中的任一个字符。

3.1 连字符

字符组元字符 -(连字符),表示一个范围,注意如果用在字符组开头,如[-]或[^-],则只代表是一个 - 字符,不表示范围

3.2 排除字符

排除型字符组:[^…] 匹配 除字符组内所有字符 之外的 任何字符

注意:在字符组内部,元字符的定义规则(及他们的意义)是不一样的。例如,在字符组外部,点号是元字符,但是在内部则不是如此。相反,连字符只有在字符组内部才是元字符,否则就不是。

Pattern 类:

pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。

Matcher 类:

Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。

//1 正则校验
//写一个正则表达式,匹配手机号
		
String str = "31415";
String regx = "\\d\\d+";
boolean tar = Pattern.matches(regx, str);
System.out.println(tar);
		
//2 正则检索
String ip = "192.168.1.141";
//
String r2 = "\\d{2,}?";
//编译指定的正则表达式
Pattern p2 = Pattern.compile(r2);
//将传入的字符串匹配指定的正则表达式
Matcher m = p2.matcher(ip);
while(m.find()) {//向下查找一次,是否存在匹配的字符串,返回布尔值
	System.out.println(m.group());//打印匹配到的字符串
}

22、Java内存模型

1、 Java内存模型JMM (Java Memory Model)

Java虚拟机(JVM)在执行Java程序的过程中,会把它管理的内存划分为几个不同的数据区域(也就是运行时的数据区域),这些区域都有各自的用途、创建时间、销毁时间。

2、 Java虚拟机运行时数据区(JVM Runtime Data Area)

在Java虚拟机规范(JVMS)中定义了多种程序运行时会用到的存储不同类型数据的内存区域,统称为“Java虚拟机运行时数据区”,有的数据区是全局共享的(static),有的是线程私有的(局部变量)。

全局共享:随着JVM启动而创建,随着JVM退出而销毁

线程私有:随着线程开始而创建,随着线程结束而销毁

2.1 运行时数据区划分

  1. 程序计数器 (program counter register)

  2. Java虚拟机栈 (VM stack)

  3. 本地方法栈 (native method stack)

  4. 堆 (heap)

  5. 方法区 (method area)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WLFK1HAh-1666355976933)(file:///C:\Users\19912\AppData\Local\Temp\ksohtml20800\wps1.jpg)]

jdk1.8之前的JMM模型图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fSV7dgAz-1666355976933)(file:///C:\Users\19912\AppData\Local\Temp\ksohtml20800\wps2.png)]

JDK1.8以后的JMM模型图

2.2 程序计数器(Program Counter Register)

  1. 一块较小的内存空间,他的作用可以看做是:当前线程所执行的字节码的行号指示器

  2. 如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Native方法(JDK自带的方法),这个计数器值为空。

  3. 此内存区域是唯一一个在JVM规范中没有规定任何OutOfMemoryError(内存溢出)情况的区域

2.3 虚拟机栈(VM Stack)

  1. 线程私有

  2. 后进先出(LIFO)栈 last in first out

  3. 存储栈帧,支撑Java方法的调用,执行和退出

  4. 可能出现OutOfMemeoryError异常和StackOverFlowError异常

OutOfMemeoryError(内存溢出):当jvm栈被设计成可动态扩展,在动态扩展时无法申请到足够的内存

StackOverFlowError(栈溢出):线程请求的栈深度大于jvm允许的最大深度

2.4 本地方法栈(Native Method Stack)

在HotSpot中本地方法栈与VM Stack合并

本地方法栈与Java虚拟机栈基本相同,区别在于:

  1. Java虚拟机栈为JVM执行字节码所服务

  2. 本地方法栈为JVM执行Native方法所服务,支撑Native方法的调用,执行和退出

2.5 方法区: static final

方法区存放了要加载的类的信息Class(名称、修饰符等)、类中的静态常量、类中定义为final类型的常量、类中的Field信息、类中的方法信息Method,当在程序中通过Class类的方法来获取对象信息时,这些数据都来源于方法区。方法区是被Java线程所共享的,不像Java堆中其他部分一样会频繁被GC回收,它存储的信息相对比较稳定,在一定条件下会被GC,当方法区要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。方法区也是堆中的一部分,就是我们通常所说的Java堆中的永久区 Permanet Generation,大小可以通过参数来设置,可以通过-XX:PermSize指定初始值方法区包含所有的class和static变量、final变量,-XX:MaxPermSize指定最大值。

· 又叫静态区,跟堆一样,被所有的线程共享。

· 方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。(两者区别为堆区存放new出来的对象信息,方法区存放类信息)

2.6 堆heap

堆是JVM所管理的内存中最大的一块,是被所有Java线程共享的,不是线程安全的,在JVM启动时创建。堆是存储Java对象的地方,这一点Java虚拟机规范中描述是:所有的对象实例以及数组(即所有的引用类型)都要在堆上分配。Java堆是GC管理的主要区域,从内存回收的角度来看,由于现在GC基本都采用分代收集算法,所以Java堆还可以细分为:新生代和老年代;新生代再细致一点有Eden空间、From Survivor空间、To Survivor空间等。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Btq9m7pc-1666355976934)(file:///C:\Users\19912\AppData\Local\Temp\ksohtml20800\wps3.jpg)]私有内存区——伴随线程的产生而产生,一旦线程终止,私有内存区也会自动消除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值