手机版 欢迎访问it开发者社区(www.mfbz.cn)网站

当前位置: > 开发

JAVA SE

时间:2021/6/6 22:03:38|来源:|点击: 次

JAVA SE 知识点浓缩总结

一. java的发展史

java之父 詹姆斯*高斯林
oak–>java1.0
Oracle 公司拥有java的版权
机器语言 --> 汇编语言 --> 高级语言

二. java体系

JAVAEE 企业版
JAVASE 标准班
JAVAME 微型版

三. java特点

支持分布式
安全
健壮
可以跨平台(因为每个系统都有相应的jvm,从而实现一次编译 到处运行。)
在这里插入图片描述

四dos命令

cd / 回到根目录

D(盘符): 切换盘符
dir: 展示当前文教家内酥油的文件和文件夹
文件夹会显示


文件会显示文件大小
cd 文件夹名: 进入文件夹
cd … 返回上一级目录
方向上下键 历史命令
cls 清屏
md 文件夹名 新建文件夹
rd 文件夹名 删除文件夹(彻底删除)
del 文件名.后缀 删除文件(彻底删除)
del 文件名.* 删除所有同名文件(彻底删除)
del *.后缀名 删除所有同类型文件(彻底删除)
del . 删除所有文件(彻底删除)

五. jdk的安装与卸载


安装:默认安装即可
jdk>jre>jvm
可以将 公共的jre 不可用

在这里插入图片描述

卸载:
1.控制面板 安全管理软件
2.卸载后删除环境变量

六. 配置环境变量

6.1 配置path
目的是在任意目录下 都可以使用 javac java命令

将jdk安装目录到 bin 放到
C:\Program Files\Java\jdk1.8.0_172\bin
配置JAVA_HOME HOU 可以 %JAVA_HOME%\bin

我的电脑 —> 右键 —> 属性 —> 高级系统设置 —> 环境变量 —> 系统变量 —> path
—> 将 bin目录放进去

6.2 配置JAVA_HOME
为了给其他软件使用java提供一个接口(访问方式)
我的电脑 —> 右键- —> 属性 —> 高级系统设置 —> 环境变量 —> 新建变量
变量名:JAVA_HOME
变量值:C:\Program Files\Java\jdk1.8.0_172

七. 第一个程序

`public class HelloWord{
    public static void main(String[] args){
        System.out.println("Hello Word!");
    }}

编译
javac Java源文件名.后缀名

运行
java 类名字

注意:
1.java的源文件是不区分大小写
2.类名如果被public 修饰 那么 类名必须与源文件的名字保持一致
3.如果一个java文件存在多个类 那么编译后 有几个类就会生成几个class文件
4.Java语言是一门严格区分大小写的语言不能用中文符号,标点符号使用英文半角,括号成对出现

八. 注释

//单行注释

/*
多行注释
多行注释
*/

注:注释内容不参与编译

九. 标识符

标识符:
在java内凡是需要自己命名的地方

规则:

  1. 字母数字下划线 美元符组成
  2. 数字不能开头
  3. 严格区分大小写
  4. 不能是java中的关键字和保留字

规范:
1.类名每一个单词的首字母都大写
2.见名之意
3.驼峰命名
方法名,变量名在命名时第一个单词的首字母小写
从第二个单词开始每一个单词的首字母要大写。 //getMaxNum();
4.对常量命名时 要求 每一个单词的字母都要大写 单词与单词之间使用下划线连接
5.包名 每一个单词的字母都要小写

十. 常量与变量

数据类型

基本类型数据:
整数型
byte 1
short 2
int 4 默认
long 8 后面加L/l
浮点型
double 8 默认
float 4 后面加F/f
字符型
char 2 [0,65535]
布尔型
boolean //值只有true/false

引用类型数据:
只要不是基本类型数据 就是引用类型数据

常量
在程序执行过程中 值不会发生改变的量

变量
在程序执行过程中 值会发生改变的量

注意:
1.变量的初始化 变量完成 赋值
2.一个方法内 不能出现同名的变量

十一. 进制

10进制 2进制 8进制 16进制

10进制转为 2进制:
除以2 取 余数 ,最后取反(逆顺序排列)。
在这里插入图片描述
2进制转为 10进制:
从右到左用二进制的每个数去乘以2的相应次方(第一位是0次方)。
在这里插入图片描述
8进制与2进制
2进制每三位一运算顺序排列成8进制
8进制每一位进行运算顺序排列成2进制

16进制与2进制
2进制每四位一运算顺序排列成16进制
16进制每一位进行运算顺序排列成2进制

java可以将不同的进制数转为10进制进行展示

二进制:前面加0b
0b101 5
8进制:前面加0
011 9
16进制:前面加0x
0x10 16

十二. 计算机的存储单位

8bit =1byte
1024byte = 1kb
1024kb = 1Mb

1024Mb = 1Gb
1024Gb = 1Tb

十三. 计算机底层存储数据的方式

计算机底层都以01二进制的方式储存数据

符号位 0 正数 1 负数

正数
源码/反码/补码:三码合一
负数
原码
反码 除了符号位 其他位 0变1 1变0
补码 反码+1

byte 8bit
[-128,127]
[-2(n-1),2(n-1)-1]

小数的存储 //了解即可
符号位
指数位
尾数位

十四. 类型转换

自动类型提升:
小的数据类型转换成大的数据类型
强制类型转换:
大的数据类型转换成小的数据类型
公式:小的数据类型 变量名 = (小的数据类型)大的数据类型的值;

十五. 运算符

算数运算符

      • / % ++ –
        前++:先加1后运算 //++i
        后++:先运算后加1 //i++
        前–:先减1后运算 //–i
        后–:先运算后减1 //i–
        赋值运算符
        = += -= *= /= %=
        x += y //x = x + y
        x -= y //x = x - y
        x *= y //x = x * y
        x /= y //x = x / y
        x %= y //x = x % y
        关系运算符

= < <= != ==
结果都是布尔类型

逻辑运算符
& && | || ^ !

&:有一个false,结果就是false。
&&:同 & 运算结果一致,但运算过程中一旦遇到false,后面就不在运算。
|:有一个true,结果就是true。
||:同 | 运算结果一致,但运算过程中一旦遇到true,后面就不在运算。
^:符号前后相同结果为false,附后前后不同结果为true。
!:取反。
! false —> true
! true --> false

三目运算符
X?Y:Z;//X是布尔型。
X为true 运行Y。
X为false 运行Z。

十六. 键盘输入

16.1 基本使用
16.1.1. 创建键盘输入对象
java.util.Scanner in = new java.util.Scanner(System.in);
16.1.2. 提示语句
System.out.println(“请您输入一个年龄”);
16.1.3. 对象调用方法
int age = in.nextInt();
16.2 常用方法(可以获取的类型)
java.util.Scanner in = new java.util.Scanner(System.in);

byte a = in.nextByte();
nextShort();
nextInt();
nextLong();
nextFloat();
nextDouble();
nextBoolean();
next();//获取字符串
16.3 next() & nextLine()
区别:

  1. next():读取空格前的内容。
    nextLine():可以读取一整行内容。
  2. 如果前面有其他的键盘输入语句。 (解决方案:输入两次nextLine() ) 。

十七. 分支结构

1. if分支

① if单分支

if(boolean表达式){
分支内容;
}

② if双分支

if(布尔表达式){
分支1;
}else{
分支2;
}

例:
int age = 19;
 if(age>=18){
  	
  	System.out.println("成年了");
  }else{
  	System.out.println("没有成年");
  
  }
String s = age>=18?"成年了":"没有成年";

注:判断闰年
判断闰年的标准:
1.能被400整除
2.能被4整除不能被100整除

③if多分支

  1. if(b1){ 分支内容1 }else if(b2){ 分支内容2 }else if(b3){ 分支内容3 }else{
    分支内容4 }

注:
1.当所有的if都不满足 会执行else。
2.else可以省略。

2 switch-case分支

2.1switch-case分支结果
switch(表达式){
case 值:
break;
case 值:
break;
case 值:
break;
default:
break;

}
2.2 switch中表达式类型 及 使用注意

  1. break作用
    防止语句块穿透
  2. default:
    当所有的case 都不满足时 会执行 default
    是可以有也可以没有
  3. 表达式类型
    byte
    short
    char
    int
    String(jdk1.7之后开始支持)
    枚举
  4. case值唯一不能重复

十八. 循环

任何一个标准的循环:
初始化条件: 只会执行一次
循环条件: 最后执行
循环体:循环的意义
迭代条件:让初始化条件 不断向循环条件靠近

0 引入:开方及获取随机数

0.1 java中怎么开方
Math.sqrt(要开平方的数)

0.2 java中怎么获取随机数
Math.random():产生随机数[0,1)
“[” 和 “]”:包含这个数
“(” 和 “)”:不包含这个数


```java
例:在n ~ m中获取随机数
(int)(Math.random()*(m-n+1)+n);
 n     m
[22 , 33]
n:较小的数
m:较大的数

1. for循环

① for循环的格式

for(初始化条件;循环条件;迭代条件){
循环体;
}

例:(打印五次Hello Worldfor(int i = 1;i<=5;i++){
	System.out.println("Hello World\t" + i);
}

② 变量定义及位置确定

没有变量记录结果,需要自己定义变量
记录的是循环的总变化:放到循环的外面
记录的是循环内单个个体变化: 放到循环内

例:求 1~100的所有数的和
int sum = 0;
	for(int i = 1;i<=100;i++){
		sum = sum + i;
		System.out.println(i);
	}
	System.out.println("总和是:"+ sum);

2. while循环

① while循环的格式

初始化条件;
while(循环条件){
循环体;
迭代条件;
}

例:
int i=1while(i<=10){
	System.out.println(i);
	i++;
}

3 .do{}while

① while循环的格式

初始化条件;
do{
循环体
迭代条件;
}while(循环条件);

例:
int i =1;
do{
 	System.out.println(i);
	i++;
}while(i<=10);

4 .嵌套循环

嵌套循环: 把一个循环作为另一个循环的循环体;
外层循环:控制行数
内层循环:控制列数
外层循环执行一次 内层循环执行一遍

例:
/*
     **********
     **********
     **********
*/
   for(int i = 1;i<=3;i++){ 
       for(int j = 1;j<=10;j++){
           System.out.print("*");
       }
       System.out.println();
   }

十九 特殊的流程控制语句

1 break

  1. 只能用在循环或者switch中
  2. 循环中
    如果不存在标签 结束break所在层循环
    如果存在标签 结束标签所在层循环
  3. switch中 防止语句块穿透
//例:存在标签
a:	for(int i = 1;i<=10;i++){
			/*
			i = 1 时 j=1 2 3 4 5
			i = 2 时 j=1 2 3 4 5
			i = 3 时 j=1 2 3 4 5
			*/
			for(int j =1;j<=10;j++){
				if(j==6){
                    //当j==6时结束标签a:for(int i = 1;i<=10;i++){}循环
					break a;
				}
			
				System.out.print(j+" ");
			}
			System.out.println();
结果:
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5

2 .continue

1.只能用在循环中
2.如果不存在标签 结束的是continue所在层这一次循环 继续下一次循环
3.如果存在标签 结束的是continue所在层这一次循环 继续的是 标签所在层循环

//例:存在标签
l:	for(int i = 1;i<=2;i++){
		for(int j = 1;j<=10;j++){
            /*
            i=1 时 j=1 2 3 4 5
            i=2 时 j=1 2 3 4 5
            i=3 时 j=1 2 3 4 5
            */
			if(j==6){
			continue l;
			}
			System.out.print(j+" ");
		}
		System.out.println();
}
结果:
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5

3. return

结束方法

//例:	
for(int i = 1;i<=10;i++){
	for(int j = 1;j<=6;j++){
    	/*
    	i = 1 时 j = 1 2
    	遇见return语句直接结束方法。
    	*/
		if(j==3){		
			return;
		}	
		System.out.print(j+" ");
	}
	System.out.println();
}
结果:
1 2 
  • [ ]

二十 数组

1 数组的概念

数组:存储【相同类型】数据的有序集合。

2 一维数组

①一 维数组的初始化

注:数组在初始化时存在默认

1.静态初始化:写完数组时,就知道数组的内容(数组存储的元素)

方式一:声明和赋值写到一起
    数据类型[] 数组名 = {元素1,元素2,......};
    数据类型 数组名[] = {元素1,元素2,......};
    
例:
    int[] arr = {10,20,30};
    int arr[] = {10,20,30};

方式二:声明和赋值可以分开
    数据类型[] 数组名 = new 数据类型[]{1,2,......};
    
    数据类型 数组名[] = new 数据类型[]{1,2,......};
例:    
    String[] sArr = new String[]{"李白","杜甫"};
    String sArr[] = new String[]{"李白","杜甫"};
    
2.动态初始化:写完数组时,只知道长度,不知道内容
    数据类型 数组名 = new 数据类型[数字];
例:    
    int[] arr = new int[6];

3.二维数组

① 二维数组的初始化

二维数组:数组元素是一维数组的数组称之为二维数组。
1.二维数组的长度 = 数组内一维数组的个数
2.访问二维数组元素
数组名[第几个一维数组][一维数组第几个元素]
arr[0][0];(二维数组中第一个一维数组中的第一个元素)

1.静态初始化:完成初始化后就知道数组的内容
    方式一:声明和赋值不可以分开
        数据类型 [][] 数组名 = {{1},{1},{1}};
例:        
        int[][] arr = {{1,2,3},{10,20,30},{4,5},{50,60}};
    方式二: 声明和赋值可以分开
        数据类型[][] 数组名 = new 数据类型[][]{{1},{1},{1}};
例:        
        String[][] sArr= new String[][]{{"李","杜"},{"安","嬴"}};

2.动态初始化
    方式一:
        数据类型[][] 数组名 = new 数据类型[3][4];
    方式二:
        数据类型[][] 数组名 = new 数据类型[3][];     

二十一 数据类型对应的默认值

整型:
	byte  0
	short 0
	int   0
	long  0L
浮点型:    
	float  0.0F
	double 0.0	
布尔型:    
	boolean  false	
字符型:   
	char \u0000  空格
引用数据类型:
    String null
    所有的引用数据类型的默认值都是null

二十二 数组的遍历

1 普通for

需要下标时使用

普通for  根据下标获取 数组元素
    for(int i = 0;i<arr.length;i++){
        System.out.println(arr[i] + " ---> " + i);
	}

2. 增强for

不需要下标时使用

增强for 直接获取数组元素
    for(数组元素类型 变量名:数组名){
        System.out.print(变量名);
    }
例:
    double dArr[] = {3.14,6.28,9.13,5.34};
    for(double ele : dArr){
        System.out.println(ele);
	}

3 用String字符串直接接收数组元素;

直接输出数组中元素情况

String字符串直接接收数组元素遍历输出;
    String 变量名 = java.util.Arrays.toString(数组名);
	System.out.pring(变量名);
例:
    int[] arr = {1,6,9,8,4,2,9}
    String result = java.util.Arrays.toString(arr);
	System.out.pring(result);

二十三 内存

jvm虚拟机内存划分:

第一步 会进行class的加载 

第二步加载到内存后会将不同的数据存贮到不同的区域

方法区:jdk1.7含之前 叫方法区   ******
    jdk1.8含之后 叫元空间 使用物理内存		
    类的信息 方法的信息  静态资源信息 常量信息
		
虚拟机栈:  ******
    在调用方法时 存储 局部变量 对象的引用  
    当方法执行结束后 销毁
		
本地方法栈:
    native方法:
    java不是万能的,在需要和计算机底层硬件沟通时能力不足 
    需要借助于其他语言C等其他语言在执行时 产生的信息 存储在本地方法栈
		 
堆: ******
	对象的信息
	数组
	new 出来的内容1
		
程序计数器:
	存储下一条线程要执行的指令

GC垃圾回收器:
	无用内存即垃圾;

二十四 冒泡排序

将数组中的数从前到后两两比较
如果前一个数大于后一个数将两个数的值交换
数组经过数组长度-1次比较排序后即可有序

每一次排序后都会将数组分为两部分:一部分有序,一部分无序
在下一次排序是只需要专注于无序部分即可,每次都会活得无序部分的最大值
在这里插入图片描述

1 普通冒泡排序

int[] arr = {10,20,30,40,70,60,50};
    //遍历数组中元素
    for(int i = 0;i<arr.length-1;i++){
        //比较元素大小,开始排序
        for(int j = 0;j<arr.length-1-i;j++){
            if(arr[j]>arr[j+1]){
            int temp = arr[j];
            arr[j] = arr[j+1];
            arr[j+1]=temp;
            }		
         }
 }
 System.out.println(java.util.Arrays.toString(arr));

2 优化冒泡排序

如果数组不是极端数据,则不需要数组长度-1次排序即可有序
当数组有序, 就可以结束排序操作,不需要做无用功
考虑:是否存在 前一个数大于后一个数

int[] arr = {40,30,10,10,50,60,70};
    //遍历数组中元素
    for(int i = 0;i<arr.length-1;i++){
        //假设此次排序 数组已经有序
        boolean flag = true;
        //比较元素大小,开始对排序
        for(int j = 0;j<arr.length-1-i;j++){
            if(arr[j]>arr[j+1]){
            int temp = arr[j];
            arr[j] = arr[j+1];
            arr[j+1]=temp;
            //如果产生了 前一个数大于后一个数的情况 那么 此数组无序
            flag = false;
            }		
         }
         if(flag){
         break;
     }
 }
 System.out.println(java.util.Arrays.toString(arr));

二十五 面向对象(上)

0. 包

包名所有字母全部小写
包:

包:
    不同包下=可以存在同名文件
    使用不同的包区分不同的功能模块
定义包:
    包名的写法 公司网址倒叙
              每一个字母都小写
    www.atguigu.com
    com.atguigu.项目名.模块名.模块一
                            .模块二

在jdk内部 通过不同的包 来区分不同的功能模块
    java.lang  jdk核心包 String  Math
    java.net  网络相关
    java.io  io流相关
    java.util 工具类相关
    .......
注意:
    1.包的声明必须位于首行
    2.使用不同包下的资源需要导包 import
    3.java.lang 包下的资源 使用时 不需要导包
    4.如果使用了同名资源 那么 必须有一个类 是采用全类名/全路径名导入
      包名+类名:全类名/全路径名

1 属性

1.1 属性的定义
属性即静态特征:
比如:姓名、年龄

1.2 属性的声明
静态属性:含有static关键字的属性
非静态属性:不含有static关键字的属性

static 数据类型 属性名;
数据类型 属性名;

int i;//声明一个int类型的数字i
static String nationality;//声明一个String类型的国籍

静态属性:含有static关键字的属性
非静态属性:不含有static关键字的属性
相同:
    1.代码位置一样 类的里面 方法的外面
    2.都有默认值
不同:
    1.分配空间的时间不一样
        静态成员变量: 随着类的加载而加载 类加载时 就已经分配默认值
                      先于对象产生
        普通成员变量:创建对象后才会分配空间
    2.内存的分数不同:
        静态成员变量:所有的对象共享一份
        普通成员变量:每创建一个对象 就会 开辟一块独立的空间
    3. 在内存的位置不同
        静态成员变量: 在方法区中
        普通成员变量: 在堆中
    4.调用方式不同:
        静态成员变量: 通过   类名.属性名(推荐)
                            对象名.属性名
        普通成员变量: 只能通过对象调用
                            对象名.属性名
    5.销毁时间不同:
        静态成员变量:   随着类的卸载而卸载
        普通成员变量:   当没有对象指向时,等待垃圾回收器回收无用内存即垃圾
    6.声明方式不同
        静态成员变量:  static 数据类型 变量名;
        普通成员变量:  数据类型 变量名;

2 方法

2.1 方法的定义

方法:是一个独立功能的定义,是一个类中最基本的功能单元。

写方法的目的:
1.对功能封装
2.实现代码复用

方法分类
静态方法:含有static关键字的方法
非静态方法:不含有static关键字的方法

注:
1.方法只声明不调用不会执行的
2.一个类中可以存在n个方法
3.方法与方法之间是并列关系
4.方法执行完毕 要回到方法的调用处

2.2 方法的声明

方法的声明/创建:
public static void abc(int a) {
    int b = a*a*a;
    System.out,print("a的立方是" + b)
}
    
public static   修饰符(可以有也可以没有)
void            返回值类型(void表示没有返回值)
                如果有返回值类型,必须返回一个匹配的数据,支持自动类型提升
abc            方法名
()             方法的标识
int a          形参列表 :可以有也可以没有
{}:            方法的范围

3 方法的资源引用问题

资源:属性及方法

静态方法不能【直接使用】非静态资源
静态资源随着类的加载而加载,而此时,非静态资源可能还没有分配空间 
不能使用还不存在资源

非静态方法 可以【直接使用】静态资源和非静态资源
非静态资源在使用时已经完成对象的创建,对象创建成功,
则静态资源肯定已经加载完毕,可以使用已经存在的资源

4 属性及方法的调用

静态方法:含有static关键字的方法
    在本类中可以直接调用
    在不同类中: 可以通过 类名.方法名() 推荐
                也可以通过 对象名.方法名()
非静态方法:不含有static关键字的方法
    在本类中可以直接调用
    在不同类中:必须通过 对象名.方法名()

5 形参 / 实参

位置不同:
形参:方法的声明处
实参:方法的调用处

作用不同:
形参:
1.告诉方法调用者在执行时需要传递参数

2.规定了参数的类型 必须与形参【匹配】才可以
实参:
1.给形参赋值

例:
定义一个方法求俩数的和
    求定义一个方法 输出两个整数的最大值
1.没有返回值:    
public class Test1 {
    public static void sum(double n1,double d2){
        double sum = n1 + d2;
        System.out.println("sum = " + sum);
    }
    
    public static void main(String[] args) {
        sum(10, 20);
    }
}
2.有返回值

public class Test2 {
    public static double sum(double n1,double d2){
        return double sum = n1 + d2;
    }
    
    public static void main(String[] args) {
        int double d = sum(10, 20);
        System.out.print("总和为:" + d)
    }
}

6 返回值及值得传递

void    没有返回值

1.方法执行完毕必须返回一个与规定的返回值类型相比配的值
2.值传递
    基本数据类型:传递的是副本,不会影响原始数据
    引用数据类型(对象):传递的是数据的地址值,会影响原始数据

二十六 面向对象(中 - 1)

0 局部变量与成员变量的区别

class A{
	String name;
	public void eat(){
		int m = 10;
		int n;
	}
    public void eat1(){
		System.out.println(m);
	}
}

1. 位置不同:
    成员变量:类中方法外
    局部变量:方法内
2. 生命周期不同:
    创建时间不同
        成员变量:创建对象的时候
        局部变量:调用方法的时候
    销毁时间不同:
        成员变量:当没有引用指向时 等待垃圾回收器回收
        局部变量:方法结束就消失
3. 默认值不同:
    成员变量:有默认值
            byte short int long 0
            float double 0.0
            boolean false
            char \u0000
            引用数据类型  null
    局部变量:没有默认值
4. 内存中位置不同:
    成员变量:堆
    局部变量:栈
5. 作用域不同:
    成员变量:整个类中有效
    局部变量: 方法内有效

1 方法的重载

方法的重载:
	使用相同的方法名 表示不同的方法
如何构成方法的重载:
	两同一不同
	同一类中同一方法名不同的形参列表 (类型不同、数量不同、顺序不同)

2 可变形参

使用数组存储多个数据
class B{
    public statci void main(String[] args){
        sum(10,20,30,40,50);
        sum();
    }
    public static void sum(int... a){
    }
}

注意:
1.位于方法的声明处 数据类型…变量名
2.使用数组存储多个数据
3.只能出现一次 必须位于参数列表的最后
4.实参的个数[0,n]

3 命令行参数

在这里插入图片描述

4 递归

递归就是方法自己调用自己递归;
	A()-->A();
	A() -->B()--->A();

注:
	1.有出口
	2.不断向出口靠近
    3.有一个上山下乡的过程
    4.有可能会出现 stackOverFLowError  栈溢出异常

5 对象数组

存储对象的数组

public class Person {
    String name;
    int age;
}

Person[] ps = {new Person(),new Person()};

6 构造器

class A{
	String name;
	int age;
    public A(){}//无参构造器
    
	public A(String name){//构造器
	   this.name = name;
	}
 
	public static void main(String[] args){
	new A();
	}
}

构造器作用:快速给成员变量赋值

注:
     1.格式:权限修饰符 类名(形参列表){}
     2.构造器支持重载
     3.每一个类都会有一个默认的无参的隐藏的构造器
     4.出现有参构造器后 默认的无参的隐藏的构造器 就会消失 
     

二十七 面向对象(中 - 2)

一. 封装

1. 封装的概念及意义

封装就是对类的属性私有化,给外界一个提供一个共有的get/set方法访问私有属性
目的:
避免外界恶意修改类的属性

2 权限修饰符

在这里插入图片描述

public        公共的 
protected     受保护的 不同包下的子类可见
default       默认的/缺省的
private       私有的

二 继承

1 继承的概念

继承就是子类中提取父类中与子类共有的资源

父类作为数组类型时,元素可以是父类以及任意子类
通过使用 extends 关键字 让 Dog类继承 Animal 中的name和age属性

class Animal{
String name;
int age;

}
class Dog extends Animal{
}

2 继承的注意点

1.java是单继承,允许多重继承
    即一个子类只有一个父类,但一个父类可以有多个子类
2.子类可以使用父类的资源(属性,方法)
3.子类调用资源的规则:
    先在本类中找,本类中没有,则沿着继承关系一直向上找,直到找到Object类为止  
    存在就返回资源,不存在就报错
4.如果一个类没有显示的继承另一个类,那么此类默认继承自Object5.父类的私有属性也是可以继承的

3 this & super

注:
在构造器中this & super时this & super都必须位于首行
所以只能存在一个

this:   代指当前对象 
        谁调用就是谁
this    调用属性/方法
        构造器:必须位于首行
常见对参调少参
源码里常见少参调用多参
    
super:  代指从父类继承的资源
        可以调用父类的属性/方法
        构造器:必须位于首行
        
每个构造器都有一个,默认的无参的super(),调用调用父类中的无参构造器
如果父类只有有参构造器,没有无参构造器,则会报错

4 方法的重写

注:
静态方法和属性不存在重写

重写格式
    权限修饰符 返回值类型 方法名(形参列表){
        具体方法;
    }
子类在从写父类方法时:
    1.权限修饰符:
        子类的权限修饰符不能比父类的更加严格
        子类的权限修饰符 >= 父类的权限修饰符
    2.返回值类型
        基本数据类型:必须与父类一致
        引用类型:可以与父类一致,也可以是父类的子类
    3.方法名
        必须与父类一致
    4.形参列表
        必须与父类一致

5 成员变量的初始化

成员变量的初始化:
    1.默认初始化
    2.显示初始化
    3.通过构造器进行初始化
public class Person {
    
    //默认初始化
    String name;
    
    //显示初始化
    int age = 100;
    
    //通过构造器进行初始化
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

.6 代码块

6.1 静态成员代码块
静态代码块:
    位置:类中方法外
    作用:给静态成员变量赋值
    声明方式: static { }
注意:
    先于构造器执行
    无论创建多少次对象  静态代码块都只会执行一次
    JDBC会用到
6.2 成员代码块
成员代码块
    位置:类中方法外
    作用: 给成员变量赋值
     声明方式:{ }
注意:
    1.每创建一个对象 成员代码块就会依次从上到下执行
    2.先执行代码块 再执行构造器

7 类的初始化

类的初始化目的:
    给类中的静态成员变量赋值
类的初初始化会调用 clinit()方法:
    将静态成员变量的显示赋值语句
    静态代码块内容进行合并
    
哪些操作会导致类的初始化:
    1.创建对象
    2.调用类中的静态资源
    3.执行该类的 main()也会导致该类的初始化
注:
    类的初始化只会执行一次
    如果存在继承关系,子类初始化,会导致父类也进行初始化
    初始化顺序 先父类 再子类
    父类和子类的初始化语句,都会合并到一个 clinit()>中
    子类调用从父类继承的静态资源时,只会导致父类初识化,不会导致子类初始化 

8 实例的初始化

类的初始化目的:
    给类中的非静态成员变量赋值
    
实例初始化:
    1.super()
    2.普通成员变量(非静态成员变量)的显示赋值语句
    3.普通成员代码块(非静态成员代码块)
    4.构造器内容
运行顺序:
    1在最前面,4在最后,23看书写书序
   
    

注意:
    1.实例初始化,会将普通成员变量的显示赋值语句、普通成员代码、构造器内容
       合并到 init()方法中
    2.每一个类进行实例初始化时都会创建一个对应的 init();
      用于存贮每一个类中的普通成员变量显示赋值语句、普通代码块内容、构造器内容
    3.创建几次对象,就会执行几次实例初始化

9 类&实例混合初始化

混合初始化:
    先执行类的初始化
            先执行父类的类初始化
            在执行子类的类初始化
    再执行实例初始化
            先执行父类的实例初始化
            在执行子类实例初始化

创建多个对象时:
        类的初始化只会执行一次
        实例初始化创建几次对象就会执行几次

二十八 面向对象(中 - 3)

1 多态

多态:

 同一个对象的不同形态
    相同的行为,不同的对象调用,会有不同的展现形式
    
实现多态要满足三个条件:
    1.有继承关系
    2.子类重写父类的方法
    3.有父类的引用指向子类的实例
        China china = new China();
        Programmer pro = china;

2 向上转型(类似自动类型提升)

多态的向上转型:

    有父类的引用指向子类的实例
       大的类型 = 小的类型
       Programmer pro = china;
       
向上转型在编译时/运行时,可以调用的资源
    编译看“=”左边,运行“=”看右边
    
注意:
    1.向上转型,可以使用子类重写父类的方法,以及从父类继承的资源
    2.不能使用子类新增的方法
    
应用:
    形参:父类类型作为形参
    数组:父类类型作为数组元素
    返回值:类似程序员工厂

3 向下转型(类似强制类型转换)

向下转型:

 可以使用子类独有的资源

前提:
    先完成向上转型

代码格式:
    小的数据类型 对象名 = (小的数据类型)大的数据类型的值;

4 instanceof 关键字

instanceof

    判断左边的对象是否属于右边的类型
    左边的对象与右边的类型存在继承关系 返回true
                                    否则false
格式:(返回值是布尔类型)
    数据类型 instanceof 数据类型
    cat instanceof Animal

二十九 非虚方法 & 虚方法

非虚方法:不能重写的方法
    1.静态方法
    2.私有方法  构造器
    3.final修饰的方法
虚方法:手动实现 ArrayList 类及相关功能.note
    可能被重写的方法
    静态分配:形参最匹配,方法重载
    动态绑定:运行时,确定有方法重写

三十 native & final关键字

1 native关键字

native:

    本地的	修饰方法
native方法:
    没有方法体,但是可以向普通方法一样调用
    有些功能java语言无法实现,需要通过 C/C++ 语言来实现
    调用 native()方法,会在【本地方法栈】中开辟空间,存储变量信息 

2 final关键字

final:

修饰的变量,是常量
修饰的方法,不能被重写
public final void show()
修饰的类,不能有子类
public final class Person
final修饰的对象,地址值不能变

三十一 Object类的API

1 toString()

直接输出对象时,会调用该对象的 toString()方法;
如果没有重写,就会去调用父类Object类中的toString
Object类中的toString: 全类名+@+16进制的hash码
希望 输出对象时可以展示 对象的属性信息
因此,可以对 toString()进行重写,方法在调用时,就会使用重写后的 toString()
com.atguigu.obj.totring.Dog@4554617c

2 getClass()

getClass() 获取当前对象的【运行时】类型
    Animal a = new Cat();
    Class aClass1 = a.getClass();
    System.out.print(aClass1);
    //输出 class com.atguigu.obj.getclass.Cat

3 equals

==:
    在比较基本数据类型时  比较的是数值
    在比较引用数据类型时  比较的是地址值是否相等
equals: 没有重写前
    this == obj 比较的是地址值是否相等
    进行重写:两个对象的属性值完全一样时,就认为两个对象为同一个对象
31.4 hashCode
hash值不同:对象肯定不同
hash值相同:对象也不一定相同

在java中实际业务中,如果对象的属性值完全一样,那么就认为,两个对象是同一个对象
hash码应该一样

三十二 抽象

抽象:
    只需要制定规则,不需要站在前台,规定子类的行为
抽象类:
    Animal,定义一组规则  
    abstract class Animal{}
抽象方法: 
    规则内容
    abstract void b();
    没有方法体
    不能被	private修饰
    	final修饰
    	static 修饰
     
注意:
    1.抽象类不可被创建对象
    2.如果一个类继承了一个抽象类,那么必须实现抽象类中【所有】的抽象方法
    3.如果想要不实现抽象方法,那么此类也需要变为抽象类
    4.抽象类中可以有普通的方法、属性、构造器
    5.抽象类中可以没有抽象方法
    6.抽象方法必须在持续类中

三十三 接口

1 接口的基本原则

接口:
    目的定义 规则
    抽象:定义规则 表示(是) is a的关系    Dog is a Animal   Cat is a Animal
    接口:定义规则 表示(有) has a的关系   bird has a Fly    SuperMan  has a Fly

如何定义接口
    interface 接口名{}

如何实现接口
    一个类实现接口类似于继承一个类,存在向上向下转型
    class 类名 implements 接口名{}
    
接口中的变量(成员):
    全局静态常量:	默认被 public static final  修饰(可以不写)
    抽象方法:	默认被 public abstract 修饰(可以不写)
    静态方法:	static 修饰(jdk1.8之后)  -->通过接口名调用 都能使用 
    默认方法:	default 修饰(jdk1.8之后) -->谁需要谁重写 
    
注意:
    1.接口只是提供一个功能,具体怎么实现,要类内部自己定义
    2.如果一个类 实现了一个接口 那么此类可以看做是 该接口的孩子
    3.接口中没有普通方法
    4.接口可以多实现,即一个类可以有多个接口
    	implements 接口1,接口2
    5.当一个类实现接口时,需要重写所有的抽象方法,要么此类变为抽象类
    6.接口可以多继承,即一个接口继承多个接口
    	interface D extends A,B,C{}
    7.如果既继承一个类又要实现一个接口,那么先继承再实现接口
    8.如果两个接口内有同名的默认方法,那么实现类必须重写,否则报错
    9.重写后若还要调用接口内的默认方法,需要使用 接口名.super.方法名()调用
    	B.super.eat();
    10.亲爹优先:
    	如果继承和实现的接口内有同名方法
    	那么创建实现类对象调用同名方法时,执行继承中的方法执行

2 经典接口

1 java.lang.Comparable(内部比较器,在类的里面)

如何使用 Comparable 进行对象比较?

 1.让比较对象的类 实现 Comparable接口
    2.重写抽象方法 制定比较规则 compareTo(Object)
    3.比较规则(比较什么属性)自己定义,返回一个整数
        大于0: 第一个对象 > 第二个对象
        ==0: 两个对象相等
        小于0:第一个对象 < 第二个对象
调用方法        
    用来比较两个对象
    通过 对象1.compareTo(对象2) 对比

例:
    public int compareTo(Object o) {//Object o = p2;
        //获取子类独有的属性 向下转型
        Person p = (Person) o;
        //一般比较
        return this.age-p.age;
        //专门用于比较小数大小
        int compare = Double.compare(this.score, p.score);
        return compare;
    }

2 java.util.Comparator(外部比较器,在类的外面)

三十四 枚举

用来表示某些类型仅有有限的几个值
    
jdk1.5前
    私有化构造器
    提供有限的枚举对象  
jdk1.5enum

 注:
    1.构造器默认私有
    2.自定义枚举类型 默认继承 Enum
    3.必须将自定义属性 放到枚举对象的下面
    4.枚举类可以实现接口  
    	既可以所有的枚举对象共有一个重写后的抽象方法 
     	也可以使用自己定义的重写后的抽象方法
    5.switch 支持 枚举类型
    	switch支出的类型:byte short int char String enum(枚举)

示例代码:

//创界枚举类Gender实现eat接口
public enum Gender implements Eat{
    MAN{
    //重写eat接口中eat的方法,MAN单独使用
        @Override
        public void eat() {
            System.out.println("男生  狼吞虎咽吃");
        }
    },WOMAN{
    //重写eat接口中eat的方法,WOMEN单独使用
        @Override
        public void eat() {
            System.out.println("女生 细嚼慢咽吃");
        }
    };    

   /* @Override
   //重写eat接口中eat的方法,所有枚举对象共用
    public void eat() {
        System.out.println("吃饭");
    }*/
}
//eat接口

interface Eat{
    void eat();
}
//测试类
public class Test {

    public static void main(String[] args) {
        Gender man = Gender.MAN;
        man.eat();
        Gender woman = Gender.WOMAN;
        woman.eat();
    }
}

三十五 包装类

1 为什么需要包装类型?

有些位置,基本数据类型不能满足要求,必须使用包装类型。

2 基本数据类型对应的包装类型

byte   	Byte
short  	Short
int    	Integer
long   	Long
float  	Float
double	Double
char   	Character
boolean	Boolean

注:
int 和 char外均是将首字母大写

3 装箱于拆箱

自动装箱:
 	将基本数据类型-->包装类型
     Integer i = 10;
 
 自动拆箱:
   包装类型-->基本数据类型
     Integer i1 = new Integer(20);
     int i3 = i1;

4 字符串—>基本数据类型之间的转换

基本数据类型----->字符串
	String.valueOf();

字符串---->基本数据类型
	包装类型.parse包装类型对应的基本数据类型
	Integer.parseInt("11");
 	Double.parseDouble("3.14");
	必须是纯数字字符串   否则 NumberFormatException  
	
   字符串.charAt(下标);
   “你好”.charAt(0)// 你

5 缓存区问题

Byte	[-128,127]
Short	[-128,127]
Integer	[-128,127]
Long   	[-128,127]

Character	[0,127]
Boolean	TRUE  FAlse

三十六 内部类

1 类的成员

类的成员
	1.成员变量
		普通成员变量
		静态成员变量
	2.构造方法
		无参
		有参
    3.方法
    	普通方法
    	静态方法
    4.代码块
    	普通成员代码块
    	静态成员代码块
    5.内部类
    	成员内部类
	
class A{
	String name;//普通成员变量
	static int age;
	//静态成员变量
	public A(){}//构造器(有参/无参)

	{}//普通代码块
	static{}
//静态代码块	
	public void show(){}//方法(普通/静态)

	class B{
	}//内部类

}

2 成员内部类

class A extends C{
	String name = "A";
	class B extends D{
        String name = "B";
       
        public void show(){
       		 String name = "C";
            System.out.println(A.this.name);//"A"
        }
	}	
}

注:
	1.位置 类中方法外
	2.外部类只能被 public default 修饰
 		成员内部类 四种权限修饰符修饰
	3.可以直接使用外部类资源
	4.可以扩展继承
	5.每一个类中都有this 获取外部类中的属性
    	外部类名.this.属性名  
    6.字节码文件:
    	外部类名$内部类名.class
    	A$B.class
    7.可以直接创建内部类对象
    	外部类对象.内部类对象
     	A.B b =   new A().new B();

3 静态成员内部类

位置:
    类中方法外
声明: 
    static class 类名{}
    
注:
    1.可以存在静态属性
    2.静态内部类可以直接使用外部类中的静态资源
      静态内部类可以间接使用外部类中的非静态资源
            创建外部类对象.外部类中的非静态资源
            例:
            Outer outer = new Outer();
    	 outer.outMethod();
    3.外部类中使用内部类静态资源
    	 内部类名.资源名
    	 Inner.innerStaticMethod();
      外部类中使用 内部类非静态资源 
      	 内部类对象.资源名
        	 Inner in = new Inner();
            in.innerMethod1();
    4.创建静态内部类  
    	 外部类名.内部类名  变量名 =  new 外部类名.内部类名()
      	 Outer.Inner inner =  new Outer.Inner();
     5.会生成独立的字节码文件
     	 外部类名$内部类名.class

4 局部内部类

参照 局部变量
位置: 
     方法内

注意:
    1.只能被 权限修饰符中的 default修饰
        允许被 abstract final修饰
    2.局部内部类不能有静态属性 但是可以有静态的常量

    3.内部类使用外部类什么资源 不是由自己决定 而是由所在方法决定
    	静态方法 只能使用 外部类中的静态资源
    	非静态方法 使用 外部类中的所有资源
    4.使用内部类中的资源 需要创建对象
    5.只有调用方法时 才会进行局部内部类的初始化
    6.局部内部类也会生成独立的字节码文件 外部类名$序号内部类名
            Test$1A.class
            Test$2A.class
    7.如果局部内部类中用到了 方法内的局部变量 必须给 局部变量前+final
       jdk1.8	会默认加final
       低于1.8	需要手动添加final

5 匿名内部类

匿名内部类就是没有名字的内部类。

声明方式:
new 父类(形参){
    方法;
}


注:
    1.匿名内部类除了没有类名,其他类的成员都可存在。
    2.匿名内部类必须继承一个抽象类或者实现一个接口。
    3.匿名内部类不能定义任何静态成员和静态方法。
    4.当所在的方法的形参需要被匿名内部类使用时,必须被final修饰。
    5.匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
    6.存在多态。 

三十七 注释

Override: 检查方法是否为重写
Deprecated:标记过时
    过时方法 不推荐使用但是可以使用
@Before....之前
@After....之后

三十八 单元测试

新建一个lib文件夹
导入
右击lib选择

@Test
public void 方法名(){
    
}

三十九 异常

异常处理: 即使发生异常 也不影响程序执行
发生异常 如果没有处理 就会将异常向上抛出 抛给方法的调用者
如果一直没有处理 就会抛给jvm
在真正开发中 需要对异常处理 一般 不会抛给 jvm

1 异常体系

异常体系:
       Throwable
            --Error: 不需要程序员处理
                    内存溢出(Out Of Memory,简称OOM)是指应用系统中存在无法回收的[内存](https://baike.baidu.com/item/内存/103614)或使用的[内存](https://baike.baidu.com/item/内存/103614)过多,
                     最终使得程序运行要用到的[内存](https://baike.baidu.com/item/内存/103614)大于能提供的最大内存。
                    内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费
                     ,导致程序运行速度减慢甚至系统崩溃等严重后果 。
            --Exception:以后处理异常
                -- 运行时异常:程序执行后才能出现的异常
                -- 检查异常/编译异常/受检异常: 代码写完后 直接报错
                  Thread.sleep(10000);

2 异常处理一(try{}catch(){}finally{})

 try{
    可能发生异常的代码
    }catch(异常类型 变量名){
        发生异常后写的代码
    }

注:
    1.try{可能发生异常的代码}
    2.try语句块内发生异常后  异常下面的代码不再执行
    3.如果发生了可以捕获的异常 发生异常后就直接进入catch内 执行里面代码
    4.没有发生异常 不会进入catch5.如果存在多个异常类型 可以在catch内声明
        异常类型1 | 异常类型2 |异常类型3...  变量名
    6.try{} 语句块内的变量,只能在语句块内使用,外部想要使用, 
        需要进行作用域的提升,将声明放到try语句块的外面
    7.允许存在多重catch
        先子类 再父类 否则 子类没有机会执行
    	
有些内容无论是否发生异常,都需要执行,得在catch后用finally{}

try{}catch(){}finally{}
finally:最后的最终的  无论如何都会执行的代码

System.exit(数字);
    0:代表正常退出
    1:代表非正常退出
    
快捷键:
1.选中可能发生异常的代码
2. ctrl + alt + t

2 异常处理二(throw & throws)

在这里插入代码片抛出异常
throw: 抛出异常对象
throws:声明此方法 有异常产生
区别:
    位置不同:
        1.throw 在方法内
          throws 在方法的声明处
        2.throw 一次只能抛出一个异常对象
          throws后可以有多个异常类型
        3.作用不同
          throw 抛出异常对象信息
          throws 告诉方法调用者 调用本方法可能出现的问题类型
注:
    如果抛出的是运行时异常 那么 方法的声明处 可以不用声明
    如果抛出的是检查异常 那么 方法的声明处 必须声明 否则报错

3 方法重写与异常

权限修饰符  返回值类型 方法名(形参列表){
 }

子类重写父类方法时:
    1.子类权限修饰符>= 父类的权限修饰符
    2.返回值类型
        基本数据类型要与父类一致
        引用数据类型可以是父类,也可以是父类的子类
    3.方法名和形参列表,必须一致
    4.抛出的异常
        如果是运行时异常,没有限制	
        如果是编译时异常,子类不能抛出比父类更大的异常

注意:
    Exception 是编译时异常

4 自定义异常

1.继承一个异常类型
    如果想要自定义异常类型为运行时异常,那么就继承运行时异常类
    如果想要自定义异常类型为编译时异常,那么就继承编译时异常类
2.创建构造器,将异常信息传递给父亲

示例代码:
public class SexException  extends RuntimeException{
   public SexException(String message){
        super(message);
    }
}

四十 线程

并行
并发
程序
软件
进程
线程

1 创建线程的两种方式

创建线程的方式一:
    1.创建一个类,继承Thread2.重写 run()  创建多线程的目的写到 run()
    3.创建线程对象
        RabbitThread rabbitThread = new RabbitThread();
    4.线程对象.调用start()将线程运行起来
       rabbitThread.start();
       
创建线程的方式二:
    1.创建一个类 实现 Runnable接口
    2.重写 run()  完成 线程内容的书写
    3.创建Runnable实现类对象
    4.将此对象作为参数传递
    5.线程对象.start();

2 设置和获取线程名字

1.当采用继承的方式,实现多线程时 
    有两种方式设置线程的名字
        1.1 线程名.setName();
        1.2 通过构造器设置
            线程类名(String name){
                super(name);
            }
2.实现接口的方式,实现多线程时 
    有两种方式设置线程的名字
        2.1 通过 Thread的构造器赋值
        2.2 通过线程对象.setName();

3 线程中的方法

3.1 isAllive():查看线程是否处于活跃状态

在 线程.start();之后,任务完成之前返回true;

通过要查看的线程对象.start()调用

3.2 sleep(毫秒数):使线程进入随便等待毫秒数时间后再运行

线程内通过 Thread.sleep(毫秒数); 调用
会报编译异常,使用 try{}catch(){} 处理

示例代码:模拟 预备 3 2 1System.out.println("预备");
for(int i = 3;i>=1;i--){
    System.out.println(Thread.currentThread().getName()+" ----> "+i);
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
System.out.println("跑");

3.3 setPriority(等级):设置优先等级

线程的优先级
    通过 线程.setPriority(等级); 调用
    等级范围[1~10];

    优先级高的线程 被 CPU调度的【概率】大
    优先级的范围  超过范围  IllegalArgumentException 参数异常
    public final static int MIN_PRIORITY = 1;
    public final static int MAX_PRIORITY = 10;
    public final static int NORM_PRIORITY = 5; 默认的优先级
    如果没有设置优先级  采用默认的优先级
    

3.4 yield():线程的礼让

将线程 从运行状态--->就绪状态

示例代码:
TortoiseThread tortoiseThread = new TortoiseThread();
tortoiseThread.setName("小乌龟");
RabbitRunnable r1 = new RabbitRunnable();
Thread th1 = new Thread(r1, "大白兔");
tortoiseThread.start();
th1.start();

3.5 setDaemon():守护线程

当主线程结束后 本线程自动结束
线程对象.setDaemon();设置守护线程
   位置必须位于 start()之前

3.6 volatile: 保证数据线程间可见

volatile: 保证数据线程间可见
         将修饰的数据,不被CPU缓存

3.7 (重要)join(毫秒数):强行插队

通过 线程.join(毫秒数) 调用

毫秒数:被插队线程等待时长,不写默认为0

4 线程的生命周期

4.1 观点一

在这里插入图片描述

    新生
    就绪
 运行   阻塞
    销毁
    
新生:创建线程对象
就绪:调用 start()方法
运行:执行线程
阻塞: sleep(),调用键盘输入方法回进入阻塞状态
销毁:执行结束

4.2 观点二

在这里插入图片描述

NEW
RUNABLE
WATTING
TIMED_WATING
BLOCKED
THMNATED

5 线程安全问题

synchronized关键字

5.1 同步代码块解决线程安全问题

synchronized(同步监视对象){
	可能出现安全问题的代码;
}

注:
    1.同步监视器对象必须是对象,一般采用共享数据
    2.想要达到同步效果,同步监视对象必须相同
    3.一条线程进入同步代码快,其他线程不能进入此同步代码块
      也不能进入拥有同一个同步监视器对象的其他代码块
    4.锁的范围
        不能太大  只有一条线程做功
        不能太小  没有同步效果

5.2 同步方法解决线程安全

同步方法的同步监视器对象
    this: 非静态同步方法
    类.class: 静态同步方法
    
    1. 普通的同步方法:同步监视器对象 this
      public synchronized void withDraw(int money){
      }
      
    2. 静态的同步方法:.class
     public static synchronized void withDraw(int money){
      }
注:
    如果一个线程进入了同步方法 其他线程不仅不能进入此同步方法 
    也无法进入拥有同一个同步监视器对象 的 其他同步方法

6 线程间通信

6.1 wait() 等待

wait();方法会释放锁
Objeck类中方法

    1.wait() 释放锁
      sleep() 会丢失CPU的执行权,但是不会释放锁
    2.调用者不同
        Thread.sleep()
        同步监视器对象调用 wait()
    3.Thread.sleep()  睡眠结束后自动苏醒
             wait()  等待 notify();唤醒
注:
    必须在同步方法 或者是同步代码块中使用

6.2 notify() & notifyAll() 唤醒等待的线程

notify();
同步监视器对象.notify();
Objeck类中方法
    多条线程等待时  随机唤醒一条
    必须在同步方法 或者是同步代码块中使用
    
notifyAll();
同步监视器对象.notifyAll();
Objeck类中方法
    唤醒所有的等待的线程
    必须在同步方法 或者是同步代码块中使用

7 死锁

死锁:互相持有对方的锁资源不放弃
解决:让一个线程执行完毕

四十一 单例设计模式

目的:保证实例(对象)是唯一的

41.1 饿汉式

无论是否需要对象,都先把对象创建
可以构造器私有,属性私有化,外界调用get方法获取,需要时调用即可
也可以使用枚举类实现

41.2 懒汉式

当真正需要此对象时,才创建出来
将构造器私有化,属性私有化,给外界提供一个get方法,
get方法内if判断 对象==nulltrue就创建新的实例对象,
注:
get语句上锁,防止线程安全问题

四十二 API

1 Math 数学类

Math类被final修饰

静态导入: 把数学类所有的静态资源导入,使用时可以省略类名直接调用
import static 包名.类名.*;
import static java.lang.Math.*;

1.Math.random() 随机数
    n:较大的数  m:较小的数
    (int)Math.random()*(n-m+1)+m);
2.Math.round() 四舍五入
    Math.round(3.5);
    Math.round(3.1);
3.Math.ceil() 向上取整
    Math.ceil(3.1);
    Math.ceil(3.5);
4.Math.floor() 向下取整
    Math.floor(3.9);
    Math.floor(3.1);
5.Math.PI 获取圆周率
6.Math.sqrt() 开平方
    Math.sqrt(9);
7.Math.pow(x,y) x^y
    Math.pow(2, 4);
8.Math.abs() 绝对值
    Math.abs(-10);
9.BigInteger: 用来表示过大的整数
    BigInteger b1 = new BigInteger("922337203685477580711");
    BigInteger b1 = new BigInteger("1");
运算方法:
    add();//加
    subtract();//减
    multiply();//乘
    divide();//除以
    remainder();//取模
示例代码:
    bi.add(b2);
10.BigDecimal 表示更加精确的小数
运算方法:
    同BigIntegerBigDecimal b1 = new BigDecimal("10.0");
    当进行除法运算时,如果是无限小数,会出现 ArithmeticException
    需要指定保留小数的位数和舍入模式
    BigDecimal divide = b1.divide(b2,10, RoundingMode.FLOOR);

2 Date 日期类

2. 1 JDK1.8前

Date date = new Date();--> 重要
    1.打印当前时间
        System.out.println(date);
    2.将时间对象 转为字符串
        String s = date.toLocaleString();--> 重要
    3.获取当前时间 距离 1970.1.1的毫秒值
        date.getTime();--> 重要
    4.距离1900年的整年数
        date.getYear();
    5.获取月份(一月从 0 开始)
        date.getMonth();
    6.获取周几
        date.getDay();
    7.Calendar
        Calendar c = Calendar.getInstance();
        c.get(属性);
            c.get(YEAR);
        c.set(属性,值);
            c.set(YEAR,1996);
        c.add(属性,值);
            c.add(YEAR,10);
日期格式化类:
    日期  ---> 字符串
        日期格式化对象.format(日期对象);
    字符串--->日期
        日期格式化对象.parse(字符串);
        字符串格式 必须与 日期格式化对象的格式完全一致
注:
    1.只能处理Date对象

2.2 JDK1.8后

  1.年月日
        LocalDate.now();
    2.时分秒
        LocalTime.now();
    3.年月日时分秒
        LocalDateTime.now(); 
    4.判断闰年
        LocalDate.of(,,).isLeapYear();
    5.获取月份值
        now.getMonthValue();
    6.获取当前月份的英文
        now.getMonth();
    7.获取指定时间
        LocalDateTime.of(2020, 2, 2, 2, 2, 2);
    8.增加时间
    
    9.减少时间
    
日期格式化类:
    日期  ---> 字符串
        预定义格式化
        本地格式化
        自定义格式化
    字符串--->日期
        
注:
    1.只能处理Date对象

2.3 String 类

常用方法
1.indexOf():查找指定字符串第一次出现的下标
2.lastIndexOf():查找指定字符串最后一次出现的下标。(没有返回-13.substring(开始下标):从开始下标一直到字符串结尾
4.substring(开始下标,结束下标)[开始下标,结束下标)
5.toCharArray():将字符串转为字符数组
6.getBytes():将字符串转为byte[]
7.split(","):按照指定的分隔符进行切割
8.replace('C', '你'):按照指定字符替换(C-->你)
9.replace("CD", "你好"):将指定的字符串替换为 指定字符串(CD-->你好)
10.split("\\d"):按照指定的分隔符进行切割(\d 代表所有数字)

四十三 二分查找

public static int halfSearch ( int[] arr, int key){
    int max = arr.length - 1;
    int min = 0;
    int mid = (max + min) / 2;
    while (max >= min) {
        if (key > arr[mid]) {
            min = mid + 1;
        } else if (key < arr[mid]) {
            max = mid - 1;
        } else {
            return mid;
        }
        mid = (max + min) / 2;
    }
    return -1;

四十四 直接选择排序

int [] arr1 = {40,20,50,10,60,30};
for (int i = 0; i < arr1.length - 1; i++) {
    int minIndex = i;
    for (int j = i + 1; j < arr1.length; j++) {
        if (arr1[j] < arr1[minIndex]) {
            minIndex = j;
        }
    }
    if (i != minIndex) {
        int temp = arr1[minIndex];
        arr1[minIndex] = arr1[i];
        arr1[i] = temp;
    }
}

四十五 正则表达式

正则表达式:一门独立的语言,用来做数据校验

[]: 只能匹配一个字符
[ABC]:匹配单个A B C
[0-9]:所有数字
\d:所有数字
[A-Z]A-Z
[a-z]:a-z
[A-z]A-z(对照acs编码,中间包含了几个标点)
\w :[a-zA-Z_0-9] 数字字母下划线

量词:
    ?: 出现0次或者1+: 代表1次或者多次
    *:代表0次或者多次
    {X}: 恰好出现X{X,}: 至少出现X{X,Y}:  出现[X,Y]
    ^: [^]取反
       [^A]: 只要不是 A 都可以
       
    ^XXX:以XXX开始
    $XXX:以XXX结束
方法:
    1.matches("[ABC]");//判断是否与ABC有匹配(单个匹配)
    2.startsWith("1A"));//判断是否以XXX(1A)开头
    3.endsWith("D");//判断是否以XXX(D)结尾
    4.replaceAll("^\\d|\\d$", "");//去除开头和结尾的数字

四十六 可变字符串

1 StringBuilder

声明:
    StringBuilder builder = new StringBuilder();
方法:
    1.builder.setLength(20);//设置StringBuilder的长度
    2.builder.insert(2, "你好");//在指定位置插入
    3.builder.deleteCharAt(2);//在指定位置删除数据
    4.builder.delete(0, 3);//删除指定范围数据 [开始,结束)
    5.builder.setCharAt(2, 'A');//更改指定下标的数据
    6.builder.indexOf("c");//查找指定元素第一次出现的下标(不存在返回-1)
    7.builder.indexOf("c", 4);//从指定位置开始查找 指定元素第一次出现的下标
    8.builder.lastIndexOf("c");//查找指定元素最后一次出现的下标
    9.builder.append("春风十里不如你");//追加数据
    10.builder.reverse();//数据反转
    11.builder.replace(0, 3, "SUCCESS");//替换指定位置[start,end)的数据
    
注:
1.final2.在创建对象时,使用父类的 char[] 存储数据
               默认长度16
3.线程不安全但效率高

2 StringBuffer

声明:
    StringBuffer builder = new StringBuffer();
方法:
     1.builder.setLength(20);//设置StringBuilder的长度
    2.builder.insert(2, "你好");//在指定位置插入
    3.builder.deleteCharAt(2);//在指定位置删除数据
    4.builder.delete(0, 3);//删除指定范围数据 [开始,结束)
    5.builder.setCharAt(2, 'A');//更改指定下标的数据
    6.builder.indexOf("c");//查找指定元素第一次出现的下标(不存在返回-1)
    7.builder.indexOf("c", 4);//从指定位置开始查找 指定元素第一次出现的下标
    8.builder.lastIndexOf("c");//查找指定元素最后一次出现的下标
    9.builder.append("春风十里不如你");//追加数据
    10.builder.reverse();//数据反转
    11.builder.replace(0, 3, "SUCCESS");//替换指定位置[start,end)的数据

注:
1.final2.继承自 AbstractStringBuilder
3.在创建对象时,使用父类的 char[] 存储数据
               默认长度16
4.线程安全但效率低

四十七 集合

集合是个容器,用来存储数据的

1 Collection

list和set的根接口

add();
contains();
remove();//按照元素删除
isEmpty();
size();
iterator();
addAll();
toArray();
retainall();//求交集

2 List

有序 下标顺序 下标从0开始
不唯一 数据可以重复

声明:
    //存在多态
    List<String>  list = new ArrayList<>();
增删改查:
    1.list.add("李白");//添加元素
    2.list.add(1,"安琪拉");//添加到指定下标的位置
    3.list.remove("杜甫");//删除指定的元素
    4.list.remove(0);//删除指定下标的元素
    5.list.get(0);//获取指定位置的数据
    6.list.set(1, "嬴政");//修改指定下标的数据
    7.list.indexOf("王安石");//指定元素第一次出现的下标
    8.list.lastIndexOf("王安石");//指定元素最后一次出现的下标
    9.list.toArray(new String[]{});//返回指定类型的数组
    10.list.addAll();//全部添加到集合
    11.list.retainall();//求交集
遍历数组:
    1.增强for
        for (String s : list) {
            System.out.println(s);
        }
    2.iterator迭代器
        Iterator<String> iterator = list.iterator();
            while (iterator.hasNext()) {
            String ele = iterator.next();
            System.out.println(ele);
        }
    3.遍历角标,通过角标获取元素
        for (int i = 0; i < list.size(); i++) {
            String ele = list.get(i);
            System.out.println(ele);
        }
    4.listIterator迭代器(自前向后遍历)
        ListIterator<String> listIterator = list.listIterator();
        while (listIterator.hasNext()) {
            //获取当前元素的前一个下标
            int previousIndex = listIterator.previousIndex();
            String next = listIterator.next();
            //获取当前元素的后一个下标
            int nextIndex = listIterator.nextIndex();
            System.out.println("previousIndex = " + previousIndex 
            + ",next = " + next + ",nextIndex = " + nextIndex);
        }
    5.listIterator迭代器(自后向前遍历,前提完成自前向后遍历)
        ListIterator<String> listIterator = list.listIterator();
        while (listIterator.hasPrevious()) {
            String previous = listIterator.previous();
            System.out.println("previous = " + previous);
        }
终极遍历:
    list.forEach(System.out::println);

3 Set

自定义类型 实现去重 需要重写hashCode(); equals();

1.HashSet:无序:不是按照添加顺序展示    唯一
    声明:
        HashSet<Person> set = new HashSet<>();
    遍历:
        1.iterator迭代器
            Iterator<String> iterator = set.iterator();
                while (iterator.hasNext()){
                String next = iterator.next();
                System.out.println("next = " + next);
            }
        2.增强for
            for (Person person : set) {
                System.out.println(person);
            }
        
2.LinkedHashSet:有序:按照添加顺序展示    唯一
    声明:
        LinkedHashSet<Person> set = new LinkedHashSet();
    遍历:同 HashSet

3.TreeSet:有序:自然顺序    唯一
    声明:TreeSet<Student> set = new TreeSet<Student>();
    遍历:
        1.iterator迭代器
            (如果存储为类类型值,需要类实现Comparable接口并重写方法,
              或在声明TreeSet时内部实现Comparator接口并重写方法)
            TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
                @Override
                public int compare(MaxStudent o1, MaxStudent o2) {
                return Double.compare(o1.score, o2.score);
                }
            });
        2.增强for:同 HashSet

4 Map

1 HashMap<> 存储键值对

key         无序唯一
            如果key重复 新的value 替换旧的value
value       随意
方法:
    1.put();//添加
    2.remove();//删除
    3.containsKey();//查找
    4.containsValue();//查找
    5.replace();//修改
    
声明:
    HashMap<String, String> map = new HashMap<>();
遍历:
    1.通过获取所有的key 获取value
        Set<String> keys = map.keySet();
        for (String key : keys) {
            String value = map.get(key);
            System.out.println(key + " --> " + value);
        }
    2.获取所有的键值对象
        //将所有的键值对存到set内
        Set<Map.Entry<String, String>> entries = map.entrySet();
        //通过iterator遍历
        Iterator<Map.Entry<String, String>> iterator = entries.iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            System.out.println(entry.getKey()+"-->"+entry.getValue());

2 LinkedHashMap

3 TreeMap

四十八 集合工具类(Collecyions)

Collection:接口
Collections:操作集合的工具类

1.Collections.binarySearch(list, 60);//二分查找 确定元素的下标
2.Collections.sort(list);//排序
3.Collections.shuffle(list);//打乱集合元素的顺序
4.Collections.addAll(list,100, 10,20,30,40,50,60);//批量新增
5.Collections.copy(dest, list);//复制(新集合长度大于原集合)
6.Collections.swap(list,0,2);//按照下标交换集合指定元素
7.Collections.frequency(list, "李白");//查询集合内指定元素出现的次数
8.Collections.synchronizedList(list);//将线程不安全的集合变为线程安全的
9.Collections.unmodifiableList(list);//将集合变为不能修改的集合
10.Collections.reverse(list);//元素反转
11.Collections.min(list);//查找最小值

四十九 泛型

为了让数据按指定的方式存储,类型化参数

泛型类示例代码:

/*
例如:我们要声明一个学生类,该学生包含姓名、成绩,
而此时学生的成绩类型不确定,为什么呢,因为,
语文老师希望成绩是“优秀”、“良好”、“及格”、“不及格”,
数学老师希望成绩是89.5, 65.0,
英语老师希望成绩是'A','B','C','D','E'。
那么我们在设计这个学生类时,就可以使用泛型
 */
 
 public class Test {
    public static void main(String[] args) {
        Student<String > s1 = new Student<>("建国", "优秀");
        //int会自动装箱为Integer
        Student<Double> s2 = new Student<>("淑芬", 100.0);
        Student<Character> s3 = new Student<>("狗蛋",'A');
    }
}
 
 public class Student<T> {
    String name;
    T score;
    public Student(String name, T score) {
        this.name = name;
        this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}

1 泛型的位置上

为了见明知意
    T type
    K key
    E element
    V value
    
1.泛型类
    声明处存在<T>
2.泛型接口
    声明处存在<E>
3.泛型方法:
    方法确定是才能确定类型的方法才是泛型方法

注:
    需要泛型,未指定泛型时,采用Object类型
    局部变量泛型,只存在编译时

泛型的上限:全部使用extende
    T extende Number & Comperbor
    
泛型擦除:
1.如果当前类型需要泛型 却没有指定泛型  那么 采用Object类型
2.如果是方法内的局部变量使用了 泛型 只会存在于编译时 class 中没有泛型约束
  但是如果是成员变量方法的形参,使用了泛型会保留到运行时 class 有泛型约束

2 泛型的上限

泛型的上限:全部使用extende
    T extende Number & Comperbor
    
注:
    要继承的类在前,要实现的接口在后

3 占位符 ?

?:不确定什么类型时使用

上限
    ? extends 类
下限
    ? super 类:传入的类型只能是当前类型或当前类型的父类(可以存在多态)

五十 数据结构初识

在这里插入图片描述

1 二叉树

在这里插入图片描述

1.1 二叉树的分类

1.满二叉树:
    除最后一层无任何子节点外,
    每一层上的所有结点都有两个子结点的二叉树。
2.完全二叉树:
    叶结点只能出现在最底层的两层,
    且最底层叶结点均处于次底层叶结点的左侧。
3.平衡二叉树:
    左右高度差不超过一

1.2 二叉树的遍历

在这里插入图片描述

1.前序遍历
    ABDHIECFG
2.中序遍历
    HDIBEAFCG
3.后序遍历
    HIDEBFGCA

2 链表

2.1 链表的分类

1.单链表
2.双链表
3.循环链表

2.2 linkedlist

双链表:可以操作首尾元素
方法:
  addFist();
  addLast();
  removeFirst();
  removeLast();
  getFirst();
  getLast();

五十一 动态数组

Vector & ArrayList

相同点:
	1.都是使用 Object 类型数组存贮数据
	2.都继承自 AbstractList 类

不同点:
	1. Vector 创建对象时,就会自动创建长度为10的数组
	   ArrayList 第一次添加的时候才创建长度为10的数组
	2. ArrayList 扩容到原来的1.5Vector capcityIncrement 当为0时,扩容到原来的2Vector capcityIncrement 当为>0时,扩容到(原有长度 + capcityIncrement)
	3. 线程安全 Vector 效率低
	   线程不安全 Vector 效率高

五十二 栈和队列

栈:FILO(先进后出)
   first in last out
    
    Stack s = new Stack();
        push();//入栈
        peek();//获取栈顶元素
        pop();//弹栈
    
    Deque  d = new LinkedList();
        push();//入栈
        peek();//获取栈顶元素
        pop();//弹栈
    
队列:FIFO(先进先出)
    first in first out
    
    Queue lisk = new LinkedList();
        list.add();//入队
        list.poll();//出队
        list.peek();//获取队头

五十三 Hashtable & HashMap

同:
	Hashtable HashMap 存储数据都采用哈西表
	都存储的是键值对
	都实现了Map接口
不同:
	1.Hashtable  线程安全,效率低
	  HashMap    线程不安全,效率高
	2.Hashtable  key和value,都不能是null
	  HashMap    key和value,都能是null

1 HashMap储值原理

1.1 JDK1.7

1.创建对象时
    默认长度:16
    阈值:12
    增长因子:0.75f
2.添加数据
	2.1 当key 为null
        存到底层顺序表下标为0的位置 
	2.2 当key 不为null  首次添加
         直接插入
	2.3 当key 不为null  非首次添加
        2.3.1 位置一样 key 不一样
            添加到原有数据的前面   七上	
        2.3.1 位置一样 key 一样
            新添加的value 会替换旧的value 并将旧的value返回
扩容:
    1.size>= 阈值
    2.即将插入的位置不是null

1.2 JDK1.8

.创建对象时
    只给成员变量 负载因子赋值
2.添加数据
    2.1 当key 为null
        存到底层顺序表下标为0的位置 
	2.2 当key 不为null  首次添加
        直接插入
	2.3 当key 不为null  非首次添加
        2.3.1 位置一样 key 不一样
            添加到原有数据的下面   八下	
        2.3.1 位置一样 key 一样
            新添加的value 会替换旧的value 并将旧的value返回		
扩容:
    1.某一个位置的节点数量>=8
    2.底层数组的长度>=64

五十四 File 类

file类:
    文件及文件夹
    
方法:
    getName();//获取名字
    length();//获取长度
    lastmodified();//获取最后修改时间
    ceateNewFile();//创建文件夹
    mkdirs();//创建文件(多个)
    delete();//删除
    isFile();//判断是否是文件
    isDiretory();//判断是否是文件夹
    
路径:
    相对路径
    绝对路径
    规范路径

五十五 IO流

四大顶流

全都是抽象类,需要通过子类实现功能
    字节:InputStream  OutputStream
    字符:Reader       Writer

1 节点流

直接作用到文件上面(形参是文件)

1.1 字节流
1.字节输入流:FileInputStream
    写出数据时,如果目的地不存在,会自动新建
注意:
    1.当写出的文件内有数据 【再次】写入数据 会将原有数据清空
    2.想要在数据末尾进行追加  可以使用 new FileOutputStream("路径", true);
2.字节输出流:FileOutputStream
    read()://一次读取一个字节的数据
    有数据返回该数据的编码值
    当没有数据时 给你返回 -1
    read(byte[]);会将数据存到 数组内  当没有数据时返回 -1
1 .2 字符流
1.字符输入流:FileReader
    1.1 一次读取一个字符数据,当没有数据时返回 -1
    1.2 一次读取一个字符数组,将数据存到数组内,
        没有数据时返回-1,有数据返回读到的有效数据个数
2.字符输出流:FileWriter
    2.1有缓存区,必须关流 或 通过 flush(); 刷出

1.3 复制文件

/**
 *示例代码
 */
 
//创建输出输入流
FileReader fe = new FileReader("E:\\1. JAVA\\1.讲师录屏等\\1.书\\a.txt");
FileWriter fw = new FileWriter("E:\\b.txt");
//边读边写实现复制
int length = 0;
while ((length = fe.read()) != -1) {
    fw.write(length);
}
//关闭资源
fe.close();
fw.close();

2 处理流

作用到流上(形参是流)

2.1 缓冲流
2.1.1 缓冲字节流
1.BufferedInputStream
    默认:8192 byte[]
    大小可以通过构造器换入实参改变
2.BufferedOutputStream
    默认:8192 byte[]
    大小可以通过构造器换入实参改变
2.1.2 缓冲字符流
1.BufferedReader  
新增方法:
    readLine();//读取一行字符
    一次读取一行数据,当么有数据时,返回 null
2.BufferedWriter   
新增方法:
    newLine();//另起一行
2.2 转换流
1.InputStreamReader: 将字节输入流--->字符输入流
        
2.OutputStreamWriter:将字节输出流--->字符输出流
2.3 数据流
1.数据输入流:DataInputStream
2.数据输出流:DataOutputStream
    保持数据提醒,只有字节流没有字符流,按照输出顺序进行读入
2.4 对象流
序列化: 将对象写到磁盘 
反序列化:将磁盘的对象读取出来

实现方式一:
将需要序列化的对象所在的类实现 Serializable 接口
被 trasient static 修饰的属性 不会被序列化

实现方式二:
1.将需要序列化的对象所在的类实现 Externalizable 接口 
  readExternale();
  writeExernale();
2.5 打印流
PrintStream();

ps.print();
ps.println();

可以改变 System.out的流向  ****

五十六 Scanner

new Scanner(new File(文件路径));

五十七 Properties

setPropertity();

getPropertity();

list(System.out);

load(); 进行加载
store();可以进行存储

五十八 网络编程

1 基本概念

软件架构:
	C/S  
	B/S
协议:网络传输的规则;
TCP/IP:(统称)	
TCP:协议
    三次握手 
    四次挥手
    面向连接的 
    安全的 可靠的
    数据量大
    
UDP:
    非面向连接的
    不可靠的
    传输的数据量下
网络传输的三要素:
    协议:
    ip:用于标记每一个通信实体的地址 127.0.0.1(本机)
    端口:每一个通信实体中软件的不同
                
InnetAddress: 获取通信实体的主机名 ip地址

2 流套接字

双向通信

客户端    服务端
    ---> A
    B<---

3 数据包接字

DatagramSocket  客户端/服务端 
DatagramPacket  信息载体  数据包

五十九 反射

1 基本概念

类的加载
   加载--->   使用---->  卸载
   
   加载:加载class文件
   
   连接:
   		验证:
   		准备:给类属性赋默认值   给类静态常量 赋默认值
   		解析:将符号引用替换为直接地址引用
   类的初识化:
       1.创建对象
       2.运行main()
       3.调用静态资源
       4.子类初始化 也会导致父类初识化
       5.反射操作  类初始化
   初始化滞后:
        1.子类使用了从父类继承的静态资源 只会导致父类初识化
        2.创建该类型数组
        3.调用本类中的静态常量

2 获取class运行时类型

public class Test2 {

    @Test
    public void test03() throws ClassNotFoundException {

        Class<B> clazz = B.class;
        Class<?> aClass = clazz.getClassLoader()
        .loadClass("com.atguigu.review.B");
    }

    @Test
    public void test02() throws ClassNotFoundException {
        //通过Class 静态方法forName()
        Class<?> aClass = Class.forName("com.atguigu.review.B");
    }
    @Test
    public void test01() {
        //类名。class
        Class<B> bClass = B.class;
        B b = new B();
        //对象名.getClass();
        Class<? extends B> aClass = b.getClass();
        System.out.println(bClass== aClass);
    }
}
class B {

}

六十 反射

1 类的加载器

引导类加载器  jre/lib/rt.jar
扩展类加载器  jre/lib/ext/*.jar
应用程序加载器 自己写的类 Student Animal 。。。。
自定义类加载器 保密性比较器 自定义程度比较高
应用程序加载器  extends  扩展类加载器 extends 引导类加载器

加载模式:
    双亲委托:未加载就逐级向上传递,在逐级向下传递。

2 反射方式获取资源

//1.获取运行时类型
    类名.class
    对象名.getClass();
    Class.forName("全类名");
    clazz.getClassLoader().load("全类名");

//2.获取所有构造器
	运行时类型.getDeclaredControctors();

//3.获取指定的构造器
  运行时类型.getDeclaredControctor(String.class,int.class);

//4.私有资源需要设置可见
    setAccessable(true);

//5.给属性赋值
    获取的构造器对象.newInstance("李白",20);

3 other

突破泛型限制
获取注解

六十一 新特性

1 lambda表达式

函数式接口:SAM	single abstract method;
只有一个抽象方法的接口就是函数式接口

()->{}

():函数式接口内的形参列表
    ->:lambda表达式的标示
    {}:方法体中的内容
        
  Thread thread = new Thread(() -> {
            System.out.println("兔子跑");
        });
        thread.start();

1.2 函数式接口

消费型
供给型
判断型
功能型

方法引用  构造器引用 数组引用
    对象::方法名;::new;

   Person::new;
   数组类型::new;
    int[]::new;

六十二 流式编程

1 创建流

list.stream();

Arrays.strem();

Stream.of();
......

2 中间操作

在这里插入图片描述

去重
排序
过滤
跳过
限制数量
映射

2.3 结尾操作

在这里插入图片描述

遍历
数量
最值
匹配
收集

六十三 Optional解决空指针问题

解决空指针问题

String s = null;

Optional o = Optional.ofNullAble(s);

o.elseGet();
o.elseThrow();

Copyright © 2002-2019 某某自媒体运营 版权所有