JAVA
搭建Java开发环境
搭建Java开发环境 安装JDK(Java开发工具集)时会安装JRE(Java运行环境) 步骤: 1,找到JDK1.8安装包 2,安装JDK与JRE 3,配置环境变量 1,新建一个变量 变量名:JAVA_HOME 变量值:JDK安装路径 2,修改Path变量 变量值尾部追加: %JAVA_HOME%\bin %JAVA_HOME%\jre\bin 3,新建一个变量 变量名:CLASSPATH 变量值:. 测试Java环境是否搭建成功 步骤: 1,打开DOS命令框 注意:从新打开DOS命令框 2,输入以下命令 java:运行class文件(字节码文件) javac:生成class文件 java -version 注意: 如果此时测试成功,后期对java没有任何修改.在从新启动电脑后,java或javac显示无效命令.这是windows系统的bug.解决方案,从新打开环境变量,打开path变量,查看.确定.从新打开dos命令框就OK 注意: 因为有些小伙伴安装过java,所以先卸载 步骤: 1,打开控制面板,卸载Java 2,删除环境变量 打开文件管理器,在其左边栏选择此电脑 右键,选择属性 点击高级系统设置 点击环境变量 查看用户变量path中是否有java相关变量,有的就删除 查看系统变量中是否存在CLASSPATH与JAVA_HOME有的就删除整个变量 查看系统变量的Path变量中是否有java相关,有的就删除相关的条 点击确定
编写第一个java程序
步骤: 1,在D盘下找一个文件夹 2,在该文件夹下新建一个文本文档,起名为HelloWorld.java 3,在该文件中编写以下代码 class HelloWorld{ public static void main(String[] args){ System.out.println("Hello World"); } } 注意: 1,以上代码中的标点符号全在英文状态下输入 2,以上代码中大小写不能有错 4,保存
编译Java程序
步骤: 1,打开DOS命令框 2,进入Java文件所在的文件夹 3,使用javac命令,将java文件编译为class文件
运行class文件
步骤: 1,打开DOS命令框 2,进入class文件所在的文件夹 3,使用java命令运行class文件
名词
JDK:Java开发工具集 JRE:Java运行环境 JVM:Java虚拟机 API:Java的说明书 GC:Java垃圾回收机制
深入了解HelloWorld
1,class前有public的类称为公共类 公共类的特点: 1,公共类的类名必须与文件名一致 2,一个Java文件中只能有一个公共类 2,一个Java文件中可以定义多个类,每个类都会生成其对应的class文件,该class文件的文件名,就是对应的类的类名 3,一个Java文件中定义的多个类的类名不能相同 4,String[] args:在运行class文件时传入的参数
注释
作用: 1,解释说明,提高代码的可读性 2,修改代码,注销无用代码 特点: 不会影响代码的运行 Java的注释 //单行注释 /* 多行注释 122 333 */ /** 文档注释 111 222 */ 开发工具的快捷键: 1,选中需要注释的内容 2,ctrl+/
输出
输出内容后换行 System.out.println(要打印的内容); 输出内容后不换行 System.out.print(要打印的内容); 注意: 1次只能打印1个内容
数据类型
基本数据类型 整数 byte 1字节 8位 取值范围:-2^7~2^7-1 -128~127 short 2字节 16位 取值范围:-2^15~2^15-1 int 4字节 32位 取值范围:-2^31~2^31-1 默认的整数类型 long 8字节 64位 取值范围:-2^63~2^63-1 值后加l或L 小数(浮点数) float 4字节 32位 值后加f或F double 8字节 64位 默认的小数类型 字符 char 2字节 hello world:由11个字符组成 你好世界:由4个字符组成 注意: 需要使用''包裹 如: 'a' 'b' '' '1' 布尔 boolean 1字节 取值: true:真 false:假 引用数据类型 所有类的对象都是引用数据类型.其对应的数据类型就是其类名 引用数据类型有无数种 String 字符串 由JDK提供的 注意:值需要使用""包裹 如: "abc" "你好世界" "" "1"
标识符
作用:标记的符号 如:类名,变量名,常量名,方法名,注解名,枚举名,包名等都是标识符 命名规范 强制要求 1,不能使用数字开头 2,不能使用特殊符号,_与$除外 3,不能使用关键字或保留字 目前学的关键字有: byte int short long float double char boolean true false 见过的关键字有 public class static void 还没有学的关键字 final abstract interface extends implements instanceof menu @interface for while do if else switch break continue return ... 潜规则 1,不建议使用中文 大驼峰 一般应用与类名,注解名,枚举名,接口名 规则:每个单词首字母大写 如: Hello HelloWorld RenLei GouLei HongAn 注意:见名知意 小驼峰 一般应用与变量名,方法名 规则:第一个单词首字母小写,其他单词首字母大写 如: hello helloWorld num shuZi 注意:见名知意 全大写 一般应用于常量名 规则:每个字母大写 如: HELLO_WORLD 全小写 一般应用与包名 规则:每个字母都小写 如: com.qf.demo01
关键字
在Java中有有特殊含义的单词 目前学的关键字有: byte int short long float double char boolean true false 见过的关键字有 public class static void 还没有学的关键字 final abstract interface extends implements instanceof menu @interface for while do if else switch break continue return
保留字
暂时没有特殊含义的关键字
变量
作用:记录可以一个值可以被改变的数据 例子: 2023年3月28日,刘去广州出差,入住都市快捷酒店502房.大床房.于2023年3月29日退房.袁入住502 2023年3月28日 502房的客人 - 刘 2023年3月29日 502房的客人 - 袁 变量使用步骤: 1,声明 2,赋值 3,使用 声明: 语法: 数据类型 变量名; 如: 声明一个变量记录人的年龄 int age; 在声明一个变量记录另一个人的年龄 int age01; 注意: 同一个作用域下变量名不能相同 可以声明多个变量 赋值: 语法: 变量名 = 值; 如: age = 18; age = "18"; 错 注意: 等号两边数据类型要相同 一个变量可以赋值多次 使用: 语法: 变量名 如: 1,打印age变量 System.out.println(age); System.out.println("age"); 注意:使用变量时不要加""号,如果使用了,那么该打印的内容是字符串,与变量无关 特殊情况: 声明并赋值 语法: 数据类型 变量名 = 值; 名词: 初始化:变量的第一次赋值称为变量的初始化
运算符
算数运算符
+:加法 -:减法 *:乘法 /:除法 %:取余 ++:自增 ++在后,先参与运算,在递增 ++在前,先递增,在参与运算符 --:递减 --在后,先参与运算,在递减 --在前,先递减,在参与运算符 注意: 小类型与大类型进行运算结果为大类型 会余到整数位 *,/,%优先级相同,高于+,- int a = 3; int b = 4; 请计算 (++a) + (a++) + (++b) + (b++) 的结果 4 + 4 + 5 + 5 = 18赋值运算符
=:将等号右边的值,赋值给左边的变量 int a = 10; int b = a; 注意: 1,等号两边数据类型要相同 2,如果等号两边数据类型不同,要么是小类型转换为大类型,要么是大类型转换为小类型 小类型转换为大类型,自动转换 如: double d = 1.0f; int a = 'a'; 大类型转换为小类型,强制转换 语法: 小类型 变量名 = (小类型) 要转换的值或变量; 如: byte b = (byte) 128; char c = (char) 97; +=:加等 int a = 1; int b = 2; //a = a + b; a += b; -= int a = 1; int b = 2; //a = a - b; a -= b; *= int a = 1; int b = 2; //a = a * b; a *= b; /= int a = 1; int b = 2; //a = a / b; a /= b; %= int a = 1; int b = 2; //a = a % b; a %= b;关系运算符
<:小于 >:大于 <=:小于或者等于 >=:大于或者等于 ==: 基本数据类型判断值是否相同 引用数据类型判断内存地址是否相同 !=: 基本数据类型判断值是否不相同 引用数据类型判断内存地址是否不相同逻辑运算符
&&:短路与 同真为真,有假为假 如: 10 < 12 && 10 > 20; ||:短路或 有真为真,全假为假 如: 10 < 1 || 10 > 2; !:非 非真为假,非假为真 !(10 < 2) true !(10 > 2) false字符串连接符
+ 如: "Hello" + "World" "HelloWorld" "World" + "Hello" "WorldHello" 区分字符串连接符与算法运算符加法,看符号两边是否有字符串.如果有字符串就是字符串连接符,否则是算法运算符加法 如: 1 + 2 + 3 6 算数运算符 1 + 2 + "3" "33" "1" + 2 + 3 "123" 注意:所有类型的数据使用字符串连接符,结果都为字符串三目运算符
名称: 三元运算符 语法: 条件表达式?值1:值2; 条件表达式:结果为boolean型的表达式都是条件表达式 当条件表达式结果为true,取值1.如果条件表达式结果为false取值2位运算符
二进制 0000 0001 0010 0011 0100 0101 0110 0111 1000 八进制 0 1 2 3 4 5 6 7 10 11 12... 十进制 00 01 02 03 04 05 06 07 08 09 10 十六进制 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 二进制转换为十进制 0001 0010 1 * 2 ^ (5 - 1) + 1 * 2^1 16 + 2 18 0000 1011 1 * 2^3 + 0 + 1 * 2^1 + 1 * 2^0 8 + 0 + 2 + 1 11 八进制转十进制 17 1 * 8^1 + 7 * 8^0 8 + 7 15 十六进制转十进制 AF 10 * 16 ^1 + 15 * 16^0 160 + 15 175 十进制转二进制 十进制转八进制 十进制转十六进行 <<:不带符号向左移 >>:不带符号向右移 >>>:带符号向右移 &:与 |:或 ^:异或
语句分类
顺序语句
代码从上向下依次执行分支语句
在多个分支选择执行其中一个循环语句
重复执行一段代码
分支语句
作用:判断
分类:
if switchif
基础的if结构 语法: if(条件表达式){ 当条件表达式值为true时,执行此处代码 }if else结构
if else结构 语法: if(条件表达式){ 当条件表达式值为true时,执行此处代码 }else{ 当条件表达式值为false时,执行此处代码 } 注意: 1,else可有可无 2,else只能有一个 3,else不能单独存在else if结构
语法: if(条件表达式1){ 当条件表达式1为true,执行此处代码 }else if(条件表达式2){ 当条件表达式2为true,执行此处代码 }else if(条件表达式3){ 当条件表达式3为true,执行此处代码 } ... else if(条件表达式n){ 当条件表达式n为true,执行此处代码 }else{ 当以上条件全为false,执行此处代码 } 注意: else if可以有多个 当上面的条件,将不会判断下面的条件总结 if的语法: if(条件表达式1){ 当条件表达式1为true,执行此处代码 }else if(条件表达式2){ 当条件表达式2为true,执行此处代码 }else if(条件表达式3){ 当条件表达式3为true,执行此处代码 } ... else if(条件表达式n){ 当条件表达式n为true,执行此处代码 }else{ 当以上条件全为false,执行此处代码 } 注意: 1,else if可以有多个 2,else if可以一个都没有 3,else if不能独立存在 4,else 可有可无,最多只能有一个 5,当多个条件同时满足时,只会执行最上面的那个switch
语法: switch(变量名){ case 常量1: 当变量值等于常量1时,执行此处代码 int a; break; case 常量2: 当变量值等于常量2时,执行此处代码 break; ... case 常量n: 当变量值等于常量n时,执行此处代码 break; default: 当变量值不等于以上常量时,执行的代码 break; } 常量:代码在编译后无法修改的值或变量称为常量 break:跳出当前代码块,case中可以没有break,但是如果没有会导致贯穿 swicth中case后的常量不能相同 JDK1.5以后switch可以判断字符串内容是否相同 switch只能判断值相等,if可以判断区间,也可以判断值是否相同
变量的作用域
概念:变量声明的代码块,为这个变量的作用域(就是这个变量可以使用的范围)
Scanner
简介:由JDK提供的一个类 作用:键盘录入 使用: 1,导包 语法:import java.util.Scanner; 书写位置:类上 2,创建Scanner对象 语法: Scanner 变量名 = new Scanner(System.in); 3,等待用户输入 输入字符串 String 变量名2 = 变量名.next(); 变量名2:就是用户输入的内容 输入整数 int 变量名2 = 变量名.nextInt(); 变量名2:就是用户输入的内容
循环语句
作用:重复执行一段代码
分类
while do while forwhile
语法: while(条件表达式){ 当条件表达式为true,执行此处代码 当此处代码执行完毕后,在判断条件表达式是否为true,如果为true,在此执行此处代码 如果为false结束循环 }do while
语法: do{ 先执行此处代码,在判断条件表达式是否为true 如果为true,在此执行此处代码 如果为false结束循环 }while(条件表达式);while:先判断,在执行 do while:先执行在判断for
作用:简化语法 语法: for(表达式1;表达式2;表达式3){ 循环体4 } 表达式1:初始化变量 表达式2:循环条件 表达式3:修改变量 循环体4:重复执行的代码 执行流程: 1,2,4,3,2,4,3,2,4,3....2 注意:表达式1只执行一次名词解释
死循环:无法结束的循环 循环嵌套:在循环语句中使用循环语句
转意字符
概念:有特殊含义的字符 \t:制表 \":双引号字符 \':单引号字符 \n:换行 \r\n:标准换行
流程控制语句
break:跳出当前循环 continue:跳过本次循环
标记
定义标记 语法: 标记名: 使用标记 语法: break 标记名;//跳出标记的循环 continue 标记名;//跳过本次标记的循环
方法(函数)
引入
描述一个人吃饭的过程作用
封装一段代码,使其便于使用优点
1,降低耦合度 2,提高复用率 3,提高代码的编写效率 4,方便使用步骤
1,定义 2,调用定义
位置: 类中,方法以外 1,无参无返回值的方法 语法: public static void 方法名(){ 方法体 } 练习: 定义一个方法计算10+20的结果 2,有参无返回值的方法 语法: public static void 方法名(形参列表){ 方法体 } 注意: 1,形参列表的语法:数据类型 变量名,数据类型变量名,... 2,多个参数直接使用逗号隔开 3,参数的数量不限 练习: 定义一个方法计算两数之和 3,无参有返回值的方法 语法: public static 返回值类型 方法名(){ 方法体 } 注意: return:单独使用,表示结束当前方法 return xxx:表示结束当前方法,并返回xxx的值 返回值类型:就是返回值的数据类型,要与xxx的数据类型一致 void:表示没有返回值或返回值为null 一个方法只能有一个返回值 一个方法中使用分支语句,导致有多个return xxx,此时要保证返回的数据类型一致 一个方法如果有返回值类型,一定要保证有返回值,并且返回值的数据类型要与返回值类型一致 4,有参有返回值的方法 语法: public static 返回值类型 方法名(形参列表){ 方法体 } 练习: 定义一个方法,计算两数之和,并返回计算的结果 5,总结 语法: 访问权限修饰符 修饰符 返回值类型 方法名(形参列表){ 方法体 } 访问权限修饰符:暂时使用public 修饰符:暂时使用static 返回值类型:就是返回值的数据类型.如果没有返回值,返回值类型为void.null表示为空 方法名:自定义,见名知意,小驼峰.一个类中不能出现方法名相同,形参列表也相同的方法 形参列表:可有可无 本质:声明的多个变量,使用逗号隔开 方法体: return:结束当前方法 return xxx:结束当前方法,并返回xxx.注意此时返回值类型要与xxx的数据类型一致.只能返回一个调用
位置: 方法中 1,调用无参无返回值的方法 语法: 方法名(); 2,调用有参无返回值的方法 语法: 方法名(实参列表); 注意: 实参列表要与形参列表一致(长度一致,顺序一致,数据类型一致)(*) 3,调用无参有返回值的方法 语法: 方法名(); 或 数据类型 变量名 = 方法名(); 注意: 调用有返回值的方法,可以使用变量接收也可以不接收 但是调用无返回值的方法,一定不能使用变量接收 4,调用有参有返回值的方法 语法: 方法名(实参列表); 或 数据类型 变量名 = 方法名(实参列表); 5,总结 语法: 1,方法名(实参列表); 2,数据类型 变量名 = 方法名(实参列表); 注意: 1,实参列表要与形参列表一致(长度一致,顺序一致,数据类型一致) 2,调用无返回值的方法只能使用语法1 3,调用有返回值的方法可以选择使用语法1也可以选择使用语法2特殊情况
多重调用
方法调用方法 A,B,C A中调用B,在B中调用C重载
要求: 1,同一个类中 2,方法名相同 3,形参列表不同递归
方法本身调用本身
数组
作用:容纳一组数据类型相同的数据
名词
长度:一个数组最大可容纳数据的个数 下标(索引):数据在数组中的位置,从0开始~长度-1 元素:数组中存储的数据特点:
1,长度不可变 2,存储的数据类型一致步骤:
1,声明 2,创建 3,使用声明:
语法: 数据类型[] 数组名; 数据类型 数组名[];创建:
静态创建: 语法: 数据类型[] 数组名 = {值1,值2,值3,值4,...值n}; 注意事项: 1,必须在声明时创建 2,其长度就是创建时值的个数 动态创建: 语法: 带值 数组名 = new 数据类型[]{值1,值2,值3,...}; 注意: 其长度就是创建时值的个数 不带值 数组名 = new 数据类型[长度]; 动态创建与静态创建的区别: 1,静态创建必须在声明时创建,动态创建可以将声明与创建分开,也可以同时进行 2,内存上来说 静态创建的内存在常量区 动态创建的内容在堆内存 3,静态创建是在代码加载时分配的内存空间,动态创建是在代码运行时分配的空间 注意: 堆内存中的数据有默认值 基本数据类型默认为0 引用数据类型默认为null使用
基本使用 改 修改指定位置的数据 语法: 数组名[下标] = 值; 查 查询数组长度 语法: 数组名.length 查询数组指定位置的数据 语法: 数组名[下标] 注意: 下标要在取值范围内,否则会产生数组下标越界异常 扩展 遍历:将数组或集合中的数据逐个取出 方式1:普通for循环 方式2:foreach(只能做遍历) foreach语法: for(数据类型 变量名:要遍历的数组或集合){ } 数据类型:遍历出的数据的数据类型 变量名:就是遍历出的数据 注意:foreach(增强for循环)在遍历时的速度是普通for的3倍 复制:将数组A中的数据,逐个复制到数组中 思路: 1,创建新数组 注意: 1,新数组长度等于老数组长度 2,新数组的数据类型与老数组一致 2,遍历老数组 使用普通for循环 3,将老数组的值取出,赋值给新数组对应的位置 扩容:将数组变大 思路: 1,创建一个新数组 注意: 1,新数组长度大于老数组长度 2,新数组的数据类型与老数组一致 2,遍历老数组 3,将老数组的值取出,赋值给新数组对应的位置 4,将新数组赋值给老数组二维数组
概念:将数组作为数据存储在数组中 步骤: 1,声明 2,创建 3,使用 声明 数据类型[][] 数组名; 创建 静态创建 注意:声明与创建同时进行 语法: 数据类型[][] 数组名 = { {值1,值2,值3,...}, {值4,值5,..}, {值6,值7,值8,值9,...}, ... }; 动态创建 带值 语法: 数组名 = new 数据类型[][]{ {值1,值2,值3,...}, {值4,值5,..}, {值6,值7,值8,值9,...}, ... }; 不带值 语法: 数组名 = new 数据类型[x][y]; x:二维数组中可容纳的一维数组的个数,必须在创建时说明 y:一维数组中可容纳的元素的个数,可以不写 注意: 二维数组的长度指的是其中存储的一维数组的个数 使用: 改 修改二维数组中指定的一维数组 数组名[下标] = 新数组; 注意:不能使用静态创建 修改二维数组中指定的位置的元素 数组名[x][y] = 新值; x:元素所在的一维数组在二维数组中的位置 y:元素在一维数组中的位置 查 查询数组长度 数组名.length 查询二维数组中指定位置的一维数组 数组名[下标]; 查询二维数组中指定位置的元素 数组名[x][y] x:元素所在的一维数组在二维数组中的位置 y:元素在一维数组中的位置 遍历: 思路: 1,遍历二维数组,获取一维数组 2,遍历一维数组 杨辉三角 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 2 1 0 0 0 0 1 3 3 1 0 0 0 1 4 6 4 1 0 0 1 5 10 10 5 1 0 1 6 15 20 15 6 1 ....数组与方法
例子:定义一个方法计算多数之和 public static void sum(int[] nums){ int sum= 0; for(int i:nums){ sum = sum + i; } } int[] nums = {1,2,3,4,5,6,7,8}; sum(nums); 例子:定义一个方法,计算两数之和.要求返回值有加数,被加数,和 public static int[] add(int a,int b){ int x = a + b; int[] nums = {a,b,x}; return nums; }
可变参数
作用:解决实参的长度必须与形参一致的问题
语法:数据类型... 变量名
使用位置:形参末尾使用
注意:一个方法只能使用一个可变参数
算法
作用:调高代码的执行效率
评判算法是否优良
时间复杂度 代码执行时间越短越好 空间复杂度 代码执行中所需的内存,越少越好常用的算法
两数交换 int red = 10; int blue = 1; int x = red; red = blue; blue = x; 寻找最大值/最小值 int[] nums = {1,17,18,19,21,5,66,17,19,0}; //假设最大值为max //注意:该数的初始化值必须是数组中的数 int max = nums[0]; //使用假设的数据与数组中其他数据一一对比 for(int x:nums){ if(x > max){ max = x; } } //假设的最大值就是真的最大值 寻找最大值下标/最小值下标 int[] nums = {1,17,18,19,21,5,66,17,19,0}; //假设最大值的下标为maxIndex int maxIndex = 0; //使用假设的最大值下标对应的数据与数组中其他数据一一对比 for(int i = 0; i < nums.length; i++){ if(nums[maxIndex] < nums[i]){ maxIndex = i; } } 排序 冒泡排序 核心思想:相邻比较,交换位置 选择排序 核心思想:确定最值与目标位置,交换位置 JDK提供的方法进行排序 使用JDK提供的Arrays 操作: 排序:sort 语法: Arrays.sort(数组名); 将数组转换为字符串:toString 语法: Arrays.toString(数组名); 返回值为转换后的字符串 二分查询 杨辉三角 x { 0 {1}, 1 {1 1} 2 {1 2 1} 3 {1 3 3 1} 4 {1 4 6 4 1} 5 {1 5 10 10 5 1} } 0 1 2 3 4 5 y 一维数组在二维数组这种的位置为x 元素在一维数组中的位置为:y 数组名[2][1] = 数组名[1][1] + 数组名[1][0]; 数组名[4][2] = 数组名[3][2] + 数组名[3][1]; 数组名[x][y] = 数组名[x-1][y] + 数组名[x-1][y-1];JDK提供的排序
核心思想:快速排序 类:Arrays 提供的方法: sort(数组);排序,默认从小到大(升序) toString(数组):将数组转换为字符串查找
顺序查找
核心思想:逐个对比二分查找
核心思想:折半法 注意: 1,使用二分查找的数组必须是有序的
数据结构
数组
链表
二叉树
树
图
栈
概念:先进后出,水桶 代码模拟: ArrayList<Integer> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { list.add(i); } while (list.size() > 0){ Integer num = list.remove(list.size() - 1); System.out.println(num); } System.out.println(list);队列
概念:先进先出,水管 代码模拟: ArrayList<Integer> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { list.add(i); } while (list.size() > 0){ Integer num = list.remove(0); System.out.println(num); } System.out.println(list);单链表
概念:上一个节点存储的是值与下一个节点的地址 代码模拟: public class Demo11 { public static void main(String[] args) { Node<String> n03 = new Node<>("德玛",null); Node<String> n02 = new Node<>("蛮王",n03); Node<String> n01 = new Node<>("寒冰",n02); System.out.println(n01.getV()); System.out.println(n01.next().getV()); System.out.println(n01.next().next().getV()); } } //节点 class Node<T>{ private T v;//值 private Node n;//下一个值的内存地址 public Node() { } public Node(T v, Node n) { this.v = v; this.n = n; } public T getV() { return v; } public void setV(T v) { this.v = v; } public Node next(){ return n; } }
编程思想
面向过程
概述:按照事物的发展顺序考虑问题 将大象装进冰箱里 1,打开冰箱门 2,放入大象 3,关闭冰箱门 开发语言: C面向对象
概念:先考虑事物中存在那些对象,在建立对象与对象的关系 将大象装进冰箱里 1,存在的对象有 冰箱 大象 2,关系 冰箱开门 放大象 冰箱关门 开发语言: Java,Python,JavaScript,Object C,C#....
对象的概念
概念:万事万物皆对象 生活中:客观存在的事物皆为对象 代码中:在代码中存在的事物
类的概念
概念:多个对象抽取其共同点形成的概念 生活中:概念 代码中:创建对象的模板
类与对象的关系
生活中:先有对象,后有类 代码中:先有类,后有对象 一个类可以有多个对象.多个对象可以属于同一个类
类的定义与组成
定义
语法: 访问权限修饰符 class 类名{ } 访问权限修饰符: 暂时使用public或不写 类名: 1,同一个文件夹下类名不能相同 2,大驼峰组成
属性: 如:人的姓名,性别,年龄,肤色等 作用:描述事物的静态特征 定义的位置:类中,方法以外 语法格式:访问权限修饰符 数据类型 属性名; 别名:全局变量,成员变量 成员变量与局部变量的区别 成员变量: 声明在类中,方法外 有默认值,基本数据类型,默认为0,引用数据类型默认为null 作用域:当前类中 生命周期:随着所属的对象的创建而生成,随着所属的对象的销毁而销毁 局部变量: 方法中 没有默认值 作用域:当前代码块中 生命周期:随着方法调用而生成随着方法执行完毕而销毁 练习:定义一个人类,在使其定义,姓名,性别,年龄属性 //1,定义一个人类 public class Person{ //2,定义属性 public String name; public char sex; public int age; } 方法: 如:人会吃饭,喝水,打游戏,学习等 作用:描述事物的行为(动态特征) 定义的位置:类中,方法以外 语法格式: 访问权限修饰符 返回值类型 方法名(形参列表){ 方法体 } 修饰符:暂时不写 别名:函数,成员函数,成员方法 练习:定义一个人类,使其会吃饭,会喝水 //1,定义一个人类 public class Person{ public String name; //2,定义方法 public void eat(){ System.out.println(name+"吃饭"); } public void eat(String foodName){ System.out.println(name+"吃"+foodName); } public void drink(){ System.out.println(name+"喝水"); } } 构造函数: 本质:特殊的方法 作用:创建该类对象 定义位置:类中,方法以外 语法: 访问权限修饰符 构造函数名(形参列表){ 方法体 } 注意: 1,构造函数没有返回值类型 2,构造函数中没有返回值 3,构造函数名必须与类名一致 4,使用new关键字调用 5,如果一个类中有多个构造函数,那么这些构造函数绝对是重载关系 6,一个类一定会有一个构造函数.如果一个类中没有定义构造函数,系统将会为其提供一个无参构造.如果一个类中有构造函数,系统将不在为其提供无参构造 7,构造函数不能形成递归 名词: 1,无参构造:构造函数没有形参 2,有参构造:构造函数有形参 3,全参构造:构造函数的形参一一对应,该类的属性 如:给人类定义一个构造函 public class Person{ String name; String sex; int age; public Person(String n,String s,int a){ } }
对象的创建与使用
创建
语法: 数据类型 对象名 = new 构造函数(实参列表); 数据类型:就是该对象所属的类的类名.就是类名 Cat cat = new Cat();做了什么? 步骤: 1,使用new关键字在堆内存中开辟一片空间 2,给属性赋初值 3,执行构造函数中的代码 4,将堆地址赋值给栈中的引用使用
操作属性
获取属性值 语法: 对象名.属性名 修改属性值 语法: 对象名.属性名 = 值;调用方法
语法: 对象名.方法名(实参列表);
this关键字
含义:谁调用this所在的方法this就表示谁
场景1:当局部变量与成员变量(属性)名称相同时,使用this区分
成员变量(属性) this.属性名 局部变量 变量名 就近使用原则
场景2:在本类方法中使用本类的属性或方法,默认使用this调用,此时this可以忽略不写
场景3:在本类构造函数中调用本类其他构造函数
语法: this(实参列表); 注意: 必须在构造函数第一行使用
面向对象三大特征
封装
概念:包装
优点:
1,方便使用 2,保护内部 3,降低耦合度 4,提高复用率体现
变量:封装这一个值或内存地址 方法:封装一堆代码 类:封装多个属性,方法与构造函数 ... Java中的封装无处不在包
本质:就是一个src下的文件夹 作用:对java文件进行分类存储,使其便于寻找 创建: 选择src -- 点击鼠标右键 -- 选择new -- 选择package -- 填写包名 包名: 命名规则:全小写 潜规则:com.公司名称缩写或项目名称.分类名称 注意: .下一级文件夹 关键字:package,说明当前java文件所在的包导包
作用:在当前java文件中使用其他文件夹下的类,此时需要导包 语法: import 包名.类名; 位置:类上 关键字:import *:所有访问权限修饰符
作用:限制其修饰的内容使用的范围 关键字 中文名 范围 public 公共的 当前项目中 protected 受保护的 当前包下或继承关系下可用 不写 默认的 当前包下 private 私有的 当前类中 总结: 属性使用private修饰 方法使用public修饰经验
1,私有化所有属性(使用private修饰所有属性) 2,编写无参构造与全参构造 3,提供公共的get与set方法,使其可以对属性进行操作
继承
概念:
生活中:晚辈继承长辈遗留下的精神或物质遗产
代码中:多个类抽取其共同点形成的类,此时该与类这几个类就可以有继承关系
优点:
子类将拥有父类的所有属性与方法,构造函数除外 1,提高复用率语法
访问权限修饰符 class 子类名 extends 父类名{ 属性 方法 构造函数 } 注意: 1,一个父类可以有多个子类 2,一个子类只能有一个父类(单继承) 3,子类构造函数中默认调用父类无参构造函数 4,子类构造函数中必须调用父类的构造函数 父类的别名:基类,根类 Object是所有类的父类,如果一个没有明确的父类,默认继承与Object 开闭原则: 对修改关闭 对扩展打开重写
在继承关系中 子类中的方法与父类的方法,方法名形同,形参列表也相同, 子类该方法的访问权限修饰符不能小于父类的 子类该方法的返回值类型与父类的一致super
含义:谁调用super所在的方法,super就表示谁的父类对象 场景1:当子类重写父类方法后,在子类中使用super区分,是子类重写的方法还是父类提供的方法 super.方法名(实参列表) 父类提供的方法 方法名(实参列表) 子类重写后的方法 场景2:当子类属性名与父类属性名重名时,使用super区分 super.属性名 父类属性 属性名 子类属性 (没人用过) 场景3:调用父类构造函数 super(实参列表); 注意: 只能在子类构造函数第一行调用 this与super this:调用该方法的对象 super:调用该方法的父类对象
多态
概念:一个事物的多种形态 物的多态 子类对象转换为父类对象 自动转换 语法 父类名 对象名 = 子类对象; 父类对象转换为子类对象 强制转换 语法: 子类名 对象名 = (子类名) 父类对象; 注意:有风险 instanceof 作用:判断该对象是否属于该类 注意:判断的对象与类之间要存在关系 语法: boolean 变量名 = 对象名 instanceof 类名; 如果结果为true,表示该对象属于该类 如果结果为false,表示该对象不属于该类 事的多态 重载 要求:在同一个类中,方法名相同,形参列表不同 重写 要求:在继承关系中,子类方法与父类方法,方法名相同,形参列表相同,返回值类型相同,访问权限修饰符不能减小 例子:动物会叫,狗也会叫 注意: 当子类对象转换为父类对象后,调用重写的方法,依据执行的是子类重写的后的方法
三大修饰符
abstract
含义:抽象的,不可描述的
可以修饰:类与方法
修饰类
特点:不能直接创建对象 语法: 访问权限修饰符 abstract class 类名{ 属性 方法 构造函数 } 名称:被称为抽象类 注意: 抽象类中不一定有抽象方法 子类继承与抽象类,要么重写父类所有抽象方法,要么自己也是抽象类修饰方法
特点:没有方法体 语法: 访问权限修饰符 abstract 返回值类型 方法名(形参列表); 注意: 有抽象方法的类一定是抽象类 抽象类中可以有多个抽象方法
final
含义:最终的,不可修改的
可以修饰:变量,方法,类
修饰变量
修饰局部变量 语法: final 数据类型 变量名; 变量名 = 值; 注意: 只能赋值一次 fianl修饰的变量就是常量 修饰成员变量 语法: 访问权限修饰符 final 数据类型 属性名 = 值; 注意: 1,final修饰的属性必须在声明时赋值 2,final修饰的属性值不能被修改修饰方法
作用:不能被重写 语法: 访问权限修饰符 final 返回值类型 方法名(形参列表){ 方法体 }修饰类
作用:不能被继承.这种类被称为最终类 语法: 访问权限修饰符 final class 类名 ...{ }
static
含义:静态的,公共的
可以修饰:属性,方法,代码块,内部类
修饰属性
特点: 该属性属于该类的所有对象,该类的一个对象对其进行修改,该类的所有对象的该属性都将被修改 可以使用类名直接调用 语法: 访问权限修饰符 static 数据类型 属性名;修饰方法
特点:可以使用类名直接调用,也可以使用对象名调用 语法: 访问权限修饰符 static 返回值类型 方法名(形参列表){ 方法体 } 注意: 1,不能使用this或super关键字 2,不能直接使用本类中其他非静态属性或非静态方法 3,可以直接使用本类的静态属性或静态方法 4,非静态方法中可以直接使用静态属性或静态方法修饰代码块
特点:在类加载时被执行 注意:一个类在程序运行时,只会被加载一次 语法: static{ 代码块 } 注意: 静态代码块中可以使用静态属性与静态方法,不能直接使用非静态属性或非静态方法 静态代码块与静态属性,谁在前,谁先执行.为了可以在静态代码块中使用静态属性,必须将静态属性声明在静态代码块之前 类加载时机:该类第一次被使用时 1,第一次创建该类对象时 2,第一次使用该类调用属性时 3,第一次使用该类调用方法时 4,第一次使用反射机制加载该类时
代码块
语法:{}
作用:封装一段代码
使用位置:
类中方法以外 每次创建该类对象时被调用 注意: 在构造函数之前执行 普通属性与代码块按顺序执行 类中方法中 相当于没写
继承关系中的执行流程
先父静,在子静
父代码块,父构造函数
子代码块,子构造函数
接口
含义
宏观:规则 微观:功能使用步骤
1,定义 2,使用定义
语法: 访问权限修饰符 interface 接口名{ } 组成: 公共静态常量 公共静态方法 公共抽象方法 default修饰的普通方法 注意: 接口中的属性默认使用public static final修饰 接口中的方法默认使用public abstract修饰使用
情况1:接口使用接口 多继承:一个接口可以继承多个接口 语法: 访问权限修饰符 interface 子接口名 extends 父接口名1,父接口名2,...{ } 注意: 不能继承父接口的静态方法,其他的均可继承 情况2:类使用接口 多实现:一个类可以实现多个接口 语法: 访问权限修饰符 class 子类名 extends 父类名 implements 父接口名1,父接口名2,...{ } 注意: 1,一个类可以实现多个接口 2,子类要么重写所有接口提供的抽象方法,要么子类也是抽象类 3,子类对象可以转换为多个实现的接口对象 4,一个接口可以被多个类现实,所以多个类的对象可以转换为同一个接口的对象
接口的特殊使用
常量接口
概念:只有常量的接口称为常量接口 public interface NetType{ int OK_NET = 200; int ERROR_NET_01 = 404; int ERROR_NET_02 = 503; int ERROR_NET_02 = 303; }接口回调
概念:接口对象回来调用接口方法 案例:按钮点击 按钮类 点击事件接口 环境类 创建点击事件接口对象 创建按钮对象,传入接口对象 按钮对象.点击方法
内部类
作用:补齐外部类功能
概念:在类中定义的类称为内部类
如: public class A { public class B{ } } 此时B类就是内部类,A类就是外部类内部类分类
1,成员内部类 定义位置:类中,方法以外 没有使用static修饰 2,静态内部类 定义位置:类中,方法以外 使用static修饰 3,局部内部类 定义位置:类中,方法中 4,匿名内部类(*) 定义位置:值或实参中成员内部类
定义位置:类中,方法以外 可以定义什么? 除静态成员(静态属性与静态方法等)以外皆可定义 如何创建对象? 情况1:在所在的外部类中创建该内部类对象 内部类类名 对象名 = new 内部类类名(实参列表); 注意:只是省略this关键字,所以这种创建方式不能在静态方法中使用 情况2:在其他类中创建该内部类对象 外部类类名.内部类类名 对象名 = 外部类对象.new 内部类类名(实参列表);静态内部类
定义位置:类中,方法外.使用static修饰的成员内部类 可以定义什么? 所有的都可以定义 如何创建对象? 外部类类名.内部类类名 对象名 = new 外部类类名.内部类类名(实参列表);局部内部类
定义位置:类中,方法中 注意: 1,此时不能使用访问权限修饰符 2,只能在当前方法中使用 可以定义什么? 除静态成员(静态属性与静态方法等)以外皆可定义 如何创建对象? 内部类类名 对象名 = new 内部类类名(实参列表);匿名内部类
概念:没有类名的内部类称为匿名内部类 定义位置:值或实参中 语法: 父类名或父接口名 对象名 = new 父类名或父接口名(){ 属性 方法 }; 注意: 1,一个类只创建一个对象时,可以使用匿名内部类 2,不能定义静态的成员与抽象方法 缺点: 1,代码混乱,降低代码可读性 优点: 1,编写方便匿名对象
概念:没有对象名的对象 new 类名(实参列表).方法名(); 缺点:只能使用一次 优点:编写方便
包装类
概念:八个基本数据类型对应的引用的数据类型
包装类有
byte Byte short Short int Integer long Long float Float double Double boolean Boolean char Character提供的方法
static xxx parseXXX();自动装箱
概念:将基本数据类型转换为其对应的引用数据类型的对象 如: Integer i = 10;自动拆箱
概念:将引用数据类型的对象转换为对应的基本数据类型的变量 如: int i2 = i;整数缓冲区
-128~127 原因: 因为系统中已经创建了-128~127之间有数的对象,在使用自动装箱时,如果值是在该范围内,直接使用已经创建好的对象,如果超过这个返回需要重新创建对象 Integer i1 = 127; Integer i2 = 127; i1 == i2; true i1 = 128; i2 = 128; i1 == i2; false
System
含义:系统
本质:由JDK提供的一个类
提供的属性或方法
static native void arraycopy(Object src,int srcPos, Object dest, int destPos, int length) 作用:将原数组中的一段数据复制到新数组 1参:原数组 2参:复制开始的位置 3参:新数组 4参:新数组开始的位置 5参:复制的长度 static native long currentTimeMillis() 作用:获取当前时间与1970年1月1日00:00:00:000的时间差(格林威治时间) static void exit(int status) 作用:结束当前程序 1参:终止状态码 0:正常退出 1:异常退出 static void gc() 作用:手动调用垃圾回收机制
Object
概念:所有类的父类
意味:
该类提供的属性与方法是所有类的对象都可以使用的提供的方法
public boolean equals(Object obj) 作用:判断调用该方法的对象与传入的对象的内存地址是否相同 如果子类重写该方法,使用子类对象调用该方法执行的是重写后的代码 如果要比较子类的对象属性值是否相同,要重写equals方法 重写步骤: 1,判断内存地址是否相同 2,判断传入的对象是否属于该类对象 3,将传入的对象转换为该类对象 4,使用调用该方法的对象的属性与传入的对象的属性一一比较 public String toString() 作用:获取对象的表名.类拼接@字符串,在拼接对象的内存地址的16进制值 注意: Object提供的toString方法返回的是对象的包名.类@对象的内存地址的16进制,可以理解为是对象的信息,但是我们在观察对象时,想看到的是对象的属性值.所以此时我们可以在子类中重写toString方法.重写后对象在调用toString方法,执行的是重写后的toString方法. 因为打印对象时默认会调用对象的toString方法.那么当子类重写toString方法后,在打印该子类对象,此时执行的是子类重写后的toString方法 public int hashCode() 作用:获取对象的哈希码值,近似可以理解为对象的内存地址 finalize() 作用:系统回收该对象的内存时,才会被调用
Math
作用:数学运算与随机数
提供的方法
static double random(); 作用:随机获取0~1之间的数 static int abs(int a) 作用:获取其指定数据的绝对值 static double floor(double a) 作用:向下取整 static int max(int a, int b) 作用:获取两数之间的最大值 static int min(int a, int b) 作用:获取两数之间的最小值 static double pow(double a, double b) 作用:计算a的b次幂的结果
字符串相关类
不可变字符串:String
提供的方法
增 + 删 改 public String replace(String old,String newStr) 作用:替换 1参:要被替换的字符串 2参:替换后的字符串 查 public int length() 作用:获取字符串长度 char charAt(int index) 作用:获取字符串中指定位置的字符 public char[] toCharArray() 作用:将字符串转换为字符数组 public boolean equals(Object anObject) 作用:比较字符串内容是否相同 public boolean equalsIgnoreCase(String anotherString) 作用:忽略大小写比较字符串内容是否相同 public String trim() 作用:忽略前后空白 boolean endsWith(String suffix) 作用:判断字符串是否以指定的字符串结束 boolean startsWith(String prefix) 作用:判断字符串以什么开始 public String toUpperCase() 作用:将字符串中的小写字母转换为大写字母 public String toLowerCase() 作用:将字符串中的大写字母转换为大写字母 boolean contains(String s) 作用:判断s是否在调用该方法的字符串中存在 public int lastIndexOf(String str) 作用:获取指定的子字符串在字符串中最后一次出现的位置 public int indexOf(String str) 作用:获取指定的子字符串在字符串中第一次出现的位置 public String substring(int beginIndex) 作用:截取指定位置的字符串,从开始位置到字符串末尾 1参:开始位置 public String substring(int beginIndex, int endIndex) 作用:截取指定位置的字符串 1参:开始位置 2参:结束位置 public String[] split(String regex) 作用:切割 1参:按什么字符串切割构造函数
public String(char value[]) 将传入的字符数组转换为字符串 public String(char value[], int offset, int count)
可变字符串
StringBuffer
特点: JDK1.0出现 线程安全的 效率低StringBuilder
特性: JDK1.5出现 线程不安全 效率高java
提供的方法
1,StringBuilder append(Object obj) 作用:给字符串尾部拼接字符串 2,StringBuilder insert(int offset, String str) 作用:插入 1参:插入开始的位置 2参:插入的数据 3,StringBuilder delete(int start, int end) 作用:删除指定区间的数据 1参:开始位置,包含 2参:结束位置,不包含 4,StringBuilder deleteCharAt(int index) 作用:删除指定位置的字符 1参:指定的位置 5,StringBuilder replace(int start, int end, String str) 作用:替换 1参:要替换的数据的开始位置,包含 2参:要替换的数据的结束位置,不包含 3参:替换后的字符串 6,toString(): 作用:将可变字符串转换为不可变字符串
精准计算
对应的类:BigDecimal
构造函数
BigDecimal(Object obj); 注意:一定要传入的是字符串提供的方法
BigDecimal subtract(BigDecimal subtrahend) 作用:减法,使用调用该方法的对象的值减去传入的对象的值,返回计算的结果 BigDecimal add(BigDecimal augend) 作用:加法 BigDecimal multiply(BigDecimal multiplicand) 作用:乘法 BigDecimal divide(BigDecimal divisor) 作用:除法 XXX xxxValue(); 作用:获取BigDecimal的值
时间相关类
Date
概念:日期
创建:
public Date():获取当前系统时间 public Date(long date):获取距离1970年1月1日 00:00:00的时间(格林威治时间),参数单位毫秒方法
public long getTime():获取当前对象距离1970年1月1日 00:00:00的时间差,单位毫秒 public boolean after(Date when):当前时间是否在指定时间之后 public boolean before(Date when):当时时间是否在指定时间之前
Calendar
概念:日历
创建:
static Calendar getInstance()方法:
get set add getTime
SimpleDateFormat
概念:时间日期格式化
特殊字符
y:年 M:月 d:日 h:十二小时值 H:二十四小时值 m:分钟 s:秒 S:毫秒 编写:2023/04/13 17:16:00 yyyy/MM/dd HH:mm:ss方法
format:将时间对象转换为指定格式的字符串 parse:将指定格式的字符串转换为时间
泛型
作用:将数据类型作为参数进行传递
语法:
定义 <泛型名1,泛型名2,..> 情况1:在方法上 访问权限修饰符 修饰符 <泛型名1,泛型名2,...> 返回值类型 方法名(形参列表){ } 情况2:在类上定义 访问权限修饰符 class 类名<泛型名1,泛型名2,...>{ } 使用 泛型名 情况1:在方法中使用 在方法中任意使用数据类型的地方都可以使用该泛型作为数据类型 情况2:在类中使用 在类中任意使用数据类型的地方都可以使用该泛型作为数据类型注意:泛型中只能使用引用数据类型
集合
作用
存储一组数据类型相同的数据
特点
长度可变
名称
长度:集合中存的元素的个数 下标:元素在集合中的位置 元素:集合中存储的数据
体系结构
Collection List 特点:有序(存入顺序与取出顺序一致),有下标,可以重复 子类: ArrayList 特点: JDK1.2出现 线程不安全的 数据结构:数组 特点: 查询效率高 增删效率低 LinkedList 数据结构:链表 特点: 查询效率低 增删效率高 单链表与双链表 Vector 特点: JDK1.0出现 线程安全 数据结构:数组 Set 特点:无序,无下标,元素不允许重复 子类: HashSet 底层:HashMap 数据结构: JDK1.8以前数组+链表 JDK1.8以后数组+链表+红黑树(哈希值) 红黑树(又名二叉树) TreeSet 数据结构:红黑树 注意:指定比较规则 LinkedHashSet 特点:有序 数据结构: JDK1.8以前数组+链表+链表 JDK1.8以后数组+链表+红黑树(哈希值)+链表
Collection提供的方法
增 boolean add(E e) 作用:一次添加一个数据 参数: 要添加的数据 返回值: 是否添加成功 boolean addAll(Collection<? extends E> c); 作用:一次添加一组数据 参数: 要添加的数据集合 返回值: 是否添加成功,注意:哪怕只添加了一个也算成功,全部失败才为失败 删 boolean remove(Object o) 作用:一次删除一个数据 参数: 要删除的数据 返回值: 是否删除成功 注意: 如果集合中有多个要删除的数据,只能删除第一个 boolean removeAll(Collection<?> c) 作用:一次删除一组输入 参数: 要删除的数据集合 返回值: 是否删除成功 注意: 如果原集合中多次出现删除集合中的数据,那么原集合中的该数据会全部被删除 void clear() 作用:清空集合中的数据 查 int size(); 作用:查询集合长度 boolean contains(Object o); 作用:判断集合中是否包含指定元素 boolean containsAll(Collection<?> c); 作用:判断集合中是否全部包含指定的集合中的元素 注意:判断的是是否全部包含 boolean isEmpty(); 作用:判断集合是否为空集合 注意:空集合表示集合中没有元素,而不是集合为null Iterator<E> iterator() 作用:获取当前集合的迭代器 迭代器的方法: boolean hasNext();判断下一个是否有值 E next();移动游标,并返回指向的数据 改 没有提供 特殊情况: 遍历 方案1:迭代器 方案2:foreach
List提供的方法
增 void add(int index, E element); 作用:给指定位置插入一个数据 void addAll(int index, Collection<E> c); 作用:给指定位置插入一组数据 删 E remove(int index); 作用:删除指定位置的数据 改 E set(int index, E element); 作用:修改指定位置的元素 参数: 1,指定的位置 2,修改后的元素 查 E get(int index); 作用:获取指定位置的元素
Set没有提供特有方法
HashSet的剔重原理
1,存入对象先判断对象的hashcode值是否与已经存储的数据hashcode值是否相同 2,如果相等,在使用本次存入的对象与集合中的对象使用equals方法一一比较 3,如果equals也相同,认为对象已经存储,将不在存入该对象
TreeSet存储
要求: TreeSet存储的数据 要么拥有比较性(让存储的对象的类实现Comparable), 要么指定比较器(创建TreeSet时传入Comparator对象)
Map
作用:存储一组键值对应的数据类型的数据
名称
键:key 值:value体系结构
Map HashMap 特点:使用键值对的中键的hashcode值进行排序,允许空键空值,JDK1.2,线程不安全的 Hashtable 特点:使用键值对的中键的hashcode值进行排序,不允许空键空值,JDK1.0,线程安全的 TreeMap 特点:要求键要么拥有比较性,要么指定key的比较器 Properties 特点:HashMap的子类,可以加载读取文件中的内容,也可以向文件中写入内容 注意: key值不能重复Map提供的方法
增 V put(K key, V value); 作用:添加 注意: 如果map中不存在该key,返回值为null 如果map中存在该key那么此时就是替换,返回被替换的值 void putAll(Map<? extends K, ? extends V> m); 作用:添加一组键值对 删 V remove(Object key); 作用:通过key删除指定的键值对 返回值:被删除的值 void clear(); 作用:清空 查 int size(); 作用:查询map中键值对的个数 boolean isEmpty(); 作用:判断是否为空map boolean containsKey(Object key); 作用:判断是否包含指定的key boolean containsValue(Object value); 作用:判断是否包含指定的value V get(Object key); 作用:获取key指定的值 Set<K> keySet(); 作用:获取所有key的集合 Collection<V> values(); 作用:获取所有值的集合 Set<Map.Entry<K, V>> entrySet(); 作用:获取所有键值对的集合 改 V put(K key, V value); 注意:如果存储数据时,key已经存在,此时就是修改
字典
概念:以键值对应的方式存储一组数据
体系
Map HashMap 特点:允许空键空值,jdk1.2,线程不安全的 TreeMap 特点:key要么拥有比较性,要么在创建TreeMap指定Key比较器 Hashtable 特点:不允许空键空值,jdk1.0,线程安全的
异常
概念:程序有问题的地方
分类
错误 概念:因为硬件问题导致的程序崩溃,称为错误(Error) 解决:不予处理 异常 检查时异常 概念:因语法问题导致的错误 解决:修改语法 运行时异常 概念:但是因为编写时思路问题,或传入的数据导致程序无法正常运行 解决:更换思路,修改传入的数据,加入容错判断异常出现后的情况
导致程序非正常结束体系
Throwable Error(错误) Exception(异常) CheckedException(检查时异常) RuntimeException(运行时异常)解决方案
方式1:try catch 语法: try{ 有异常的代码; }catch(异常类型 变量名){ 处理方式 }catch(异常类型 变量名){ 处理方式 }... catch(异常类型 变量名){ 处理方式 }finally{ 必须要执行的代码 } 注意: catch可以有多个,必须先子类在父类,如果没关系,那么不需要关系顺序 finally可有可无,最多只能有一个 方式2:throw 语法: throw 异常对象; 使用位置:方法中 方式3:throws 语法: throws 异常类型1,异常类型2,... 使用位置:形参之后 注意:先子后父(可以不这么干)常见的异常
NullPointerException 名称:空指针异常 原因:因为使用null调用属性或方法 IndexOutOfBoundsException 名称:数组下标越界异常 原因:在操作数组或集合时,下标不在取值范围内 ArithmeticException 名称:算数异常 OutOfMemoryError 名称:内存溢出错误自定义异常
步骤: 1,创建一个类 2,使其继承与Exception或Exception的子类 3,编写其构造函数
线程的初识
作用
使代码可以同时执行多个事物
名词
进程: 一个正在进行的程序 线程: 一个执行路径 多线程: 一个进程中有多个线程 主线程: 一个进程在创建时自带的一条线程,该线程被称为主线程 子线程: 除主线程以外的线程都是子线程 守护线程(后台线程): 特点:如果一个进程的前台线程全都被销毁,此时不管是否有守护线程正在执行,此时进程都将被回收 前台线程 特点:如果一个进程中有前台线程存活,此时系统将不会回收进程
线程的组成
CPU时间片
线程抢夺到CPU执行权后可执行的时间内存
一个线程一个栈内存,多个线程共享一个堆内存逻辑
使用步骤
1,创建 2,使用
线程的创建
方案1:创建Thread的子类对象
方式1:创建Thread的子类对象 步骤: 1,创建一个类 2,使其继承与Thread 3,重写run方法 注意:当前线程启动后,将执行run方法中的代码 4,创建该类对象 优点: 可以创建无数个该类对象 方式2:使用匿名内部类的形式创建Thread的子类对象 步骤: Thread 对象名 = new Thread(){ 重写run方法 }; 优点: 便于书写 缺点: 只能创建一个该线程对象方案2:将线程(Thread)与线程任务(Runnable)分开
方式1:普通方式创建Runnable的子类对象 步骤: 1,创建一个类 2,使其实现Runnable接口 3,重写run方法 4,创建该类对象 5,在创建线程对象时传入该类对象(线程任务对象) 方式2:使用匿名内部类创建Runnable的子类对象 步骤: 1,Runnable 对象名 = new Runnable(){ 重写run方法 }; 2,创建线程对象时传入该类对象(线程任务对象)
线程的启动
线程对象.start(); 注意: 1,当线程启动后会开启新的执行路径,执行run方法中的代码 2,如果直接使用线程对象调用run方法,不会开启新的执行路径
线程的销毁
线程已经启动,无法控制,需要等待执行完run方法中的代码
获取当前线程对象
Thread.currentThread();
线程名称
获取线程名称 线程对象.getName(); 修改线程名称 线程对象.setName(name); 注意:在启动之前
线程的优先级
作用:提高线程抢夺到CPU执行权的概率
语法: 线程对象.setPriority(int); 注意: 1,取值范围1~10 2,必须在线程启动前
线程休眠
作用:让线程暂时停止运行
方法: static void sleep(休眠时间); 注意: 1,单位毫秒 2,使用类名调用,使当前线程休眠 3,线程休眠期间不会抢夺CPU执行权
线程的礼让
作用:将获取到的CPU执行权让出,重新参与抢夺
方法: static native void yield();
线程合并
作用:合并线程
方法: public final void join()案例
package com.qf.demo011; public class Test { public static void main(String[] args) { Thread t01 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 100; i++) { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程1:" + i); } } }); Thread t02 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 100; i++) { try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程2:" + i); if (i == 50){ try { //将线程1合并到线程2中 //此时先执行完线程1未完成的代码,在执行线程2未完成的代码 t01.join(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }); t01.start(); t02.start(); } }
守护线程
简介
又名:后台线程 特点: 当一个进程中有前台线程存活,此时该进程就不会被系统回收 如果一个进程中只剩后台线程,此时不管后台线程中的代码是否运行完毕,系统都将回收该进程 方法: public final void setDaemon(boolean on); true表示守护线程,默认为false,表示前台线程 注意: 1,创建的线程对象与主线程默认为前台线程 2,必须在线程启动前
线程的生命周期
创建 就绪 运行 消亡 休眠 有限期 无限期
线程安全问题
原因
多个线程操作同一个数据,会导致线程安全问题解决思路
保证同时只能有一个线程操作该数据方案
方案1:同步代码块 语法: synchronized(锁对象){ 要同步的代码 } 注意: 1,所有对象都可以作为锁对象 2,多个线程的锁对象要是同一个对象 方案2:同步方法 语法: 访问权限修饰符 synchronized 返回值类型 方法名(形参列表){ } 注意: 1,同步方法的锁对象是this 2,多个线程的锁对象要是同一个对象 方案3:同步静态方法 语法: 访问权限修饰符 synchronized static 返回值类型 方法名(形参列表){ } 注意: 1,同步静态方法的锁对象时该类的类对象 类对象:当JVM加载类的时候,会生产一个对象,该对象就是该类的类对象 一个类只有一个类对象 2,多个线程的锁对象要是同一个对象
死锁
原因
多个线程互相持有对方所需的锁资源例子
Object A = new Object(); Object B = new Object(); 线程1: xxx synchronized (A){ xxx synchronized (B){ xxx } } 线程2: xxx synchronized (B){ xxx synchronized (A){ xxx } }避免的思路
不要在同步中使用同步
线程间通讯
注意
1,线程间通讯的方法由Object提供 2,只能在同步中使用 3,只能使用所在的同步的锁对象调用方法
唤醒: notify():随机唤醒一个 notifyAll():唤醒所有 注意: 只能唤醒以同一个对象调用wait方法的线程 休眠: wait():无限期休眠 wait(int ms):有限期休眠 wait(int ms,int ns):有限期休眠 注意: 1,参数就是休眠时间,ms毫秒,ns纳秒 wait与sleep的区别: 1,wait在休眠期间会释放所持有的锁资源,sleep不会 2,wait必须在同步中使用,sleep没有限制 3,wait必须使用所在的同步的锁对象调用,sleep使用Thread类或Thread类的对象调用 4,wait由Object提供,sleep由Thread类提供
生产者与消费者模式
设计模式
作用:解决特定问题的思路 生产者与消费者模式解决的是进销存业务生产者与消费者模式解决的问题
工厂的进销存业务分析
生产的任务 无限生产 销售的任务 无限销售 工厂 属性: 库存数量 最大库存数量 最小库存数量 方法: 生成的方法:同步的 判断库存数量 < 最大库存数量 true 继续生产 false 唤醒销售 休眠自身 销售的方法:同步的 判断库存数量 > 最小库存数量 true 继续销售 false 唤醒生产 休眠自身 环境类 创建工厂对象 创建线程对象(传入线程任务(生产任务或销售任务)) ... 启动
线程池
作用:优化线程
原因:
一个线程大约占1MB的运行内存 大量创建线程时可能会导致内存溢出 大量的创建的线程也导致需要对象线程频繁的创建与回收思路
1,使用空闲的线程的执行新的任务(线程的复用) 2,使用一个容器来管理线程的创建,回收,复用等 注意:Java中提出线程池来完成以上操作线程池的体系结构
Executor(接口) 提供的方法: void execute(Runnable command): 作用:执行线程任务,子接口提供了submit优于该方法 子类或子接口 ExecutorService(接口) 提供的方法: void shutdown(); 作用:关闭线程池 boolean isShutdown(); 作用:判断线程池是否关闭 Future<T> submit(线程任务) 作用:提交线程任务 子类或子接口 ScheduledExecutorService(接口) ThreadPoolExecutor(类) 构造函数: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) corePoolSize:核心线程数,线程池中最少有几个线程 maximumPoolSize:最大线程数,线程中最多可以容纳几个线程 keepAliveTime:销毁时间,当线程执行完任务后,多久销毁 unit:时间单位 workQueue:存储执行的线程任务的集合(队列形式) threadFactory:创建线程 handler:优化线程,使其线程复用的算法Executors
作用:创建线程池 原因:因为ThreadPoolExecutor过于麻烦,所以JDK提供该类帮助我们创建线程池 提供的方法: 1,固定线程池 特点:线程池中的线程数量恒定,当线程任务小于线程数量时,随机在线程池中挑选线程执行任务.当线程任务大于线程数量,会先执行前面的任务,后等前面任务执行完毕后,使用执行完毕的线程,执行剩余任务 static ExecutorService newFixedThreadPool(int nThreads) nThreads:线程池中线程的数量 2,可变线程池 特点:线程池中的线程数量可变 static ExecutorService newCachedThreadPool() 3,单例线程池 特点:一个线程池中只有一个线程 static ExecutorService newSingleThreadExecutor() 4,抢占线程池(了解) 特点:JDK1.8出现的 static ExecutorService newWorkStealingPool() 5,调度线程池 特点:该线程池执行任务可以延迟,也可以延迟重复执行 static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) corePoolSize:线程池中线程的数量 6,单例调度线程池 特点:调度线程池中只有一个线程 static ScheduledExecutorService newSingleThreadScheduledExecutor()线程池使用
步骤: 1,创建线程池 2,提交任务 3,关闭线程池调度线程池:ScheduledExecutorService
提供的方法: public ScheduledFuture<?> schedule(线程任务, long delay, TimeUnit unit) 作用:延迟执行 public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit); 作用:延迟重复执行 1参:执行的任务 2参:延迟时间 3参:间隔时间=本次任务开始时间-上次任务开始时间 注意:如果上次任务执行时间>间隔时间,那么当上次任务执行完毕后,本次任务直接开始 4参:时间单位 public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit); 作用:延迟重复执行 1参:执行的任务 2参:延迟时间 3参:间隔时间=本次任务开始时间-上次任务结束时间 4参:时间单位
Callable
作用:有返回值的线程任务对象
注意:
无法在创建Thread对象时传入,必须配合线程池使用
Lock
作用:简化同步
同步
同步代码块 synchronize(锁对象){ //关锁 代码 //开锁 } 同步方法 访问权限修饰符 synchronize 返回值类型 方法名(形参列表){ //关锁 方法 //开锁 } 同步静态方法 访问权限修饰符 synchronize static 返回值类型 方法名(形参列表){ //关锁 方法 //开锁 }Lock体系
Lock 提供的方法: void lock():关锁 void unLock():开锁 Condition newCondition():获取锁对象 void await():无限期休眠 void signal():随机唤醒一个 void signalAll():唤醒所有 子类: ReentrantLock ReadWriteLock 提供的方法: Lock readLock():获取读锁 Lock writeLock():获取写锁 注意: 读-写 互斥 读-读 不互斥 写-写 互斥 子类 ReentrantReadWriteLock
IO流
作用
传输数据
分类
按照流向分类 输入流 输出流 按照传输的最小数据单位分类 字节流 最小单位:byte 字符流 最小单位:char 按照功能分类 节点流: 从数据源到程序,或从程序直接到数据源 包装流(过滤流): 在节点流的基础是上增强功能 注意:所有的包装流都使用了装饰者模式
字节流
体系
InputStream(字节输入流顶级接口) 方法: int read():一次读取一个字节,返回值为读取到的字节 int read(byte b[]):一次读取一组字节数据到数组b中,返回值为读取到的字节长度,当返回值为-1时表示读取结束 int read(byte b[], int off, int len) 一次读取一组字节数据到数组b中,从off位置开始存储,存储len个字节 返回值为读取到的字节长度,当返回值为-1时表示读取结束 void close(): 关流 OutputStream(字节输出流顶级接口) 方法: void write(int b):一次写入一个字节 void write(byte b[]):一次写入一组字节 void write(byte b[], int off, int len):一次写入一组字节,从off位置开始,写入lenge void flush():冲刷 void close():关流 文件字节流 FileInputStream 分类: 输入流:文件到程序 节点流 FileOutputStream 分类: 输出流:程序到文件 节点流 内存流 作用:在读取数据过程中,因数据不全导致的乱码问题 ByteArrayInputStream ByteArrayOutputStream 特有方法: byte toByteArray();将内存流中的数据获取出来 缓冲流 作用:提高读写效率 注意: 包装流 BufferedInputStream BufferedOutputStream 注意: 默认缓冲区大小为8kb 对象流 作用:将对象写入到文件中,或从文件中读取对象 注意: 1,读写的对象所属的类要实现序列化接口 2,一个对象流只能读写一个对象 3,存储的所有数据都必须进行序列化 4,static修饰的属性不参与序列化 5,transient修饰的属性也不参与序列化 ObjectInputStream readObject():读取对象,只读第一个 ObjectOutputStream writeObject():写入对象
文件流
内存流
注意:节点流 ByteArrayInputStream:内存输入流(了解) 作用:将运行内存中的数据读取到程序中 ByteArrayOutputStream:内存输出流 作用:将程序中数据存储运行内存中 注意: 内存输入流自带内存默认初始大写为32字节,当不够时会自动扩容 特有方法: toByteArray():通过内存输出流获取其存储数据的数组
缓冲流
作用:提高读写效率 注意:过滤流(包装流) BufferedInputStream 作用:提高读的效率 BufferedOutputStream 作用:提高写的效率 注意: 1,包装流在关闭时,会关闭他所包装的节点流 2,默认缓冲区为8kb
对象流
作用:读写对象 注意:过滤流(包装流) ObjectInputStream 特有方法: readObject():读取对象 注意:要保证文件中有对象 ObjectOutputStream 特有方法: writeObject():写出对象 注意: 读写的对象所属的类必须实现序列化接口,包括对象的属性的数据类型也需要实现序列化 序列化: 让对象所属的类实现Serializable接口 注意: 1,八个基本数据类型包装类与String都已经实现了Serializable接口 2,不能序列化的属性有: 1,使用transient修饰的属性为瞬时属性,不参与序列化 2,使用static修饰的属性,不参与序列化
字符编码
常用的编码格式是:UTF-8
编码格式
最原始的计算机数据:0,1 所以将01可以排列使其形成二进制 在将2进制转换为10进制 a:97 b:98 c:99 .: :0 ... ASCAII:因为只有一些国家的文字 Unicode:万国码,在ASCAII上增加多国字符 一个字符2个字节 GBK:加了一些中文,在Unicode基础上增加中文 假设:12345:你 UTF-8:加了一些中文,在Unicode基础上增加中文 假设:12345:爜 UTF-8:对中文的支持比GBK好
字符流
概念
传输的数据单位最小为字符(char)字符流体系
Reader 概念:所有字符输入流的父类 提供的方法: int read();一次读取一个字符,返回值为读取到的字符 int read(char c[]): 一次去取一组字符到数组c中,返回值为读取到的字符长度,当为-1时表示读取结束 int read(char c[], int off, int len) 一次去取一组字符到数组c中 从off位置开始存储,存储len个 返回值为读取到的字符长度 当为-1时表示读取结束 void close() 关闭 Writer 概念:所有字符输出流的父类 提供的方法: void write(int c) void write(char cbuf[]) void write(char cbuf[], int off, int len) void write(String str) void flush() void close() 文件流 FileReader FileWriter 缓冲流 BufferedReader readLine():读取一行 BufferedWriter newLine():写入一个换行 转换流 InputStreamReader OutputStreamWriter 标准输出流 PrintStream 注意:是字节流
文件流
FileReader 作用:将文本文件的内容读取到程序中 FileWriter 作用:将程序中的数据写入到文本文件中 优点: 相对与字节流读取文本文件,字符流不会出现乱码,因为一次就将一个字符读取结束了.不会像字节流可能会读取一个字符的一半字节 缺点: 相对与字节流而言,字符流只能操作文本文件
缓冲流
BufferedReader 作用:提高字符流读取的效率 默认缓冲区大小:8192字符 特有方法: readLine():一次读一行 BufferedWriter 作用:提高字符串写出的效率 默认缓冲区大小:8192字符 特有方法: newLine():给内容中写入一个换行
转换流
InputStreamReader 作用:将字节流输入流转换为字符输入流 注意:当读取到的文本文件与代码的编码格式不同时,转换流可以设定读取的编码格式,防止中文乱码.参数为文本文件的编码格式,ANIS==GBK,Eclispe不支持ANIS OutputStreamWriter 作用:将字符输出流转换为字节输出流 注意:当写入到的文本文件与代码的编码格式不同时,转换流可以设定写入的编码格式,防止中文乱码
标准输出流
PrintWriter 特有方法: print(); println();
File
概念
文件或文件夹对应的类使用
1,创建File类的对象 2,对调用属性或方法创建File对象
公共构造函数: File(String pathname) pathname:文件或文件夹的路径 File(String parent, String child) parent:上级文件夹的路径 child:当前文件的名称.后缀名 如 D:\2304班授课\day20\笔记\day20.md D:\2304班授课\day20\笔记 parent day20.md child File(File parent, String child) parent:上级文件夹的file对象 child:当前文件的名称.后缀名 File(URI uri) uri:资源所在位置 如: URI uri = URI.create("D:\\a.txt"); File file = new File(uri); 注意: 路径分为相对路径与绝对路径 绝对路径: 从盘符开始书写 如:D:\\a.txt 相对路径 相对于项目路径下 注意: .:当前路径 ..:上级文件夹属性
public static separator:获取当前系统的路径分割符方法
mkdir():创建一级文件夹 mkdirs():创建多级文件夹 createNewFile():创建一级文件 delete():删除一级文件或一级文件夹 getParent():获取上级文件夹路径 getParentFile():获取上级文件夹的file对象 getPath():获取当前路径 getAbsolutePath():获取当前文件的绝对路径 getAbsoluteFile():获取绝对路径的文件 isDirectory():判断是否为文件夹 isFile():判断是否为文件 exists():判断文件或文件夹是否存在 length():获取文件大小,单位字节 renameTo():修改文件名称 File[] listFiles(); File[] listFiles(FileFilter ff); File[] listFiles(FilenameFilter ff); 获取当前文件夹下的文件或文件夹 注意: FileFilter是文件过滤器 重写的是boolean accept(File pathname) 当返回值为true表示可以通过,反之false不通过 FilenameFilter是文件名称过滤器 重写的是boolean accept(File f,String name) 当返回值为true表示可以通过,反之false不通过 f:父级文件对象 name:当前文件的名称
网络
简介
网络 计算机网络什么是网络?
概念:由点和线构成,表示多个对象之间互相联系 计算机网络: 互联网:Interner 万维网:WWW(World Wide Web) 物联网:Iot(Interner of things) 网络模型(了解): OSI参考模型: 应用层:如http协议,SMTP协议(邮件)... 表示层:将数据格式进行传话与加密. 会话层:维持通讯 传输层:如恢复通讯,数据流重用等事情.UDP,TCP 网络层:ip,计算机在互联网的地址 数据链路层:对其数据进行格式化的要求 物理层:硬件设备,如网线,网线接口等 因为OSI过于理想化,所有没有被实现 TCP/IP模型 应用层 对应OSI模型的应用层,表示层,会话层 对应的协议:HTTP,SMTP,HTTPS 传输层 对应OSI模型的传输层 对应的协议:TCP,UDP协议 网络层 对应OSI模型的网络层 对应的协议:IP 网络接口层 对应OSI模型的数据链路层与物理层 对应协议:以太网协议,ADSL协议等网络编程需要什么?
IP 端口号 通讯协议常用名词
互联网(Internet): 点与点相连 万维网(www-world wide web): 端与端相连 物联网(IoT-Internet of things): 物与物相连 网络编程: 让计算机与计算机之间建立连接,进行通讯
OSI网络架构
简介: Open System Interconnect 开放式系统互连 存在于概念和理论上的一种模型,它的缺点是分层太多,增加了网络工作的复杂性,所 以没有大规模应用第一层:物理层为设备之间的数据通信提供传输信号和物理介质。(双绞线、 光导纤维) 作用:建立、维护、断开物理连接。 第二层:链路层在物理层上,通过规程或协议(差错控制)来控制传输数据的正确性。(MAC) 作用:接收来自物理层的位流形式的数据,并封装成帧,传送到上一层;同样,也将来自 上层的数据帧,拆装为位流形式的数据转发到物理层;并且,还负责处理接收端发回的确认 帧的信息,以便提供可靠的数据传输。 第三层:网络层负责定义了能够标识所有网络节点的逻辑地址。(IP地址) 作用:逻辑寻址,IP地址,在下两层的基础上向资源子网提供服务 第四层: 传输层负责是否选择差错恢复协议、数据流重用、错误顺序重排。(TCP、 UDP) 作用:提供可靠和不可靠的传输机制,TCP、UDP 第五层:会话层负责使应用建立和维持会话,使通信在失效时继续恢复通信。(断点续传). 作用:建立、终止、管理实体间的会话连接 第六层:表示层负责定义转换数据格式及加密,允许选择以二进制或ASCII格式传输。 作用:封装数据的格式(加密解密、压缩解压缩) 第七层:应用层负责文件访问和管理、可靠运输服务、远程操作服务。(HTTP、 FTP、SMTP) 作用:人与机器电脑交互的窗口
TCP/IP网络框架
TCP协议: Transmission Control Protocol传输控制协议 是一种面向连接的、可靠的、基于字节流的传输层通信协议。数据大小无限制。建立连 接的过程需要三次握手,断开连接的过程需要四次挥手。 UDP协议: User Datagram Protocol用户数据报协议 是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,每个包的大小 64KB。
IP
概念(重点):计算机在互联网中的地址 IPV4 4个字节,每个字节由8位组成.所以每段的值0~255 0000 0000 ~ 1111 1111 192.168.7.151 IPV6 16个字节,每个字节8位组成,每段32位,所以每段取值范围0~65535 查看当前计算机IP: 步骤: 1,打开dos命令框 2,输入ipconfig IP地址的分类: A类地址:大型网络,主要服务与国家与政府企业 B类地址:中型网络,主要服务与大型实验室等 C类地址:个人网络,咱们普通人与普通企业用的网络 特殊IP:(重点) 127.0.0.1表示本机 因为不好记,所以变为了英文localhost 专业名称:回路地址 相关命令: ipconfig 作用:查看当前计算机的ip信息 ping 作用:尝试连接对方 InetAddress类: 作用:表示计算机在网络中的地址 常用方法: 见Day23com.qf.ip的Test类简介: Internet Protocol Address 互联网协议地址/网际协议地址 分配给互联网设备的数字标签(唯标识)。说人话就是计算机在互联网中的地址 IP地址分为两种: IPV4: 4字节32位整数,并分成4段8位的进制数,每8位之间用圆点隔开,每8位整数可 以转换为一个0~255的十进制整数。 格式: D.D.D.D 例如: 255.255.255.255 如:10.35.162.64 IPV6: 16字节128位整数,并分成8段十六进制数,每16位之间用圆点隔开,每16位整 数可以转换为一个0~65535的十进制数。 格式: X.X.X.X.X.X.X.X 例如: FFFF.FFFF.FFFF.FFFF.FFFF.FFFF.FFFF.FFFF IPV4应用分类 A类:政府机构,1.0.0.1 ~ 126.255.255.254 B类:中型企业,128.0.0.1 ~ 191.255.255.254 C类:个人用户,192.0.0.1 ~ 223.255.255.254 D类:用于组播,224.0.0.1 ~ 239.255.255.254 E类:用于实验,240.0.0.1 ~ 255.255.255.254 回环地址: 127.0.0.1(localhost),指本机,一般用于测试使用。 查看IP命令: ipconfig 测试IP命令: ping D.D.D.D 对应类:InetAddress 常用方法: public static InetAddress getLocalHost():获取本机地址 如: InetAddress localHost = InetAddress.getLocalHost(); System.out.println(localHost); 打印结果: LAPTOP-RE2FI941/192.168.0.105 public static InetAddress getByName(String host):通过主机名词获取地 址 如: InetAddress inetAddress = InetAddress.getByName("LAPTOPRE2FI941"); System.out.println(inetAddress); 打印结果: LAPTOP-RE2FI941/192.168.0.105 注意: 127.0.0.1,Localhost,域名都表示本机 public static InetAddress[] getAllByName(String host):获取所有相关地 址对象 如: InetAddress[] addresses = InetAddress.getAllByName("www.baidu.com"); for (InetAddress address : addresses) { System.out.println(address.getHostAddress()+"-- "+address.getHostName()); } 输出结果: 14.215.177.39--www.baidu.com 14.215.177.38--www.baidu.com public String getHostAddress():获取主机地址 public String getHostName():获取主机名词
Port:端口
端口号:在通信实体上进行网络通讯的程序的唯一-标识。端口分类: 公认端口: 0~1023 注册端口: 1024~49151 动态或私有端口: 49152~65535 常用端口: MySql: 3306 Oracle: 1521 Tomcat: 8080 SMTP: 25 Web服务器: 80 FTP服务器: 21概念:程序在计算机中的地址 范围:0~65535 注意: 0~1023:一般被系统占用 1024~49151:注册端口 49151~65535:动态端口 常见的端口: mysql端口号:3306 Tomcat端口号:8080 http协议端口号:80 Oracle端口号:1521 redis端口号:6379
通讯协议
TCP 中文名:传输控制协议 特点:面向连接,安全可靠,效率低,基于字节流进行通讯的,传输数据大小无限制 三次握手,四次挥手 第一次握手第一次挥手:客户端向服务器发起请求 第二次握手第二次挥手:判断是否连接成功 第三次握手第三次挥手:客户端上传数据或服务器反馈数据 第四次挥手:客户端断开连接 俗称:打电话 如:去朋友家做客 1,打电话,询问是否方便 对方接听电话(一次握手),打完电话后会挂断电话(一次挥手) 2,去朋友家,敲门 开门(一次握手),朋友倒茶(一次挥手) 3,开始聚会 聊天(一次握手,一次挥手) 4,说拜拜 一次挥手 Java中对应的类: Socket:客户端 ServerSocket:服务器 UDP 中文名:数据包协议 特点:面向无连接,不安全,效率高,基于数据包格式进行传输,一个数据包最多64kb 俗称:对讲机 如:用对讲机通知同事有小偷 1,直接对着对讲机说有小偷
基于TCP协议的通讯
技术 服务器 创建ServerSocket 等待客户端连接 关闭资源 客户端 创建客户端Socket 关闭资源 案例1: 客户端给服务器发一条消息 案例2: 客户端给服务器发送一条消息,服务器接收后回复一条消息,客户端接收 案例3: 客户端上传文件给服务器
基于UDP协议的通讯
技术: 接收端 DatagramSocket(端口号) 接收端对象.receive(数据包):接收数据 发送端 DatagramSocket() 发送端对象.send(数据包):用于发送数据包 数据包 DatagramPacket
Socket编程
简介
Socket:套接字,网络中的一个节点 通讯要求:IP地址+端口号TCP与UDP的区别
TCP:面向有连接,安全,可靠的,慢 特点:三次握手,四次挥手 UDP:面向无连接,不安全的,快 特点:面向无连接,不安全,效率高,基于数据包格式进行传输,一个数据包最多64kb
TCP
简介:是一种面向连接的、可靠的、基于字节流的传输层通信协议。数据大小无限制。建立连 接的过程需要三次握手,断开连接的过程需要四次挥手。 注意:分为客户端Scoket与服务器ServerSocket 开发步骤: 服务端:ServerSocket 1,创建ServerSocket,指定端口 2,调用accept等待客户端接入 3,使用输入流,接收客户端请求中的数据 4,使用输出流,给客户端回馈数据(可选) 5,关闭释放资源 客户端:Socket 1,创建Socket对象,指定服务器IP+端口 2,使用输出流,发起请求,给服务器发生数据 3,使用输入流,接收服务器返回的数据(可选) 4,关闭释放资源代码: 服务器: import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; public class TcpServer { public static void main(String[] args) throws Exception{ //1 创建ServerSocket 并指定端口号 ServerSocket listener=new ServerSocket(8899); //2 调用accept(),接收客户端请求,阻塞方法(如果没有客户端请求, 则阻塞) System.out.println("服务器已启动..."); Socket socket=listener.accept(); //3 获取输入流,读取客户端发送的数据 InputStream is=socket.getInputStream(); BufferedReader br=new BufferedReader(new InputStreamReader(is,"utf-8")); String data=br.readLine(); System.out.println("客户发送:"+data); //4 获取输出流,发送数据给客户端[可选] //5 关闭释放资源 br.close(); socket.close(); listener.close(); } } 客户端: import java.io.BufferedWriter; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Socket; public class TcpClient { public static void main(String[] args) throws Exception{ //1 创建客户端套接字,并指定服务器的地址和端口号 Socket socket=new Socket("192.168.0.103", 8899); //2 获取输出流,发送数据给服务器 OutputStream os=socket.getOutputStream(); BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(os,"utf-8")); bw.write("好久不见"); //3 获取输入流,读取服务器回复的数据[可选] //4 关闭释放资源 bw.close(); socket.close(); } }文件上传
练习:文件上传 服务器: import java.io.FileOutputStream; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; public class TcpFileServer { public static void main(String[] args) throws Exception { //1创建ServerSocket ServerSocket listener=new ServerSocket(9999); //2侦听,接收客户端请求 System.out.println("服务器已启动........."); Socket socket=listener.accept(); //3获取输入流 InputStream is=socket.getInputStream(); //4边读取,边保存 FileOutputStream fos=new FileOutputStream("d:\\002.jpg"); byte[] buf=new byte[1024*4]; int count=0; while((count=is.read(buf))!=-1) { fos.write(buf,0,count); } //5关闭 fos.close(); is.close(); socket.close(); listener.close(); System.out.println("接收完毕"); } } 客户端: import java.io.FileInputStream; import java.io.OutputStream; import java.net.Socket; public class TcpFileClient { public static void main(String[] args) throws Exception { //1创建Socket Socket socket=new Socket("192.168.0.103", 9999); //2获取输出流 OutputStream os=socket.getOutputStream(); //3边读取文件,边发送 FileInputStream fis=new FileInputStream("d:\\001.jpg"); byte[] buf=new byte[1024*4]; int count=0; while((count=fis.read(buf))!=-1) { os.write(buf,0,count); } //4关闭 fis.close(); os.close(); socket.close(); System.out.println("发送完毕"); } }服务器与客户端一句句循环对话
练习:服务器与客户端一句句循环对话 服务器: import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; public class TcpServer { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务器已启动"); Socket accept = serverSocket.accept(); System.out.println(accept.getInetAddress()+"来了"); InputStream is = accept.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8")); OutputStream os = accept.getOutputStream(); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os)); Scanner scanner = new Scanner(System.in); while(true) { String str = br.readLine(); System.out.println(accept.getLocalAddress()+"说:"+str); if (str != null && str.equals("886")) { break; } System.out.println("请输入您要回复的内容:"); String str02 = scanner.next(); bw.write(str02); bw.newLine(); bw.flush(); } scanner.close(); bw.close(); br.close(); accept.close(); serverSocket.close(); } UDP(了解) } 客户端: import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.Socket; import java.util.Scanner; public class TcpClient { public static void main(String[] args) throws IOException { Socket socket = new Socket("192.168.0.105", 9999); InputStream is = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8")); OutputStream os = socket.getOutputStream(); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os)); Scanner scanner = new Scanner(System.in); while(true) { System.out.println("请输入您要说的内容:"); String str02 = scanner.next(); bw.write(str02); bw.newLine(); bw.flush(); if (str02 != null && str02.equals("886")) { break; } String str = br.readLine(); System.out.println(socket.getLocalAddress()+"说:"+str); } scanner.close(); bw.close(); br.close(); socket.close(); } }多人聊天
import java.net.*; import java.io.*; public class TCPServer { private static final int PORT = 12345; private ServerSocket serverSocket; public TCPServer() throws IOException { serverSocket = new ServerSocket(PORT); System.out.println("Server started. Listening to port " + PORT + " ..."); start(); } private void start() throws IOException { while (true) { Socket clientSocket = serverSocket.accept(); System.out.println("Client connected: " + clientSocket); ClientHandler clientHandler = new ClientHandler(clientSocket); clientHandler.start(); } } public static void main(String[] args) throws IOException { new TCPServer(); } } class ClientHandler extends Thread { private Socket clientSocket; private PrintWriter out; public ClientHandler(Socket socket) { this.clientSocket = socket; } public void run() { try { BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); out = new PrintWriter(clientSocket.getOutputStream(), true); String inputLine; while ((inputLine = in.readLine()) != null) { if (inputLine.equals("exit")) { break; } System.out.println("Message received: " + inputLine); out.println("Echo: " + inputLine); } in.close(); out.close(); clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } import java.net.*; import java.io.*; import java.util.Scanner; public class TCPClient { private static final int PORT = 12345; private static final String SERVER_HOST = "localhost"; public static void main(String[] args) throws IOException { Socket socket = new Socket(SERVER_HOST, PORT); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); Scanner scanner = new Scanner(System.in); String inputLine; while ((inputLine = scanner.nextLine()) != null) { out.println(inputLine); String responseLine = in.readLine(); System.out.println(responseLine); if ("exit".equals(inputLine)) { break; } } out.close(); in.close(); socket.close(); } }
UDP
简介:UDP协议是一种不可靠的网络协议,提供面向事务的简单不可靠信息传送服务,每个包的 大小64KB。 注意:分为接收端与发送端 开发步骤: 发送端: 1.创建发送端的Socket对象(DatagramSocket) 2.创建数据,并打包 3.调用DatagramSocket对象的方法发送数据 4.关闭发送端 接收端: 1、创建接收端的Socket对象(DatagramSocket) 2、创建一个数据包,用于接收数据 3、调用DatagramSocket对象的方法接收数据 4、解析数据包,并在控制台显示 5、关闭接收端代码
代码: 发送端: import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UdpSend { public static void main(String[] args) throws IOException { //1,创建发送端Socket对象 DatagramSocket socket = new DatagramSocket(); //2,准备发送内容 byte[] sendData = "要发送的内容".getBytes(); //3,接收端地址 InetAddress address = InetAddress.getByName("192.168.0.105"); //4,封装发送信息包 DatagramPacket packet = new DatagramPacket(sendData, sendData.length, address, 9999); //5,发送信息 socket.send(packet); //6,关闭发送端 socket.close(); } } 接收端: import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; public class UdpGet { public static void main(String[] args) throws IOException { //1,创建接收端Socket DatagramSocket socket = new DatagramSocket(9999); //2,创建接收数据的包 byte[] b = new byte[1024]; DatagramPacket packet = new DatagramPacket(b, b.length); //3,等待接收数据 socket.receive(packet); //4,获取数据 byte[] data = packet.getData(); //5,获取数据长度 int length = packet.getLength(); //6,打印输出 System.out.println("接收的内容:"+new String(data,0,length)); //7,关闭资源 socket.close(); } }
反射
类对象
一个类被加载时会生成一个对象,该对象称为该类的类对象 该对象属于Class类的对象 类对象中包含该类的所有信息,如包,父类,实现的接口,类名,属性,方法,构造函数,注解等内容 注意: 一个类只有一个类对象如何获取类对象
方式1:类名.class 方式2:对象名.getClass() 方式3:Class.forName("类的全路径") 类的全路径:类所属的包名+类名类对象提供的方法
类相关: 包 Package getPackage() 类名 String getSimpleName() 类的全路径 String getName() 父类的类对象 Class<? super T> getSuperclass() 接口的类对象 Class<?>[] getInterfaces() 属性相关 获取所有的公共属性,包含父类提供的 Field[] getFields() 获取所有的属性,不包含父类提供的 Field[] getDeclaredFields() 获取指定的公共属性 Field getField(String name) 获取指定的属性 Field getDeclaredField(String name) Field提供的方法 Object get(Object obj); 作用:获取指定对象的该属性值 1参:指定的对象 void set(Object obj,Object v); 作用:修改指定对象的该属性值 1参:指定的对象 2参:修改后的值 setAccessible(boolean flag):是否略过访问权限修饰符 默认为false,表示不略过 当值为true表示略过 方法相关 获取所有的公共方法,包含父类提供的 Method[] getMethods() 获取所有的方法,不包含父类提供的 Method[] getDeclaredMethods() 获取单独一个公共的方法 Method getMethod(String name, Class<?>... parameterTypes) 1参:要获取的方法名 2参~:该方法的形参列表对应的数据类型的类对象 注意:按顺序书写,基本数据类型的类对象是数据类型.class,其包装类的类对象是类名.class 获取单独一个方法 Method getDeclaredMethod(String name, Class<?>... parameterTypes) 1参:要获取的方法名 2参~:该方法的形参列表对应的数据类型的类对象 注意:按顺序书写,基本数据类型的类对象是数据类型.class,其包装类的类对象是类名.class Method提供的方法: Object invoke(Object obj, Object... args) 作用:执行该方法 1参:执行该方法的对象 2参~:执行该该方法所需的实参列表 返回值:执行该方法的返回值 setAccessible(boolean flag):是否略过访问权限修饰符 默认为false,表示不略过 当值为true表示略过 构造函数相关 Constructor<?>[] getConstructors() 作用:获取该类中所有公共构造函数 Constructor<?>[] getDeclaredConstructors() 作用:获取所有构造函数 Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 作用:获取指定的一个构造函数 参数: 构造函数对比的形参列表的数据类型的类对象 Constructor提供的方法 T newInstance(Object ... initargs) 作用:创建该类对象 参数:对应的构造函数的实参列表 setAccessible(boolean flag):是否略过访问权限修饰符 默认为false,表示不略过 当值为true表示略过
枚举
使用步骤
1,定义 2,使用定义
语法: 访问权限修饰符 enum 枚举名{ 属性名1,属性名2,属性名3,...属性名n }使用
情况1:使用枚举的属性 语法: 枚举名.属性名 情况2:枚举作为形参 传递实参时必须传入枚举的属性
注解
作用
解释代码的代码,称为注解,又名元代码注释与注解的区别
注释:不会影响代码 注解:对代码有一定的约束作用常见的注解
@Override 作用:说明当前方法为重写的方法 @SuppressWarnings("all") 作用:忽略警告 元注解 概念:解释注解的注解 @Target 作用:注解使用位置 值: TYPE:类,接口,枚举上使用 FIELD:属性上使用 METHOD:方法使用 PARAMETER:参数上使用 CONSTRUCTOR:构造函数 LOCAL_VARIABLE:局部变量使用 ANNOTATION_TYPE:注解使用 PACKAGE:包使用 注意:没有写可以在任何地方使用 @Retention 作用:注解作用时机 值: SOURCE:java源程序中存在 CLASS:字节码文件中存在 RUNTIME:运行时存在 @Documented 作用:可以生成API文档 @Inherited 作用:说明当前注解是否可以被子类继承,默认不能被子类继承自定义注解
语法: 访问权限修饰符 @interface 注解名{ 数据类型 属性名1() [default 默认值]; 数据类型 属性名2() [default 默认值]; ... }注解的使用
@注解名(属性名 = 属性值,属性名 = 属性值,...); 注意: 1,当注解中的属性有默认值,可以在使用注解时不用赋值 2,当注解中所有属性都有默认值或没有属性时,可以省略小括号不写 @注解名 3,当注解中只有一个属性,并且该属性的属性名为value,此时在使用注解时可以省略属性名不写 @注解名(属性值)
设计模式
概念
程序员总结出的解决特定问题的思路
单例模式
特定问题
一个类只能有一个对象分类
懒汉式 步骤: 1,私有化构造函数 2,提供一个公共的属性,记录该类的唯一对象 3,提供一个公共的静态方法返回该类创建好的对象 优点: 节省内存 缺点: 有线程安全问题 饿汉式 步骤: 1,私有化构造函数 2,提供一个公共的属性,记录该类的唯一对象,并创建该对象 3,提供一个公共的静态方法返回该类创建好的对象 优点: 不存在线程安全问题 缺点: 浪费内存 线程安全的懒汉式 代码: public class C { private static C c; private C(){ } public synchronized C getInstance(){ if (c == null){ c = new C(); } return c; } } 优点: 线程安全 缺点: 效率慢 内部类饿汉式 代码: public class D { private D(){ } public static D getInstance(){ return InClass.getD(); } static class InClass{ private static D d = new D(); public static D getD(){ return d; } } }
工厂模式
特定问题
特定编号生产特定商品例子
家具厂 沙发 椅子 床 衣柜 茶几 ... 分析: 类 家具厂类 家具接口对象 生产的方法(编号){ switch(编号){ case 1: } } 家具接口 沙发类 实现 家具接口 椅子类 实现 家具接口 床类 实现 家具接口 衣柜类 实现 家具接口 茶几类 实现 家具接口