admin管理员组

文章数量:1588254

Java运行环境的部署(JDK)

我们想要在任意的目录下都可以打开指定的软件,就可以把软件的路径配置到环境变量中。


Javac是JDK提供的编译工具,可以把.java文件编译成.class文件。

Java程序的开发步骤:编写(.Java)>通过Javac.exe编译生成字节码文件(.class)>通过Java.exe对字节码文件进行运行(输出)


JDK(Java开发工具包)5.0/8.0/11.0/17.0 LTS 长期使用版本

JRE(Java运行时环境)

JVM(Java虚拟机)

JavaSE标准类库(API :预先定义好可以直接调用的函数)

他们之间的关系如下:

JDK=JRE+开发工具

JRE=JVM+JavaSE标准类库+运行工具


跨平台中平台的意思就是操作系统(Linux、MocOS、Window)

跨平台的原理是Java不是直接运行在操作系统中的,而是运行在虚拟机中的,我们只需要针对不同的操作系统给出不同的虚拟机就可以了。


Java数据类型

声明long类型变量时需要提供后缀,后缀为“l”或“L”

声明float类型变量时需要提供后缀,后缀为“f”或“F”

boolean类型只有两个数值:true、false 常使用在流程控制语句中

取值范围:

byte<short<int<long<float<double


字符集

制表符'\t'强制延伸至8个空格(补1-8空格)

\ 转义字符

char字符类型''单引号中有且仅有一个字符,字符集ASCLL码 a=97 A=65 48=0


Scanner键盘录入

//1.导包,找到Scanner类在哪,要写在类定义的上面
import java.util.Scanner;

class ScannerDemo{
    public static void main(String[] args){
        //2.创建对象,表示我现在准备要用这个类
        Scanner sc = new Scanner(System.in);
        //3.接受数据
        System.out.print("请输入第一个数:");
        int i = sc.nextInt();
    }
}

体系一:nextint();nextdouble();next(); 遇到空格、制表符、回车、就停止接收后面录入的数据。

体系二:nextLine()可以接受空格、制表符、只有遇到回车才停止接收数据。

占位符:%s   System.out.printf("你好啊%s","张三");//你好啊张三


IDEA

IDEA使用教程

项目(project) module(模块) ackage(包) class(类)

快捷键

Ctrl+Alt+M 抽取方法的快捷键

Shift+f6 改全部变量的快捷键

Ctrl+Alt+T 包裹代码选择语句

Ctrl+Alt+L 格式化代码

Ctrl+Alt+V 自动生成左边

Ctrl+Alt+方向键 返回/跳转

Ctrl+D 复制到下一行

Ctrl+B 查看类源码

Ctrl+N+f12  搜索

Alt+回车 可以选择相对应的提示

Ctrl+Shift+U 小写字母变大写字母

Ctrl+Shift+方向键 移动一行代码

Alt+Fn+Insert Constructor快速生成有参构造方法 Getter and Setter快速生成getset方法


三元运算符
格式: 关系表达式?表达式1:表达式2

如:

int a = 10;
int b = 20;
int max = a>b?a:b;
System.out.println(max);


原码、反码、补码

原码:十进制数据的二进制表现形式,最左边是符号位,0为正,1为负。

利用原码对正数计算是不会有问题的。正数的原、反、补都是一样的。

如:0000 0100(4)+ 0000 0001(1) = 0000 0101 (5)

但如果是负数计算,结果就出错,实际运算的结果,跟我们预期的结果是相反的。

如:1000 0100(-4)+ 0000 0001(1) = 1000 0101(-5)跟正确答案1是相反的。

原因是:二进制后面数字先表示完,最后再由最左边的符号位决定正负的。有两个0[+0(0000 0000)和-0(1000 0000)]也是因此而导致。所以为了解决原码不能计算负数的问题,发明了反码。

反码:正数的反码不变,负数的反码在原码的基础上,符号位不变。数值取反,0变1,1变0。

如: 1000 0100(-4)+ 0000 0001(1) = 1000 0101(-5)

1111 1011 (-4反码)+ 0000 0001 (1) = 1111 1100(再转原码)=1000 0011(-3)

转码运算再转码的意义在于:运算完之后再决定符号位的正负。

但因为符号位导致了有+0和-0的存在,所以

1000 0001(-1)反码1111 1110 +0000 0001(1)= 1111 1111(-0)

-1+1=-0=0 好像也没问题,但是---

当1000 0000(-0)反码1111 111 + 0000 0001(1)= 0000 0000(+0)

-0+1=0,误差为1,继续:

当1000 0101(-5)反码 1111 1010 + 0000 0110(6)= 0000 0000(+0)

-5+6=0,误差为1,继续:

当1000 0100(-4)反码 1111 1011 + 0000 0110(6)= 0000 0001(1)

-4+6=1,误差为1,继续:

当1000 0100(-4)反码1111 1011 + 0000 0111(7)= 0000 0010(2)

-4+7=2,误差还是为1,为什么呢?

还是因为符号位的问题导致在二进制中,有两种表现形式0,一个0000 0000(0),一个1111 1111(-0),所以导致最后运算的结果有1的误差。为了解决原码不能计算负数的问题,又有了补码。

补码:负数的补码=反码+1,因为有两个0,所以把11111111这个原本的-0作为-1的反码的补码,

-4的反码+1=1000 1100 + 0000 0010(2)= 1000 1110(-2补码)  

-4的反码+1=1000 1100 + 0000 0101(5)= 0000 0001(1)

因为反码+1=补码,所以补码到-128有一个补码1000 0000,没有原码也没有反码。

补码解决了负数计算时跨0的问题,也正因如此,数字的存储和计算都是以补码的形式来进行的。

扩展知识:

在不同的数据类型下有不同的字节占用,如:

byte类型的10 1个字节 0000 1010

short字节的10 2个字节 0000 0000 0000 1010

int类型的10 4个字节 0000 0000 0000 0000 0000 0000 0000 1010

long字节的10 8个字节 0000000000000000000000000000000·· 1010

进而解释了隐式转换和强制转换:

byte a = 10;//0000 0010

int b = a;//0000 0000 0000 0000 0000 0000 0000 1010

隐式转换=前面补0

int a = 300;//0000 0000 0000 0000 0000 0001 0010 1100

byte b = (byte)a;//0010 1100

强制转换=截断

public class test08 {
public static void main(String[] args) {
int a = 200;//0000 0000 0000 0000 0000 0000 1100 1000
byte b =(byte)a;//1100 1000//最左边的1是符号位,11001000是补码形式,补码-1=11000111,再转原码是00111000
System.out.println(a);//=200
System.out.println(b);//00111000//-56

int c = 12;
int d = 2 ;
System.out.println(c&d);//逻辑与 0为false 1为true 把两个数都转为二进制,只有两个都是1,才有1,再转成十进制。=0
System.out.println(c|d);//逻辑或 0为false 1为true 把两个数都转为二进制,只要其中一个是1,才是1,再转成十进制。=14
System.out.println(c<<2);//左移 向左移动,低位补0 转2进制整体左移2bit,每左移1次就是×2,然后再转十进制。=48
System.out.println(c>>2);//右转 向右移动,高位补0或1(与右移前原符号位相等) 转2进制整体右移2bit,每右移1次就是除2,然后再转十进制。=3
System.out.println(c>>>2);//右转 向右移动,高位补0 转2进制整体右移2bit,每右移1次就是/2,然后再转十进制。=3
}}


流程控制语句

顺序结构:

Java默认的执行结构,从上往下,依次执行。

分支结构:

  • if语句

if(a>b){}{} 如果表达式不成立,则语句体不再执行。

if(a>b){}else{} 不会都执行也不会都不执行。二者选其一。

if(a>b){}else if(){}else{};n者选其一。

如果对一个boolean类型的变量进行判断,不要用==号,直接把变量写在判断语句中。因为boolean类型的值本身就是判断的结果。而其他判断语句要用==号,因为=是赋值,==才是判断。

补充:

if (flag)相当于 if (flag == true)

if (!flag)相当于 if (flag == false)

if判断语句中使用布尔值作为判断式,只有在布尔值为true时才会执行,为false则跳过,不执行。

  • switch语句

switch(a){case 值1:语句体1;break;case 值2:语句体2;break;default: break;}

如:int a = 10 switch(a){case 10: a;}//case 10 ->{a};

case具有穿透性。当输出语句重复时可以不写break;让case穿透输出。

 jdk12之后优化了switch语句:case 1 ->{}//如果大括号里只有一行代码,{}可以省略。

switch语句中ab取值为byte、short、int、char、JDK5以后可以是枚举,JDK7以后是String。

default可以省略不写,且位置没有上下顺序。

综上所述,if适用于范围判断,swich适用于有限个列举。

循环结构:

  • for循环

for(int i = 1;i <= 10;i++){System.out.println("helloworld");}s

for( 初始语句; 执行条件; 增量 ){循环体}

for循环嵌套的处理逻辑:

只要内循环满足执行条件,是先内循环的,如果内循环不满足执行条件了再跳出内循环到外循环。

  • while循环

while(a >1){}

while(条件判断语句){循环体语句;条件控制语句;}循环下面的语句

for和while的区别:

for循环中:知道循环次数或者循环的范围。

while循环:不知道循环的次数和范围,只知道循环的结束条件。

  • do...while循环

do{循环体语句;条件控制语句;}while(条件判断语句);

先执行后判断。

无限循环:

for(;;){}

while(true){}

do{}while(true);

跳转控制语句:

for (int i = 1; i <= 5; i++) {if (i == 3) {continue;}System.out.println(i);}//1245//

continue:跳过本次循环,继续执行下次循环。

for (int i = 1; i <= 5; i++) {if (i == 3) {break;}System.out.println(i);}//12

break:结束整个循环。

当内外循环嵌套时,假设break是在内循环,这样是无法停止整个循环的,我们可以在外循环格式前输入“xxx:”给外循环命名,这样break xxx就可以跳出指定命名的那个循环了。或在结束整个循环的语句中写:System.exit(0);该输出语句为:停止虚拟机运行。


Random生成随机数:

//1.导包,找到Random类在哪,要写在类定义的上面

import java.util.Random;

class RandomDemo{
    public static void main(String[] args){
        //2.创建对象,表示我现在准备要用这个类
        Random r = new Random();
        int num =r.nextInt();
        //3.接受数据
        System.out.print("请输入一个数:");
        int i = sc.nextInt(100);//包左不包右,0~99
    }
}

生成固定范围随机数:int num = r.nextInt((范围最大值-最小值)+1)+最小值;

如:生成5~15随机数 

数组

数组的定义:

格式1:数据类型[]数组名,如int[]arr【常用】

格式2:数据类型数组名[],如int arr []

数组的静态初始化:

完整格式:数据类型[]数组名=new 数据类型[]{元素1,2,3};如:int[]arr = new int[]{11,22,33};

简化格式:数据类型[]数组名={11,22,33};如:int[]arr = {11,22,33};【常用】

int[]arr1 = new int[]{11,22,33};System.out.println(arr1);//[I@4eec7777

地址值:[I@4eec7777

[:表示当前是一个数组

I:表示当前数组的数据类型都是int类型的

@:表示一个间隔符号(固定类型)

4eec7777:数组真正的地址值(十六进制)

索引(下标):

索引从0开始,最小索引是0,最大索引是length-1

把数据存储到数据中,格式:数组名[索引] = 具体数据/变量;如:arr[0] = 100;

length是Java当中,关于数组的一个长度属性,调用方式:数组名.length

数组遍历:

遍历就是利用循环将数组中所有的内容取出来,取出来之后可以打印、求和、判断,但要注意:遍历指的是去除数据的过程,不要局限的理解为:遍历=打印。

idea中快速生成数组遍历的快捷键为:数组名.fori

一个循环尽量只做一件事情。

数组动态初始化:

初始化时只指定数组长度,由系统为数组分配初始值。

格式:数据类型[]数组名 = new 数据类型[数组长度];如:int[]arr = new int[3];

数组类型默认初始化值:

整数类型:0

小数类型:0.0

字符类型:'\u0000'(空格)

布尔类型:false

引用数据类型:null

Java内存分配

JVM占用的内存空间分为:

栈:方法运行时使用的内存,比如main方法运行。开始执行时进入方法栈中运行,代码执行完毕会出栈。

堆:存储对象或者数组,new来创建的,都存储在堆内存。new出来的东西会在这块内存中开辟空间并产生地址。在堆里面开辟的空间会有地址值。而每一块小空间的地址都是不一样的。

方法区:存储可以运行的class文件。

本地方法栈:JVM在使用操作系统功能时的时候使用,和我们开发无关。

寄存器:给CPU使用,和我们开发无关。


方法

方法是程序中最小的执行单元。如我们经常使用的打印sout就是一个方法,在out类下面out.println就是调用这个方法,里面的东西是参数。重复的代码、具有独立功能的代码可以抽取到方法中。可以提高代码的复用性和可维护性。

方法的格式

public static void main 方法名() {方法体;}

如:public static void main studyJava() {“学习”;}

方法的调用

方法名(); 如:studyJava();

方法必须先定义后调用,方法要写在main方法的里面,类的外面。

调用过程:看到方法进入方法,执行完毕回到调用处。

带参数的方法定义和调用

public static void main 方法名(参数) {...} 如:public static void main (int num){...}

public static void main 方法名(参数1,参数2,..) {...}        

如:public static void main (int num1,int num2){...}。

参数

形参:形式参数,是指方法定义中的参数()方法小括号中,形参

实参:实际参数,是指方法调用中的参数{...}中定义的int a = 1;实参

方法的完整定义和调用(带返回值、参数、return)

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

如:public static int getNum(int a,int b){int c = a + b; return c;}

直接调用:方法名(实参);

赋值调用:整数类型 变量名 = 方法名(实参);

输出调用:System.out.println(方法名(实参));

return:返回值,如果方法执行到了return,那么整个方法全部结束。方法内的循环也会随之结束。

重载

 在一个类中,方法名相同,参数不同的方法,就是重载,与返回值无关。 

内存

基本数据类型:变量存储的是真实的数据,如:在main方法中定义int a = 10,那就是在栈内存中真实的开辟了一个空间,这个空间就叫做a,而10则是真实的存储在小空间里的数据。

方法传递基本数据类型时,传递的是真实的数据。形参的改变不影响实际参数的值。

引用数据类型:当一个变量当中,存储的不是真实的数据,而是存储的其他空间的地址值时,这个变量我们就称为引用数据类型。如数组,实际上在栈内存中记录的是存储在堆内存中的地址值。

方法传递引用数据类型是,传递的是地址值形参的改变影响实际参数的值。

二维数组

但我们需要把数据分组管理的时候,就需要用到二维数组。

1.二维数组静态初始化格式

完整格式:数据类型[][]数组名 = new 数据类型[][]{{元素1,元素2},{元素1,元素2}};

如:int[][]arr = new int[][]{{11,22},{33,44}};

简化格式:数据类型[][]数组名 = [][]{{元素1,元素2},{元素1,元素2}};

如:int[][]arr = {{11,22},{33,44}};【常用】

2.获取元素
arr[i][j]
arr: 二维数组
i: 二维数组的索引,获取出来的是里面的一维数组

j: 表示一维数组中的索引,获取出来的就是真正的元素

3.二维数组遍历
外循环:表示二维数组中的每一个元素 (一维数组)
内循环:遍历一维数组,得到里面的每一个元素

4.二维数组动态初始化格式
格式: 数据类型[][]数组名 = new 数据类型[m][n];

m表示这个二维数组,可以存放多少个一维数组

n表示每一个一维数组,可以存放多少个元素
如: int[]arr = new int[2][3];
该数组可以存放2个一维数组,每个一维数组中可以存放3个int类型元素


面向对象

  • 类和对象

类:是对象共同特征的描述;(好比于设计图,一个结构,一个模型。)

对象:是真实存在的具体东西。(对象就是按照这张设计图而创建出来的具体实例。)

在Java中必须先设计类,才能获取对象。类是对象的模板,对象是类的实体。

举个例子:在动物这个类中,小狗就是一个具体的对象。小狗的体重、年龄、年龄都属于是动物类的属性,而小狗撒欢的跑、汪汪叫都属于是动物类的行为所以,对象是具体存在的,具备该类事物的属性和行为。

参考:类与对象之间的关系_简述类和对象的关系_陇上乐的博客-CSDN博客

面向对象完成具体功能的操作的三步流程:

步骤1:创建类,并设计类的内部成员(属性、方法)

步骤2:创建类的对象。比如: Scanner sc = new Scanner();

表示创建一个Scanner类的对象sc,当需要使用到Scanner类里面的属性和方法时,就需要通过对象.的格式来调用。因为不在同一个包下,所以还需要导包才能使用。

步骤3:通过对象,调用其内部声明的属性或方法,完成相关的功能


定义类的格式:

public class 类名{
1、成员变量 (代表属性,一般是名词)
2、成员方法(代表行为,一般是动词)

3、构造器

4、代码块

5、内部类

如:
public class Phone{
// 属性 (成员变量)类内、方法外
String brand;
double price;
// 行为 (方法)不写static
public void call(){}
public void Study(){}


创建类的对象的格式:
类名 对象名 = new 类名();

如:Phone p = new Phone();

类的实例化:

等价描述:类的实例化 <=> 创建类的对象 <=> 创建类的实例

格式:类类名 对象名 = 通过new创建对象实体

举例:

Phone p1 = new Phone ();

Scanner sc = new Scanner(system.in);

String str = new String();


调用对象使用的格式:
调用属性:对象名.成员变量

如:p.brand = "小米"; p.price = "599.9";//赋值


调用方法:对象名.方法名(...

如:p.call; p.Study


定义类的补充注意事项:
用来描述一类事物的类叫做Javabean类,在Javabean类中,是不写main方法的。
而编写main方法的类,叫做测试类

我们可以在编写main方法的类中创建/Javabean类的对象/并进行赋值调用。


成员变量的完整定义格式是: 修饰符 数据类型 变量名称 = 初始化值;

一般无需指定初始化值,调用时再赋值。

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

封装

封装就是将一些细节信息隐藏起来,对于外界不可见,利用抽象数据类型将数据(如方法)和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口(如使用方法名调用方法)使之与外部发生联系。系统的其他对象只能通过包裹在数据外面的已经授权的操作来与这个封装的对象进行交流和交互。也就是说用户是无需知道对象内部的细节,但可以通过该对象对外的提供的接口来访问该对象。

1.方法就是一种封装。

2.关键字private也是一种封装。 

private关键字

权限修饰符 可以修饰成员(变量和方法),被private修饰的成员只能在本类中才能访问。

对于基本类型当中的boolean值,Getter方法一定要写成isXxx的形式,而setXxx规则不变。

成员变量和局部变量

成员变量:类中,方法外。

局部变量:方法中、方法申明中(形参)。

this关键字

如果方法内的局部变量和方法外的成员变量重名的时候,使用该变量就采用就近原则,在这种情况下赋值,方法内的局部变量被赋值之后还是等于重新赋值给了局部变量,没有成功赋值给成员变量。如果方法内想要使用到方法外的成员变量时,就需要使用到this关键字,因为this关键字代表方法调用者的地址值,这样可以区别成员变量和局部变量。通过谁调用的this,谁就是this。 

原理:main方法先进栈,然后执行main方法里的第一行代码:Student s = new Student,这里用到了Student这个类,会把Student类的字节码文件加载到方法区,=的左边因为定义了一个变量s,所以会在栈中记录一个变量Student s =,因为new关键字,所以在堆当中开辟了一个空间,假设空间地址值是001,Student s = 记录的就是这个空间的地址值001。那么使用s.调用方法,this记录的就是s的地址值001,所以当this.去获取成员变量时,获取的就是地址值001中的成员变量。

构造方法

在创建对象的时候给成员变量进行初始化(赋值)的。

无参数构造方法:初始化的对象时,成员变量的数据均采用默认值。

有参数构造方法:在初始化对象的时候,同时可以为对象进行赋值。

构造方法的格式:
public class Student {
修饰符 类名(参数){
方法体;

}
特点:
1.方法名与类名相同,大小写也要一致
2.没有返回值类型,连void都没有
3.没有具体的返回值 (不能由retrun带回结果数据)

4.如果我们没有写任何的构造,那么虚拟机会默认给我们一个无参构造方法。

5.带参构造方法,和无参数构造方法,两者方法名相同,但是参数不同,这叫做构造方法的重载。

6. 无论是否使用,都手动书写无参数构造方法,和带全部参数的构造方法。


标准的JavaBean类
1.类名需要见名知意
2.所有的成员变量都要使用private修饰
3.提供至少两个构造方法:无参构造方法和带全部参数的构造方法
4.成员方法:提供每一个成员变量对应的setXxx()/getXxx()如果还有其他行为,也需要写上


API&字符串

API(应用程序编程接口):API就是别人已经写好的东西,我们不需要自己编写,直接使用即可。


字符串:

1.使用直接赋值的方式获取一个字符串对象——String s1 = "abc";


2.使用new的方式来获取一个字符串对象
可以获取一个空白的字符串对象——String s2 = new String();//空参
传递一个字符串,根据传递的字符串内容再创建一个新的字符串对象String s3 = new String("abc");


3.传递一个字符数组,根据字符数组的内容再创建一个新的字符串对象
需求: 我要修改字符串的内容。
char[]chs = {'a','b','c','d'};
String s4 = new String(chs);


4.传递一个字节数组,根据字节数组的内容再创建一个新的字符串对象
应用场景: 以后在网络当中传输的数据其实都是字节信息
我们一般要把字节信息进行转换,转成字符串,此时就要用到这个构造了
byte[] bytes = {97,98,99,100};
String s5 = new String(bytes);


字符串比较:
字符串的内存原理:等号直接赋值的字符串是优先去串池复用的,如果串池里面没有才重新创建,而new出来的字符串是在堆里面开辟了一个新的空间,每一次new都是创建了新的小空间,所以不能直接==判断进行比较,每一个new出来的字符串对象的地址值在堆里肯定是不一样的。

boolean equals方法(要比较的字符串) 完全一样结果才是true,否则为false
boolean equalslgnoreCase(要比较的字符串) 忽略大小写的比较


遍历字符串可以用到的API:

public char charAt(int index): 根据索引返回字符 调用格式:字符串名.charAt(索引);返回char类型

public int length(): 返回此字符串的长度 调用格式:字符串名.length();


截取

String substring(int beginlndex, int endindex)

截取到末尾String substring(int beginIndex)

调用格式:字符串名.substring(索引1,索引2)

注意点: 包头不包尾,包左不包右


替换

String replace(旧值,新值)  调用格式:字符串名.replace


链式编程:
当我们在调用一个方法的时候,不需要用变量接收他的结果,可以继续调用其他方法


StringBuilder

使用场景:
1.字符串的拼接
2.字符串的反转

StringBuilder可以看成是一个容器,创建之后里面的内容是可变的。可以提高字符串的操作效率。

构造方法
public StringBuilder——创建一个空白可变字符串对象,不含有任何内容
public StringBuilder(String str)——根据字符串的内容,来创建可变字符串对象

成员方法
public StringBuilder append(任意类型)——添加数据,并返回对象本身

public StringBuilder reverse()——反转容器中的内容
public int length()——返回长度(字符出现的个数)
public String toString() ——通过toString就可以实现把StringBuilder转换为String

额外拓展:

StringJoiner类对象的初始最大容量capacity默认为16,当字符串的长度超过默认容量后会自动扩容,扩容后容量为原容量16*2+2,扩容容量再超出后是以实际字符串长度为准的。


StringJoiner
JDK8出现的Stringjoiner跟StringBuilder一样,也可以看成是一个容器,创建之后里面的内容是可变的作用:提高字符串的操作效率,而且代码编写特别简洁,但是目前市场上很少有人用。

构造方法
public StringJoiner (间隔符号)——创建一个StringJoiner对象,指定拼接时的间隔符号
public StringJoiner (间隔符号,开始符号,结束符号)——创建一个StringJoiner对象,指定拼接时的间隔符号开始符号、结束符号
成员方法
public StringJoiner add (添加的内容)——添加数据,并返回对象本身
public int length()——返回长度( 字符出现的个数)

public String toString()——返回一个字符串(该字符串就是拼接之后的结果)

如果我们看到要修改字符串的内容
可以有两个办法:
1.用substring进行截取,把左边的字符截取出来拼接到右侧去

2.可以用toCharArray()方法把字符串先变成一个字符数组,然后调整字符数组里面数据,最后再把字符数组变回字符串。

集合

集合和数组都是容器,不同之处在于,集合的长度自动扩容和改变,集合只能存引用数据类型,如果要存储基本数据类型,需要提供他们对应的包装类,

ArrayList

格式:ArrayList<String> list = new ArrayList();

<泛型>:限定集合中存储数据的类型

成员方法
boolean add(E e)——添加元素,返回值表示是否添加成功
boolean remove(E e)——删除指定元素,返回值表示是否删除成功
E remove(int index)——删除指定索引的元素,返回被删除元素
E set(int index,E e)——修改指定索引下的元素,返回原来的元素
E get(int index)——获取指定索引的元素
int size()——集合的长度,也就是集合中元素的个数


static关键字

static表示静态,是Java中的一个修饰符,可以修饰成员方法和成员变量。

静态变量

指得是被static修饰的成员变量 如:static String teacherName;
静态变量被该类所有对象共享,该变量不属于对象,属于类。随着类的加载而加载,优先于对象存在。
调用方式:【类名.成员名】 对象名.成员名

静态方法

指得是被static修饰的成员方法 如:public static String getSum(){
多用在测试类和工具类中,Javabean类中很少会用,把复用性高的方法抽取到一个独立的类中,这个类就叫做工具类。调用方式:【类名.方法名】对象名.方法名

注意事项:

静态方法中只能访问静态变量,不能访问非静态的实例变量,因为被静态修饰的变量会加载到堆内存的静态区当中,而非静态的变量的存储位置是方法区,所以静态方法是调用不了存储在方法区的实例变量的。也正因如此,静态方法中是不能有this关键字的。

被static修饰的成员,称为类成员,所以被static修饰的变量和方法可以直接被类名.调用,而不被static修饰的成员属于对象。只能通过对象.调用。


继承

继承可以把多个子类中重复的代码抽取到父类中,子类可以直接使用。

继承的格式:public class 子类 extends 父类 {}

继承的特点:

Java只支持单继承,不支持多继承,但支持多层继承。(ABC中AB直接继承,AC间接继承)

Java中所有的类都直接或者间接继承于Object类。

super:用于调用父类中的成员变量 调用方法:super.变量名

方法的重写:

当父类的方法不能满足子类现在的需求时,需要进行方法重写
书写格式
在继承体系中,子类出现了和父类中一模一样的方法声明,我们就称子类这个方法是重写的方法
@Override
重写注解,@Override是放在重写后的方法上,校验子类重写时语法是否正确

方法重写注意事项和要求:
1.重写方法的名称、形参列表必须与父类中的一致
2.子类重写父类方法时,访问权限子类必须大于等于父类 ( 空着不写< protected< public)

3.子类重写父类方法时,返回值类型子类必须小于等于父类
4.建议: 重写的方法尽量和父类保持一致l
5.只有被添加到虚方法表中的方法才能被重写

虚方法表:在子类继承父类时,父类会默认自动生成一个虚方法表,没有被private,static,final修饰的方法会被添加到虚方法表中,当子类调用父类中的方法时,父类虚方法表中的方法会依次向下继承。如果子类中的方法名和形参列表和权限修饰符一致,则会在虚方法表中覆盖原方法表中的方法,这也就是方法重写的本质。

继承中成员方法的访问特点:

this调用:就近原则,优先子类,子类中没有,才会去找父类中的方法

super调用:直接找父类 

继承中的构造方法的访问特定:
父类中的构造方法不会被子类继承,子类中所有的构造方法默认先访问父类中的无参构造,再执行自己,因为子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。子类构造方法的第一行语句默认都是super(),不写也存在,且必须在第一行。如果要调用父类的有参构造,那就需要自己手动写super(参数)。

this() 访问本类的其他构造,添加了this() 之后就无需访问父类的空参构造supe()。


多态

多态指的是对象的多种形态,多态的前提:1、有继承/实现关系,2、有父类引用指向子类对象。

如父类person,子类student、teacher,在test类的eat方法中可以传入person类作为方法参数,可以接受所有子类对象。person p = new student();当p.eat时,调用的是子类中重写的方法。

多态调用成员的特点:

变量调用:编译看父类,运行也看父类。
方法调用:编译看父类,运行看子类。(父类有,才继续执行。执行子类中重写之后的方法。)

instanceof

当需要调用子类中特有的功能时,需要先强制类型转换,转换成真正的子类类型,但需要注意转换类型与真实对象类型不一致会报错的。转换的时候可以用if和instanceof关键字进行判断

如:Person p = new Student (); if{(p instanceof student){student s = (student)p;}


包就是文件夹。用来管理各种不同功能的lava类,方便后期代码维护。
包名的规则: 公司域名反写+包的作用,需要全部英文小写,见名知意。如: com.itheima.domain

包名+类名 被称为全类名/全限定名 如:com.itheima.domain.Student

使用同一个包中的类时,不需要导包
使用java.lang包中的类时,不需要导包
其他情况都需要导包
如果同时使用两个包中的同名类,需要用全类名


final

被final修饰的情况——

方法:表明该方法是最终方法,不能被重写

类:表明该类是最终类,不能被继承

变量:叫做常量,数据值/地址值不能发生改变。(常量命名规范:全部大写,单词之间用_隔开)


权限修饰符

权限修饰符是用来控制一个成员能够被访问的范围的,可以修饰成员变量,方法,构造方法,内部类,作用范围从小到大:private < 空着不写(缺省) < protected < public


代码块

局部代码块:用来提前结束变量

构造代码块:格式{}写在成员位置的代码块,可以把多个构造方法中重复的代码抽取出来。构造代码块是优先于对象执行的

静态代码块:格式static{},需要通过static关键字修饰,随着类的加载而加载,并且自动触发,只执行一次。在类加载的时候,做一些数据初始化的时候使用。


抽象类

抽象方法:将共性的行为 (方法) 抽取到父类之后由于每一个子类执行的内容是不一样的,所以,在父类中不能确定具体的方法体该方法就可以定义为抽象方法。

抽象方法的定义格式:public abstract 返回值类型 方法名(参数列表);


抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类

抽象类的定义格式:public abstract class 类名{}

抽象类和抽象方法的注意事项
抽象类不能实例化
抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
可以有构造方法
抽象类的子类
要么重写抽象类中的所有抽象方法
要么是抽象类


接口

接口就是一种规则,是对行为的抽象。

当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称之为接口多态
接口用关键字interface来定义——public interface 接口名{}
接口不能实例化
接口和类之间是实现关系,通过implements关键字表示:public class 类名 implements 接口名

接口的子类(实现类)要么重写接口中的所有抽象方法※要么是抽象类。



接口和类的实现关系,可以单实现,也可以多实现。(一个类可以实现多个接口)如:

public class 类名 implements 接口名1,接口名2,

实现类还可以在继承一个类的同时实现多个接口。如:

public class 类名 extends 父类 implements 接口名1,接口名2。

接口和接口之间是继承关系,可以单继承,也可以多继承。


接口中成员的特点
成员变量只能是常量。默认修饰符:public static final

没有构造方法,(JDK7以前)成员方法只能是抽象方法。默认修饰符:public abstract

JDK8的新特性: 接口中可以定义有方法体的方法。 

默认default

为解决接口升级的问题,允许在接口中定义默认方法,需要使用关键字 default 修饰
格式: public default 返回值类型 方法名(参数列表){} 如: public default void show(){};

如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写。不然当实现对象调用时,无法确定使用的是哪个接口中的方法。

静态static

允许在接口中定义定义静态方法,需要用static修饰
格式: public static 返回值类型 方法名(参数列表){} 如: public static void show(){}
静态方法只能通过接口名调用,不能通过实现类名或者对象名调用

JDK9的新特性: 接口中可以定义私有方法。
格式1:private 返回值类型 方法名(参数列表){}如:private void show(){}(default方法)
格式2:private static 返回值类型 方法名(参数列表){}如: private static void method(){}(static方法)


内部类

在A类的内部定义B类,B类就被称为内部类,B类表示的事物是A类的一部分,且B单独存在没有意义,比如: 汽车的发动机ArrayList的迭代器,人的心脏等等。

内部类可以直接访问外部类的成员,包括私有。外部类要访问内部类的成员,必须创建对象。


成员内部类:

  • 写在成员位置的,属于外部类的成员。
  • 成员内部类可以被一些修饰符所修饰,比如: private,默认,protected,publicstatic等。
  • 在成员内部类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量。

获取成员内部类对象:

  • 方法一:当成员内部类被private修饰时。在外部类中编写方法,对外提供内部类的对象。
  • 方法二:当成员内部类被非私有修饰时,直接创建对象。
  • 格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象
  • Outer.Inner oi = new Outer.new Inner();

静态内部类:属于成员内部类其中的一种,是一种特殊情况。当成员内部类前面被static修饰时,我们就称这个类为静态内部类。静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象。因为静态只能访问静态。

  • 创建静态内部类对象的格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
  • Outer.Inner oi = new Outer.inner()
  • 调用非静态方法的格式: 先创建对象,用对象调用。Inner.方法名();
  • 调用静态方法的格式: 外部类名.内部类名.方法名();Outer.Inner.方法名();

局部内部类:

1.将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。

2.外界是无法直接使用,需要在方法内部创建对象并使用。

3.该类可以直接访问外部类的成员,也可以访问方法内的局部变量

(以上三种内部类使用场景较少,简单了解即可)

匿名内部类:

匿名内部类本质上就是隐藏了名字的内部类。可以写在成员位置,也可以写在局部位置。

格式:new 类名或者接口名(){重写方法;}

包含了继承或实现关系,方法重写,创建对象。整体就是一个类的子类对象或接口的实现类对象。

使用场景:当方法的参数是接口或者类时,以接口为例,可以传递这个接口的实现类对象,如果实现类只要使用一次,就可以用匿名内部类简化代码。


拼图游戏

JavaGUI(图形化界面):AWT包(先发布,存在不兼容问题。) 【Swing包】(常用)

服务器通过网络传递到浏览器中做一个展示功能,而登录注册等业务逻辑是在服务器上实现的。

在一个项目中用户是接触不到服务器的,他只能接触到客户端(浏览器或APP)。而Java语言主要是做后台服务器开发的,很少跟用户之间做交互,很少会有人用java去写GUI。

两个月学到Javaweb全部学完之后才会写到项目。

没有图形化界面只能在控制台显示的不能称之为项目。只能算是综合案例。

主界面分析

JFrame:窗体、框架

JMenuBar:菜单栏——JMenu: 菜单 JMenuItem:条目

JLabel:管理文字和图片的容器——ImageIcon:图片

以上三种都可以统称之为组件(JavaBean)

JDialog:弹框


JFrame:窗体、框架 

创建主界面——new JFrame();

设置主界面的大小——setSize(int width , int height);

设置界面的标题——setTitle(String);

界面默认是隐藏的,显示——setVisible(boolean);

设置界面置顶——setAlwaysOnTop(boolean);

设置界面居中——setLocationRelativeTo(null);

设置关闭模式——setDefaultCloseOperation(int);

为界面设置菜单——setJMenuBar(jmenubar);

获取窗体中的容器——窗体.getContentPane();

取消容器的默认居中放置——容器.setLayout(null);

刷新容器——容器.repaint();

清空容器——容器.removeAll();

JDialog:弹框

创建弹框——new JDialog();

弹窗不关闭则无法执行其他操作——setModal(boolean);

其余设置与JFrame相同。


JMenuBar:菜单栏

创建菜单栏——new JMenuBar();

JMenu:菜单

创建菜单——new JMenu();

JMenuItem:条目

创建菜单——new JMenuIItem();

条目add.添加到菜单,菜单add添加到菜单栏。再调用界面.setJMenuBar()为整个界面设置菜单。


JLabel:管理文字和图片的容器 ImageIcon:图片

创建图片——new ImageIcon(filename:“文件路径”);

创建文字和图片的容器——new JLabel("图片");

设置图片容器的位置——JLabel.setBounds(x,y,int width , int height);

先添加图片到容器,再getContentPane()获取到窗口容器,再.add图片容器添加到窗口容器。

给图片添加边框——setBorder(new BevelBorder(1));


事件

事件源:按钮(JButton)、图片、窗体..

事件:某些操作,如鼠标单击,鼠标划入..

绑定监听

当事件源上发生了某个事件,则执行某段代码。格式:事件源.addxxxListener();

键盘监听KeyListener

keyPressed——按下

keyReleased——松开

keyTyped——键入某个键时调用此方法

e.getKeyCode——获取键盘上每一个按键的编号

鼠标监听MouseListener

mouseClicked——单击

mouseEntered——划入

mouseExited——划出

mousePressed——按下

mouseReleased——松开

动作监听ActionListener

actionPerformed——鼠标的点击和键盘的空格


按钮(JButton)

创建一个按钮对象——new JButton(text:"点我啊");

设置位置和宽高——setBounds(x,y,width,heigth);

设置大小——setSize(width,height);

设置位置——setLocation(x,y);

添加动作监听——addActionListener(ActionListener);

获取被操作的按钮对象——getSource();


输入框

明文输入框:JTextField

密文输入框:JPasswordField


常用API

math类——数学计算
public static int abs(int a)——获取参数绝对值
public static double ceil(double a)——向上取整
public static double floor(double a)——向下取整
public static int round(float a)——四舍五入
public static int max(int a,int b)——获取两个int值中的较大值
public static double pow(double a,double b)——返回a的b次幂的值

public static double sqrt(double a)——返回a的平方根
public static double cbrt(double a)——返回a的立方根
public static double random——(返回值为double的随机值,范围[0.0,1.0)

System类——系统相关

public static void exit(int status)——终止当前运行的 java虚拟机

public static long currentTimeMillis()——返回当前系统的时间毫秒值形式(1秒=1000毫秒)

public static void arraycopy(数据源数组,起始索引,目的地数组,起始索引,拷贝个数)-数组拷贝

Runtime——虚拟机当前的运行环境

public static Runtime getRuntime()——当前系统的运行环境对象

public void exit(int status)——停止虚拟机

public int availableProcessors()——获得CPU的线程数

public long maxMemory()——JVM能从系统中获取总内存大小(单位byte)

public long totalMemory——JVM已经从系统中获取总内存大小(单位byte)

public long freeMemory——JVM剩余内存大小(单位byte)

public Process exec——运行cmd命令

Object——顶级父类

public Object 空参构造

tostring()public string——返回对象的字符串表示形式
public boolean equals(object obj)——比较两个对象是否相等
protected object clone(int a)——对象克隆

Objects——工具类

public static boolean equals(object a, object b)——先做非空判断,比较两个对象

public static boolean isNull(Object obj)——判断对象是否为null,为null返回true ,反之
public static boolean nonNull(Object obj)——判断对象是否为null,跟isNull的结果相反

BigInteger——大的整数

构造方法

public BigInteger(int num, Random rnd)——获取随机大整数,范围:[0~2的num次方-1]
public BigInteger(String val)——获取指定的大整数
public BigInteger(string val, int radix)——获取指定进制的大整数

静态方法
public static BigInteger valueof(long val)——静态方法获取BigInteger的对象,内部有优化

成员方法

public BigInteger add(BigInteger val)——加法
public BigInteger subtract(BigInteger val)——减法

public BigInteger multiply(BigInteger val)——乘法

public BigInteger divide(BigInteger val)——除法,获取商
public BigInteger[] divideAndRemainder(BigInteger val)——除法,获取商和余数
public boolean equals(Object x)——比较是否相同
public BigInteger pow(int exponent)——次幂
public BigInteger max/min(BigInteger val)——返回较大值/较小值
publicint intValue(BigInteger val)——转为int类型整数,超出范围数据有误
BigDecimal——大的小数和小数的精确运算

构造方法
public BigDecimal(double val)——这种方式有可能是不精确的,不建议使用。
public BigDecimal(String val)
静态方法
public static BigDecimal valueOf(double val)——静态方法获取BigDecimal的对象,内部有优化

成员方法

public static BigDecimal valueOf(double val)——获取对象
public BigDecimal add(BigDecimal val)——加法

public BigDecimal subtract(BigDecimal val)——减法

public BigDecimal multiply(BigDecimal val)——乘法

public BigDecimal divide(BigDecimal val)——除法

public BigDecimal divide(BigDecimal val,精确几位,舍入模式) ——除法
正则表达式

作用一:校验字符串是否满足规则
作用二:在一段文本中查找满足要求的内容
字符类(只匹配一个字符)
[abc]只能是a,b,或c

[^abc]除了a,b,c之外的任何字符  

[a-zA-Z]a到Z A到Z,包括 (范围)

[a-d[m-p]]a到d,或m到p

[a-z&&[def]]a-z和def的交集。为: d,e,f

[a-z&&[^bc]]a-z和非bc的交集。(等同于[ad-z])

[a-z&&[^m-p]] a到z和除了m到p的交集。(等同于[a-lq-z])

预定义字符(只匹配一个字符)

任何字符

\d 一个数字: [0-9]

\D 非数字: [^0-9].

\s 一个空白字符: [\t\n\x0B\f\r]

\S 非空白字符: [^\s]

\w [a-ZA-Z_0-9]英文、数字、下划线

\W [^\w]一个非单词字符

数量词

X? X一次或0次
X*  X零次或多次
X+ X一次或多次
X{n} X正好n次
X{n,} X至少n次

X{n,m} X至小n但不招过m次

(?i)X忽略X的大小写

爬虫

Pattern:正则表达式

ppile(regex):设置正则规则

p.matcher(Str):文本匹配器

m.find(booean):

返回匹配结果,并且在底层记录子串的起始索引和结束索引+1

m.group():

返回截取的小串,subString(起始索引,结束索引);包头不包尾


//1.获取正则表达式的对象
Pattern p = Patternpile("Java\\d{0,2}");
//2.获取文本匹配器的对象
//拿着m去读取str,找符合p规则的子串
Matcher m = p.matcher(str);
//3.利用循环获取
while (m.find()){
String s = m.group();
System.out.println(s);}


有条件的爬取数据

String regex = X(?空1|2|3)

其中?相当于前面的数据X

?=爬取X后面为123的文本(不包含123)

?:爬取带123的Java(包含123)【常用】

?!爬取除了123的X文本

但是在获取的时候,只获取前半部分。

贪婪爬取和非贪婪爬取

str=“abbb”

贪婪爬取(默认):regex="ab+" //abbb

非贪婪爬取:regex="ab+?"//ab


正则表达式在字符串方法中的使用
public String[] matches(string regex)——判断字符串是否满足正则表达式的规则
public String replaceAll(String regex,String newStr)——按照正则表达式的规则进行替换
public String[] split(string regex)——按照正则表达式的规则切割字符串


分组()

每组()是有序号的,从1开始,连续不间断,以左括号为基准,最左边的是第一组。

捕获分组

作用:可以获取每组中的内容反复使用。

正则内部使用:\\组号

正则外部使用:$组号

非捕获分组

分组之后不需要再用本组数据,仅仅是把数据括起来。

(?=)(?:)(?!)都是非捕获分组,是不占用组号的。


时间类

Date时间(JDK7以前)

构造方法

public Date()——当前时间

public Date(long date)——指定时间

成员方法
public void setTime(long time)——设置/修改毫秒值获取时间对象的毫秒值

public long getTime()——获取时间对象的毫秒值

SimpleDateFormat格式化时间

构造方法

public SimpleDateFormat()——使用默认格式
public SimpleDateFormat(string pattern)——指定格式

成员方法
public final String format(Date date)——格式化 (日期对象->字符串)
public Date parse(String source)——解析 (字符串 ->日期对象)


Calendar日历
public static Calendar getInstance()——获取当前时间的日历对象

public final Date getTime()——获取日期对象
public final setTime(Date date)——给日历设置日期对象
public long getTimeInMillis()——拿到时间毫秒值
public void setTimeInMillis(long millis)——给日历设置时间毫秒值
public int get(int field)——取日历中的某个字段信息
public void set(int field,int value)——修改日历的某个字段信息
public void add(int field,int amount)——为某个字段增加/减少指定的值


Date时间(JDK8新增)

Date类

ZoneId:时区

static Set<String> getAvailableZoneIds()——获取Java中支持的所有时区
static ZoneId systemDefault()——获取系统默认时区
static ZoneId of(String zoneId)——获取一个指定时区

Instant:时间戳

static Instant now()——获取当前时间的Instant对象(标准时间)
static Instant ofXxxx(long epochMilli)——根据(秒/毫秒/纳秒)获取Instant对象
ZonedDateTime atZone(ZoneId zone)——指定时区
boolean isXxx(Instant otherInstant)——判断系列的方法
Instant minusXxx(long millisToSubtract)——减少时间系列的方法
Instant plusXxx(long millisToSubtract)——增加时间系列的方法

ZoneDateTime:带时区的时间

static ZonedDateTime now()——获取当前时间的ZonedDateTime对象
static ZonedDateTime ofXxxx(。。。)——获取指定时间的ZonedDateTime
ZonedDateTime withXxx(时间)——对象修改时间系列的方法
ZonedDateTime minusXxx(时间)——减少时间系列的方法
ZonedDateTime plusXxx(时间)——增加时间系列的方法


SimpleDateFormat日期格式化类:

DateTimeFormat:用于时间的格式化和解析

static DateTimeFormatter ofpattern(格式)——获取格式对象
String format(时间对象)——按照指定方式格式化


Calender日历类

LocalDate:年、月、日

LocalTime:时、分、秒

LocalDateTime:年、月、日、时、分、秒

static XXX now()——获取当前时间的对象
static XXX of(。。。)——获取指定时间的对象
get开头的方法——获取日历中的年、月、日、时、分、秒等信息
isBefore,isAfter——比较两个 LocalDate
with开头的——修改时间系列的方法
minus开头的——减少时间系列的方法
plus开头的——增加时间系列的方法

public LocalDate toLocalDate()——LocalDateTime转换成一个LocalDate对象
public LocalTime toLocalTime()——LocalDateTime转换成一个LocalTime对象


工具类

Duration:时间间隔(秒,纳秒)

Period:时间间隔(年,月,日)

ChronoUnit:时间间隔(所有单位)


包装类

包装类指的是基本数据类型对应的对象,在JDK5以后对包装类新增了自动装、拆箱的特性。获取包装类对象不需要new不需要调用方法,直接赋值即可。Integer i = 10;

JDK5之前

public Integer(int value)——根据传递的整数创建一个Integer对象
public Integer(string s)——根据传递的字符串创建一个Integer对象
public static Integer valueOf(int i)——根据传递的整数创建一个Integer对象
public static Integer valueOf(String s)——根据传递的字符串创建一个Integer对象
public static Integer valueOf(String s, int radix)——根据传递的字符串和进制创建一个Integer对象

public static String toBinaryString(int i)——得到二进制
public static String toOctalString(int i)——得到八进制
public static String toHexString(int i)——得到十六进制
public static int parselnt(String s)——将字符串类型的整数转成int类型的整数

常见算法

查找算法:基本查找、二分查找、分块查找

排序算法:冒泡排序、选择排序、插入排序、快速排序

字符串匹配算法:基本查找、KMP算法

Arrays:

public static String toString(数组)——把数组拼接成一个字符串
public static int binarySearch (数组,查找的元素)——二分查找法查找元素
public static int[] copyof(原数组,新数组长度)——拷贝数组
public static int[] copyofRange(原数组,起始索引,结束索引)——拷贝数组(指定范围)
public static void fill(数组,元素)——填充数组
public static void sort(数组)——按照默认方式进行数组排序
public static void sort(数组,排序规则)——按照指定的规则排序

Lambda表达式:函数式编程思想,忽略复杂语法,可以简化函数式接口的匿名内部类的写法。

使用前提:必须是接口的匿名内部类。接口中只能有一个抽象方法。可推导,就可省略。

@FunctionalInterface:函数式接口:接口内有且仅有只有一个抽象方法。

省略规则:
1.参数类型可以省略不写。
2.如果只有一个参数,参数类型可以省略,同时()也可以省略。
3.如果Lambda表达式的方法体只有一行,大括号、分号、return可以省略不写,需要同时省略。

        //匿名内部类
        Arrays.sort(arr, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        });

        //Lambda完整格式
        Arrays.sort(arr, (Integer o1, Integer o2) ->{
                return o1 - o2;
            }
        );

        //Lambda简化格式
        Arrays.sort(arr, (o1,  o2) -> o1 - o2);

数据结构

数据结构是计算机底层存储、组织数据的方式。是指数据相互之间是以什么方式排列在一起的。数据结构是为了更加方便的管理和使用数据,需要结合具体的业务场景来进行选择般情况下,精心选择的数据结构可以带来更高的运行或者存储效率。

常见的数据结构:栈、队列、数组、链表、二叉树、二叉查找树、平衡二叉树、红黑树。

栈:后进先出,先进后出。(水杯模型,一端开口,一端封闭。弹匣的方式进栈出栈。)
队列数组:先进先出,后进后出。(队列模型,两端开口,排队买票的方式进栈出栈。)

数组:内存连续区域,查询快,增删慢。
链表:元素是游离的,查询慢,增删相对快。
二叉树:每一个节点的子节点数量叫做度,在二叉树中,任意节点的度<=2,树的总层数叫做树高,最顶层的节点叫做根节点,往下还细分为:左子节点,右子节点,左子树,右子树。
二叉查找树:任意节点左子树上的值都小于当前节点,任意节点右子树上的值都大于当前节点。添加节点的规则:小的存左边,大的存右边,一样就不存。
平衡二叉树:任意节点左右子树高度差不超过1

旋转机制:左旋和右旋

旋转步骤:

1.确定支点从添加的节点开始,不断的往父节点找不平衡的节点,把不平衡的点作为支点

2.把支点左旋降级,变成左子节点

3.晋升右子节点,如果有多余的左子节点出让,给已经降级的根节点当右子节点

如果存在左右或右左的情况,需要先局部旋转,再整体旋转。

红黑树:特色二叉查找树,但不是高度平衡的,条件是特有的红黑规则。

红黑规则

1.每一个节点是红色的,或者是黑色的

2.根节点必须是黑色
3.叶节点是黑色的
4.两个红色节点不能相连
5.任意节点到所有后代叶节点的简单路径上,黑色节点数量相同

红黑树在添加节点的时候,添加的节点默认是红色的,因为红色节点效率更高。

遍历方式

前序遍历:当前节点,左子节点,右子结点
中序遍历:左子节点,当前节点,右子结点
后序遍历:左子节点,右子结点,当前节点
层序遍历:一层一层的去遍历


泛型

泛型可以在编译阶段约束操作的数据类型,并进行检查。统一了数据类型。

泛型类

当一个类中,某个变量的数据类型不确定时,就可以定义带有泛型的类。

格式:修饰符 class 类名<类型> 如:public class ArrayList<E>{}

泛型方法

方法中形参类型不确定时,可以使用类名后面定义的泛型<E>。

格式:修饰符<> 返回值类型 方法名(类型 变量名) 如:public <T>  void show(T t){}

泛型接口

接口中形参类型不确定时,可以使用接口名后面定义的泛型<E>。

格式:修饰符 interface 接口名<类型>{} 如:public interface List<E>{}

泛型接口的两种使用方式:
1.实现类给出具体的类型。如:implements List<String>
2.实现类延续泛型,创建实现类对象时再确定类型

如:public class MyArrayList3<E> implements List<E>

泛型的继承和通配符

泛型不具备继承性,但是数据具备继承性。此时我们就可以使用泛型的通配符:

?:也表示不确定的类型,但可以进行类型的限定
? extends E: 表示可以传递E或者E所有的子类类型

? super E:表示可以传递E或者E所有的父类类型

应用场景:

1.如果我们在定义类、方法、接口的时候,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口。

2.如果类型不确定,但是能知道以后只能传递某个继承体系中的,就可以泛型的通配符泛型的通配符:
关键点: 可以限定类型的范围。


集合体系结构

单列集合Collectionp

-List(ArrayList)(LinkedList)(Vector)

-Set(HashSet(LinkedHashSet))(TreeSet)

Collectionp是单列集合的顶层接口,所有方法被List和Set系列集合共享。

常见方法:
public boolean add(E e)——添加
public void clear()——清空

public boolean remove(E e)删除

public boolean contains(Object obj)判断是否包含

public boolean isEmpty()判断是否为空
public int size()——集合长度

遍历方式

迭代器遍历

迭代器不依赖索引,迭代器在Java中的类是lterator,迭代器是集合专用的遍历方式。

iterator<E>iterator()——返回迭代器对象,默认指向当前集合的0索引。
boolean hasNext()——判断当前位置是否有元素,有元素返回true,没有元素返回false。
E next()——获取当前位置的元素,并将迭代器对象移向下一个位置。

Iterator<String> it = coll.iterator();
        while (it.hasNext()) {
            String str = it.next();
            System.out.println(str);
        }

增强for遍历

增强for是JDK5之后出现的,它的底层就是迭代器,为了简化迭代器的代码书写的。
所有的单列集合和数组才能用增强for进行遍历。

格式:for(元素的数据类型 变量名:数组或者集合){}

如:for(String s:list){System.out.println(s);}

    //匿名内部类
    coll.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });       
    
    //Lambda表达式
    for (String s : coll){
            System.out.println(s);
        }

Lambda表达式遍历

得益于JDK8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式.

default void forEach(Consumer<? super T> action)——结合lambda遍历集合

coll.forEach(s -> System.out.println(s));

List集合

List(ArrayList)(LinkedList)(Vector)

List系列集合添加的元素:有序、可重复、有索引

特有方法

void add(int index,E)——在此集合中的指定位置插入指定的元素element
E remove(int index)——删除指定索引处的元素,返回被删除的元素
E set(int index,E element)——修改指定索引处的元素返回被修改的元素
E get(int index)——返回指定索引处的元素

List系列集合的五种遍历方式
1.迭代器——在遍历的过程中需要删除元素时使用
2.列表迭代器——在遍历的过程中需要添加元素时使用
3.增强for——仅仅想遍历
4.Lambda表达式——仅仅想遍历
5.普通for循环——在遍历时想操作索引时使用


Set集合

Set(HashSet(LinkedHashSet))(TreeSet)

Set系列集合添加的元素:无序、不重复、无索引

可以利用Set集合的不重复特性进行数据去重。

set集合的实现类
HashSet:无序、不重复、无索引

LinkedHashSet: 有序、不重复、无索引

TreeSet:可排序、不重复、无索引
Set接口中的方法上基本上与Collection的API一致

HashSet
HashSet集合底层采取哈希表存储数据,哈希表是一种对于增删改查数据性能都较好的结构

哈希表组成:JDK8之前:数组+链表 JDK8开始: 数组+链表+红黑树

哈希值:对象的整数表现形式,根据hashCode方法计算出来的int类型的整数。该方法定义在object类中,所有对象都可以调用,默认使用地址值进行计算。一般情况下,会重写hashCode方法,利用对象内部的属性值计算哈希值。

1.如果没有重写hashcode方法,不同对象计算出的哈希值是不同的。
2.如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的,但是在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。(哈希碰撞 )

LinkedHashSet

有序、不重复、无索引:这里的有序指的是保证存储和取出的元素顺序一致
原理:底层数据结构依然是哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序

TreeSet

不重复、无索引、可排序:按照元素的默认规则 (有小到大)排序。

对于数值类型:Integer,Double,默认按照从小到大的顺序进行排序。

对于字符、字符串类型:按照字符在ASCII码表中的数字升序进行排序。

TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。

TreeSet的两种比较方式
方式一:默认排席/自然排序:Javabean类实现Comparable接口指定比较规则
方式二:比较器排序: 创建TreeSet对象时候,传递比较器Comparator指定规则
使用原则:默认使用第一种,如果第一种不能满足当前需求,就使用第二种


双列集合Map

①双列集合一次需要存一对数据,分别为键和值
②键不能重复,值可以重复
③键和值是一一对应的,每一个键只能找到自己对应的值
④键+值这个整体,我们称之为“键值对”或者“键值对对象”,在Java中叫做“Entry对象”

Map是双列集合的顶层接口,它的功能是全部双列集合都可以继承使用的

-HashMap(LinkedHashMap)

-TreeMap

常见方法
put(K key,V value)——添加元素
V remove(Object key)——根据键删除键值对元素
void clear()——移除所有的键值对元素
boolean containsKey(object key)——判断集合是否包含指定的键

boolean containsValue(object value)——判断集合是否包含指定的值

boolean isEmpty()——判断集合是否为空
int size()——集合的长度,也就是集合中键值对的个数

遍历方式

键找值

获取所有的键,把这些键放到一个单列集合当中
Set<String> keys = m.keySet();
遍历单列集合,得到每一个键

利用map集合中的键获取对应的值
String value = m.get(key);

键值对

通过一个方法获取所有的键值对对象,返回一个Set集合
Set<Map.Entry<String, String>> entries = m.entrySet();

Lambda表达式

default void forEach(BiConsumer<? super K,? super V > action)——结合lambda遍历Map集合


HashMap

1.HashMap底层是哈希表结构的
2.依赖hashCode方法和equals方法保证键的唯一

3.如果键存储的是自定义对象,需要重写hashCode和equals方法,如果值存储自定义对象,不需要重写hashCode和equals方法。

LinkedHashMap

由键决定:有序、不重复、无索引。这里的有序指的是保证存储和取出的元素顺序一致。
原理:底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序。遍历时按照存储顺序来进行遍历。


TreeMap
TreeMap跟TreeSet底层原理一样,都是红黑树结构的。

由键决定特性:不重复、无索引、可排序
可排序:对键进行排序
注意: 默认按照键的从小到大进行排序,也可以自己规定键的排序规则
代码书写两种排序规则
1.实现Comparable接口,指定比较规则。
2.创建集合时传递Comparator比较器对象,指定比较规则


可变参数

可变参数底层就是一个数组。

作用:在形参中接收多个数据,

格式:数据类型...参数名称 如:int...a

1.在方法的形参中最多只能写一个可变参数。
2.在方法当中,如果除了可变参数以外,还有其他的形参,那么可变参数要写在最后。


Collectionps集合工具类
public static <T> boolean addAll(Collection<T> c,T...elements)——批量添加元素
public static void shuffle(List<?> list)——打乱List集合元素的顺序
public static <T> void sort(List<T> list)——排序
public static <T> void sort(List<T> list,Comparator<T> c)——根据指定的规则进行排序
public static <T> int binarySearch (List<T> list, T key)——以二分查找法查找元素

public static <T> void copy(List<T> dest, List<T> src)——拷贝集合中的元素

public static <T> int fill (List<T> list, T obj)——使用指定的元素填充集合

public static <T> void max/min(Collection<T> coll)——根据默认的自然排序获取最大/小值

public static <T> void swap(List<?> list,int i,int j)——交换集合中指定位置的元素


创建不可变集合

不想让别人修改集合中的内容,就可以使用不可变集合。

创建不可变集合的书写格式。
在List、Set、Map接口中,都存在静态的of方法,可以获取一个不可变的集合。
static <E> List<E> of(E...elements)——创建一个具有指定元素的List集合对象

static <E> Set<E> of(E...elements)——创建具有指定元素的Set集合对象

static <K,V> Map<K,V> of(E...elements)——创建一个具有指定元素的Map集合对象

注意:这个集合不能添加,不能删除,不能修改。


Stream流

结合了Lambda表达式,简化集合、数组的操作。

1.先得到一条Stream流,并把数据放上去,利用stream流中的API进行各种操作。
2.中间方法——方法调用完毕之后,还可以调用其他方法最后一步,如:过滤、转换。
3.终结方法——调用完毕之后,不能调用其他方法。如,统计、打印。

Stream流的使用步骤
先得到一条Stream流(流水线),并把数据放上去
单列集合:default Stream<E> stream():Collection中的默认方法
双列集合:无法直接使用stream流,可以先转换成单列集合或先获取其键值对再使用。
数组:public static <T> Stream<T> stream(Til array):Arrays工具类中的静态方法
一堆零散数据:public static<T> Stream<T> of(T... values):Stream接口中的静态方法


Stream流的中间方法
Stream<T> filter(Predicate<? super T> predicate)——过滤
Stream<T> limit(long maxSize)——获取前几个元素
Stream<T> skip(long n)——跳过前几个元素
Stream<T> distinct()——元素去重,依赖(hashCode和equals方法)
static <T> Stream<T> concat(Stream a, Stream b)——合并a和b两个流为一个流
Stream<R>map(Function<T,R> mapper)——转换流中的数据类型

注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程

注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据发送


Stream流的终结方法

void forEach(Consumer action)——遍历
long count()——统计
toArray()——收集流中的数据,放到数组中
collect(Collector collector)——收集流中的数据,放到集合中


方法引用

把已经有的方法拿过来用,当做函数式接口中抽象方法的方法体。

方法引用符::

1.引用处需要是函数式接口
2.被引用的方法需要已经存在
3.被引用方法的形参和返回值需要跟抽象方法的形参和返回值保持一致

4.被引用方法的功能需要满足当前的要求


方法引用的分类

  • 引用静态方法

格式:类名::静态方法

如:Integer::parseInt

  1. 引用其他类的成员方法
  2. 引用本类的成员方法
  3. 引用父类的成员方法
  • 引用成员方法

格式:对象::成员方法

其他类:其他类对象::方法名

本类:this::方法名(非静态)

父类:super::方法名(非静态)

  • 引用构造方法

格式:类名::new 如:student::new

  • 其他构造方法
  • 使用类名引用成员方法

格式:类名::成员方法 如:string::substring

  • 引用数组的构造方法

格式:数据类型[]::new 如:int[]::new


异常Excpetion

异常就是程序中可能出现的问题,子类分为运行时异常RuntimeExcpetion和编译时异常。

捕获异常

格式:try{可能出现异常的代码}catch(异常类名 变量名){};

常见方法

Throwable 的成员方法
public String getMessage()——返回此 throwable 的详细消息字符串
public string tostring()——返回此可抛出的简短描述
public void printStackTrace()——把异常的错误信息输出在控制台【常用】

抛出处理

throws:写在方法定义处,表示声明一个异常告诉调用者,使用本方法可能会有哪些异常。

格式:public void 方法() throws 异常类名1,异常类名2...{}

编译时异常必须要写,运行时异常可以不写。

throw:写在方法内,结束方法手动抛出异常对象,交给调用者方法中下面的代码不再执行了。

格式:public void 方法(){throw new NullPointerException();}

自定义异常

自定义异常是为了让控制台的报错信息更加的见名知意。

步骤:定义异常类,书写继承关系,生成空参和带参的构造方法。


路径File

File对象表示文件的路径或者文件夹的路径。这个路径可以是存在的,也允许是不存在的。


字符集

1.在计算机中,任意数据都是以二进制的形式来存储的
2.计算机中最小的存储单元是一个字节
3.ASCII字符集中,一个英文占一个字节
4,简体中文版Windows,默认使用GBK字符集
5.GBK字符集完全兼容ASCII字符集
一个英文占一个字节,二进制第一位是0一个中文占两个字节,二进制高位字节的第一位是1

Unicode字符集的UTF-8编码格式
一个英文占一个字节,二进制第一位是0,转成十进制是正数
一个中文占三个字节,二进制第一位是1,第一个字节转成十进制是负


IO流

I:input:输入 读 O:output 输出 写 

IO流用于用于读写文件中的数据(可以读写本地文件或网络中的数据)

按照流向可分为输入流(本地文件读取到程序当中)和输出流(程序写出到本地文件)
按照操作文件的类型可分为字节流(可以操作所有类型得文件)和字符流(只能操作纯文本文件)


IO流体系:字节流 字符流 

字节流:InputStream OutputStream

基本字节流:FileInputStream FileOutputStream 

缓冲字节流:BufferedInputStream BufferedOutputStream 

对象专属流/序列化流:ObjectInputStream  ObjectOutputStream

打印流:PrintStream

字符流:Reader Writer

基本字符流:FileReader FileWriter

缓冲字符流:BufferedReader BufferedWriter

转换流:(将字节流转换成字符流)InputStreamReader OutputStreamWriter


配置文件properties

properties是一个双列集合,继承于HashTable集合,实现了Map集合接口,可以把集合中的数据,按照键值对的形式写到配置文件当中,也可以把配置文件中的数据,读取到集合中来。


多线程

线程:线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运算单位。在应用软件内互相独立,可以同时进行运行的功能。

如:360安全卫士为一个进程,而360安全卫士内的木马查杀、电脑清理、系统修复等等,则为一个个可以同时运行功能的线程,也就是多线程。

并发和并行

并发:在同一时刻,有多个指令在单个CPU上交替执行
并行:在同一时刻,有多个指令在多个CPU上同时执行

多线程的实现方式

继承Thread类的方式进行实现
实现Runnable接口的方式进行实现
利用Callable接口和Future接口方式实现

常见的成员方法
string getName()——返回此线程的名称
void setName(string name)——设置线程的名字(构造方法也可以设置名字)
static Thread currentThread()——获取当前线程的对象
static void sleep(long time)——让线程休眠指定的时间,单位为毫秒
setPriority(int newPriority)——设置线程的优先级
final int getPriority()——获取线程的优先级
final void setDaemon(boolean on)——设置为守护线程
public static void yield()——出让线程/礼让线程
public static void join()——插入线程/插队线程

同步代码块

synchronized (任意锁对象,一般是方法体的字节码文件) {方法体};

同步方法

格式:修饰符 synchronized 返回值类型 方法名(方法参数) [...}
特点1: 同步方法是锁住方法里面所有的代码
特点2:锁对象不能自己指定

非静态: this
静态:当前类的字节码文件对象
Lock锁
为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock
Lock实现提供比使用Synchronized方法和语句可以获得更广泛的锁定操作

获得锁和释放锁的方法
void lock()—— 获得锁
void unlock():——释放锁

手动上锁、手动释放锁
Lock是接口不能直接实例化这里采用它的实现类ReentrantLock来实例化ReentrantLock的构造方法
ReentrantLock():创建一个ReentrantLock的实例

常见方法
void wait()——当前线程等待,直到被其他线程唤醒
voidnotify()——随机唤醒单个线程
void notifyAll()——唤醒所有线程

阻塞队列的继承结构

接口Iterable->Collection->Queue->BlockingQueue

实现类ArrayBlockingQueue(数组、有界) LinkedBlockingQueue(链表、无界[int.len])

线程池

Executors:线程的工具类,通过调用方法返回不同的线程池对象。

1.创建线程池

public static ExecutorService newCachedThreadPool()创建一个没有上限的线程池
public static ExecutorService newFixedThreadPool(int nThreads)创建有上限的线程池

2.提交任务

submit(Runnable task);

提交任务时,池子会创建新的线程对象,任务执行完毕,线程归还给池子。下回再次提交任务时,不需要创建新的线程,直接复用已有的线程即可。

3.关闭线程池

shutdown();

但是如果提交任务时,池子中没有空闲线程,也无法创建新的线程,任务就会排队等待。

自定义线程池

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor

(核心线程数量,最大线程数量,空闲线程最大存活时间,任务队列,创建线程工厂,任务的拒绝策略);

任务拒绝策略

ThreadPoolExecutor.AbortPolicy——默认策略:丢弃任务并抛出RejectedExecutionException异常
ThreadPoolExecutor.DiscardPolicy——丢弃任务,但是不抛出异常,这是不推荐的做法
ThreadPoolExecutor.DiscardoldestPolic——抛弃队列中等待最久的任务,然后把当前任务加入队列中
ThreadPoolExecutor.CallerRunsPolicy——调用任务的run()方法绕过线程池直接执行

线程池多大合适呢?
CPU 密集型运算——最大并行数 +1

l/O 密集型运算——
最大并行数 * 期望 CPU 利用率 * 总时间(CPU计算时间+等待时间)/计算时间CPU


网络编程

计算机跟计算机之间通过网络通信协议进行数据传输。
常见软件架构

C/S和B/S
C/S: Client/Server 客户端/服务器 

在用户本地需要下载并安装客户端程序,在远程有一个服务器端程序。
B/S: Browser/Server

浏览器/服务器 只需要一个浏览器,用户通过不同的网址客户访问不同的服务器

网络编程三要素

IP、端口号、协议。


IP:设备在网络中的地址,是唯一的标识。

互联网协议地址,也称IP地址,是分配给上网设备的数字标签。

IPv4:互联网通信协议第四版。

采用32位地址长度,分成4组。点分十进制表示法表示。

IPv6:互联网通信协议第六版。为了解决IPv4IP不够用而出现的。
采用128位地址长度,分成8组。冒分十六进制表示法。

IPv4的地址分类形式
公网地址(万维网使用)和私有地址(局域网使用)。
192.168.开头的就是私有址址,专门为组织机构内部使用,以此节省IP。

目前就是利用局域网IP解决IPv4不够的问题
特殊的IP——127.0.0.1 (永远表示本机)
ipconfig: 查看本机IP地址

ping:检查网络是否连通

InetAddress类

static InetAddress getByName(String host)——确定主机名称的IP地址

主机名称可以是机器名称,也可以是IP地址
String getHostName()——获取此IP地址的主机名
String getHostAddress()——返回文本显示中的IP地址字符串


端口号:应用程序在设备中唯一的标识

由两个字节表示的整数,取值范围:0~65535

其中0~1023之间的端口号用于一些知名的网络服务或者应用

我们自己使用1024以上的端口号就可以了

注意:一个端口号只能被一个应用程序使用


协议:数据在网络中传输的规则,常见的协议有UDP、TCP、http、https、ftp。

计算机网络中,连接和通信的规则被称为网络通信协议。

OSI参考模型:世界互联协议标准,全球通信规范,单模型过于理想化,未能在因特网上进行广泛推厂。TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。

UDP协议
用户数据报协议(User Datagram Protocol)
UDP是面向无连接通信协议。
速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据。

UDP的三种通信方式:单播、组播、广播

通信的两端各建立一个DatagramSocket对象来进行网络通信

TCP协议
传输控制协议TCP(Transmission ControlProtocol)

TCP协议是面向连接的通信协议。

速度慢,没有大小限制,数据安全。

通信的两端各建立Socket/ServerSocket对象产生IO流来进行网络通信

三次握手:确保连接建立 c-s s-c s=c

四次挥手:确保连接断开、且数据处理完毕 c-s s-c c=0 c!s

反射

反射允许对成员变量,成员方法和构造方法的信息进行编程访问。

获取class对象的三种方式
①Class.forName("全类名");——源代码阶段
②类名.class——加载阶段
③对象.getClass();——运行阶段
Class类中用于获取构造方法的方法
Constructor<?>[] getConstructors(): 返回所有公共构造方法对象的数组

Constructor<?>[] getDeclaredConstructors(): 返回所有构造方法对象的数组Constructor<T>getConstructor(Class<?>... parameterTypes): 返回单个公共构造方法对象Constructor<T>getDeclaredConstructor(Class<?>... parameterTypes): 返回单个构造方法对象
Constructor类中用于创建对象的方法
T newInstance(Object...initargs): 根据指定的构造方法创建对象

setAccessible(boolean flag):设置为true,表示取消访问检查


Class类中用于获取成员变量的方法

Field[] getFields():返回所有公共成员变量对象的数组

Field[] getDeclaredFields(): 返回所有成员变量对象的数组

Field getField(String name): 返回单个公共成员变量对象

Field getDeclaredField(String name): 返回单个成员变量对象
Field类中用于创建对象的方法

void set(Object obj, Object value): 赋值

Object get(Object obj) 获取值


Class类中用于获取成员方法的方法
Method[] getMethods(): 返回所有公共成员方法对象的数组,包括继承的Methodll getDeclaredMethods(): 返回所有成员方法对象的数组,不包括继承的

Method getMethod(String name, Class<?>... parameterTypes): 返回单个公共成员方法对象Method getDeclaredMethod(String name,Class<?>... parameterTypes): 返回单个成员方法对象
Method类中用于创建对象的方法
Object invoke(Object obj, Object... args): 运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)

反射的作用
①获取任意一个类中的所有信息

②结合配置文件动态创建对象


动态代理

代理可以无侵入式的给对象增加其他的功能,而不需要修改对象的代码。代理里面就是对象要被代理的方法,对象和代理都需要实现同一个接口,接口中定义了被代理的所有方法。

java.lang.reflect.Proxy类:提供了为对象产生代理对象的方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>11 interfaces, Invoca
参数一:用于指定用哪个类加载器,去加载生成的代理类
参数二:指定接口,这些接口用于指定生成的代理长什么样,也就是有哪些方法
参数三:用来指定生成的代理对象要干什么事情


参考资料:

黑马程序员Java零基础视频教程_上部

尚硅谷Java零基础全套视频教程(宋红康2023版,java入门自学必备)

类与对象之间的关系

本文标签: 学习笔记JavaSE