Java 小总结

一、 Java 概

1、Java

Java是sun在1995年推出的,前身是OAK,Java之父詹姆斯·高斯林(James Gosling)、2009被甲骨文收购——->:https://www.oracle.com

2、Java跨平台原理

  • Java程序运行在jvm(Java虚拟机)上,Java编译器将Java源程序编译成字节码文件(class文件),然后由jvm对字节码文件解释执行,所以在不同的操作系统上,只需安装不同的java虚拟机即可实现跨平台
  • 平台:操作系统
  • 跨平台:就是idea可以在不同的操作系统程序上运行,只需这些系统安装相应版本的jvm即可

3、JRE 和 JDK

  • JVM:Java虚拟机
  • JRE:java运行环境,包括了JVM和Java的核心类库(API)
  • JDK:Java开发工具,包含了JRE和开发工具

4、关键字

  • 有特殊作用
  • 字母全部小写
  • 一般都会高亮显示
关键字:
4.1 访问控制修饰符----关键字

所有类成员的默认访问范围都是 package 访问

到达 44 中访问修饰符 详解

  • private 私有的:访问控制修饰符,在类的外部或者对于子类而言,它们是不可见的。
  • protected 受保护的:自身、子类及同一个包中的类可以访问
  • public 公共的:可以被所有类访问
4.2 类、方法和变量修饰符

抽象-----重写 接口------实现

  • class类:来声明新的Java类

  • extendes: 继承、扩展:是用在 class、interface 声明中,是表示后面的是前面的子类。只能继承一个,单继承。

  • final 最终、不可改变:final可以应用于类、方法、变量,final不能于abstract在一起,abstract 意味:抽象类扩展类(增加子类),abstract必须重写抽象方法,但是final 定义的是最终的类、方法不可改变

    到达 45、 final 关键字,详解

  • abstract 声明抽象:定义为抽象类、方法,方法不在声明的类中实现,而在其子类中重写

    • 如果abstract类的子类没有实现其超类的所有abstract方法,该子类也是abstract类。
    • abstract关键字不能应用于static、private或final方法,因为这些方法不能被重写,因此,不能在子类中实现。
    • final类的方法都不能是abstract,因为final类不能有子类
  • interface 接口:实现Java的接口,接口是方法的集合,任何类都可声明并实现一个或多个接口,实现接口也就是实现了接口中所定义的方法,实现了接口的任何类都必须提供在该接口中的所有方法的实现。

  • implements 实现:在class声明中使用,指定所class声明的类要 implements(实现) 接口类

  • native 本地:关键字可以应用于方法,以指示该方法是用 Java 以外的语言实现的。

  • new 创建:用于创建类的实例。

  • static静态

    46、 static 关键字

    • 方便与在没有创建对象的情况下进行调用(方法/变量),不需要对象就能使用/访问
    • this 和 static 关键字不能同时出现在一个类中,this关键字是对 对象引用
    • 修饰成员变量,成员方法、代码块等,即被 饰的成员属于类(类变量、类方法),可以直接调用。
    • static 字段(类的成员变量)在类的所有实例中只存在一次。
    1. static 方法
    • static 方法一般称为静态方法,不需要对象就能调用所以一般是没有this的,并且因为这个特性-------->**在静态方法中不能访问类的非静态成员变量和非静态成员方法,**因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。 但是:非静态方法/变量都可以调用静态方法/变量
    • 如果说想在不创建对象的情况下调用某个方法,就可以将这个方法设置为static。
    • 我们最常见的static方法就是main方法,**为什么main方法必须是static的,因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。 **
    • 静态方法中不能使用 this、super 关键字(因为 this 和 super 都是表示的是一个对 象,而 static 修饰的属于类
    1. static 变量
    • static 修饰的变量称为静态变量,静态变量被所有的对象使用,在内存中只有一个副本,只会在类初次加载时,才会初始化。非静态变量:是对象所拥有,在创建对象时初始化,有多个副本,但副本之间互相不影响
    • 初始化顺序就是定义的顺序
    1. static 代码块
    • static代码块可以置于**类中的任何地方,**一个类可以有多个static代码块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次优先于执行 static 代码块,即使static代码块在main() 之后。
    • static 特性:只会在类加载的时候执行一次。所以可以用来优化性能。
    • 很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。 如:赋值初始化
    1. static
    • static是不允许用来修饰局部变量

    局部变量:

    • 函数内部的变量称为局部变量(Local Variable),它的作用域仅限于函数内部, 离开该函数后就是无效的,再使用就会报错。
  • **strictfp 严格、精准:**精确浮点

  • synchronized 线程同步:

    • 可应用于方法或者语句块,一次给一个线程执行的关键代码段执行保护
    • 线程安全、同步:防止关键代码段一次被多个线程执行
    • 如果应用于静态方法、实例方法、对象或者数组:该方法一次由一个类执行,整个类、实例、对象或数组将被锁定
  • volatile 易失:**用于表示可以被多个线程异步修改的成员变量

程序控制语句
  • break 跳出、中断:用于提前退出 for、while、do循环,或在 switch 语句结束 case 块,退出的是总的本次循环,即使还有条件没执行,也会退出这个循环,继续执行循环外的语句。

  • continue 继续:用来暂停本次小的循环,即本次小循环的结果并不会输出,会继续执行总循环的其它条件,总循环的所有条件都执行完毕后,才会退出本次循环,但continue的条件结果,并不会输出

  • return 返回:会使方法返回到调用它的方法,从而传递与返回方法的返回类型匹配的值,返回值两侧的括号使可选的 void代表的使无返回值类型。

  • **if 如果:**if表示有条件的执行语句,if里面的条件结果必须是布尔类型的,if语句可以有可选的else子句,也可没有,包含 boolean 操作数的表达式只能包含 boolean 操作数。

  • else 否则:在于和if 结合使用,组成 if…else…

    • if…else… : if 的执行结果为false时运行else的
  • switch 观察(循环):switch…case…

    • switch 语句中变量必须是:byte、short、int 、char、String、enum
    • 一个switch可以拥有多个case,每一个case后面跟一个要比较的值和冒号
    • 遇上break;时语句停止,如果没有则会继续执行下一条case语句
  • **case 返回观察里的结果:**case 用来标记switch语句中的默认分支,case没有隐式结束点,如句末没有break; 执行流将进入所有后面的case/default 块里

  • default 默认:用来标记switch语句中的默认分支,没有隐式结束点(在最后最好加一个break;),一般在末尾,方便完成时退出switch语句 如果没有default语句,其参数与任何case块都不匹配时,switch语句则不起操作

  • while 循环:只要判断条件(while括号里)是正确,就会执行。

  • do while循环:do里面放执行语句(do{} )while里放判断条件(while()); 无论判断条件是否正确,do里面的语句都会执行一遍

  • for循环:在进入for语句时,将执行一次赋值语句,每次执行循环体之前都将计算判断条件的结果,如果时true则执行循环体,在进入循环体之后,在计算下一个迭代的判断条件时,先执行自加或自减 语句

  • instanceof 实例 :确定对象所属的类

错误(异常)处理
  • try 捕获异常:try 关键字包含可能引发异常的语句块,每一个 try块都至少有一个 catch或finally 子句
    • 每一个 try块 都必须至少有一个 catch或finally子句
    • 如果某个特定异常类未被任何 catch 子句处理,该异常将沿着调用栈递归地传播到下一个封闭 try 块。如果任何封闭 try 块都未捕获到异常,Java 解释器将退出,并显示错误消息和堆栈跟踪信息
  • catch 处理异常:catch关键字用来在 try–catch 或 try–catch–finally 语句中定义异常处理块
    • 开始和结束的 { } 也是catch子句的一部分
  • throw 抛出一个异常对象: throw用于引发异常,throw是语句抛出一个异常,一般在代码块的内部,throw 出现在函数体,执行throw抛出了异常,执行throw 一定是抛出了某种异常对象
  • throws 声明一个异常可能被抛出:throws 关键字可以应用于方法,指出方法引发了特定类型的异常
包相关
  • import 引入:import 关键字使一个包中的一个或所有类在当前 Java 源文件中可见。可以不使用完全限定的类名来引用导入的类。

  • package 包:package 关键字指定在 Java 源文件中声明的类所驻留的 Java 包 。

    ​ package 语句(如果出现)必须是 Java 源文件中的第一个非注释性文本 。

基本类型
  • boolean 布尔类型:是Java的原始类型,值为:true、false,不能进行类型转换,包含boolean类型的表达式只能含有boolean 类型。
  • byte 字节类型:是Java的原始类型,存储范围在[-128,127]范围内。
  • short 短整型:原始类型,short可存储16位带符号的整数,占用2个内存
  • int 整型:原始,可存储32位整数值。
  • long 长整型:原始,存储64位带符号整数,一般定义long类型,在值后面添加 L/l
  • float 浮点:原始,存储单精度浮点数,定义float类型,在值后面添加 F/f
  • double 双精度:原始,存储双精度
    • 由于浮点数据是实际数据的近似值,所以一般不进行是否相等的比较
  • char 字符型:原始,存储一个 Unicode 的字符,char值没有符号,可以与int类型进行强转得到符号的阿斯克码值和阿斯克码值的符合
  • null 空:null是Java的保留字,表示无值,将null赋值给非原始变量(基本数据类型八种)相当于释放变量先前所引用的对象 不能将null赋值给基本数据类型
  • true 真:boolean值得一个
  • false 假:boolean值得一个
变量引用
  • super 父类、超类、基类:只能出现在继承关系的子类中 作用:对当前类父类的对象的引用
    • 第一种用法: super.属性名、super.方法名(参数列表)
    • 第二周用法:super(参数列表) 的形式出现在子类构造方法的第一句代码时,就明确指明了通过参数列表来匹配父类的构造方法,来创建父类对象
  • this 本类:this关键字 只能用在没有被【static关键字】修饰的方法中
    • 作用:表示对当前对象的引用
    • 第一种用法:区分成员、局部变量
    • 第二种用法:以this(参数列表)的形似出现在第一句代码是,代表应用其它类中的构造方法
  • void 无返回值:表示null类型,用作方法中,代表该方法无返回值
保留字
  • 保留字是为java预留的关键字
  • goto 跳转:保留关键字,java不允许goto跳转
  • const 静态:类型修饰符,声明的对象不能更新
  • native 本地:Java无法直接访问到操作系统底层(如系统硬件等),为此Java使用native方法来扩展Java程序的功能。

5、常量

  • 常量:在程序运行的过程中,其值不可以发生改变的
  • 空常量外,其它常量均可使用输出语句直接输出
  • ----->例: System.out.println(10)

6、数据类型

  • 计算机存储最小的单元信息是“位(bit)”,比特位用“b”表示。
  • 计算机最基本的存储单元是字节(byte),通常用“B”表示,字节是连续8个位组成
  • Java数据类型分 基本数据类型、引用数据类型

7、变量

  • 在程序运行的过程中,其值是可以发生变化的
  • 从本质上讲,变量是内存中的一小块区域,其值可以在一定范围内变化。
  • 定义格式: 数据类型 变量名 = 初始化值
注意事项:
  • 变量名不能重复
  • 必须要初始化
  • long类型后面加 L/l,整型默认为int
  • float类型后面加 F/f,浮点型默认为double

8、标识符

  • 标识符是编程时使用的名字,用于给类、方法、变量、常量等命名
标识符规则:
  • 由字母、下划线、数字、美元符号组成,第一个字符不能是数字。
  • 不能使用Java的关键字
  • 区分大小写、长度无限制
  • 最好见明知意

9、类型转换

1、自动类型转换:
  • 数据范围小的------>数据范围大的
    • double dou01 = 10; System.out.print(dou01) //10.0
2、强制转换类型:
  • 数据范围大的----->数据范围小的 需要强转
    • 强转格式: 目标数据类型 变量名 = (目标数据类型)值或者变量
    • long lo01 = (long)23.8F; System.out.print(lo01) //23
3、转换注意:
  • 数据范围从小到大:

    ​ byte —> short/char —> int —> long —> float —> double

  • char 转 int类型是按照阿斯克码值表的转换

  • 整数默认是 int 类型,byte、short、char 类型参与运算会自动转换成int类型

  • boolean类型不能与其他基本数据类型相互转换。

10、算术运算符

1、运算符:
  • 对常量或者变量进行操作的符号
  • +、-、*、/、%
2、表达式:
  • 用运算符将常量和变量连接起来符合Java语法的式子,表达式的结果就是表达式的数据类型

  • / 和 % 的区别:两个数据做除法,/取结果的商,%取结果的余数。

  • 整数操作只能得到整数,要想得到小数,必须有浮点数参与运算

  • “+” :连接符、相加

3、基本阿斯克码值:
  • ’a’ – 97 a-z是连续的,所以’b’对应的数值是98,'c’是99,依次递加
  • ’A’ – 65 A-Z是连续的,所以’B’对应的数值是66,'C’是67,依次递加
  • ’0’ – 48 0-9是连续的,所以’1’对应的数值是49,'2’是50,依次递加
4、 ++ – 运算符:
  • ++ 和 – 单独使用的时候,无论放在前还是后,结果都是一样的
  • ++/-- 自增/自减:放在变量的前面先+/-1在操作(输出)
  • ++/-- 自增/自减:放在变量的后面,**先操作(输出)**在+/-1

11、算术表达式

  • 一般含有算术运算符的式子都是算术表达式

  • 算术表达式中包含不同的基本数据类型的值的时候,整个算术表达式的类型会自动进行提升。

提升规则:
  • byte类型,short类型和char类型将被提升到int类型,不管是否有其他类型参与运算。
  • 整个表达式的类型自动提升到与表达式中最高等级的操作数相同的类型
  • 等级顺序:byte,short,char --> int --> long --> float --> double

12、关系运算符

  • 关系运算符有6种关系,分别为小于、小于等于、大于、等于、大于等于、不等于。
  • 关系运算符的结果都是boolean类型,要么是true,要么是false。
  • == 是判断是否相等,判断地址

13、 逻辑运算符

  • 判断结果是 true/false
  • &、|、^ 、!
  • a^b,a和b结果不同为true相同为false
短路逻辑运算符,规律
  • &&、||
  • 相比较于关系运算符:提高了效率、节约了时间
  • 逻辑与& : 无论左边真假,右边都要执行
  • 短路与&& :如果左边为假,右边不执行(左边为真,右边也要执行)
  • 逻辑 | : 无论左边真假,右边都要执行
  • 短路逻辑或 ||:如果左边为真,右边不执行(左边为假,右边执行)

14、 三元运算符

  • 格式:
    • 关系表达式 ? 结果正确执行的语句 :结果错误执行的语句
    • 关系表达式是判断条件,判断结果为boolean类型

15、Scanner数据输入

  • java.util 包下的 Scanner类
  • 使用步骤:
    • 需要 导包 import java.util.Scanner;
    • 创建Scanner 对象 Scanner sc(自定义的变量名)= new Scanner(System.in);
    • 接受数据 数据类型 变量名 = sc.next数据类型();next数据类型---->数据类型首字母大写

16、流程控制语句

4、关键字 —> 程序控制语句 中也有介绍

流程控制语句分为:
1、顺序结构
  • 按照先后顺序进行执行(程序中最简基本的流程控制语句)
2、分支结构(if,swich)
  • if(关系表达式1){ 语句体1; }

  • if(关系表达式1){ 语句体1;}else{ 语句体2; }

  • if(关系表达式1){ 语句体1;}else if(关系表达式2){ 语句体2; }…else{ 语句体; }

  • switch(表达式){ case 值1:语句体1;break; case 值2:语句体2;break;

    … default: 语句体; break; } // 表达式的值只能是:byte\char\short\int\enum\String,case的值为数字、char类型。

3、循环结构(for,while,do…while)
  • for(初始化语句;条件表达式;条件控制语句){ 循环语句体; }
  • while(条件判断语句){ 循环体语句; 条件控制语句; }
  • do{ 循环体语句; 条件控制语句; }while(条件判断语句);
三种循环的区别:
  • for循环和while循环:都是先判断后执行
  • do…while:无论条件是否成立都会执行一次语句体,先执行后判断
  • for循环和while的区别:
    • for 循环结束后,不能访问其条件控制语句:归宿于for循环语句中,结束后就消失了
    • 但对于while来讲条件控制语句不归属其语法结构中,所以在该循环结束后还能继续使用
死循环:
  • for( ; ; ){}
  • while(true){}
  • do{}while(true);

16、跳转控制语句

  • break:跳出循环,结束循环
  • continue:跳过本次循环,继续下次循环
  • continue只能在循环中进行使用!

17、循环嵌套

  • 循环嵌套概述:在循环中,继续定义循环
  • (整个内循环,就是外循环的一个循环体,内部循环体没有执行完毕,外循环是不会继续向下执行的)
  • 外循环执行一次,内循环执行一圈

18、数组

​ -----> 一维数组

概述:

  • 数组:就是存储一组相同类型数据的数据结构
  • 数组元素可以是基本数据类型,也可是引用数据类型【引用数据类型:数组、类、接口

定义:

  • 数组存储的数据类型[] 数组名字 = new 数组存储的数据类型[长度]

  • 数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,…}

  • 数据类型[] 数组名 = {元素1,元素2,元素3,元素4…}

    ​ -------> 二维数组

  • 声明:数据类型【】【】 数组名; 数据类型 数组名[][];

  • 数组名=new 【数据类型】【表示二维数组的长度][表示每个一维数组有几个元素】;

19、 数组的访问

  • 索引:每一个存储到数组的元素,都会有一个整数编号,从0开始
  • 语法:数组名[索引]
  • 数组的长度是固定的 --------> 获取数组长度:数组名.length
    • 数组最大索引值:数组名.length-1
  • 索引访问数组的元素:
    • 数组名[索引] = 数值 为数组的元素赋值
    • 数组名[索引] 获取数组中的元素
1、数组越界:
  报出异常:ArrayIndexOutOfBoundsException数组索引越界异常
2、数组空指针:

​ 报出异常:NullPointerException空指针异常。

20、 数组的遍历

一般有三种方法:
1、for循环遍历:

​ 遍历一维数组:一般单层for循环,遍历二维数组时:使用双重for循环

2、Arrays 工具类:

to String 静态方法遍历:可以将一维数组转化成字符串形式并输出

3、foreach循环:也就是增强for循环:

使用foreach循环时,并不能改变数组元素的值,所以不要对foreach的循环遍历赋值

  • 数组常用方法
  1. 反转:利用一个变量

  2. 复制:System.arraycopy(arg[]1,index1, arg[]2,index2, arr[].length)

    • arg[]1 : 源数组
    • index1: 表示源数组从哪个索引位置开始复制
    • arg[]2 : 目标数组
    • index2: 表示目标数组从那个位置开始存储数据
    • arr[].length:表示要复制的个数

    【如果目标数组是空数组,但存储位置(下标)不是0,则会报数组索引越界异常】

  3. 升降序:

    • 升序:Arrays.sort(数组名称);

    • 降序:

      //降序排列for(int i=0;i<nums.length-1;i++){//外层循环控制的循环的次数 //里层循环控制,外层循环每执行一次,需要对比的次数for(int j=0;j<nums.length-1-i;j++){//if(nums[j]<nums[j+1]){int temp=nums[j+1];nums[j+1]=nums[j];nums[j]=temp;}}}

21、 增强for循环

增强for循环,也叫foreach循环。

语法:

  • for ( 数据类型 变量名:数组名或集合名) { }

  • 内部原理为:Iterator 迭代器,所以在遍历过程中,无法对元素中其它元素进行操作

    【 弊端:无法获取元素的索引值 只适合对数组中的元素进行遍历操作】

可变参数
  • 定义一个方法接收多个参数,并且类型一致
    • 修饰符 返回值类型 方法名(参数类型… 参数名){ }
    • 修饰符 返回值类型 方法名(参数类型[] 数组名){ }

22、 数组内存分析

1、内存概述:
  • 内存是计算机中,临时数据存储区域,作用是运行程序
  • 我们写的程序是存放在硬盘中,只有放在内存中才会运行,运行完毕后会清空内存。
2、Jvm内存划分
  • 方法区:存储可运行的class文件
  • 堆内存:存储对象或者数组,new 来创建的,都存储在堆内存中
  • 方法栈:方法运行时使用的内存,比如main 方法运行,进入方法栈中

23、 数组在内存中的存储

日后填坑

24、 方法

方法概念:具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集

  • 方法必须先创建才能使用,该过程称为方法定义
  • 方法创建后并不是直接可以运行的,需要手动使用后, 才执行,该过程成为方法调用
1、方法的定义(无参):
  • public static void 方法名( ){ //方法体 }
2、方法的调用(无参):
  • 方法名( );

    ​ 【方法必须先定义,后调用,否则会报错】

方法调用过程:

【总结:每个方法在被调用执行的时候,都会进入栈内存,并且拥有自己独立的内存空间,方法内部代码调用完毕之后,会从栈内存中弹栈消失】

3、方法的定义(带参数):
  • public static void 方法名( 参数1 ){ 方法体 }
  • public static void 方法名( 参数1,参数2,参数3,… ){ 方法体 }
4、方法的调用(带参数):
  • 方法名(参数);

  • 方法名(参数1,参数2,参数3…)

    【方法定义时:参数中的数据类型和变量名都不能缺少,多个参数用逗号分隔】

    【方法调用时:参数的数量和类型必须与方法定义中的设置相匹配】

25、 形参和实参

  • 49、 参数传递
形参于实参对应两种类型:

值类型(八种基本数据类型)与引用类型 (类、接口、数组)

1、形参:
  • 不是实际存在变量,又称虚拟变量
  • 形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存单元。因此,形参只有在函数内部有效。 函数调用结束返回主调函数后则不能再使用该形参变量。
  • 是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数.在调用函数时,实参将赋值给形参。
  • 形参的个数一定要与实参一一对应,并却实参要有一定的值
2、实参:
  • 实参可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参**。所以要给它们予设值。**
3、注意:
  • 在值的传递过程中,只能 实参—>形参,不能形参传递实参。
  • 值传递调用过程中,只能把实参传递给形参,而不能把形参的值反向作用到实参上。

4、参数传递:

  • 基本数据类型:形式参数的改变,不影响实际参数的值
  • 依据:每个方法在栈内存中,都会有独立的栈空间,方法运行结束后就会弹栈消失
  • 引用类型:形参的改变,影响世界参数的值
  • 依据:引用数据类型的传参,传入的是地址值,内存中会造成两个引用指向同一个内存的效果,所以即使方法 弹栈, 堆内存中的数据也已经是改变后的结果
  • 传值时:为值类型时,形参方法内的参数值改变,并不会影响到实参的值
  • 传值时:为引用类型时,形参方法内的参数值改变时,会影响到实参的值。注意是地址所指向的堆中的值,如果形参的地址改变了,那么这个改变不会影响到实参。

26、带返回值的方法

1、定义

​ public static 数据类型 方法名 ( 参数 ){ return 数据; }

​ 【方法定义时 return 后面的返回值与方法定义上的数据类型要匹配】

2、调用:

​ 方法名( 参数 );

​ 数据类型 变量名 = 方法名(参数);

【方法的返回值通常会使用变量接收,否则该返回值将无意义】

方法注意事项:
  • 方法不能嵌套定义
  • void 表示无返回值,可以省略 return,也可以单独的书写 return,后面不加数据

27、 方法通用格式

格式:

​ public static 返回值类型 方法名(参数){ 方法体; return 数据; }

注意:

  • 定义方法时:要明确是否有返回值
  • 明确参数,有无

28、 方法重载

概念:

  • 在一个类中,有多个方法名一致,但是参数列表不同

  • 不能通过返回值来判断两个方法是否重载

    【返回值一样不一样都可,但方法重载必须是参数列不同方法名相同】

    【参数列表不一样】

public class Demo {

    //一个普通得方法,不带参数,无返回值
    public void add(){
        //method body
    }

    //重载上面的方法,并且带了一个整形参数,无返回值
    public void add(int a){
        //method body
    }

    //重载上面的方法,并且带了两个整型参数,返回值为int型
    public int add(int a,int b){
        //method body
        return 0;
    }

}

29、Debug

  • F8:单步调试,不进入函数内部
  • F7:单步调试,不进入函数内部

30、 面向对象

特征:三大:(封装、继承、多态) (四大:封装、抽象、继承、多态)

1、对象:
  • 没有相同的对象,对象唯一
2、抽象:
  • 就是把同一类事物中共有的特征(属性)和行为(方法)进行抽取,归纳,总结

    接口(interface) 抽象(abstract) 实现接口类
    接口中的所有方法均为抽象方法
  • abstract class Es{ public static void a(){}; abstract void aa(); }

  • class Sa extends Es{@Override void aa() {} }

3、抽象方法的特点
  • 只有方法头没有方法体的方法称之为抽象方法。(即只有方法的声明,没有方法的实现)
  • 抽象方法用abstract关键字来修饰。
  • 抽象方法代表一种不确定的操作或行为。(由子类去具体实现)
  • 抽象方法不能被调用。
4、抽象类的特点
  • 定义中含有抽象方法的类叫做抽象类。
  • 抽象类用abstract关键字来修饰。
  • 抽象类代表一种抽象的对象类型。
  • 抽象类不能实例化。
  • 抽象类中可以有具体方法,可以没有抽象方法。(也就是说一个类中只要有一个方法是抽象方法那么这个类一定是抽象类,反过来,一个抽象类中可以没有抽象方法,可以带有具体 实现的方法)
  • 一旦一个类中有抽象方法,那么这个类必须也要用abstract来修饰,代表这个类是抽象类,它是不能被实例化的
5、封装:
  • 封装:就是包装,对抽象出来的数据进行包装,为了数据的安全性
  • 包括:属性和方法的封装,不是绝对的封装,可以通过指定的入口
  • 抽象和封装这两个特征,在程序中的具体体现形式就是【类】 属性和方法的封装两者是相辅相成密不可分的。

31、 类

1、定义:

public class 类名{ //成员变量 //成员方法 }

变量的分类:

  • 数据类型:
    • 基本数据类型变量
    • 应用数据类型变量
  • 位置划分:
    • 局部变量:定义在方法内部或某个语句块的内部,只限于本方法或者本语句块内使用
    • 全局变量:定义在类的内部,任何方法的外部,范围是整个类
    • 局部变量:只有初始化才能使用
2、 类和对象:
  • 类是对对象的抽象
  • 对象是类的实例化

32、 创建对象

  • 格式: 类名 对象名 = new 类名();
  • 对象的使用:
    • 对象名.成员属性(变量)
    • 对象名.方法名(参数列表)
  • 成员属性都有默认值,所以在声明成员属性时,可以不用初始化,就能使用 默认值跟数据类型有关系

33、 成员方法的应用

语法:访问修饰符 返回值类型 方法名称(参数列表){ }

成员方法之间调用,直接写方法名(参数列表)杰克

代码都是从 main方法开始到main结束

34、构造方法

  • 对象是通过构造方法创建出来的

public 类名称(参数类型 参数名称){ 方法体 }

构造方法定义:
1、定义语句:
  • 访问修饰符 类名(参数列表){ }
2、构造方法规则:
  • 方法名必须和类名一致
  • 方法中没有return 也没有返回值和void
  • 构造方法不能被 static 等关键字修饰
  • 也可以重载,构造方法之间的参数列表(个数、类型、顺序的 不同)不同即可
3、作用:
  • 创建对象
  • 可以对成员变量进行初始化
构造方法分类:
  • 无参数(默认)构造方法:
    • 显示无参数的构造方法
    • 隐私无参数的构造方法
      • 当一个类中没有任何构造方法时,jvm就会默认创建一个
      • 有了后 jvm创建的就会自动消失
    • 有参的构造方法

35、 this关键字

1、前提条件:
  • 只能在没有被 static 关键字修饰的方法中
2、作用:
  • 表示对当前类某个对象的引用
3、用法:
  • 区分成员、局部变量
  • 以this(参数列表) 的形似出现在第一句代码是,代表应用其它类中的构造方法

36、 JavaBean

  • 凡是符合JavaBean的定义规范都统称为JavaBean,但是JavaBean也是一个类

JavaBean定义规范:

  • 成员属性使用private关键字来修饰 语法:private 数据类型 属性名;
  • 提供一个公共无参的构造方法
  • 为所有的私有属性,提供set/get方法
    • set是无返回值有参数,目的是给成员属性赋值
    • get是有返回值无参数,目的是获取私有属性的值

37、 private 访问修饰符

private 表示私有的,修饰的属性,只能在当前类中使用,私有的

【类和类之间的方法或属性可以相互被调用,只需要创建一个目标类的对象即可】

38、package 创建包

  • 包名可以是多级目录层次,层次之间用英文的点分割

  • 包一定是位于源代码的第一句

    • 带包的类编译语法: javac –d . 类名.java 点的意思表示当前类生成的带包的字节码文件位于当前目录
    • 运行带包的字节码文件: java 包名.类名 包名.类名又称为类的全限定名
  • 导包的语法:

    • import 包名.类名; 或者 import 包名.*; *表示包下所有的类。
    • 【import 导包一定要位于 package 的下面】
  • 一个Java源文件中存在多个类

    【一个 Java 源文件中,可以存在多个类,但是只能有一个类带 public 访问修饰符,而且 main 方法就要位于该类中,而且 java 源文件的名称还要和带 public 修饰的类类名相同,其它类 都要位于每个类结束大括号的外面,而且不需要添加 public 访问修饰符。】

39、Random 随机数类

1、此类用于产生伪随机数

方法:

Random 变量名r = new Random(); 数据类型 变量名 = 变量名r.next数据类型();

Random 变量名r = new Random(); 数据类型 变量名 = 变量名r.next数据类型(10/10L);

40、 包装类

​ -----> 51、 包装类

Java中的基本数据类型没有方法和属性,而包装类就是为了让这些拥有方法和属性,实现对象化交互。

  • 八种基本数据类除int、char外其余的首字母大写

    • int ----> Integer
    • char —> Character
  • 为了方便基本数据类型和包装类之间的相互转换,从 JDK5.0 开始,提供了装箱和拆箱。

    • 装箱:就是把基本数据类型可以直接赋值给所对应的包装类对象
    • 拆箱:可以把一个包装类对象直接赋值给所对应的基本数据类型

    装箱和拆箱是自动完成的

    Java中除了float和double的其他基本数据类型,都有常量池

  • 所有整型包装类对象之间值的比较,全部使用equals方法比较。

    • 说明:对于Integer var = ? 在-128至127 范围内的赋值,Integer 对象是在 IntegerCache.cache 产 生,会复用已有对象,这个区间内的 Integer 值可以直接使用==进行判断,但是这个区间之外的所有数 据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用 equals方法进行判断
  • 【强制】浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用 equals来判断

41、 String 类

java.lang.String

  • 只要是用双引号引起来的内容,就是一个String字符串内容
特点:
  • 字符串是一个不可变的类,也就是字符串的值在创建后不可改变
    • 不可变指的是值本身不可变,但是重新给字符串对象赋值会改变字符串对象原本指向的内存地址
    • 字符串池的原理来实现以上的过程:字符串池是一个专门用来存储字符串值得空间,所有创建的字符串对象在赋值时,都需要和字符串池中已有的 内容进行对比,如果内容已经存在,直接引用已存在的值得内存地址;如果不存在,才会把新的内容放到字符串池
String 的构造方法
  • 默认创建一个字符串对象:直接把内容使用双引号引起来即可
  • 可以使用 String 的构造方法来创建对象。
    • 例如: String name=new String(“李四”);但是,该方式会创建两个对象,原始对象是构造方法中的字符串参数,name 其实就是一个对象副本
== 和 equals
  • ==:比较的是两个字符串对象指向的内存地址是否相同
  • equals:判断内容是否相同

42、继承

1、特点:
  • 继承有一定的层次结构,有一定的可传递性
  • 子类继承父类的所有的属性和方法,除私有的**,父类的构造方法是用来创建父类对象的,子类无法继承**
  • 子类除了可以拥有继承的属性、方法,也可以有自己的属性、方法
  • Java只支持单一的继承,只能有一个父类,但父类可以拥有多个子类,利用 implements关键字实现多个接口
2、好处弊端:
  • 好处:
    • 提高了复用性,利于维护
  • 弊端:
    • 类的耦合性增强,父类发生变化,子类也会变化
  • 场景:
    • is…a 的关系
3、语法格式:
  • 格式:
    • class 子类 extends 父类 { }
  • 子类则可以使用父类中非私有的成员。
4、继承中构造方法:
  • 在执行有继承关系的子类时,会先执行父类中默认的构造方法,然后再执行子类

43、 super关键字

1、前提条件:
  • super 关键字只能出现在有继承关系的子类中
2、作用:
  • super 表示对当前父类对象的引用,super表示的就是父类的某个对象的引用
3、用法:
  • 第一种:super.属性名、super.方法名(参数列表);
  • 第二种:当super(参数列表)的形式出现在子类构造方法的第一句代码的时候,就明确指明了通过和参数列表匹配的父类的构造方法,来创建父类对象 。

44、 权限修饰符

对 4.1 、关键字 访问控制修饰符----关键字的补充

大到小:public > protected > 默认 >private

45、 final 关键字

对 4.2 关键字 类、方法和变量修饰符–final 的补充

  • fianl 修饰类:该类不能被继承(不能有子类,但是可以有父类)
  • final 修饰方法:该方法不能被重写
  • final 修饰变量:表明该变量是一个静态的常量,不能再次赋值
  • final 修饰方法中的参数,该参数称为最终参数,在方法体中,不能对参数进行重新 赋值
  • final 修饰基本数据类型变量:指的是基本类型的数据值不能发生改变
  • final 修饰引用数据类型变量:指的是引用类型的地址值不能发生改变,但是地址里面的内容是可以发生改变的

46、 static 关键字

对 4、关键字 类、方法和变量修饰符–static 的补充

  • 静态变量的定义语法:
    • static 数据类型 变量名; 类变量,建议使用 类名.变量名的形式来调用,不建议使用对象名.变量名

47、 方法重写

1、前提条件:
  • 只能是子类重写父类中的方法
2、目的:
  • 当父类的方法无法满足子类的需求时,子类可以进行方法的扩展
3、重写:
  • 方法重写就是,子类重写父类中的方法,必须和父类中的方法名,返回值类型,参数列表完全一致,而且访问修饰符的范围不能缩小
  • 覆盖

48、 多态

面向对象三大特征:(封装、继承、多态)

1、概述:
  • 同一行为,通过不同的事物,可以体现出不同的形态,多态就是描述的这样的状态
2、前提:
  • 多态:同一个行为,具有不同的表现形式
  • 继承或者实现【二选一】
  • 方法重写
  • 父类引用指向子类对象
3、发生多态的条件:
  • 继承
  • 重写
  • 向上转型
  • 用向上转型的对象,调用被子类重写的方法

4、格式:

  • 父类类型 对象名 = new 子类类型();
  • 对象名.方法名();

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译失败;如果 有,就执行子类重写后的方法。

  • 好处:
  • 父类类型作为方法中的形式参数,传递子类对象给方法,进行方法的调用, 更能体现出多态的扩展性与便利性
5、引用类型转换
  • 向上转型:
    • 多态本身就是子类类型向父类类型向上转换的过程,这个过程是默认的
    • 当父类引用指向一个子类对象时,便是向上转型。
    • 使用格式:
      • 父类类型 对象名=new 子类类型();
    • 可以把向上转型的对象,看作是父类对象。
    • 向上转型的对象,可以调用父类中所有的普通方法和成员属性,但是只能调用子类中重 写的方法。
  • 向下转型:
    • 向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。
      • 不能直接把一个父类对象,强制转换成一个子类对象
      • 向下转型,一定是在向上转型的基础上,做类型的还原。
    • 一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换,
    • 格式: 子类类型 对象名=(子类类型)经过向上转型的父类对象;
  • 想调用子类特有的方法,必须做向下转型。
6、转型的异常
  • java.lang.ClassCastException,类型转换异常!这 是因为,两个对象类型不匹配,不能做类型转换。
  • 可以用 instanceof 关键字判断
7、动态(延迟)绑定机制

当有多态发生时,一定会发生动态绑定机制。 动态绑定机制,就是程序在运行期间,会判断对象的真正的创建者是谁,就调用谁里面的方法。

49、 参数传递

  • 25、形参、实参
1、形参和返回值
  • 方法的形参是类名,其实需要的是该类的对象 实际传递的是该对象的地址值
  • 类名作方法的返回值,返回的是该类的对象,实际传递的也是对象的 地址值
  • 抽象类的时候,传递的和返回的都是该抽象类的子类的对象
  • 接口的时候,传递和返回的都是该接口的是实现类对象
2、内部类

不能有 static 方法和属性

  • 概念:在一个类中,定义另一个类
  • 格式:class 外部类名 { 访问修饰符 class 内部类名 {} }
  • 特点:
    • 内部类可以直接访问外部类的成员,包括私有的
    • 外部类要想访问内部类,必须创建对象
  • 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
3、局部内部类
  • 位置:方法中定义的类

  • 方式:

    • 局部内部类,外界无法直接使用,需要在方法内部创建对象并使用
    • 该类可以直接访问外部类的成员,也可以访问方法内的局部变量
4、匿名内部类
  • 前提:存在一个类或者接口,这里的类可以实具体类也可以是抽象类
  • 格式:
    • new 类名(){重写方法} new 接口名 (){重写方法}
  • 本质:是一个继承了该类或者实现了该类的子类匿名对象
  • 匿名内部类可以通过多态的形式接受 匿名内部类直接调用方法

50、 Math、System 类

Math类
  • 包含了基本数字运算的方法
  • 无构造方法,方法都是静态的
System类
  • System.exit(0) 终止当前运行的Java虚拟机,非零表示异常
  • long lon01 = System.currentTimeMillis(); 返回当前时间
Object 类的toString 方法
  • Object类可以是每个类的父类
  • toString 更方便展示对象的属性
Object类的equals方法
  • equals是否相同,结果为true/flase
Arrays类
  • public static String toString(int[] a) 返回指定数组的内容的字符串表示形式
  • public static void sort(int[] a) 按照数字顺序排列指定的数组

51、 包装类

​ -------> 40、 包装类

  • int 转换成 String

    • 1 直接在数字后加一个空字符串
    • 2 通过String类静态方法valueOf()
  • String转换成int

    • 1 将字符串数字转换成Integer,在调用valueOf()
    • 2 通过Integer 静态方法parseInt()进行转换
  • Date类 日期

    • 精准到毫秒
  • SimpleDateFormat类的常用方法

    • public final String format(Date date):将日期格式化成日期/时间字符串
    • public Date parse(String source):从给定字符串的开始解析文本以生成日期

52、 异常

98、部分总结–>1、catch捕获异常

  • RuntimeException 运行时异常
  • 非 RuntimeException 编译时异常
jvm默认处理异常
  • 方式:

    • 把异常的名称,错误原因及一场出现的位置等信息输出在控制台
    • 程序停止执行,报出异常
  • 编译时异常和运行时异常

    • 编译时异常
      • 都是Exception类及其子类
      • 必须显示处理,否则程序就会发生错误,无法通过编译
    • 运行时异常
      • 都是RuntimeException 类及其子类
      • 无需显示处理,也可以和编译时异常一样处理
throws 和 throw 的区别
  • throws:
    • 用在方法声明后面,跟的时异常类名
    • 表示抛出异常,由该方法的调用者来处理
    • 表示出现异常的一种可能性,并不一定会发生这些异常
  • throw:
    • 用在方法体内,跟的是异常对象名
    • 表示抛出异常,由方法体内的语句处理
    • 执行throw 一定抛出了某种异常

53、集合

1、合集和数组的区别:
  • 数组长度是固定的,集合的长度可以改变
  • 数组中存储的是同一类型的元素,可以存储基本数据类型值,但集合存储的都是对象,而且对象的类型可以不一致

单列集合:java.util.Collection 双列集合:java.util.Map

2、Collection
  • 单列集合类的根接口,java.util.List 和 java.util.Set 是其子接口。

    • list:元素有序、可以重复
    • set:元素无序、不可以重复
  • List接口的主要实现类:

    • java.util.ArrayList
    • java.util.LinkedList
    • java.util.Vector
  • Set接口的主要实现类:

    • java.util.HashSet
    • java.util.LinkedHashSet
    • java.util.TreeSet
  • 集合本身是一个工具类,它存放在java.util 包中

3、 Itreator 迭代器

Iterator主要用于迭代访问(即遍历**)Collection**中的元素,因此Iterator对象也被称为迭代器。

  • 迭代概念
    • 即Collection集合元素的获取方式,在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续再判断,如果还有就继续取出来,一直把集合中所有的元素全部取出。这种取出方式专业术语称为迭代。
  • Iterator常用方法
    • public E next():返回迭代的下一个元素
    • public boolean hasNext():如果仍有元素可以迭代,则返回true

迭代器实现原理

  • 遍历集合时:
    • 首先同过集合的 iterator() 方法获取迭代器对象,然后使用 hashNext() 方法判断集合中是否 存在下一个元素,存在就用next() 元素取出,没有则停止
  • Iterator 迭代器对象遍历集合时:
    • 采用内部指针的方式
    • 在调用next() 方法前,迭代器索引会位于第一个元素之前,并不会指向任何元素,当第一次调用next方法后,迭代器索引就会往后移动一位,指向第一个元素并将其返回,依次调用,知道 hashNext()返回fslae后,终止遍历

54、 泛型

  • 泛型:可以在类或方法中预支地使用未知的类型
    • 一般在创建对象时,将未知类型确定为具体类型,当没有指定泛型时,默认类型为Object类型
1、使用泛型的好处
  • 运行时期的 ClassCastException,转移到编译时期
  • 避免了类型强转的麻烦
2、泛型定义、使用
  • 消除类型转换
    • 集合类<泛型类型> 对象名=new 集合类<>();
  • 定义和使用含有泛型的类
    • 定义格式:
      • 修饰符 class 类名<代表泛型的变量>{ }
    • 在定义泛型类时,要给泛型类确定具体类型
  • 含有泛型的方法
    • 定义格式:
      • 修饰符 <代表泛型的变量> 返回值类型 方法名(参数列表){ }
    • 无论使用泛型类、泛型方法、泛型接口,传递的泛型类型只能是引用类型
  • 含有泛型的接口:
    • 定义格式:
      • 修饰符 interface 接口名<代表泛型的变量>{ }
    • 不能直接new泛型变量的对象,因为无法保证泛型变量就一定是类
3、通配符
  • 不知道什么类型接收数据时,用 ? ,但此时只能接收数据,不能集合中存储

  • 受限泛型(通配符)

    设置泛型的上限、下限

    • 泛型的上限
      • 格式: 类型名称<? extends 类>对象名称
        • 意义:只能接收该类以及子类类型
    • 泛型的下限
      • 格式:类型名称<? super 类>对象名
        • 意义:只能接收该类型以及父类类型
4、数字格式化类 DecimalFormat
  • 针对十进制数字格式化的一个类
  • 规则:
    • 0 就代表一个数组(0 也可以代表整体整数)
    • #也是代表的一个数字(#也可以代表整体整数),只不过他如果对应的位数上是0,则返回空
    • . 小数的分隔符
    • ,数字的分隔符
    • %当前数字所对应的百分比

55、 数据结构

数据存储的常用结构有:栈、队列、数组、链表、红黑树 栈(堆栈)和队(队列)都是运算受限的线性表

1、栈
  • 栈:stack—堆栈,其限制是:仅仅允许在栈的一端进行插入和删除操作,不允许再其它任何位置进行添加、查找、删除
  • 存储特点:先进先出 -----> 进 1、2、3、4 出 4、3、2、1
  • 压栈:就是存元素,先存储的在最顶端然后依次往栈底的方向移动
  • 弹栈:就是取元素,栈顶端的元素最先取出来,然后栈中的元素依次往栈顶的位置移动
2、队列
  • 队列:queue—队,其限制是:只允许在表的表头进行删除操作,在队尾进行插入操作
  • 存储特点:先进先出 —> 进1、2、3、4、出 1、2、3、4
  • 可以空队列
  • JDK还提供了另外一种链队列ConcurrentLinkedQueue,它基于一种先进的、无等待(wait-free)队列算法实现。
  • 链式队列就是一个操作受到限制的单链表
3、数组
  • Array数组:有序的,可重复的元素序列

  • 存取特点:

    • 查找快,通过索引
    • 增删慢,通过下标在指定位置添加元素,但是需要创建一个新的数组,将指定的新元素存储在指定的位置,并且要把原来的数组根据索引,复制到新数组对应的位置上
  • ArrayList想象成一个会自动扩容的Array

  • Array数组:最高效,但是其容量固定且无法动态改变 Array[] a = new Array[5];//不固定长度则会报错

  • ArrayList:容量可以动态增长,但是会牺牲效率

  • Arraylist:底层是Object数组,所以ArrayList具有数组的查询速度快的优点以及增删速度慢的缺点。

  • https://www.cnblogs.com/wangbin2188/p/6524200.html

4、链表
  • 链表:linked list 有一系列结点 node (链表中每一个元素被称为一个结点)组成,节点可以在运行时动态生成
  • 每个节点包括:
    • 一个是存储数据的数据域
    • 一个是存储下一个节点地址的指针域
    • 连接时前一个可能是null
  • 链表分为:单向链表、双向链表
  • 单向链表:存取特点:
    • 对各结点之间,通过地址进行连接
    • 查找元素慢,通过连接的结点,依次往后查找
    • 增删元素快
      • 只需要修改连接下个元素的地址即可
5、红黑树
  • 二叉树:binary tree 是每个节点不超过2的有序树
  • 二叉树是每个结点最多有两个子节点的树结构,顶上的叫根结点,两边的称作左子树和右子树
  • 红黑树本身就是二叉树,也意味着,存放的数据必须是可排序的。

56、List接口

java.util.List接口继承自Collection接口,是单列集合的一个重要分支,习惯性的将实现了List接口的对象称为List集合。

  • list集合特点:可重复、有序
  • 增删慢 添加一个或删除一个元素,都要把该位置以后的元素进行索引的调整。

57、 实现类

1、ArrayList集合
  • 存储结构是:动态数组,容量会自动的改变

  • 查找快:索引

  • 增删慢:增删一个元素都要将该位置以后的元素进行所有的调整

2、LinkedList集合
  • 存储结构:链表结构,方便添加、删除的集合
  • 是一个双向链表集合
  • 有大量首尾操作的方法(添加、删除)

58、 Set接口

  • 继承于 Collection 接口
  • 无序不可重复
  • 在数据的存储、检索,效率都比较高

59、 Set 接口实现类

1、java.util.HashSet
  • 底层实现类是一个 java.util.HashMap

  • 不可重复,无序

2、Set 集合无序不重复:

不重复:

  • 对于基本数据类型数据,Set集合会之间比较值是否相等
  • 对于引用数据类型数据,Set集合会:
    • 自动提取两个对象
    • 再让这两个对象调用自己的hashCode() 方法(继承至Object)得到彼此的哈希值(内存地址)
    • 然后判断其哈希值是否相同
    • 如果相同则会
      • 这两个对象进行equlas 比较,相同去一个,不同都保留

无序:

  • Set集合底部是基于哈希表存储的
  • jdk1.8 之前 哈希表由:数组和链表组成
  • jdk1.8之后 由:数组+链表+二叉树组成
  • JDK 1.8之后,如果链表的长度超过获取等于了阈值(7)的时候会自动转成红黑树。
  • 二叉树:只有一个个节点,两个分节点。
  • 排序二叉树:小在左,大在右。

【如果两个对象相同,则他们的hashCode值就一定相同;但是两个对象的hashCode值相同,但是这两个对象不一定相同】

2、LinkedHashSet

  • java.util.LinkedHashSet它可以记录元素存储的顺序,并且能够按照所记录的顺序进行输出。
  • 有序

60、 Map集合

一一对应

61、 Map实现类

HashMap
  • HashMap 存储数据采用的是哈希表结构,元素无序、但要保证键的唯一性
  • HashMap由数组+链表组成的,数组是HashMap的主体 。
  • 元素不重复,需要重写键的hashCode方法和equals方法。
  • 元素无序,但是查询速度快
LinkedHashMap
  • 是 HashMap的子类,采用哈希表+链表结构。
  • 通过链表可以保证元素的存取顺序一致,元素有序
  • 不重复就需要需要重写键的hashCode方法和equals方法。
  • 元素有序,查询速度快

62、 Collection

  • java.util.Collection 是一个集合接口(结合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口的方法。
  • Collection 接口的意义是为了各种具体的集合提供了最大化的同意操作方式其直接继承类有 List和Set

63、 Collections

  • java.util.Collections 是一个集合的工具类/帮助类,其中提供了一系列**静态多态方法,此类不能被实例化,**用于对集合中元素进行排序、搜索以及线程安全等各种操作。

Collections的一些方法

  • 排序 Sort -----> 按照自然顺序进行升序排序。 Collections.sort(int01);
  • 混排 Shuffling ----> 混排相当于随机排序。 Collections.Shuffling(list)
  • 反转 Reverse -----> 根据自然顺序,进行降序排列。 Collections.reverse(list)
  • 替换元素 Fill -----> 使用指定的元素替换指定列表的所有元素。 Collections.fill(list01,“aaa”);
  • 拷贝 Copy -----> 用两个参数 list01 和list02,将list01 copy 到list02 上,01可以比02短,但不能比02长,否则报出 IndexOutOfBoundsException 异常,Collections.copy(list02,list01);。
  • 返回 Collections 中最小元素 min -----> 根据指定比较器产生的顺序,返回给定 collection 的最小元素 System.out.println(Collections.min(list01));
  • 返回 Collextions 中最大元素 max -----> System.out.println(Collections.max(list01));
  • IndexOfSubList
  • Rotate -----> Collections.rotate(int01,-1); 负数时将把第一位放在后面 -1 放在最后一位,-2时将第一位和第二位共同放在后,正数反之

64、Comparable

Comparable 接口

  • 死板,写死
  • 所有可以排序的类都实现了 java.lang.Comparable 接口,此接口只有一个方法
    • public int compareTo(Object obj);
    • 在此方法中定义排序规则
      • 返回 0 表示 this == obj
      • 返回整数表示 this > obj
      • 返回负数表示 this < obj
  • 实现了 Comparable 接口的类通过实现 comparaTo 方法从而确定该类对象的排序方式

65、Comparator 比较器

Java中有两种比较实现方式:一种是比较死板的 java.lang.Comparable 接口、一种是比较灵活的 java.util.Comparator 接口完成的

  • Comparator 比较器,比较方法是:

    • public int compare(类名一(如:Student) o1, 类名二(如:Student)

      o2) {比较条件}

    • 两个对象比较的结果有三种:大于,等于,小于 。

66、Comparable、Comparator 接口的区别

  • Comparable 接口使用:是类(如:Student)实现接口,然后再实现这个接口的 compareTo(Object o) 方法写比较条件,进行比较,之后 再传入创建的集合充当数据类型,在之后使用:Collections.sort(arrayList01);后输出即可。
  • Comparator 接口使用:也是放在类(不是Student 之类的类)中,但是这个类是一个单独的比较、判断方法的类,这个类实现这个接口( implements Comparator<类似于Student的这种类> ),之后实现 compare() 方法的实现,并在这个方法中写入比较条件,后使用:Collections.sort(arrayList01,new 实现Comparator接口的类);后输出即可

Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo方法一次不能经常修改类的代码实现自己想要的排序。实现此接口的对象可以通过Collection.sort()方法进行自动排序。

Comparator强行对某个对象进行整体排序,可以将Comparator传递给sort方法,从而允许在排序顺序上实现自定义控制。

​ 程序—> 【day14/text】

67、File类

1、概述:
  • java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建,查找,删除等操作
  • 一个File对象代表的是某个路径下的一个文件或者目录
  • 无论该目录下是否存在文件或目录,都不影响
2、路径:
  • 绝对路径:从盘符开始的路径,这是一个完整的路径
  • 相对路径:相对于某个目录的路径,这是一个便捷的路径

68、 目录的遍历

  • public String[] list(); 返回一个String 数组,表示该File目录中所有的子文件或目录
    • 获取 new File(“文件路径”) 里所有的文件/文件夹(只是第一层的,文件夹套文件夹,不会获取第二层文件夹),把获取的多个名称储存在一个String[]
    • 遍历一个空文件、路径有问题时,会报出空指针异常
    • 可以遍历隐藏的文件或者文件夹
    • File file = new File(“F:\”); String[] str = file.list();

、无论该目录下是否存在文件或目录,都不影响File对象的创建

  • public File[] listFiles();返回一个 File[] 表示文件下的所有目录和文件
    • 遍历构造方法中给出的目录,然后获取,将获取到的文件/文件夹封装成一个 File 对象,然后再将这多个File对象封装到 **File[]**中
    • File file = new File(“F:\”); File[] files = file.listFiles();

69、 递归

  • 递归:指在当前方法内调用自己的这种现象
  • 递归的分类:
    • 递归分为两种,直接递归和间接递归
      • 直接递归称为方法自身调用自己
    • 间接递归可以理解为:A方法调用B方法,B方法调用C方法,C方法调用A方法
  • 注意事项
    • 递归一定要有条件限定,保证递归能够停止下来,否则会发生内存溢出
    • 在递归中虽然有条件限定,但是递归次数不能太多,否则也会发生内存溢出
    • 构造方法,禁止递归

70、 IO流

为什么要序列化?
  • 序列化后的数据,都会以二进制的形式在网络中进行传输,通过反序列化可以在任何一个终端进行数据的还原,简单的来说就是为了数据能够更方便地在网络中进行传输

在Java程序运行时,系统自动通过System类创建三个静态的I/O对象,它们是标准输入流对象InputStream 、标准输出流对象OutputStream 、和标准错误流对象ErrorStream 。

所有文件的输入输出都继承于 InputStream、OutputStream

71、IO流

I: input:输入(读取) 把硬盘中的数据,读取到内存中使用

O:output:输出(写入) 把内存中的东西,写入到硬盘中

流:数据(字符字节) 1个字符 = 2个字节 = 8个二进制位

72、字节流

72、字节输出流(抽象类)

OutputSrteam

OutputSrteam 字节输出流的超类,将指定的字节信息写出到目的地

73、字节输入流(抽象类)

InputStream

InputStream 字节输入流,读取字节信息到内存里

74、文件输出流

FileOutputStream 继承于字节输出流 用于将数据写出到文件里(进入.txt等)

75、文件输入流

FileInputStream 文件输入流,从文件中读取字节(输出在控制台)

FileInputStream使用 字节 读取文件,不能直接处理Unicode字符

76、字节流优点

【字节流只适合用于操作,图片、视频、音频等以字节为单位存储数据的文件,不适合操作文本文件

77 、字符流

77、 字符输出流(抽象类)

Writer 用于写出字符流的所有类的超类,将指定的字符信息写出到目的地

75、字符输入流(抽象类)

Reader用于读取字符的所有类的超类,可以读取字符信息到内存中

75、写入字符流(写出字符到文件)

FileWriter 写出字符到文件的类,构造时使用系统的默认的字符编码和默认字节缓冲区**(写入到文件)**

76、 读取字符流(读取字符文件的类)

FileReader 读取字符文件的类,构造方法使用系统默认的字符编码和默认字节缓冲区。(输出到控制台)

**将字节流转换为字符流的两个类是 InputStreanReader 和 OutputStreamWriter **

77、序列化

对象二进制进内存

反序列化:将内存的文件以二进制码输出到程序中

必须实现Serializable 接口

77、ObjectOutputSteam类

将Java对象的原始数据类型写出到文件,实现对象的持久存储。 (写入到文件中)

实现序列化必须实现一个 Serializable 接口,该接口是一个标记接口

实现序列化的类所有属性必须是可序列化的,不能被static、transient关键字修饰

78、反序列化

78、ObjectInputStream 类

  • ObjectInputStream 反序列化流,将序列化的对象还原**(输出到控制台)**

    ​ public final Object readObject():读取一个对象

  • 当JVM反序列化对象时,抛出了一个InvalidClassException异常原因:

    • 该类的序列化版本号与从流中读取的类描述的版本不匹配
    • 该类包含未知数据类型

Serializable 接口给需要序列化的类,提供了一个序列化版本号,该版本号的目的在于验证序列化的对象和对应类是否版本匹配

79、关闭和刷新

  • flush:刷新缓冲区,流对象可以继续使用
  • close:先刷新缓冲区,然后通知系统释放资源,流对象不可再用

80、 属性集(文件集)

【HashMap和Hashtable 都是通过key=value的方式来存储数据的,它俩的区别:Hashtable不能把null作为key和value】

java.util.Properties继承自Hashtable,来表示一个持久的属性集。它使用键值对结构存储数据,每个键及其对应值都是一个字符串。

  • 一般与序列化时作公共数据存储

80、 异常

  • JDK 7 之前:try {} catch( ) { }
  • JDK 7 的处理:支持try-with-resource语句,该语句确保了每个资源在语句结束时关闭,所谓的资源(resource)指在程序完成后,必须关闭的对象。
    • try(需要关闭的资源对象,如果多个使用;隔开){ }catch(Exception ce){ }
  • JDK 9 的改进:try-with-resource的改进,对于引入对象的方式,支持的更加简洁,被引入的对象,同样可以启动关闭无需手动close.

81、 枚举enum

1、枚举
  • 枚举也是类(也是一种数据类型)也可以定义在类中

  • 语法:

    • [访问修饰符] enum 枚举名称{ }

    • 单独创建一个枚举类,语法:

      [访问修饰符] enum 枚举名称{ }

2、特点
  • 声明枚举后,必须在枚举类中第一句代码中,声明枚举类的实例,实例之间用逗号隔开,列出实例后自动添加 public static final 修饰
  • 如果不存在任何实例,枚举类第一句代码添加一个分号
  • 每个枚举类都有一个 values() 方法,用来获取枚举中所有实例对象
  • 枚举类.对象名.属性名/方法名的方式调用枚举类中的普通方法和属性
  • 枚举类.静态属性/静态方法,调用枚举类中的静态方法和属性
  • 枚举类也可以有构造方法,而且构造方法的访问修饰符必须是private。当枚举类在被使用时,枚举类会自动调用构造方法,创建出在枚举中声明的所有实例对象。
  • 枚举中的构造方法也可以有参数,如果构造方法是有参数的,那么在声明枚举实例对象时,就必须传递参数,语法:实例名称(参数列表)
  • 枚举也可以实现接口
  • 枚举不可以继承任何形式的类。

82、 缓冲流

能够高效读写的缓冲流,能够转换编码的转换流,能够持久化存储对象的序列化流等。

  • 字节缓冲流:BufferedInputStream、BufferedOutputStream
  • 字符缓冲流:BufferedReader、BufferedWriter
  • 原理:
    • 缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写(往内存中读写数据的速度是最快的),减少系统IO次数,从而提高读写的效率。
1、字节缓冲流
  • public BufferedInputStream(InputStream in):创建一个新的缓冲流输入对象
  • public BufferedOutputStream(OutputStream out):创建一个新的缓冲流输出对象
2、字符缓冲流
  • public BufferedReader(Reader in) 创建使用默认大小的输入缓冲区的缓冲字符输入流。
  • public BufferedWriter(Writer out) 创建使用默认大小的输出缓冲区的缓冲字符输出流。
  • BufferedReader :public String readLine():读一行文字
  • BufferedWriter :public void newline():写一行分隔符

83、 转换流

1、字符编码
  • 计算机存储的信息都是用二进制表示的,将字符存储到计算机中,称为编码
  • 将存储在计算机中的二进制数按照某种规则解析出来,成为解码
2、字符集
  • 字符集 Charset:也叫编码表,是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等
    • ASCII 字符集、GBxxx字符集、Unicode字符集
3、InputStreamReader 类
  • 是Reader的子类,是从字节流到字符流的桥梁,它读取字节,并使用指定的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集

构造方法:

  • InputStreamReader(InputStream in) 创建一个使用默认字符集的InputStreamReader。
  • InputStreamReader(InputStream in, String charsetName) 创建一个使用命名字符集的InputStreamReader。

【 InputStreamReader isr=new InputStreamReader(new FileInputStream(“e:\a.txt”),“GBK”); int read; while((read=isr.read())!=-1){}】

4、OutputStreamWriter类
  • 是Writer的子类,是从字符流到字节流的桥梁,使用指定的字符集将字符编码为字节,它的字符集可以由名称指定,也可以接受平台默认的字符集。

构造方法

  • OutputStreamWriter(OutputStream out) 创建一个使用默认字符编码的OutputStreamWriter。
  • OutputStreamWriter(OutputStream out, String charsetName) 创建一个使用命名字符集的OutputStreamWriter

【OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream(“e:\a.txt”),“utf-8”); osw.write(“你好”); 】

5、打印流
  • PrintStream 类

输入文件里 【PrintStream ps=new PrintStream(“e:\c.txt”); System.setOut(ps);】

84、 线程

在JAVA编程中,基于线程的多任务处理环境中,执行特定任务的可执行代码的最小单位是线程,服务一般包括一到多个线程

1、进程
  • 当一个程序进入内存运行,即变成一个进程。进程是处于运行过程中的程序,并且具有一定独立功能,进程是操作系统进行资源分配和调度的一个独立单位。

特点:

  • **动态性:**进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的;
  • **并发性:**任何进程都可以同其他进行一起并发执行,并不会互相影响;
  • 独立性:进程是系统进行资源分配和调度的一个独立单位;
  • **结构性:**进程由程序,数据和进程控制块三部分组成
2、线程

分为:单线程、多线程 单线程:一条执行路径 多线程:多条执行路径

并发性(concurrency)和并行性(parallel)

  • 并行是指在同一时刻,有多条指令在多个处理器上同时执行并发是指在同一个时刻只能有一条指令执行,但多个进程的指令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。
3、线程创建
  • Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的对象
  • 每个线程的作用是完成一定的任务,实际上就是执行一段代码,我们称之为线程执行体
  • 使用run方法来封装这段代码,即run方法的方法体就是线程执行体

使用Thread 类创建线程类

1、继承Thread 类

  • 继承Thread类,重写run()方法,线程执行体在run()中

    • Thread.currentThread()方法总是返回当前在执行的线程对象;
    • getName()方法是 Thread 的实例方法,该方法返回当前线程对象的名字,可以通过setName(String name)方法设置线程名称,否则依次为Thread-0,Thread-1…等
  • JavaSE的程序至少有一个main主线程,它的方法体即是线程体。

  • Thread-0和Thread-1线程虽然都是MyThread类的线程对象,但是各自调用自己的run(),互相之间是独立的。

  • 启动线程用start()方法,而不是run()调用start()方法来启动线程,系统会把该run()方法当成线程执行体来处理。但是如果直接调用run(),系统会把线程对象当成一个普通对象,而run()就是一个普通方法

    2、实现Runnable接口
  • 定义实现 Runnable 接口的实现类,并重写run()方法

  • 创建Runnable实现类对象

4、线程生命周期

线程状态:新建、就绪、运行、阻塞、死亡

  • 新建:当一个 Thread 类或其子类的对象被声明并创建时,此时仅仅由JVM为其分配了内存,并初始化了实例变量的值,此时不会执行线程体run()
  • 就绪:当线程对象调用 start()方法之后,线程就从新建转为就绪状态,这个状态的线程并没有开始运行,但是具备了运行的条件
  • 运行:处于就绪状态的线程获得了CPU,开始执行run()方法
  • **就绪:**当正在运行的线程遇到:
    • 线程调用了 sleep() 方法,主动放弃CPU资源
    • 调用一个阻塞式IO方法
    • 线程试图获取一个同步监视器,但该同步监视器正被其他线程持有;
    • 线程执行过程中,同步监视器调用了wait(),让它等待某个通知(notify);
    • 线程执行过程中,遇到了其他线程对象的加塞(join)
    • 线程被调用suspend方法被挂起(已过时,因为容易发生死锁)
  • **死亡:**结束的线程属于死亡状态
    • run()方法执行完成,线程正常结束
    • 线程执行过程中抛出了一个未捕获的异常(Exception)或错误(Error)
    • 直接调用该线程的stop()来结束该线程(已过时,因为容易发生死锁)

可以调用线程的isAlive()方法判断该线程是否死亡,当线程处于就绪、运行、阻塞三种状态时,该方法返回true,当线程处于新建、死亡两种状态时,该方法将返回false。

程序只能对新建状态的线程调用start(),并且只能调用一次,如果对非新建状态的线程,如已启动的线程或已死亡的线程调用start()都会报错IllegalThreadStateException异常 。

5、继承Thread类和实现Runnable接口两种方式的区别

采用继承Thread的方式:

优势:

(1)直接线程对象启动,比较简单。

(2)如果在线程体中要访问当前线程,直接this即可。

劣势:

(1)Java有单继承线程,继承了Thread类就不能再继承其他类了。

(2)如果多个线程要共享数据,就比较麻烦,使用static的变量共享,范围又太大。

采用Runnable的方式:

优势:

(1)避免单继承;

(2)可以多个线程共享同一个target对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU、代码和数据分开,形成清晰的模型,较好的体现了面向对象的思想。

劣势:

(1)启动线程需要再new Thread的对象;

(2)在线程体中要访问当前对象,需要用Thread.currentThread()先获取当前线程对象。

86、 控制线程

1、线程睡眠:sleep
  • 使线程进入休眠状态(阻塞状态) public static void sleep(long millis,int nanos):在指定的毫秒加纳秒内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响
2、线程让步:yield
  • 可以让当前执行的线程暂停但它不会阻塞线程,只是将该线程转入就绪状态
  • yield只是让当前线程暂停一下,让系统的线程调度器重新调度一次,希望优先级与当前线程相同或更高的其他线程能够获得执行机会
3、线程加塞:join
  • 当在某个线程的线程体中调用了另一个线程的join()方法,当前线程将被阻塞,直到join进来的线程执行完它才能继续
4、停止线程:标识符

87、 守护线程

  • 目的:为其它线程提供服务 ------>jvm的垃圾回收
  • 特点:所有非守护线程死亡,那么守护线程自动死亡
  • 调用 **setDaemon(true) ** 方法可将指定线程设置为守护线程。必须在线程启动之前设置,否则会报IllegalThreadStateException异常。
  • 调用**isDaemon()**可以判断线程是否是守护线程。

88、 线程安全,线程同步

1、线程安全

vector 、statck、hashtable、enumeration

当多个线程共同访问一组数据时,就会发生线程安全问题。

ThreadLocalRandom是线程安全的

2、同步代码块

【线程同步也就是线程安全】

【多线程只要不牵扯操作成员变量的问题,就不会引发线程安全问题】

  • 语法:
    • synchronized(同步监视器对象){ }

线程开始执行同步代码块之前,必须先获得对同步监视器的锁定,换句话说没有获得对同步监视器的锁定,就不能进入同步代码块的执行,线程就会进入阻塞状态,直到对方释放了对同步监视器对象的锁定。

任何时刻只能有一个线程可以获得对同步监视器的锁定,当同步代码块执行结束后,该线程自然会释放对同步监视器对象的锁定。

Java程序运行使用任何对象来作为同步监视器对象,只要保证共享资源的这几个线程,锁的是同一个同步监视器对象即可

89、 同步方法

  • 同步方法就是使用synchronized关键字来修饰某个方法,则该方法称为同步方法。对于同步方法而言,无须显式指定同步监视器,静态方法的同步监视器对象是当前类的Class对象,非静态方法的同步监视器对象是调用当前方法的this对象。
  • 不要对线程安全类的所有方法都加同步,只对那些会影响竞争资源(即共享资源)的方法进行同步即可。而且也要注意同步方法的默认同步的监视器对象对于多个线程来说是否是同一个 。
线程安全的集合

因为Vector是线程安全的集合,打开Vector类的源代码查看,它的很多方法都是同步发方法,即有synchronized修饰。

90、 释放同步监视器的锁定

1、释放锁的操作
  • 当前线程的同步方法、同步代码块执行结束。
    • 遇到break、return终止了该代码块、该方法的继续执行。
    • 出现了未处理的Error或Exception,导致当前线程异常结束。
    • 执行了锁对象的wait()方法,当前线程被挂起,并释放锁。
2、不会释放锁的操作
  • 线程执行同步代码块或同步方法时,程序调用Thread.sleep()、Thread.yield()方法暂停当前线程的执行。
  • 线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该该线程挂起,该线程不会释放锁(同步监视器)。
  • 应尽量避免使用suspend()和resume()这样的过时来控制线程
3、死锁

两个进程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是两个进程都陷入了无限的等待中。不会报异常。

【如何避免线程出现死锁?加大锁的粒度】

91、 线程通讯

  • 线程A在生产数据,线程B在消耗数据,A生产的数据会放在缓冲区中,B也会从缓冲区里拿取数据,问题就是:保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。

存在:

  • 线程安全问题
    • 也就是同步
      • 这里讲的同步是指多个线程通过synchronized关键字这种方式来实现线程间的通信。
  • 线程协调问题:
    • wait()、notify()、notifyAll()方法
      • 让A线程在缓冲区满时调用 等待wait() 方法,进入堵塞,当B消耗后,通知 notify() 使 等待的线程恢复到就绪状态。
      • 也可以使B进入wait,后再利用notify唤醒

92、 单例(单态)设计模式

它是指某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式。例如:代表JVM运行环境的Runtime类。

1、饿汉式

所谓饿汉式,就是在类初始化时,直接创建对象。

优势:因为Java的类加载和初始化的机制可以保证线程安全,所以这类形式的单例设计模式不存在线程安全问题。

【Java加载类是通过一个ClassLoader类加载器来完成的】

劣势:不管你暂时是否需要该实例对象,都会创建,使得类初始化时间加长。

2、懒汉式

所谓懒汉式:即延迟创建对象,直到用户来获取这个对象时,再创建。

优势:不用不创建,用时再创建

劣势:有线程安全问题

93、线程池

94、 网络编程

  • 拓扑结构分:
    • 星型网络、总线网络、环线网络、树型网络、网状网络、混合型网络等。
  • 规模:
    • 局域网、城域网、广域网
  • 互联网:
    • 能够彼此通信设备组成的网络就是互联网,国际标准的互联网写法是internet,字母i小
  • 因特网:
    • 基于TCP/IP 协议实现的,国际标准的因特网写法是Internet,字母I大写。
  • 万维网:
    • 只要应用层使用的是HTTP协议,就称为万维网。
  • 网络协议:
    • OSI把计算机网络分成物理层、数据链路层、网络层、传输层、会话层、表示层、应用层等七层。
    • TCP/IP协议模型,网络通常被分为四层:网络访问层、互联网层、传输层和应用层。
  • IP地址:
    • IP地址还分为IPV4和IPV6 。
      • 公共端口号:0-1023
      • 注册端口号:1024-49151
      • 动态/私有端口:49152-65535
1、InerAddress
  • 表示互联网协议(ip)地址,两个子类Inet4Address和Inet6Address,分别对应IPV4和IPV6。
  • InetAddress ip1 = InetAddress.*getLocalHost*(); 
    
2、URL
  • 用来唯一的标识一个资源
  • URL的基本结构由5部分组成:
    • <传输协议>://<主机名>:<端口号>/<文件名>#片段名
    • <传输协议>://<主机名>:<端口号>/<文件名>?参数列表
  • URL url = new URL(“http://www.baidu.com”);
3、URLConnection
  • URL的方法openStream(),能从网络上读取数据 ,无法给服务器端发送数据
  • URLConnection 给服务器端发送数据
    • URLConnection uc = url.openConnection(); //通过 URL对象调用 openConnection 方法创建URLConnection连接对象
    • uc.setDoOutput(true); //处理设置参数
    • uc.getOutputStream().write(“username=admin&password=123”.getBytes()); //给服务器发送请求参数
    • uc.connect(); //使用 connect 方法建立到远程对象的实际连接。
    • //获取资源
4、 Socket

通信的两端都要有Socket(也可以叫“套接字”),是两台机器间通信的端点。网络通信其实就是Socket间的通信。Socket可以分为:

  • 流套接字(stream socket):使用TCP提供可依赖的字节流服务
  • 数据报套接字(datagram socket):使用UDP提供“尽力而为”的数据报服务
  • 【基于TCP的网络编程都是采用的流套接字,它是面向连接,提供可靠无差错的网络通信】
  • 【基于UDP的网络编程是面向无连接,不可靠的网络通信,大多数网络会议软件都是采用的UDP协议】

95、 基于TCP协议的网络编程

  • TCP(Transmission Control Protocol,传输控制协议)被称作一种端对端协议。是一种面向连接的、可靠的、基于字节流的传输层的通信协议,可以连续传输大量的数据。
  • TCP协议会采用“三次握手”方式让它们建立一个连接。
  • 数据传输完毕TCP协议会采用“四次挥手”方式断开连接。
  • 。。。。。。

96、 基于UDP协议的网络编程

UDP(User Datagram Protocol,用户数据报协议):是一个无连接的传输层协议、提供面向事务的简单不可靠的信息传送服务

UDP协议是一种面向非连接的协议 UDP协议是一种不可靠的协议

1、基于UDP协议的网络编程
  • 基于UDP协议的网络编程仍然需要在通信实例的两端各建立一个Socket,但这两个Socket之间并没有虚拟链路,这两个Socket只是发送、接收数据报的对象,Java提供了DatagramSocket对象作为基于UDP协议的Socket,使用DatagramPacket代表DatagramSocket发送、接收的数据报。
  • 发送端
  • 步骤流程:
    • 建立发送端的DatagramSocket,需要指定本端的端口号
    • 建立数据包DatagramPacket
      • 数据
      • 接收端的IP地址
      • 接收端的端口号
    • 调用DatagramSocket的发送方法
    • 关闭DatagramSocket
  • 接收端
  • 步骤流程:
    • 建立接收端的DatagramSocket,需要指定本端的IP地址和端口号
    • 建立数据包DatagramPacket
      • 需要指定装数据的数组
    • 调用Socket的接收方法
    • 拆封数据
    • 关闭Socke
2、使用MulticastSocket实现多点广播
  • Datagram只允许数据报发送给指定的目标地址,而MulticastSocket可以将数据报以广播方式发送到数量不等的多个客户端。
  • IP协议为多点广播提供了这批特殊的IP地址,这些IP地址的范围是224.0.0.0至239.255.255.255。

97、Lambda表达式

Java 8 于2014年3月14号发布,可以看成是自Java 5 以来最具革命性的版本。

  • lambda表达式其实就是实现SAM接口的语法糖,使得Java也算是支持函数式编程的语言。Lambda写的好可以极大的减少代码冗余,同时可读性也好过冗长的匿名内部类
  • Lambda 表达式时用来实现 SAM 接口的,就是接口中只有一个抽象方法需要实现,当然该接口可以包含其他非抽象方法。
  • 满足 SAM 特征的接口都可以称为函数式接口 ,但是如果要更明确一点,最好在声明接口时,加上@FunctionalInterface。
1、消费型接口

特点:有形参,但是返回值类型是void 。

2、供给型接口

特点:无参有返回值

3、判断型接口

特点:有参,返回值类型是 boolean 结果

4、功能型接口

特点:既有参数又有返回值

5、Lambda 表达式

Lambda表达式是用来实现SAM接口的,它相当于一个匿名函数

  • 格式:
    • (形参列表) -> {Lambda体}
  • 格式要求:
    • 关于(形参列表)
      • 如果没有形参,那么()不可以省略;
      • 如果有形参,并且形参只有一个,并且形参类型已知或可推断,那么可以省略()和数据类型,只写形参名;
      • 如果形参不止一个,那么()不可以省略,但是如果形参类型已知或可推断,那么可以数据类型。
  • 关系{Lambda体}
    • 如果函数式接口的抽象方法有返回值,即返回值类型不是void,那么Lambda体必须要有“return 返回值;”语句;
    • 如果{Lambda体}只有一个语句,那么{}可以省略,如果{}省略了,那么语句后面的;也要省略,如果{Lambda体}只有一个return 返回值;语句,那么{return;}都可以省略,Lambda体只写返回值即可。
6、方法引用和构造器引用
  • 方法引用的语法格式:
    • 类或对象::方法名
  • 构造器引用的语法格式:
    • 类名或数组类型::new
  • 对象::实例方法名
  • 类::静态方法名
  • 类::实例方法名
  • 类名::new
  • 数组类型::new
7、Optional 类

Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

【Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。 】

8、Stream API

Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另外一个则是 Stream API。

Stream API ( java.util.stream) 把真正的函数式编程风格引入到Java中。

Stream是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“集合讲的是数据,负责存储数据Stream流讲的是计算,负责处理数据!”

注意:

  • Stream 自己不会存储元素。
  • Stream 不会改变源对象。每次处理都会返回一个持有结果的新Stream
  • Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行

Stream 的操作三个步骤:

  • 创建 Stream:通过一个数据源(如:集合、数组),获取一个流
  • 中间操作:中间操作是个操作链,对数据源的数据进行n次处理,但是在终结操作前,并不会真正执行。
  • 终止操作:一旦执行终止操作,就执行中间操作链,最终产生结果并结束Stream。

创建 Stream 流

  • 通过集合
    • Java8 中的 Collection 接口被扩展,提供了两个获取流的方法:
      • default Stream stream() : 返回一个顺序流
      • default Stream parallelStream() : 返回一个并行流
  • 通过数组
    • Java8 中的 Arrays 的静态方法 stream() 可以获取数组流:
      • static Stream stream(T[] array): 返回一个流
    • 重载形式,能够处理对应基本类型的数组:
      • public static IntStream stream(int[] array):返回一个整型数据流
      • public static LongStream stream(long[] array):返回一个长整型数据流
      • public static DoubleStream stream(double[] array):返回一个浮点型数据流
  • 通过 Stream 的 of()
    • 可以调用Stream类静态方法 of(), 通过显示值创建一个流。它可以接收任意数量的参数。
      • public static Stream of(T… values) : 返回一个顺序流
  • 创建无限流
    • 可以使用静态方法 Stream.iterate() 和 Stream.generate(), 创建无限流。
      • public static Stream iterate(final T seed, final UnaryOperator f):返回一个无限流
      • public static Stream generate(Supplier s) :返回一个无限流

98、部分总结

1、catch

52、 异常

Java7 新增,一个jdk可以捕获多个异常,多个异常之间用 | 隔开,多异常捕捉是,异常变量之前有隐式 final 修饰

【说明:如果使用一个catch捕获多个异常,必须保证在catch中所有的异常类必须是同一个级别,不能够直接或间接存在继承关系】

2、BigInteger和BigDecimal

位于:java.math 包下

BigInteger可以表示不可变的任意精度的整数

BigDecimal类支持不可变的、任意精度的有符号十进制定点数。(小数)

3、国际化

Java程序的国际化的思路是将程序中的标签,提示等信息放在资源文件中,程序需要支持哪些国家、语言环境,就需要提供相应的资源文件。资源文件是key-value对,每个资源文件中的key是不变的,但value则随不同国家、语言改变。

Java程序的国际化主要通过如下三个类完成:

java.util.ResourceBundle:用于加载一个国家、语言资源包。

java.util.Locale:用于封装一个特定的国家/区域、语言环境。

java.text.MessageFormat:用于格式化带占位符的字符串。

Java国际化的资源文件:

资源文件的名字必须为baseName_language_country

资源文件基名语言代码国家代码.properties

4、Objects 类

JDK7新增的Objects类,Objects提供了一些工具方法来操作对象。

hashCode():返回指定对象的hashCode值。

toString():返回指定对象的“描述性”字符串。

requiredNonNull():检查对象是否为null。

5、Runtime

Runtime类代表Java程序的运行时环境

6、ThreadLocalRandom

ThreadLocalRandom是Java 7新增的,它可以在多线程环境下代替Random减少多线程资源竞争,从而提供更好的线程安全。

ThreadLocalRandom是线程安全的;Random是线程不安全的。

7、JDK8 日期包

在JDK8中新增了一个java.time包。

  • Clock类

    • 用于获取该类用于获取指定时区的当前日期、时间。该类可代替System类的currentTimeMills()方法
  • Duration

    • 代表持续时间,获取一段时间
  • Instant

    • 静态的now()方法来获取clock对应的时刻
    • minuxXxx()方法在当前时刻基础上减去一段时间。
    • plusXxx()方法在当前时刻基础上加上一段时间。
  • LocalDate

  • 不代表时区时间 静态的now()方法来获取当前日期

  • minusXxx()方法在当前年份基础上减去几年、几月、几周或几日等。

  • plusXxx()方法在当前年份基础上加上几年、几月、几周或几日等

  • LocalTime

    • 不代表时区的时间 静态的now()方法来获取clock对应的时间。
    • minusXxx()方法在当前的年份基础上减去几小时、几份、几秒。
    • plusXxx()方法在当前年份基础上加上几小时、几分、几秒等。
  • LocalDateTime

    • 不代表时区的时间 静态的now()方法来获取clock对应的时间。
    • minusXxx()方法在当前的年份基础上减去几年、几月、几日、几小时、几分、几秒等
    • plusXxx()方法在当前年份基础上加上几年、几月、几日、几小时、几分、几秒等。
  • Year,YearMonth,MonthDay

    • MonthDay:该类代表月日
      • 静态的 now() 获取对应的月日
    • Year:该类代表年
      • 静态的now()方法来获取当前年份
      • minusYears()方法在当前年份基础上减去几年
      • plusYears()方法在当前年份基础上加上几年。
    • YearMonth:代表年月
      • 静态的now()方法来获取clock对应的年月。
      • minusXxx()方法在当前年月基础上减去几年、几月
      • plusXxx()方法在当前年月基础上加上几年、几月。
  • DateTimeFormatter

    • java.time.format包下还提供了一个DateTimeFormatter格式化类
    • 使用 DateTimeFormatter 进行格式化或解析,必须先获取其对象,获取其对象的方法
      • 静态常量创建其格式化的对象,DateTimeFormatter 类中有ISO_LOCAL_DATE、ISO_LOCAL_TIME、ISO_LOCAL_DATE_TIME等静态常量,这些静态常量本身就是DateTimeFormatter的实例。
      • 用不同风格的枚举值来创建,在FormatStyle枚举类中定义了FULL、LONG、MEDIUM、SHORT四个枚举值,它们代表日期、时间的不同风格。
      • 根据字符串来创建 DateTimeFormatter 格式类对象
  • 使用DateTimeFormatter将日期、时间(LocalDate、LocalDateTime、LocalTime等实例)格式化为字符串,可以使用以下两种方式:

    1、调用DateTimeFormatter的format(TemporalAccessor temporal)方法进行格式化,其中LocalDate、LocalDateTime、LocalTime等类都是TemporalAccessor接口的实现类。

    2、调用LocalDate、LocalDateTime、LocalTime等日期、时间对象的format(DateTimeFormatter formatter)方法进行格式化。

8、JDK1.8 新增日期时间类型
  • 本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)
    • LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储“生日、纪念日”等日期。
    • LocalTime表示一个时间,而不是日期
    • LocalDateTime是用来表示日期和时间的,这是一个最常用的类之一
  • 瞬时:Instant
    • Instant:时间线上的一个瞬时点。 这可能被用来记录应用程序中的事件时间戳。
  • 带时区的日期、时间的处理

java.time包下的LocalDate、LocalTime、LocalDateTime和Instant基本能满足需求。当你不可避免时区时,ZonedDateTime等类可以满足我们的需求。

  • now():使用系统时间获取当前的ZonedDateTime
  • now(ZoneId):返回指定时区的ZonedDateTime

ZoneId:该类中包含了所有的时区信息,一个时区的ID,如 Europe/Paris

  • getAvailableZoneIds():静态方法,可以获取所有时区信息

  • of(String id):静态方法,用指定的时区信息获取ZoneId对象

Clock:使用时区提供对当前即时、日期和时间的访问的时钟

  • 持续时间:Duration

    • Duration:用于计算两个“时间”间隔
  • 日期间隔:Period

    Period:用于计算两个“日期”间隔

  • 时间校正器

    java.time.temporal .TemporalAdjuster : 时间校正器

    • TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整到“下一个工作日”等操作。
    • TemporalAdjusters : 该类通过静态方法(firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用TemporalAdjuster 的实现。
  • java.time.format.DateTimeFormatter 类

  • 该类提供了三种格式化方法:

    • 预定义的标准格式。如:ISO_DATE_TIME;ISO_DATE
    • 本地化相关的格式。如:ofLocalizedDate(FormatStyle.MEDIUM)
    • 自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)

99、 泛型

JDK1.5改写了集合框架中的全部接口和类,为这些接口、类增加了“类型形参”,这个类型形参将在声明变量、创建对象时确定,即传入实际的类型,称为“类型实参”。把这个“参数化的类型”称为泛型(Generic)。

1、泛型类、接口
  • 我们可以为任何类和接口增加泛型声明,并不是只有集合类才可以使用泛型声明。
  • 泛型形参的命名一般使用单个的大写字母,如果有多个类型形参,那么使用逗号分隔,例如:Map<K,V>。

常见字母(见名知意):

  • T:Type
  • K,V:Key,Value
  • E:Element

泛型类或泛型接口上的泛型形参,不能用于声明静态变量,也不能用在静态方法中,那是因为静态成员的初始化是随着类的初始化而初始化的,此时泛型实参无法指定,那么泛型形参的类型就不确定。

2、泛型实参

泛型实参必须是引用数据类型,不能是基本数据类型,因为集合中只能存储对象。

ArrayList<Integer> list = new ArrayList<Integer>(); 
3、什么时候指定泛型实参
  • 用泛型类、接口声明变量时
  • 在继承泛型类或实现泛型接口时,如果子类不延续使用该泛型,那么必须明确指定实际类型。此时子类不再是泛型类了。
  • 在创建泛型类对象时
4、延续使用父类、父接口的泛型形参
  • 如果继承泛型类、实现泛型接口时,想要继续保留父类、父接口的泛型,必须在父类、父接口和子类、子接口中都要保留泛型。

    //SubArrayList和ArrayList保持一样的泛型字母即可

    class SubArrayList extends ArrayList{ //在子类中泛型形参还是E}

5、设定泛型形参上限
  • 如果泛型形参没有设定上限,那么泛型实参可以是任意引用数据类型。如果泛型形参设定了上限(例如:T extends 父类上限),那么只能指定为该父类本身或其各子类类型。

    ​ 例如:class Student{}

  • 在一种更极端的情况下,程序需要为形参设定多个上限(至多有一个父类上限,可以有多个接口上限)表明该类型形参必须是其父类的子类(包括是父类本身也行),并且实现多个上限接口。

    ​ 例如:class Student<T extends Number & java.io.Serializable> { }

  • 类的上限必须在第一位,其余是接口

6、定义泛型方法

Collection不是Collection类的父类

  • 声明泛型方法
    • 泛型方法的方法签名比普通方法的方法签名多了类型形参声明,类型形参声明以尖括号括起来。
    • [修饰符] <泛型形参列表> 返回类型 方法名([形参列表]) 抛出的异常列表{ //方法体… }

其中泛型形参列表,可以是一个或多个,如果多个,使用逗号分隔,和定义泛型类、接口时一样。而且<泛型形参列表>必须在修饰符和返回值类型之间。

与接口、类声明中定义的泛型形参不同,方法声明中定义的泛型形参只能在当前方法中使用,和其他方法无关。

与接口、类声明中定义的泛型形参不同,方法声明中定义的泛型形参无需显式传入实际类型参数,编译器可以根据实参类型直接推断形参的实际类型。

7、泛型形参的上限

public static void printArea(List graphics){ for (T t : graphics) {System.out.println(t.getArea());}

​ 其实没有设定泛型形参上限的,可以看成它的上限默认是Object。

8、类型通配符

list<?>

9、通配符下限

Java允许设定通配符的下限:<? super Type>,这个通配符表示它必须是Type本身或是Type的父类。

100、 反射

在Java中编译时类型和运行时类型?

答:在Java中,引用变量有两种类型,一种是编译时类型,一种是运行时类型,编译时类型是由声明变量时使用的类型决定,运行时类型是由实际赋给变量的对象决定,例如:Zoon zoo=new Dog();(Dog是Zoon的子类),zoo的编译时类型是Zoon,编译时JVM在栈内存中创建一个引用对象,new Dog()代码运行时JVM在堆内存中开辟一块新的内存空间,所以zoo的运行时类型是Dog

【C:\Users\Lenovo\Desktop\文件接收柜\七\day01\第16章】

110、 JDBC

  • JDBC 是 SUN ,提供的一套用于数据库操作的接口API,JDBC规范定义接口,具体的实现由各大数据库厂商来实现
  • JDBC是一个独立于特定数据库管理系统(DBMS)、通用的SQL数据库存取和操作的公共接口(一组API)
1、使用JDBC的好处
  • 直接底层操作,提供了很简单、便捷的访问数据库的方法,跨平台性比较强。灵活性比较强,可以写很复杂的SQL语句。
  • 使用同一套Java代码,进行少量的修改就可以访问其他JDBC支持的数据库
2、加载和注册驱动
  • 方法:

    • Class.forName(数据库驱动实现类),数据库驱动由mysql厂商提供,它的驱动类是:com.mysql.cj.jdbc.Driver

    • Class.forName(“com.mysql.cj.jdbc.Driver”);

      【从JDBC3开始,Class.forName可以省略】

DriverManager 类
  • 作用:
    • 管理和注册驱动
    • 创建数据库的连接,并返回一个连接对象 Connection
  • DriverManager 中的方法
    • Connection getConnection(String url,String user,String password):通过连接字符串,用户名,密码返回一个数据库连接对象
3、URL 地址格式

URL = “jdbc:mysql://localhost:3306/库名?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8”

4、Connection 接口

Connection接口:具体的实现类由数据库厂商实现,代表一个数据库连接对象

  • Connection方法
    • Statement createStatement():创建一个SQL语句对象
  • Connection conn= DriverManager.getConnection(url,user,password);
5、Statement 接口
  • 作用:
    • 代表一条SQL语句对象,用于发送SQL语句给服务器,用于执行静态SQL语句并返回它所生成结果的对象
  • Statement statement= conn.createStatement();
  • int n=statement.executeUpdate(sql);
  • ResultSet resultSet=statement.executeQuery(sql);
6、释放资源
  • 需要释放的对象,ResultSet结果集,Statement对象,Connection对象
  • 释放原则:先开的后关,后开的先关:ResultSet->Statement->Connection
  • 放在finally代码块中,或者try()自动关闭
7、JDBC 核心API
接口说明
DriverManager管理和注册数据库驱动,得到数据库连接对象
Connection一个连接对象,可用于创建Statement和PreparedStatement对象
Statement一个SQL语句对象,用于将SQL语句发送给数据库服务器
PreparedStatement一个SQL语句对象,是Statement的子接口
ResultSet用于封装数据库查询的结果集,返回给客户端Java程序

111、 数据库

Java中创建对象,对象存储在内存中,学习了IO流,可以把数据存储到文件中。

1、数据库
  • 概念:
    • DB:数据库(Database)即存储数据的仓库,它保存类一系列有组织的数据。
    • 本质上是一个文件系统,还是以文件的方式存储在服务器上的
    • 所有的关系型数据库都可以使用SQL语句进行管理
    • DBMS (DataBase Management System)数据库管理系统:是一种操作和管理数据库的大型软件,例如:数据库的创建、维护等
    • 关系型数据库是目前最普遍的一种数据库类型
2、MySql
  • 优点:
    • 免费
    • 功能强大:
      • MySQL是一种开放源代码的关系型数据库管理系统
      • 关系型数据库:关系型数据库的表采用二维表格来存储数据,是一种按行与列排列的具有相关信息的逻辑组,它类似于Excle工作表
3、数据库管理系统

指一种操作和管理数据库的大型软件,用于建立、使用和维护数据库,对数据库进行统一管理和控制,以保证数据库的安全性和完整性。用户通过数据库管理系统访问数据库中表内的数据

4、管理系统、库、表关系
  • 一个数据库服务器可以包含多个数据库
  • 一个数据库可以包含多张表
  • 每张表中都可以存储多条记录
5、SQL
  • 概念:
    • 结构化查询语言,一个专门用来操作关系型数据库的语言
  • 作用:
    • 是一种所有关系型数据库的查询规范,不同的数据库都支持
    • 通用的数据库操作语言,可以用在不同的数据库中
    • 不同的数据库SQL语句有一些区别
    • SQL规范就是普通话,MYSQL特有(方言)、Oracle特有(方言)
  • 语句:
    • Data Manipulation Language(DML数据操作语言)如,对表中记录操作增删改
    • Data Query Language(DQL数据查询语言),如,对表中的数据进行查询操作
  • 语法:
    • 每条语句以分号结尾
    • SQL中不区分大小写,关键字大写和小写一样
    • 注释: --空格 /**/ #(mysql特有的)
6、创建数据库
  • 语法:
    • CREATE DATABASE 数据库名;
    • 判断数据库是否已经存在,不存在则创建数据库:CREATE DATABASE IF NOT EXISTS 数据库名;
    • 创建数据库并指定字符集:CREATE DATABASE 数据库名 CHARACTER SET 字符集;
7、查看数据库
  • 语法:
    • 查看所有的数据库 show databases;
    • 查看某个数据库的定义信息 show create database 数据库名;
8、修改数据库
  • 语法:
    • 修饰数据库默认的字符集 ALTER DATABASE 数据库名 DEFAULT CHARACTER SET 字符集;
9、删除数据库
  • 语法:DROP DATABASE 数据库名;
10、使用数据库
  • 语法:
    • 查看正在使用的数据库:SELECT DATABASE();
    • 使用/切换数据库:USE 数据库名;
11、面试题

在MYSQL数据库中,有三个数据库,分别是db1,db2,db3,登录数据库之后,输入语句:select database db1 运行结果是什么?

  • 这是一条错误的语句,如果要选中一个数据库,应该使用use db1;

112、 操作表结构

在: 115、MYSQL 约束和设计

前提:先使用库:use 数据库名

1、创建表
  • 语法:
    • CREATE TABLE 表名( 字段名1 字段类型, 字段名2 字段类型 );
2、数据类型
  • 常用数据类型:
    • int -----> 整型 double -----> 浮点类型 varchar -----> 字符串 data -----> 日期格式:yyyy-MM-dd 只有年月日,没有时分秒
  • 详细数据类型:
    • 整数:
      • tinyInt 微整型,很小的整数(占8位)
        smallInt 小整型(占16位)
        mediumint 中整型(占24位)
        int(integer) 整型(32位)
    • 小数:
      • float 单精度
        double 双精度
    • 日期类型:
      • time 表示时间类型
        date 表示日期类型
        datetime 同时可以表示日期和时间类型
    • 字符串:
      • char(m) 固定长度的
        varchar(m) 可变长度的字符串,使用几个字符占用几个,m为0-65535之间的数据
    • 大二进制:
      • blob 允许长度0-65535
        longblob
    • 大文本:
      • text 允许长度0-65535
        longtext 最大可以存储4G的内容
3、创建表:
  • 语法:
    • CREATE TABLE 表名( 字段名1 字段类型, 字段名2 字段类型 );
4、查看表:
  • 语法:
    • 查看某个数据库中所有的表:show tables
    • 查看表结构:DESC 表名;
    • 查看创建表的SQL语句:show create table 表名;
5、复制表(mysql特有)
  • 语法:
    • create table 新表名 LIKE 旧表名;
6、删除表
  • 语法:
    • 直接删除表:DROP TABLE 表名;
    • 判断表是否存在,如果存在则删除表:DROP TABLE IF EXISTS 表名;
7、修改表结构
  • 语法:
    • 添加列:ALTER TABLE 表名 ADD 列名 类型;
    • 修改列类型:ALTER TABLE 表名 MODIFY 列名 新的类型
    • 修改列名:ALTER TABLE 表名 CHANGE 旧列名 新列名 类型
    • 删除列: ALTER TABLE 表名 DROP 列名
    • 修改表名: RENAME TABLE 表名 TO 新表名
    • 修改字符集:ALTER TABLE 表名 character set 字符集
8、操作表中的数据
  • 插入
    • INSTER INTO 表名(字段名1,字段名2,…) values(值1,值2,…)
  • 更新(修改)
    • UPDATE 表名 SET 列名=更新值,列名=更新值
    • UPDATE 表名 SET 列名=更新值,列名=更新值 WHERE 字段名=值 ;
  • 修改
    • 不带条件删除数据:delete from 表名;
    • 带条件删除数据:delete from 表名 where 字段名=值;
    • 重置表:truncate table 表名
      • truncate相当于删除表的结构,在创建一张表,实际上就是表的重置
  • 查询
    • 查询表中所有行和列的数据
      • SELECT * FROM 表名;
    • 查询指定列
      • SELECT 字段名1,字段名2,… FROM 表名;
    • 给列指定别名
      • SELECT 字段名1 AS 别名,字段名2 AS别名 FROM 表名;
    • 查询指定列并且结果不出现重复数据
      • SELECT DISTINCT 字段名 FROM 表名;
    • 列数据算术运算:
      • SELECT 列名1+固定值 FROM 表名;
    • 某列数据和其它列数据参与运算
      • SELECT 列名1+列名2 FROM 表名;
9、条件查询
  • 语法:SELECT * FROM 表名 WHERE 条件;
    • LIKE ‘规则’ 模糊查询,_ 代表一个字符,%代表任意字符

113、封装JDBC

118、JDBC高级---->改进

114、PreparedStatement

1、Statemrnt的不足
  • SQL 注入
  • SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令,从而利用系统的 SQL 引擎完成恶意行为的做法。对于 Java 而言,要防范 SQL 注入,只要用 PreparedStatement 取代 Statement 就可以了
2、处理Blob类型的数据
  • BLOB (binary large object),二进制大对象,BLOB常常是数据库中用来存储二进制文件的字段类型。
  • 插入BLOB类型的数据必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接写的
  • 实际使用中根据需要存入的数据大小定义不同的BLOB类型。 需要注意的是:如果存储的文件过大,数据库的性能会下降。
  • 使用拼接时,有可能用户输入的内容作为了SQL语句语法的一部分,改变了原有SQL真正的含义,称为SQL注入 。
3、PreparedStatement 接口
  • PreparedStatement是Statement接口的子接口,继承了父接口中的所有方法,它是一个预编译的SQL语句。
  • PreparedStatement 会先将SQL语句发送给数据库编译,PreparedStatement会引用预编译后的结果,可以多次传入不同的参数给PreparedSatement对象执行。 l 减少了SQL语句编译的次数,提供了执行效率。
  • 防止SQL的注入问题,提高了安全性

用法:

  • PreparedStatement preareStatement(sql) 指定预编译的SQL语句,SQL语句中使用占位符?表示参数,创建一个语句对象
  • int executeUpdate() 执行DML语句
    ResultSet executeQuery() 执行DQL语句
4、PreparedStatement 好处
  • 会先预编译,PreparedStatement引用预编译的结果,可以多次传入不同的参数,减少了SQL编译次数,提高效率
  • 安全性更高,没有SQL注入的隐患
  • 提高了程序的可读性
5、Statement 和 PreparedStatement之间的关系和区别

118、JDBC高级

  • PreparedStatement继承于 Statement 是其子类

  • PreparedStatement 安全,效率高

  • PreparedStatement 预编译,解决了 Statement 的SQL注入问题

  • 代码的可读性和可维护性. Statement的sql拼接是个难题。

  • PreparedStatement 可以防止 SQL 注入

  • PreparedStatement 可以处理Blob类型的数据

  • PreparedStatement 能最大可能提高性能:(Oracle和PostgreSQL8是这样,但是对于MySQL不一定比Statement高)

    • DBServer(数据库管理工具)会对预编译语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。

115、MYSQL 约束和设计

1、排序
  • ORDER BY 子句
    • 可以将查询的结果进行分组排序
      • SELECT 字段名 FROM 表名 WHERE 字段=值 ORDER BY 排序字段 ASC|DESC
      • 可以与where连用,但order by 必须在where 条件的后面使用,否则会出错
      • ASC 默认升序
      • DESC 降序
  • 单列排序
    • 就是只按某一字段进行排序
      • SELECT 字段名 FROM 表名 ORDER BY 排序字段 ASC|DESC
  • 组合排序
    • 多字段进行排序如果第一个字段相同则按第二个字段排序以此类推
      • SELECT 字段名 FROM 表名 ORDER BY 字段1 [asc|desc],字段2 [asc|desc];
2、聚合函数
  • 聚合函数是纵向查询,它是对一列的值进行计算,然后返回一个结果值,聚合函数都会忽略NULL值。
  • max(列名) 求一列最大值
  • min(列名) 求一列最小值
  • avg(列名) 求一列平均值
  • count(列名) 统计一列有多少条记录
  • sum(列名) 对一列进行求和

语法:

  • SELECT 聚合函数(列名) FROM 表名;
  • 聚合函数对于NULL的记录不会统计,IFNULL(列名,默认值) 如果列名不为空,返回列值,如果为NULL,则返回默认值
3、分组
  • 分组查询是指使用GROUP BY 语句对查询信息进行分组,相同数据作为一组。
    • SELECT 字段1,字段2,… FROM 表名 GROUP BY 分组字段 [HAVING 条件]
4、having 与 where的区别
  • where:
    • 对查询结果进行分组前,将不符合where条件的行去掉
    • 即在分组之前过滤数据,即先过滤再分组
    • where后面不可以使用聚合函数
  • having:
    • having子句的作用是筛选满足条件的组,即在分组之后过滤数据,即先分组再过滤
    • having后面可以使用聚合函数
    • 相当于是 对分组(group by)结果的一个再筛选
5、limit语句
  • limit是限制的意思,所以limit的作用是限制查询记录的条数
    • – SELECT *|字段列表 [as 别名] FROM 表名 [limit 子句]
      – LIMIT offset,length; offset:起始行数,从0开始计数,如果省略,默认就是0 length:返回的行数
    • 一般用于分页查寻
6、备份格式
  • DOS下,不要登录MYSQL数据库,执行:
    • mysqldump –u用户名 –p密码 数据库>文件的路径
7、还原格式
  • mysql中的命令,需要登录后才可以操作
    • USE 数据库;
    • SOURCE 导入文件的路径;
8、数据库约束作用
  • 能确保数据的正确性、有效性和完整性
9、约束分类
  • 主键: primary key
  • 唯一: unique
  • 非空: not null
  • 外键: foreign key
  • 检查约束: check

主键的作用:

  • 用来唯一标识数据库中的每一条记录
  • 设置主键
    • 通常不用业务字段作为主键,单独给每张表设计一个id的字段,把id作为主键。主键是给数据库和程序使用的,不是给最终的客户使用的。所以主键有没有含义没有关系,只要不重复,非空就行。

创建主键:

  • 关键字:primary key
  • 特点:唯一、非空
  • 创建主键方法:
    • 在创建表的时候给字段添加主键
      • 字段名 字段类型 primary key
    • 在已有表中添加主键
      • ALTER TABLE 表名 ADD PRIMARY KEY(字段名)

删除主键约束:

  • 方法:
    • alter table 表名 drop primary key;

主键自增

  • 方法:利用:AUTO_INCREMENT
    • 字段名 数据类型 primary key auto_increment,

修改 AUTO_INCREMENT 的默认值

  • 常见表后在修改

    • 创建好以后修改起始值:

      ALTER TABLE 表名 AUTO_INCREMENT=起始值;

DELETE 和 TRUNCATE 对自增的影响

  • DELETE,删除所有的记录之后,自增没有影响
  • TRUNCATE,删除以后,自增又重新开始

唯一约束

表中某一列不能出现重复值,只能有一个

  • 创建表时:
    • 字段名 数据类型 UNIQUE ,

非空约束

某一列不能为空

  • 创建表时:
    • 字段名 字段类型 NOT NULL

默认值

在常见表时,给予某一字段一个默认值

  • 字段名 字段类型 DEFAULT 默认值;

【如果一个字段设置了非空与唯一约束,该字段与主键的区别?

1、 主键在一个表中,只能有一个,不能出现多个主键,主键可以是单列,也可以是多列(复合主键)

2、 自增长只能用在主键上】

外键约束

外键:在从表中与主表主键对应的那一列

主表:用来约束别人的表

从表:被别人约束的表

  • 添加外键约束
    • 新建表时添加外键
      • [CONSTRAINT][外键约束名称] FOREIGN KEY(外键字段名) REFERENCES 主表名(主键字段名)
    • 已有表添加外键
      • ALTER TABLE 从表 ADD [CONSTRAINT][外键约束名称] FOREIGN KEY(外键字段名) REFERENCES 主表名(主键字段名)

删除外键约束

ALTER TABLE 从表 drop foreign key 外键约束名称;

10、表与表之间的关系
  • 表和表之间的三种关系

    • 一对多:最常用的关系 部门和员工
    • 多对多:学生表和选课表,一门课程可以有多个学生选择,一个学生可以选择多门课程
    • 一对一:相对使用比较少,公民和身份证号码
  • 一对多,主外键关系

  • 多对多,中间表,拆分成两个一对多

  • 一对一:比较的特殊的一对多,从表中的外键设置为唯一;而且从表中的主键又是外键

11、范式

目前关系型数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式、第四范式(4NF)、第五范式(5NF),又称为完美范式。

1NF

2NF

3NF

116、MYSQL 多表查询

1、多表查询分类
  • 分类
    • 内连接
      • 隐私内连接
      • 显示内连接
    • 外连接
      • 左外连接
      • 右外连接
2、内连接

from 后面的是主表

  • 分为:隐式内连接、显示内连接
  • 概述:用主表的记录去匹配从表的记录,符合则显示
  • 特点:内连接:只查询多个表中符合连接条件的记录
  • 说明:
    • 使用内连接(显示、隐式)
      • 都是组合两个表中的记录,返回关联字段相符的记录,也就是返回两个表的交集部分。
3、显示内连接
  • 显示内连接:使用 INNER JOIN … ON 语句,INNER 可以省略
    • select 字段名 from 左表(主表) [inner] join 右表(从表) on 连接条件(左表.主键=右表.外键)
4、隐式内连接
  • 隐式内连接:看不到 JOIN 关键字,条件使用 WHERE 指定
    • SELECT 字段名 FROM 主表(左表),从表(右表) WHERE 连接条件(左表.主键=右表.外键)
5、外连接
  • 分为:左外连接、右外连接
6、左外连接(左连接)
  • 使用:LEFT [OUTER] JOIN…ON,OUTER 可以省略
  • 语法:
    • SELECT 字段名 FROM 主表 LEFT JOIN 从表 ON 条件
  • 特点:
    • 左外连接会把主表(左表)中所有的数据都查询出来,从表中只查询符合连接条件
7、右外连接(右链接)
  • 使用:RIGHT [OUTER] JOIN … ON , OUTER 可以省略
  • 语法:SELECT 字段名 FROM 主表 RIGHT JOIN 从表 ON 条件
  • 右外连接的特点
    • 右外连接会把从表中所有的数据都查询出来,主表只查询符合条件的。
8、子查询
  • 概念:
    • 一个查询的结果作为另一个查询的条件
    • 有查询的嵌套,内部的查询称为子查询
    • 子查询要使用小括号
  • 查询的情况:
    • 结果是单行单列
    • 结果是多行单列
    • 结果是多行多列
9、子查询的结果是一个值
  • 方法:SELECT 字段名 FROM 表名 WHERE 字段=(子查询)
  • 例如:
    • 查询大于员工平均年龄的员工信息
    • select * from employee where age>(select avg(age) from employee);
10、子查询的结果是多行单列
  • 多行单列–>结果类似一个数组,父查询使用 IN 运算符
  • 方法:SELECT 字段名 FROM 表名 WHERE 字段 in (子查询)
  • 逻辑运算符:
    • and 多个条件同时成立
    • or 多个条件任一成立
    • not 不成立
  • 运算符:
    • 单行单列子查询:
      • 单行比较操作符:= 、!= 、>、>=、<、<=
    • 多行单列子查询:
      • 多行比较操作符:IN、NOT IN、ANY、ALL ;
      • IN:检查指定值是否包含在一个值列表中。
      • ANY:用指定值与一个列表中的任意一个值进行比较。
      • ALL:用指定值与一个列表中的所有值进行比较。
    • ANY和ALL必须组合=、!=、>、>=、<、<=来使用。
      • =ANY:与IN操作符相同
      • >ANY:比列表中最小值更大
      • <ANY:比列表中最大值更小
      • >ALL:比列表中最大值还要大
      • <ALL:比列表中最小值还要小
11、子查询的结果是多行多列
  • 子查询的结果只要是多列,肯定在FROM后面作为表
  • 子查询作为表需要取别名,否则这张表没有名称则无法访问表中的字段
  • select ename,dname from (SELECT e.name as ename,e.age,d.dept_name as dname,d.dept_location from dept as d ,employee as e where e.dept_id=d.id) m;
  • 子查询结果只要是单列,则在WHERE后面作为条件
  • 子查询结果只有是多列,则在FROM后面作为表进行二次查询的
  • 【子查询的效率不如多表连接查询】

117、事务

1、事务
  • 事务执行是一个整体,所有的SQL语句都必须执行成功,如果其中任何一条SQL语句出现异常,则所有的SQL语句都要回滚,整个业务执行失败。
  • 事务是在数据库上按照一定的逻辑顺序执行的任务序列

当 操作数据时,保持A数据和B数据总量不变,但A减少后,B并没有增加,而且数据也没有回滚,所以这个程序失败,只有两条SQL都成功了才算成功,这个时候就需要用到事务。

  • 在MYSQL中 有手动提交事务、自动提交事务之分
2、手动提交事务
  • 开启事务: start transaction;
  • 提交事务:commit;
  • 回滚事务:rollback;
  • 提交和回滚相当于同一级别,回滚后也会自动提交

使用过程:

  • 执行成功:开启事务 —> 执行多条SQL语句 —> 成功提交事务
  • 执行失败:开启事务 —> 执行多条SQL语句 —> 事务回滚
3、自动提交事务
  • MYSQL默认每一条DML(增删改)语句都是一个单独的事务,每条语句都会自动开启一个事务,语句执行完毕自动提交事务,MYSQL默认开启自动提交事务。

自动提交

  • 查看MYSQL 是否开启自动提交事务:select @@autocommit;
    • @@表示全局变量 1 表示开启 0 表示关闭
  • 取消自动提交事务:set @@autocommit = 0;
4、事务原理

事务开启之后,所有的操作都会临时保存到事务日志中,事务日志只有在得到commit命令才会同步到数据库中,其它任何情况(rollback,断开连接)都会清空事务日志。

5、事务的步骤
  • 客户端连接数据库服务器,创建连接时此用户临时日志文件

  • 开启事务以后,所有的操作都会先写入到临时日志文件中

  • 所有的查询操作从表中查询,但会经过日志文件加工后才返回

  • 如果事务提交则将日志文件中的数据写到表中,否则清空日志文件

6、回滚点
  • 概述:
    • 在某些操作完成之后,后续的操作可能会失败,但是前面的操作是正确并且成功的,此时就可以在这成功的位置设置一个回滚点,即使后续的操作失败,返回时也不会返回所有的操作,而是返回到这个回滚点的位置,就会停止
  • 在开启事务之后,才会有回滚点
  • **设置回滚点:**savepoint 名字;
  • 回到回滚点:rollback to 名字;
7、事物的隔离级别
  • 事物的四大特征:
    • 原子性
      • 每个事务都是一个整体,不可再拆分,事务中所有的SQL语句除了全部成功就是全部失败
    • 一致性
      • 事务在执行前和执行后的数据总体状态保持不变
    • 隔离性
      • 事务和事务之间不应该互相影响,执行时保持隔离的状态
    • 持久性
      • 一旦事务执行成功,对数据库的修改是持久性的
  • 事务在操作时理想状态:
    • 所有的事务之间保持隔离,互不影响。因为开发中,多个用户同时访问一个数据,可能引发并发访问的问题。
  • 并发访问问题:
    • 脏读
      • 一个事务读取到另一个事务中尚未提交的数据
    • 不可重复读
      • 一个事务中两次读取的数据不一致,要求的是一个事务中多次读取数据是一致的,这是事务update时引发的问题
    • 幻读
      • 一个事务中两次读取的数据的数量不一致,要求在一个事务多次读取的数据的数量是一致的,这是insert或delete时引发的问题
  • 隔离级别
级别名字隔离级别脏读不可重复读幻读数据库默认级别
1读未提交read uncommitted
2读已提交read commitedOracle和SQL Server
3可重复读repeatable readMYSQL
4串行化serializable
  • 查询、设置隔离级别
    • 查询全局事务隔离级别
      • MYSQL8 : SELECT @@transaction_isolation;
      • MYSQL5:SELECT @@tx_isolation
    • 设置事务隔离级别,需要退出MYSQL再重新登录才能看到隔离级别的变化
      • set global transaction isolation level 级别字符串
      • global 全局的
8、mysql
  • mysql 默认账号是 root,它是mysql的超级管理员,拥有全部权限
  • mysqld是mydql的主程序,服务器端,mysql是mysql的命令行工具,客户端
9、创建用户
  • 语法:
    • CREATE USER ‘用户名’@‘主机名’ IDENTIFIED BY ‘密码’;
      • 用户名:创建的用户名
      • 主机名:本地是:localhost 任意电脑是:%
      • 密码:用户的登陆密码,可以为空
    • 创建的用户信息都在mysql数据库中的user表中看到
      • use mysql;
      • select host , user from user;
  • 给用户授权
    • 用户创建后没有任何权限
    • 语法:GRANT 权限1,权限2, … ON 数据库.表名 TO ‘用户名’@ ‘主机名’;
      • 权限:CREATE、ALTER、SELECT、INSERT、UPDATE等,如果要授予用户所有权限使用ALL
      • 数据库.表名:所有库 —> * . * 在A库中的所有的表 —> A.* .*
    • 例如:
      • 给user1用户分配db2中所有表,创建,修改,插入等权限
        • grant create,alter,insert,update,select on db2.* to ‘user1’@‘localhost’;
      • 给user2用户分配所有的权限,对所有的数据库的所有表。
        • grant all on . to ‘user2’@’%’ ;
  • 撤销权限
    • 语法:
      • REVOKE 权限1,权限2 ON 数据库.表名 from ‘用户名’@’主机’;
  • 查看权限
    • 语法:
      • show grants for ‘用户名’@’主机名’ ;
  • 删除用户
    • 语法:
      • DROP USER ‘用户名’@’主机名’ ;
  • 修改管理员密码
    • 语法:
      • mysqladmin –uroot –p password 新密码,然后点击回车,输入旧密码,密码修改成功
  • 修改普通用户密码
    • 语法:
      • 需要使用管理员账号登录MYSQL情况下,才可以修改普通用户的密码:
      • MYSQL8
        • alter user ‘用户名’@‘主机’ identified by ‘新密码’;

118、JDBC高级

1、PreparedStatement
  • PreparedStatemrnt 和 Statement 区别

    114、PreparedStatement —>5

2、批处理
  • 当需要成批插入或者更新记录时。可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率。
  • JDBC 批处理语句:
    • addBarch():添加需要批量处理的SQL语句或参数
    • executeBatch():执行批量处理语句
  • 注意:
    • JDBC连接MySQL时,如果要使用批处理功能,请再url中加参数 ?rewriteBatchedStatements=true PreparedStatement作批处理插入时使用values(使用value没有效果)
    • 一般不加也可以
3、事务
  • JDBC程序中当一个连接对象被创建时,默认情况下是自动提交事务:每次执行一个 SQL 语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
  • JDBC程序中为了让多个 SQL 语句作为一个事务执行:(重点)
    • 调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务
    • 在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务
    • 在其中某个操作失败或出现异常时,调用 rollback(); 方法回滚事务
    • 若此时 Connection 没有被关闭, 则需要恢复其自动提交状态 setAutoCommit(true);
  • 注意:
    • 如果多个操作,每个操作使用的是自己单独的连接,则无法保证事务。即同一个事务的多个操作必须在同一个连接下
5、数据库连接池
  • 不使用数据库连接池存在的问题:

    • 普通的JDBC 数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证IP地址,用户名和密码,需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接。这样的方式将会消耗大量的资源和时间。数据库的连接资源并没有得到很好的重复利用,同时访问量增多,则可能造成服务器的崩盘
    • 对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将导致重启数据库。
    • 这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃

    解决这种问题,采用 数据库连接池技术(connection pool)

数据库连接池
  • 数据库连接池

    • 数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”
    • 预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个使用完毕之后再放回去。
    • 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个
    • 连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中
      • 【在缓冲池中有一定数量的连接,当需要和数据库进行连接时,就会抽取一个,在缓冲池中完成了对数据库的链接等操作,并且可以重复使用一个数据库,而不是使用一个建立一个】
数据库连接池优点
  • 使用数据库连接池的优点

    • 资源重用:
      • 由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性。
    • 更快的系统反应速度
      • 数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间
    • 新的资源分配手段
      • 对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制避免某一应用独占所有的数据库资源
    • 统一的连接管理,避免数据库连接泄露
      • 在较为完善的数据库连接池实现中,可根据预先的占用超时设定强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露
  • 开源的数据库连接池

JDBC 的数据库连接池使用 javax.sql.DataSource 来表示,DataSource 只是一个接口,该接口通常由服务器(Weblogic, WebSphere, Tomcat)提供实现,也有一些开源组织提供实现:

  • DBCP、C3P0、Druid、等等

注意:

  • 数据源和数据库连接不同数据源无需创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可。
  • 当数据库访问结束后,程序还是像以前一样关闭数据库连接:conn.close(); 但conn.close()并没有关闭数据库的物理连接,它仅仅把数据库连接释放,归还给了数据库连接池
6、Druid(德鲁伊)数据源

Druid是阿里巴巴开源平台上一个数据库连接池实现,它结合了C3P0、DBCP、Proxool等DB池的优点 ,据说是目前最好的连接池。

  • 需要导包:
    • druid-1.2.1.jar 包

119、ThreadLocl(线程局部变量)

1、ThreadLocal

JDK 1.2 版本提供了 java.lang.ThreadLocal

  • ThreadLocal (线程局部变量)功能:
    • 为每一个使用该变量的线程都提供了一个变量值的副本,是一种特殊的系统绑定机制,每一个线程都可以拥有自己的副本,而不会与其它线程(副本)进行冲突
  • ThreadLocal 它可以为每一个线程提供一个共享变量的副本,每个线程都可以对自己的副本进行操作,不会影响其它线程中的数据
    • 也就是:把某个共享变量和当前线程进行绑定,只要在当前线程上任何时候获取的这个共像变量是一个
  • 总结:
    • ThreadLocal 使用场合主要解决多线程中数据因并发产生的不一致问题
    • 会为每一个线程中并发访问的数据提供一个副本,通过副本来访问数据在副本中操作,也就是通过访问副本来运行业务,这样会消耗内存,但大大减少了线程同步所带来的性能消耗,也减少了线程并发控制的复杂度(建立的自己的副本,并在副本中访问的数据,改变的是自己副本中的数据,不是线程中的)
    • ThreadLocal 不能使用原子类型,只能使用 Object 类型,
    • ThreadLocal的使用比Synchronized 要简单的多
  • ThreadLocal与synchronized相同、区别:
    • 相同:
    • 解决多线程并发访问
    • 不同:
      • Synchronized 利用的时锁的机制,使用变量或代码块在某一时刻只能让一个线程访问
      • 而ThreadLocal则为每一个线程提供了一个副本,使每个线程在某一时间访问的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。
      • Synchronized 用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
    • ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂。
2、使用步骤
  • 先封装一个类,在这个类中完成对数据库的连接操作

    • 获取连接或释放连接的工具类 ,步骤:
      • 获取数据源,即连接池 private static DataSource dataSource;
      • ThreadLocal 对象 :private static ThreadLocal threadLocal;
      • 进行连接库,并且连接连接池和创建线程池
    • 获取连接方法:
      • 获取当前线程中连接
      • 在连接池中获取一个连接
      • 将连接与当前线程绑定
    • 释放连接
      • 获取当前线程连接
      • 将已关闭的连接从当前线程中移除
  • 相当于一个访问连接,已经都连接好,节省时间

3、Apache----DBUtils
  • commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。
  • 需要导包:
    • commons-dbutils-1.6.jar 包

DBUtils

提供如关闭连接、装载JDBC驱动程序等常规工作的工具类,里面的所有方法都是静态的。

4、QueryRunner类

该类封装了 SQL的执行,是线程安全的

  • 可以实现增、删、改、查、批处理(118---->3)、

  • 考虑了事务处理需要共用Connection。

  • 该类最主要的就是简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。

QueryRunner类提供了两个构造方法:

  • QueryRunner():默认的构造方法
  • QueryRunner(DataSource ds):需要一个 javax.sql.DataSource 来作参数的构造方法。

更新、插入、批处理、使用QueryRunner类实现查询(会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。 )

5、ResultSetHandler 接口

该接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。ResultSetHandler 接口提供了一个单独的方法:Object handle (java.sql.ResultSet rs)该方法的返回值将作为QueryRunner类的query()方法的返回值

  • 表与JavaBean
    • int,double等在Java中都用包装类,因为mysql中的所有类型都可能是NULL,而Java只有引用数据类型才有NULL值
    • 通过给列取别名的方式,来告知数据库的列名与其对应实体的属性名

120、Junit 单元测试

1、概述
  • 软件测试分类:
    • 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望值
    • 白盒测试:需要写代码,关注程序具体的执行流程
  • junit是一个java语言的单元(就是方法)测试框架,属于白盒测试
    • 可以用于取代main方法,junit属于第三方工具,需要导入jar包后使用
  • 包:
    • hamcrest-core-1.3.jar
    • junit-4.12.jar
2、使用
  • 编写测试类,简单理解为junit可以用于取代java的main方法

  • 在测试类方法上添加注解@Test

  • @Test修饰的方法要求:public void 方法名(){},方法名自定义建议test开头,没有参数

  • 添加junit jar包到lib文件夹中,然后进行jar包关联

3、常用注解
  • @Test,用于修饰要执行的测试方法
  • @Before,修饰的方法会在测试方法之前被自动执行,常用来在测试时进行数据的初始化工作
  • @After,修饰的方法会在测试方法执行后自动被执行,常用来在测试时进行资源的销毁

在方法之前进行注解:

​ @Test

​ public void a(){}

4、IDEA 导出jar包
  • 步骤:
    • step1:Project Structure
    • step2:Artifacts —> + —> JAP —> From modules with dependencies…
    • step3:选择 Module和Main Class —> OK
    • step4:Build —> Build Artifacts —> Build
    • step5:jar包的运行命令: java –jar xxx.jar

121、注解

1、概述
  • 注解(Annotation),也叫元数据(元数据:就是用来描述数据的数据)。一种代码级别的说明,它是JDK1.5及其以后版本引入的一个特征,与类、接口、枚举是在同一个层次。
  • 它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明。
  • 作用分类:
    • 编写文档:通过代码里标识的注解生成文档
    • 代码分析:通过代码里标识的注解对代码进行分析
    • 编译检查:通过代码标识里的注解让编译器能够实现基本的编译检查【@Override】
2、定义
  • 一:
    • 可以生成一个注解文件
  • 二:
    • public @interface 注解名称{ 属性列表;}
3、注解的属性
  • 属性作用:

    • 可以让用户在使用注解时传递参数,让注解的功能更加强大
  • 属性格式:

    • 格式1:数据类型 属性名();
    • 格式2:数据类型 属性名() default 默认值
  • 属性数据类型:

    • 八种基本数据类型
    • String类型,Class类型,枚举类型,注解类型
4、使用注解(示例)
//定义注解
public @interface Stud {
    String name();
    int age();
    String sex() default "男";
}
//使用注解类 Stud
//@Stud("小明",22)  报错
@Stud(name="小明",age=22)  //性别默认值
public class Stud01 {
    @Stud(name="小兰",age=121)
    private static String studin;
    public static void main(String[] args) {
        a();
    }
    @Stud(name="小红",age=23,sex="女")
    public static void a(){
        System.out.println("aaa");
    }
}
5、特殊属性 Value
  • 条件:
    • 当注解中只有一个属性且名称是value,在使用注解时给value属性赋值可以直接给属性值,无论value是普通类型还是数组类型。
    • 如果注解中除了value属性还有其它属性,且至少有一个属性没有默认值,则在使用注解给属性赋值时,value属性名不能省略
  • 示例:
public @interface Book {
    String value();
}
//@Book(value = "xzxzx")
@Book("xzxzx")
public class Book01 {

    @Book("asa")
    public void a(){}
}
6、元注解
  • 默认情况下:
    • 注解能应用在任意地方
    • 如果想要限制,通过元注解实现
  • 元注解之**@Target:**不写则是默认,默认是任意地方都可使用
    • 可选的参数值在枚举类ElementType中包括:
      • TYPE:用在类,接口上
      • FIELD:用在成员属性上
      • METHOD:用在方法上
      • PARAMTER:用在参数上
      • CONSTRUCTOR:用在构造方法上
      • LOCAL_VARIABLE:用在局部变量上
  • 元注解之**@Retention:**作用:定义该注解的生命周期(有效范围)
    • 可选参数值在枚举类:RetentionPolicy中包括
      • SOURCE:注解只存在与java源代码中,编译生成的字节码文件就不存在
      • CLASS:注解存在于java源码中、编译以后的字节码文件中,运行的时候内存中没有,默认
      • RUNTIME:注解存在与Java源码中、编译后的字节码文件中、运行时内存中,程序可以通过反射获取该注解
7、注解的解析

注解解析就是通过java技术获取注解数据的过程 。

8、与注解相关的接口

Annotation:所有注解类型的公共接口,类似所有类的父类是Object

AnnotatedElement:定义了与注解解析相关的方法

  • 如果注解作用在方法上,就通过方法(Method)对象得到它的注解
  • 如果注解作用在类上,就通过Class对象得到
9、通过反射来获取注解的数据
//注解类 Stab
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Stab {

    String name();
}
//引用注解类的普通类
@Stab(name="aa")
public class Strance01 {
    @Stab(name="bb")
    public void aa(){
    }
}
/利用反射 测试 
public class StaTest {
    @Test
    public void TestOne(){
        Class c = Strance01.class;
        if (c.isAnnotationPresent(Stab.class)){
            Stab stab = (Stab)c.getAnnotation(Stab.class);
            System.out.println("name:"+stab.name());
        }
    }

    @Test
    public void TestWor()  {
        Class<?> a = Strance01.class;
        Method m = null;
        try {
            m = a.getDeclaredMethod("aa");
            if (m.isAnnotationPresent(Stab.class)){
                Stab stab = m.getAnnotation(Stab.class);
                System.out.println("name:"+stab.name());
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

122、HTML中的简单应用

1、概念
  • 超文本标记语言(英语:HyperText Markup Language,简称:HTML)是一种用于创建网页的标准标记语言。
  • 后缀:.html/.htm
  • <!DOCTYPE html> 是 html5
  • <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">是 html4
  • <meta charset="utf-8"> 定义网页编码格式为 utf-8。
  • HTML 不是一种编程语言,而是一种标记语言,超文本标记语言
  • HTML 使用标记标签来描述网页
  • HTML 文档包含了HTML 标签文本内容
  • HTML文档也叫做 web 页面
2、HTML5常用标签
  • 标题:<h1> - <h6>

  • 段落:<p>

  • 换行<br>

  • 着重:<em> </em>

  • 上标字:<sup></sup>

  • 下标字:<sub></sub>

  • 预格式文本:<pre></pre>

  • 斜体:<i></i>

  • 水平线:<hr>

  • 链接:<a href=" "></a>

  • 图像:<img src=" " width=" " hright=" ">

  • <link>元素:

    • 链接的是文档外的资源
    • <link rel="stylesheet" type="text/css" href="资源地址">
  • 表格:

   <table>定义表格

    ​	<tr>定义表格行

    ​		<td>定义表格单元</td></tr>

    </table>

 
  <th>定义表格的表头</th>

   <caption>定义表格标题</caption>

   <colgroup>定义表格列的组</colgroup>

   <thead> 定义表格的页眉</thead> 

   <tbody> 定义表格的主体</tbody>

   <tfoot>  定义表格的页脚</tfoot>
  • 列表:

    • 无序列表:

<ul><li></li>

      </ul>
  • 有序列表:

<ol><li></li>

      </ol>
  • 自定义列表:
   <dl><dt><dt><dd></dd><dd></dd>

      </dl>
  • 表单:
<from><input>

</from>
  • 输入:

    • 用户名:<input type="text" name="Username" placeholder="请输入用户名"> <br/>
    • 密 码: <input type="password" name="password" placeholder="请输入密码"><br/>
  • 提交:

    • 提交1: <input type="submit" value="提交,转入"><br>
    • 提交2: <button type="submit">提交,转入</button><br>
    • 提交按钮,点击会将表单中数据提交到 中的action中的地址里去
  • 按钮:

    • 按钮:<input type="button" value="普通按钮,button"><br/>
    • 按钮:<button>普通按钮</button><br/>
    • 按钮,普通按钮,不会提交
  • 音频:

    • 标签定义声音,比如音乐或其他音频流

<audio controls>  <!--control 属性供添加播放、暂停和音量控件。--><source src="https://www.runoob.com/try/demo_source/horse.ogg" type="audio/mpeg"></audio>
  • 视频:

    • 标签定义视频,比如电影片段或其他视频流。

<video width="320" height="240" controls>   controls 控制视频

      ​        <source src="https://www.runoob.com/try/demo_source/movie.mp4" type="video/mp4">
        </video>
3、CSS
  • 概念:
    • CSS通常称为CSS样式或层叠样式表,主要用于设置HTML页码中的文本内容(字体、大小、对齐方式等)、图片的外形(高度、边框样式、边距等)以及版面的布局等外观显示样式。
  • 解释:
    • CSS(Cascading Style Sheets):层叠样式表
    • **样式:**给HTML标签添加需要显示的效果
    • **层叠:**使用不同的添加方式,给同一个HTML标签添加样式,最后所有的样式叠加在一起,共同作用于该标签。
  • CSS样式规则:
    • 选择器{属性1:属性值;属性2:属性值;……}
      • 属性和属性值以键值对方式出现,使用英文的冒号:分割,多个属性之间使用英文分号;分割
  • CSS样式规则规范:
    • CSS样式“选择器”严格区分大小写“属性”和“属性值”不区分大小写
    • 多个属性之间必须用英文的分号隔开,最后一个属性的分号可以省略,为了便于增加新样式最好保留
    • 如果属性的值有多个单词组成且中间包含空格,则必须为这个属性值添加英文状态下的引号。例如:p{font-family:”Times New Roman”}
    • 在编写CSS代码时,为了提高代码的可读性,通常会加CSS注释,例如: / 注释内容 */*,注释的内容不会再浏览器中显示
    • 在CSS代码中空格是不被解析的,花括号以及分号前后的空格可有可无。因此,可有使用空格键、Tab键、回车键等对样式代码进行排版,即所谓的格式化CSS代码。这样可有提高代码的可读性。
4、引入CSS样式:

​ 如果是单独的CSS文件,则必须以**.css**为扩展名

  • 行内样式: 通过标签的 style 属性设置元素的样式
    • CSS行内样式

    • 没有做到结构效果分离
  • **内部样式:**在文档的 中使用
  • 内嵌式CSS样式只对所在的HTML页面有序,可以对多处标签同一设置样式,因此,仅设计一个页面时,使用内嵌样式是个不错的选择
  • **外部样式:**一个.css文件
    • 利用 引入外部的 .css 文件,来对文档进行样式
      • rel=“stylesheet”,固定值,当前文件和引入文件的关系,rel是relationship的缩写
      • stylesheet是样式表
      • type=“text/css”,固定值,表示浏览器解析方式
      • href=“xxxx.css”,表示CSS文件的位置
    • 链入式最大的好处是同一个CSS样式表可以被不同的HTML页面链接使用,同时一个HTML页面也可以通过标签链接多个CSS样式表。
  • 5、选择器
    • 元素选择器、类选择器、id选择器
    • 更多选择器:【https://www.runoob.com/cssref/css-selectors.html】

    113、属性、标签

    1、属性、标签css
    • background:

      • /* background-image: url("../imgs/img.PNG")   设置网页背景是图片*/
        /*background-attachment: fixed; background-attachment: scroll;  设置背景和字体是否一起滚动*/
        /*background-repeat: no-repeat;   设置图片是否平铺*/
        
      • background-position:xxxx; 设置图片初始位置

    • border:

      • .p_01{border-style: none}/*无边框*/
        .p_02{border-style: dotted}/*虚线边框*/
        .p_03{border-style: dashed}/*虚线边框*/
        .p_04{border-style: double}/*双线边框*/
        .p_05{border-style: groove}/*凹边框*/
        .p_06{border-style: inset}/*嵌入框*/
        .p_07{border-style: outset}/*外凸边框*/
        .p_08{border-style: hidden}/*隐藏边框*/
        .p_09{border-style: ridge}/*垄状边框*/
        
      • .p_01{border-style: dotted solid double dashed}/*上右下左*/
        
    • 链接:

      • a:link {color:#000000;}      /* 未访问链接*/
        a:visited {color:red;}       /* 已访问链接 */
        a:hover {color:#FF00FF; font-size: 20px}     /* 鼠标移动到链接上 */
        a:active {color:#0000FF;}    /* 鼠标点击时 */
        
    • 下划线:

      • .te_01{text-decoration: underline}/*文字下划线*/
        .te_01{text-decoration: overline}/*文字上划线*/
        .te_01{text-decoration: line-through}/*文字中划线*/
        
        .p_a a{text-decoration: none} /*删除默认下划线*/
        
    2、属性、标签css
    • float:浮动

      • 会影响周围的元素
      • clear:清除
    • 居中、垂直居中

      •  text-align: center; line-height:xxxpx;
        
    • 圆角

      • .yj{border: 3px solid red; border-radius: 5px; margin-top: 10px}
        
    • 布局

      • .di_te01{width: 150px;height: 150px; overflow: scroll}/*显示滚动条,右侧和下方*/
        .di_te02{width: 150px;height: 150px; overflow: hidden}/*超出大小的内容无法显示*/
        .di_te03{width: 150px;height: 150px; overflow: auto}/*滚动条仅右侧*/
        .di_te04{width: 150px;height: 150px; overflow: visible}/*默认值,超出显示*/
        /*overflow: inherit  继承父类的overflow属性*/
        
    • 边距

      • 内边距 :padding
      • 外边距:margin

    114、WEB开发简介

    1、Web
    • 概述:
      • Web 互联网总称
      • web 即全球广域网,也称万维网,是一种基于超文本的和HTTP的、全球的、动态交互的、跨平台的分布式图形信息系统
    2、JavaWeb开发中的资源
    • 静态的web资源
      • HTML
      • CSS
      • JavaScript
    • 动态的web资源
      • Servlet
      • JSP
    3、URL请求路径
    • URL
      • 统一资源定位符是对互联网上资源位置的一种表示,互联网上的每个文件都有一个唯一的标识URL
    • URL 格式:
      • 协议://域名:端口号/资源位置?参数=值&参数2=值
        • 协议:http、https、ftp等
        • 端口号:使用端口号,才能让另一个计算机访问
          • http端口:80 https端口:443
        • 资源位置:描述web资源在服务器上的位置
        • 参数=值:浏览器和服务器交换数据传递的参数
    4、软件结构分类
    • CS结构
      • C:Client S:Server 客户端和服务器。
      • 优点:
        • 减轻服务器压力,客户端也会携带部分代码
        • 界面美观,速度快
      • 缺点:
        • 服务器更新,客户端也必须更新
        • 分布式开发较弱
        • 人力资源成本大
    • BS结构
      • B:Browser S:Server 浏览器和服务器
      • 优点:
        • 专注于服务器开发即可
        • 分布式开发较器强
      • 缺点:
        • 服务器压力问题
        • 网速问题
    5、WEB服务器

    只要是遵循HTTP协议而设计的网络应用程序都可以是Web客户端。 Web服务器 约等于 HTTP服务器 + 其他服务

    • 服务器:
      • 硬件:一台电脑
      • : 为Web提供服务
    • 流程
      • 客户端浏览器发送请求,服务器接收请求并处理,将处理的结果相应到客户端
      • TomCat接收客户端的请求,并将数据相应给客户端
    6、常见的WEB服务器
    • 常见的web服务器
      • TomCat(免费)、WebSphere、WebLogic、IIS、Apache

    115、Tomcat 服务器

    1、TomCat 概述:
    • Tomcat就是一个web的服务器,用来发布web项目。
    • Tomcat目前存在很多版本,你需要了解tomcat的版本和规范之间的关系
    • 官方网站:http://tomcat.apache.org
    2、Tomcat:
    • 启动:
      • tomcat解压目录/bin/startup.bat双击运行启动tomcat
      • 访问路径,http://localhost:8080
    • 关闭:关闭tomcat,在bin目录下有一个shutdown.bat,双击即可
    • 作用:
      • 一个免费开源的WEB应用服务器,用户通过浏览器发送的http请求,通过tomcat发送到服务器,在经过tomcat返回到浏览器

    116、HTTP协议

    1、Http简介:
    • HTML:超文本标记语言

    • HTTP协议:超文本传输协议,是定义WEB浏览器与WEB服务器之间交换数据的过程

      • 请求:resquest
      • 响应:response
      • 必须是现有请求再有响应
    2、作用、特点:
    • 作用:一种网络协议
    • 特点:
      • 基于请求/响应的协议:
        • 请求和响应必须成对
        • 先有请求后又响应
      • 简单快捷
        • 发送请求时只需要发送请求的方式和请求路径即可
      • HTTP协议默认端口号:80
      • 是一种明文协议、无状态协议(无状态是服务器端不会记录客户端的任何信息)
    3、版本、报文格式:
    • 版本:HTTP/1.0 和 HTTP/1.1
    • 报文格式
      • 请求报文:客户端向服务器端发出的报文
      • 响应报文:服务器到客户端的报文
    4、HTTP 协议之HTTP请求报文格式:
    • 请求行、请求头、空行、请求体

    • 请求头和请求体之间有空行

    • 只有POST请求时,才会有请求体,如果是GET请求,给服务器端的数据会直接放在URL的后面,不安全

    • 请求行:

      • 格式:
        • 请求方式 资源路径 协议/版本
        • 请求方式:常用的是 GET\POST
          • GET请求:
            • 将自己请求的数据(请求参数),追加到URL后面
            • URL长度限制GET请求方式的数据大小
            • 没有请求体
          • POST请求:
            • 请求参数显示在请求体处,比较安全
            • 没有数据大小的要求
      • 只有在表单中设置 method=”post“ 才是post请求。一般默认是 get 请求
    • 请求头:

      • 客户端向服务器发送的协议、编码、内容长度等,请求头也是键值对 key:value
    • 请求体:

      • 只有post请求方式才会使用到请求体,请求体中的数据是用户提交的数据,是key=value键值对,多组使用&链接。
    • MIME 类型

      • 互联网内容类型的标准
        • html–>text/html
    5、HTTP协议之HTTP响应报文:

    格式:响应行、响应头、空行、响应体

    • 响应行:
      • 协议/版本 状态码 状态码描述
      • 状态码:
        • 200成功
        • 404:资源不可访问,一般路径问题
        • 304:缓存
        • 500:错误
    • 响应头:
      • 服务器给客户端返回一些描述
      • 而是键值对
    • 响应体:
      • 就是服务器发送给浏览器的内容

    117、Servlet

    1、概述:
    • 没有main方法,具有独立于平台和协议的特性,主要功能在交互式浏览和生成数据、生成动态的WEB内容
    • Servlet 也是指Java中的一个接口
    • Servlet 必须运行在一个WEB容器中
    • Servlet 支持多线程,避免线程安全问题,一般不在Servlet中操作全局变量
    • 可以接受请求并做出响应
    2、执行原理:
    • Tomcat 容器(引擎)执行的操作:
      • 接受客户端浏览器的请求:URL
      • 在web.xml 中解析URL 并找到相应的Servlet文件
      • Tomcat会为当前的Servlet对象作初始化,并且创建 request、response
      • 调用Servlet 接口中的 service 方法来处理请求,并作出响应,响应的数据会写在 response 对象的缓冲区中
      • service方法结束后,数从 response 的缓冲区取出,组装成HTTP响应信息,再交给Tomcat对象
      • 最后,再由Tomcat容器将相应的结果,回传给客户端的浏览器
    3、生命周期Servlet:
    • Servlet 对象的创建和生命周期的管理都是由Tomcat负责的
    • 生命周期
      • 用户发送请求,到达web容器,然后web根据其URL,与web.xml进行匹配,找到对应的Servlet 类。
      • 然后容器会判断这个类是否已经存在,如果存在就之间调用servlet方法
      • 如果不存在 就会调用Servlet类的参构造方法,创建对象,创建完成后,就会自动调用 init()方法,进行对Servlet对的初始化,后再回自动调用service方法,对用户的请求进行处理
      • 当web容器停止工作后,容器就会自动调用 servlet中的destroy方法,进行servlet的销毁,释放资源
    • init(ServletConfig config) Servlet对象的初始化方法,对象被创建的时候自动回调
      • 只会执行一次
    • service(request,response)客户端访问一次,执行一次
      • 客户端发送一次请求,service处理一次
    • destory()方法,Servlet对象销毁时调用
      • 仅执行一次,进行销毁,然后垃圾回收器将Servlet对象回收
    • Servlet对象什么时候被创建
      • 默认情况下,第一次访问的时候,对象被创建 也可以在tomcat容器启动时就创建Servlet的对象,需要修改web.xml(一般不配置)
      • 容器启动时,就创建servlet的对象,正整数,值越小优先级越高
        • 0

    118、HttpServletquest 接口

    HttpServletRequest对象负责获取客户端的请求数据

    1、reques 接口
    • request是对象从客户端向服务器发送请求,包括提交的一些信息
    • HttpServletRequest 接口的对象是由Tomcat容器来提供的,可以通过request 对象来获取的数据包括:请求行、请求头、请求体
    2、Request 对象获取请求行
    • //获取用户的请求方式 String method=req.getMethod();
    • //获取WEB应用名称(获取web的根路径) String webapp=req.getContextPath()
    3、Request 对象获取请求头

    请求头数据键值对 k:v

    • //获取请求头 String accpet=req.getHeader(“Accept”);
    • Enumeration getHeaderNames()获取所有请求头的key Enumeration enums=req.getHeaderNames();
    4、Request 对象获取请求参数
    • getParameter(String name) 数据类型 String 获取请求中的数据,根据name获取 (name就是表单中元素的name属性值)
    • getParameterValues(String name) String 获取请求中的数据,针对复选框
    • getParameterMap() Map<String,String[]> 获取提交的参数,将提交的参数名称和 对应的值存入到一个Map集合中
    5、Request 接收数据,中文乱码
    • post 方式接收
      • post方式提交的数据是在请求体中,request 接收数据后,放入到request缓冲区中,缓冲区的默认编码是 ISO-8859-1
      • 将 编码改为 utf-8
        • //设置请求的编码 req.setCharacterEncoding(“UTF-8”);
    • get 方式接收
      • Tomcat8.5之后的版本自行解决
    6、Map对象和JacaBean相互转换
    • BeanUtils包 和 commons-logging 日志包
    • Map转换成 JavaBean
      • 准备一个 JavaBeam
      • Map<String,String[]> map=req.getParameterMap();
      • Student stu=new Student ();
      • //把Map转换成JavaBean BeanUtils.populate(user,map);
    • 将对象转成Map对象
      • Student stu=new Student(); stu.setUsername(“哈哈哈”);
      • //把对象转换成Map对象 Map<String,String> map1=BeanUtils.describe(user1);

    119、HttpServlrtResponse 接口

    1、response概述:
    • 请求路径:服务器到浏览器 对浏览器进行响应的对象
    • request 服务器接收到请求需要进行处理,将处理以后的结果显示到浏览器端。
    2、Response 对象设置响应行:
    • setStatus(int code) void 设置响应的状态码
    3、Response 对象设置响应头:

    格式:k:v

    • addHeader(String name) void 添加响应头,值可以为:Sting、int、日期类型
      setHeaderNames() void 跟更改响应头,值可以为:Sting、int、日期类型
    4、Request 对象设置相应体:
    • 向浏览器写入数据
      • write() 返回值PrintWriter 往浏览器写数据,使用字符串数据没有差别,输出的是整数,查询编码表
      • print() PrintWriter 无论是什么数据类型,都原样输出
        • PrintWriter pw=resp.getWriter()
    5、中文乱码:
    • 原因:字符流是由缓冲区,response获得字符流,response设计默认的缓冲区编码是ISO-8859-1。
      • setCharacterEncoding(String str) void 设置响应内容的编码方式
      • setContextType(String type) void 设置浏览器打开页面时采用的字符集
        • resp.setContentType(“text/html;charset=utf-8”);

    120、资源跳转(重定向,请求分配)

    • Servlet通过重定向、请求分配 进行Servlet之间和网页资源的跳转
    1、重定向的实现:
    • 浏览器进行重定向:
      • 设置重定向状态码:302
      • 设置重定向资源的地址:
        • 第一种方式,分解
          • 设置状态码为302,告诉浏览器访问新的资源
          • resp.setStatus(302);
          • 设置新的资源路径
          • resp.setHeader(“location”); Servlet类
          • resp.setHeader("info.html)
        • 第二种,合成方式
          • resp.sendRedirect(“info.html”);
    2、重定向特点:
    • 重定向是发生在客户端的浏览器上
    • 重定向有两次请求两次响应
    • 使用重定向,浏览器地址栏中会发生变化
    3、请求分派(转发)
    • request对象方法获取转发器
      • RequestDispathcher request.getRequestDispatcher(“转发的地址”)
    • 使用转发器对象的forward方法
    • 示例:
      • //请求转发来实现资源跳转
      • //step1:获取请求转发器对象 RequestDispatcher dispatcher=req.getRequestDispatcher(“responseDemo3”);
      • //step2:调用forward方法实现请求的转发 dispatcher.forward(req,resp);
    4、请求分派(转发)特点:
    • 请求转发:只有一次请求,一次响应
    • 请求转发:地址栏中的地址不会发生变化
    • 请求转发:是在服务器端完成的
    5、重定向和请求分派的区别
    • 区别:
      • 请求转发是一次请求一次响应,而重定向是两次请求两次响应
      • 请求转发地址栏不会发生变化,重定向地址栏会发生变化
      • 重定向会丢失第一次请求的数据(也就是在新的资源中,是无法获取第一次请求的数据),而请求转发不会丢失数据
      • 在重定向中/ 表示http://localhost:8080,也就是没有项目名称路径 在请求转发中/表示http://localhost:8080/项目名称,包含项目名称路径
      • 重定向是在客户端浏览器上完成的,请求分派是在服务器端的servlet上完成的
      • 请求转发只能转发到同一个应用中的其它资源,但是重定向可以定向到任意的网站资源

    121、请求域参数

    1、请求域范围:
    • Request对象就是从客户端浏览器向服务器发送一次请求信息的封装,那么实质上向request中保存的数 据有效期就是所谓的请求域范围。
    • 一次请求范围,从客户端浏览器向服务器发送一次请求,服务器针对这次请求对浏览器做出响应,当服务器做出响应后,请求对象就销毁类,保存在其中的数据就无效了。
    • 每次请求都会创建新的request对象,当响应结束了立刻销毁request对象。
    2、方法 :
    • setAttribute(String name,Object value) void 向request域中保存数据
    • getAttribute(String name) Object 获取request域中相应的数据
    • removeAttribute(String name) void 从request域中移除相应的数据

    122、ServletContext 对象

    • 在Tomcat容器里面的Web项目,也叫做Web应用程序
    1、注意:
    • 在一个WEB应用程序中,只能存在一个ServletContext对象
    • 每个WEB应用程序,都有他自己所对应的ServeltContext对象
    • 在WEB容器启动的时候,会为每个WEB应用程序创建一个单独的ServletContext对象
    • ServletContext是接口,此接口的实现类是Tomcat容器提供的
    2、作用:
    • 获取Web应用程序的初始化参数
    • 获取Web应用程序下任意资源的绝对路径
    • ServletContext也是域对象,存储数据
    3、获取ServletContext对象:
    • 方式一:通过ServletConfig接口获取
      • //通过ServletConfig对象获取 ServletConfig config = this.getServletConfig();
      • ServletContext context2 = config.getServletContext();
    • 方式二:通过继承HttpServlet父类GenericServlet获取,GenericServlet提供类一个 getServletContext()方法。
      • //获取ServletContext对象 ServletContext context=this.getServletContext();
    4、作用
    • 作用一:获取WEB应用程序初始化参数

      • web.xml 配置 WEB 应用程序的初始化参数

        • ​ version

          ​ V1.0

      • 获取初始化参数

        • ServletContext context=this.getServletContext();
        • //获取WEB应用程序的初始化参数
        • String version=context.getInitParameter(“version”);
    • 作用二:获取WEB应用程序下任意资源的绝对路径

      • getRealPath(String path) String 接收一个资源的相对路径,返回真实路径的字符串
        • //获取src目录下的c.txt绝对路径 String cpath=context.getRealPath(“WEB-INF/classes/c.txt”)
    • 作用三:ServletContext 作为域对象

      • ServletContext是在Web容器启动的时候为每个web项目,单独创建类一个ServletContext对象,当 web项目从WEB容器中移除,或者服务关闭的时候ServletContext对象会被销毁

      方法:

      • setAttribute(String key,Object value) void 存储数据
        getAttribute(String key) Object 获取数据
        removeAttribute(String key) void 移除数据

    123、ServletConfig 对象

    Web容器会为每个Servlet都创建一个对应的ServletConfig对象,ServletConfig代表的是Servlet初始化 参数的的对象

    1、第一种
    • web.xml中为servlet配置初始化参数

      • 配置初始化参数 (设置)

        • address beijing
        • 放在 中
      • 获得初始化参数

        • //获取ServletConfig对象 ServletConfig config=this.getServletConfig();
        • //获取初始化参数 String address=config.getInitParameter(“address”);
    2、第二种
    • 基于注解的
      • @WebServlet(initParams = { @WebInitParam(name = “age”,value = “55”), @WebInitParam(name=“gender”,value=“man”) } )
      • 获取是相同的

    124、JSP

    1、概念:
    • JSP:称为 Java的动态服务器端
      • JSP需要依赖WEB容器,才能运行
      • 动态网页,扩展名为 .jsp
    • JSP其实就是把Java程序嵌入到类HTML中,页面称为JSP页面。
    2、JSP和Servlet
    • JSP更擅长页面展示
    • Servlet更擅长对请求业务逻辑的处理
    • 在JSP中是网页嵌套Java代码,而在Servlet中,是Java代码嵌套HTML
    3、JSP基本语法:
    • JSP注释:
      • <%-- JSP特有的注释 --%>,只在JSP源代码中出现,浏览器中看不到
    • JSP 中的 代码片段:
      • 语法格式:<% Java代码片段%>
      • 作用:
        • 当请求JSP页面时,会执行<%%>中的Java代码
        • 拼接java逻辑代码,实现嵌套html标签
     第一种作用: <% System.out.println(" java语法代码块"); %>
     第二种作用: <%  for (int i = 0; i < 5; i++) {  %>
       		  <h2> System.out.printf("页面输出--") <h2>
      		  <h2>直接在jsp中写html代码</h2>
    		  <%  }  %>
    
    • JSP 中的表达式:
      • JSP中的表达式,就是往页面中输出内容的。 语法格式:<%=Java表达式内容%>
     <h3>JSP表达式</h3><hr/>
        <%="zhangsan"%>    <%=100*100%>    <%=false%>    <%="lisi"+"zhangsan"%>
    输出到网页
    
    • JSP中的声明:
      • 定义全局变量和方法
      • 语法格式:<%! Java代码 %>
    <%!
        int num=100;
        public String getInfo(){
            return "2020年10月19号";
        } 
    %>
        <%=num%>    <%=getInfo()%>
    
    4、JSP 页面执行的原理
    • JSP页面执行的时候转成 .java 文件,编译成.class文件
      • JSP 文件也是一个 Servlet 文件,并且把JSP文件中相关的内容添加到 _jspServive 方法中,然后通过输出流将数据输出到页面中
    • 过程:
      • 客户端发出请求(JSP),web容器自动找响应的Servlet进行处理
      • 将seevlet转成字节码文件
      • 将字节码文件加载到web容器里
      • 这时就会在web容器里建立实例
      • 进行初始化,通过service接受请求
      • 然后 web 容器会自动产生两个对象servlet和service最后进行销毁
    • 【https://www.cnblogs.com/dreamworlds/p/5383884.html】
    1、-------

    字节流转换为字符流的两个类是 InputStreanReader和 OutputStreamWriter

    2、------

    FileInputStream使用字节读取文件,不能直接处理Unicode字符。

    3、------

    线程可以主动调用sleep()方法或者yield()方法主动放弃CPU

    4、-----

    在Java网络编程中,TCP和UDP都基于Socket。

    5、-----

    double —> 默认值为:0.0d

    float f=5+5.5; //只能无小数相加

    ++在后,先输出在+1

    6、-----

    final,关键字,被修饰成员变量不可变;finalize,垃圾收集器执行时会调用被回收对象的finalize方法;finally,异常处理部分必须被执行的部分;catch,异常处理时必须和try一起使用。

    7、-----

    编译失败。FileOutputStream为字节输出流,它的write方法不能直接传入字符串,应该利用getBytes()方法把字符串转换成字节数组。

    8、-----

    wait()使当前线程阻塞,前提是 必须先获得锁,一般配合synchronized 关键字使用,即,一般在synchronized 同步代码块里使用 wait()、notify/notifyAll() 方法。

    由于 wait()、notify/notifyAll() 在synchronized 代码块执行,说明当前线程一定是获取了锁的。

    当线程执行wait()方法时候,会释放当前的锁,然后让出CPU,进入等待状态。

    只有当 notify/notifyAll() 被执行时候,才会唤醒一个或多个正处于等待状态的线程,然后继续往下执行,直到执行完synchronized 代码块的代码或是中途遇到wait() ,再次释放锁。

    也就是说,notify/notifyAll() 的执行只是唤醒沉睡的线程,而不会立即释放锁,锁的释放要看代码块的具体执行情况

    https://www.cnblogs.com/moongeek/p/7631447.html

    out输入

    9、-----

    简述接口和抽象类的区别。

    · 只有接口能继承接口。

    · 接口中的所有变量被自动设为final。

    · 接口的执行比抽象类要慢。

    · 接口中方法的作用域只能是public的,抽象类则无此限制。

    · 抽象类可以实现方法,但接口不行。接口只包含方法签名,不包含方法体。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值