Java基础详解

Java知识总结:

  • Ⅰ、Java基础:ballot_box_with_check:
    • 一、初识java:rainbow_flag:
      • 1、Java的定义
      • 2、Java的版本分类
      • 3、Java的特性
      • 4、JDK、JRE、JVM三者的联系
      • 5、Java的配置及使用
          • 1、下载并安装JDK
          • 2、配置环境变量
          • 3、开始编码
      • 6、创建第一个Java程序
          • 1、创建类
          • 2、main方法
          • 3、输出语句
          • Hello World程序:
      • 7、Java中的书写规范
  • 二、数据类型、变量:rainbow_flag:
    • 1、数据类型
    • 2、变量
      • 1、变量的特性
      • 2、使用变量的过程:
      • 3、定义变量的规则
    • 3、运算符
      • 1、赋值运算符
      • 2、算术运算符
      • 3、比较运算符
      • 4、布尔运算-真值表
      • 5、三目运算符
      • 6、运算符优先级
  • 三、idea工具类的使用:rainbow_flag:
    • 1、字体的设置
    • 2、配置JDK
    • 3、idea的快捷键
  • 四、选择结构、循环结构:rainbow_flag:
    • 1、选择结构
      • 1、if else
      • 2、switch
    • 2、循环结构
      • 1、for
      • 2、while
      • 3、do...while
      • 4、增强for循环
    • 3、关键字
      • 1、brrak:
      • 2、contiune:
      • 3、return:
      • 4、final关键字:
      • 5、打标签:
    • 4、代码的简化
      • 1、switch简化
      • 2、if简化
  • 五、数组:rainbow_flag:
    • 1、数组的定义
    • 2、数组的性质
    • 3、数组的简单使用
      • 1、打擂台的形式找最大值
      • 2、通循环遍历打印数组的每一个值
      • 3、查找一个数组里存在的值。
      • 4、元素的位移。
    • 4、数组的排序
      • 1、选择排序
      • 2、冒泡排序
  • 六、方法:rainbow_flag:
    • 1、方法的定义及使用
      • 1、方法的定义
      • 2、方法的优点
      • 3、方法名的命名规范
      • 4、方法的调用
      • 5、方法的几种形式
      • 6、方法重载
      • 7、方法中形参和实参的区别
      • 8、return的作用
    • 2、方法的深入使用
      • 1、方法的使用
      • 2、值传递和引用传递
      • 3、可变参数
      • 4、方法递归
      • 5、斐波纳契数列
      • 6、方法内存当中的调用过程
  • Ⅱ、Java面向对象:ballot_box_with_check:
    • 一、类:balloon:
      • 1、包
        • 1、包名
        • 2、类名
        • 3、包的引入
      • 2、修饰符
        • 1、权限修饰符
        • 2、状态修饰符
        • 3、抽象修饰符
      • 3、类和对象、构造方法
        • 1、类
        • 2、对象
        • 3、类和对象的关系
        • 4、构造方法
        • 5、new对象
        • 4、setter和getter
        • 5、String类型
        • 6、基础类型的包装类
        • 7、画图解释了类加载运行过程:paintbrush:
    • 二、封装:balloon:
      • 1、封装的定义
      • 2、封装的优点
      • 3、封装的作用
      • 4、封装的实现
        • 1、修改属性的权限性
        • 2、对每个值属性提供对外的公共方法访问
    • 三、继承:balloon:
      • 1、继承的概念
      • 2、继承的实现
      • 3、继承的图解
    • 四、多态:balloon:
      • 1、多态的概念
      • 2、多态的优点
      • 3、多态存在的三个必要条件
        • 1、继承
        • 2、重写
        • 3、父类引用指向子类对象
      • 4、重写(Override)与重载(Overload)
        • 1、重写(Override)
        • 2、重载(Overload)
        • 3、重写和重载的区别:
    • 五、抽象类:balloon:
    • 六、接口:balloon:
      • 1、接口的概念
      • 2、接口的特性
      • 3、接口与类的区别
      • 4、接口和抽象类的区别
  • Ⅲ、Java高级:ballot_box_with_check:
    • 一、超级数组、栈、队列:four_leaf_clover:
      • 1、自己封装一个超级数组
      • 2、自己封装一个栈
      • 3、自己封装一个队列
    • 二、对象转型、泛型、链表:four_leaf_clover:
      • 1、对象转型
      • 2、泛型
      • 3、链表(单向链表)
      • 4、数组和链表的区别:
        • 不同点:
        • 相同点:
    • 三、集合:four_leaf_clover:
      • 1、集合的定义
      • 2、Java集合框架主要结构图:
      • 3、集合中常用集合类的继承关系及特点:
      • 4、List集合
      • 5、Map集合
        • HashMap集合原理图:
      • 6、Set集合
      • 7、Iterator迭代器
        • 迭代器中常用的方法:
    • 四、java的工具类:four_leaf_clover:
      • 1、Object类
      • 2、Date类
      • 3、Calendar 类
      • 4、Math类
      • 5、Random类
      • 6、Arrays工具类
      • 7、Collections工具类
    • 五、垃圾回收机制:four_leaf_clover:
      • 1、概念
    • 六、File类、IO流:four_leaf_clover:
      • 1、File类
        • 1、File类简介:
        • 2、File类常用构造方法
        • 3、File类常用方法
          • 注意:
      • 2、IO流
        • 1、Java中IO流的概念
        • 2、IO流的分类
        • 2.1、 按照流的流向分
        • 2.2、按照操作单元划分
          • 2.3、按照流的角色划分
          • 3、java输入/输出流体系中常用的流的分类表
          • 4、java流类图结构
    • 七、异常:four_leaf_clover:
      • 1、异常的定义
      • 2、异常实现及分类
      • 3、常见的内置异常类:
      • 4、异常的处理
          • 抛出异常:throw,throws
          • 捕获异常:try,catch,finally

今天看到一份面试题,发现里边好多都是基础性的内容.尝试着答了一下发现已经忘记大半了.赶紧把以前的笔记翻出来重新看一看

Ⅰ、Java基础☑️

一、初识java️‍

1、Java的定义

Java是一门跨平台的面向对象编程语言,Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称。Java之父是詹姆斯·高斯林(James Gosling),他和同事们共同研发,并在1995年正式推出。

2、Java的版本分类

  1. JavaSE标准版:是为开发小型客户端应用程序提供的解决方案,可以完成一些桌面应用的开发。其他两个体系,必须依赖于这个体系;
  2. **JavaME小型版:**这个体系主要是为嵌入式设备或外接系统提供的解决方案;
  3. JavaEE企业版:这个体系中包含有为企业进行软件开发所需要的全部解决方案。它主要倾向于进行企业级web开发,是我们主要学习的方向。

3、Java的特性

Java的特性有: 简单性、安全性、解释性、健壮性、面向对象、高性能、多线程、分布式、开源和跨平台。

跨平台: java跨平台的关键是JVM,JVM本身并不能跨平台,每个操作系统都要下载对应的JVM。JVM的职责只是加载、执行.class文件。将人能看懂的java文件编译成class文件 ,将class文件加载到内存,生成一个Class对象。以上是一个静态过程,文件的内容没有变化。

4、JDK、JRE、JVM三者的联系

JDK(Java开发工具包): JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包括了JRE。所以安装了JDK,就不用在单独安装JRE了

JRE(Java运行时环境): 包括Java虚拟机和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,必须安装JRE环境

JVM(Java虚拟机): JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的

因为有JDK的工具包,使得JRE可以被构建出来,一旦JRE成功构建并运行,就产生了JVM。

5、Java的配置及使用

1、下载并安装JDK

JDK是所有JAVA环境的基础,首先安装。登录Oracle官网进行下载。

2、配置环境变量

安装JDK后需要配置系统的环境变量。

寻找一个可执行文件,会先从环境中(当前的文件夹,当前的工程)找,如果找不到,就去环境变量里的目录里边找,直到找到为止,找不到就报错。

在外边定义一个 JAVA_HOME
C:\Program Files\Java\jdk1.8.0_221

path  增加一个路径  为了找到对应的exe
%JAVA_HOME%\bin
3、开始编码
  1. 环境安装配置完毕后,在当前盘的地址栏中输入CMD,回车打开命令行
  2. 输入javac命令编译java类文件
  3. 输入java命令运行编译后的二进制文件

6、创建第一个Java程序

1、创建类
  • class用来创建类
  • Hello World是类名
  • {}表示类的范围
public class Hello World{}
2、main方法
  • main方法是程序的入口,每个程序都要找到这个方法
  • {}内表示main方法的内容
public static void main(String[] args){}
3、输出语句
  • 表示要将小括号内的信息输出到控制台
  • 双引号表示一长串信息,可以写中文
System.out.rintln("Hello World");
Hello World程序:
class HelloWorld{
	public static void main(String[] args){
		System.out.println("HelloWorld");
	}
}

7、Java中的书写规范

  • 缩进: 每当代码出现在大括号内,内部的代码要有一次缩进(TAB或8个空格);
  • 类名首字母大写: 每当创建类时,类名的首字母必须大写;
  • **大小写敏感:**Java语法严格,大小写必须区分;
  • 大括号成对出现: 每当编写带有大括号的代码,大括号必须成对出现;
  • 所有符号都是英文: 代码中会用到各种各样的特殊符号,这些符号必须都是英文符号;
  • 以分号结尾: 每当一句代码写完,必须用分号结尾。

二、数据类型、变量️‍

1、数据类型

计算机要存储数据,就必须将数据进行合理分类,不同类型的数据对应使用不同的方式进行处理

java中的数据类型有:

  • 基本数据类型:
    • 整数:
      • byte(1字节)
      • short(2字节)
      • int(4字节)
      • long(8字节)
    • 小数:
      • float(4字节)
      • double(8字节)
    • 布尔类型:
      • boolean(2个字节)
    • char类型
      • char(1个字节)
  • 引用数据类型:
    • 类(class)
    • 接口(interface)
    • 数组(array)

2、变量

1、变量的特性

  • 方便使用: 一次定义,“到处”(作用域内)使用
  • 方便查找: 可以快速的拿到想要的结果
  • 能够保存一些可以改变的量

2、使用变量的过程:

  1. 声明: 先声明变量的数据类型以及变量名称,int i;
  2. 申请空间: 向内存中去申请空间;
  3. 赋值: 将具体的值赋给变量,i = 5,定义和赋值可以一起使用,int i = 5;
  4. 使用: 成功完成了对内存的使用,并得到一块存有数据的空间

3、定义变量的规则

1、变量名字里不能有空格。

2、避免使用关键字,class public int static

3、避免使用汉字

4、整体是驼峰命名,首字母小写

5、$和_可以到处使用

6、数字不能开头

3、运算符

1、赋值运算符

=就是赋值运算符,目的是将=右边的数据,赋值给=左边的空间。
//即:=右边永远都是数据,或可以得到数据的表达式;=左边永远都是一块可以存放对应数据类型的空间

2、算术运算符

+-*/%++--+=-=*=/=%=

a++和++a的区别❗️❗️❗️

num++: 先赋值 再运算

int num = 10;
int i = num++;
i=10,num=11;

++num:先运算 再赋值

int num = 10;
int i = ++num;
i=11,num=11;

3、比较运算符

><>=<===!=、equals
//比较运算符是用来对运算符左右两个变量的值进行比较,得到结果是boolean类型,因为无论是何种比较,结果只有真或假两种。

==和equals的区别: ❗️❗️❗️

  1. 值类型是存储在内存中的堆栈(简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中。
  2. ==操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。
  3. equals操作表示的两个变量是否是对同一个对象的引用,即堆中的内容是否相同。
  4. ==比较的是2个对象的地址,而equals比较的是2个对象的内容,显然,当equals为true时,==不一定为true。

4、布尔运算-真值表

与 &

条件1 condition1 条件2 condition2 结果
1 1 1
1 0 0
0 1 0
0 0 0

或 |

条件1 condition1 条件2 condition2 结果
1 1 1
1 0 1
0 1 1
0 0 0

非 !

条件1 condition1 结果
1 0
0 1

短路和长路的区别:

&& 短路运算符 如果是false 直接 结果就是false 不会继续运算

|| 短路运算符 如果是true直接 结果就是true 不会继续运算

5、三目运算符

条件?结果1:结果2;

条件的结果一定是boolean ,true ,false;

xboolean condition1 = 5 > 3;
boolean condition2 = 5 > 3;
boolean condition3 = 5 > 3;
int num = (condition1 && (condition2 || condition3)) ? 1 : 2;

6、运算符优先级

()>!>算数运算符>比较运算符>&&>|| >赋值运算符

当运算优先级不够时,可以在表达式外边增加小括号()来提升表达式的优先级。

三、idea工具类的使用️‍

1、字体的设置

非代码块设置主题和字体

file --》 settings ---》appearance---》theme  更换主题
Use custom font 勾上  选择字体 和 文字大小
file --》 settings --》 plugins --》 installed ---》theme   插件
ctrl art shift +s

修改代码块的字体

file --》 setting --》editor --》font

2、配置JDK

  1. 启动的时候就能配置
  2. ctrl + alt + shift + s 工程配置
project ---> project Sdk   --> new   找到自己安装的jdk
一定要保存  点击ok

3、idea的快捷键

main方法
新版的输入 main
老版的输入 psvm

输出语句   sout
复制一行   ctrl+D
剪切       ctrl+X

自动改错   alt + enter

ctrl+shift+下   和下一行交换位置
ctrl+alt+L     格式化代码

shift+F6		统一改名字
ctrl+单机			直接进入方法
ctrl+shift+U		将所有字符串都大写
alt+insert       生成getter和setter方法  

四、选择结构、循环结构️‍

1、选择结构

1、if else

if(){
    代码块.....
}
//当if()小括号中的表达式结果如果为true,则执行if(){}大括号内的代码,否则不执行。
//-------------------------------------
if(){
    代码块1.....
}else{
    代码块2.....
}
//首先判断if()小括号中的表达式结果,如果是true,则执行if(){}大括号内的代码;如果是false,则执行else{}大括号内的代码。必然会也只会执行一个大括号内的代码。
//-------------------------------------
if(){
    代码块1.....
}else if(){
    代码块2.....
}else{
    代码块3.....
}
//功能与三目运算相同。但不能如同三目运算一样直接将结果进行赋值操作,if没有结果反馈,三目运算始终有结果反馈。
//首先判断if()小括号中的表达式结果,如果是true,则执行if(){}大括号内的代码;如果是false,则执行else{}大括号内的代码。必然会也只会执行一个大括号内的代码。

2、switch

switch(表达式) {
    case1:
        语句体1;
        break;
    case2:
        语句体2;
        break; 
    default:	
        语句体n+1;
        break;
}

使用switch的注意事项:
1.case后面只能是常量,不能是变量,而且,多个case后面的值不能相同。
2.default可以省略。但一般不建议,除非结果是可以预计且不会发生变化的。
3.break可以省略,一般不建议。
4.default的位置可以出现在switch语句任意位置。
5.switch语句的结束条件必定是遇到break或已经执行到最末尾。

2、循环结构

1、for

for(声明循环变量;循环条件;迭代){
	被循环的代码块
}

for循环可以在循环条件满足的情况下,反复执行{}大括号内的代码块。
执行顺序:声明循环变量——>判断循环条件——>执行循环代码——>迭代——>判断循环条件…

2、while

声明循环变量
	while(循环判断){
    	被循环的代码块
    	迭代
}

for循环语句和while循环语句可以等价转换,循环需要的内容只是换了位置而已。
for循环和while循环的不同:
在for循环中声明的循环变量无法在循环外部使用,而while循环却是在循环结构外部声明的循环变量,所以即便循环结束,也可以继续使用。但更推荐使用for循环,for循环的循环变量在循环结束后会直接被销毁,更合理的使用内存空间。

3、do…while

声明循环变量
do{
    被循环的代码块
    迭代
}while(循环判断);

for循环与while循环都是先进行循环条件判断,在执行循环内的代码。

而do-while循环更加特殊,它会先执行循环内的代码,再进行循环条件的判断。如果循环条件最一开始就不满足,for循环和while循环一次都不会执行,而do-while循环由于先执行循环体的原因,即便不满足也会执行一次。

4、增强for循环

增强for循环在遍历数组和集合时会更加方便简洁,但是会有一定的局限性。

//增强for循环(for each)
for(元素类型 元素名称 :遍历数组(集合)(或者能进行迭代的)){
      语句
}

3、关键字

1、brrak:

无论如何都要结束当前的全部循环,彻底跳出循环,程序会继续向下执行。

2、contiune:

跳过本次循环继续下一次循环。

3、return:

  1. 终止方法:方法中如果没有返回值,使用return可以终止方法,使方法不再继续执行;
  2. 返回所需类型的值:有返回值的话,一方面会终止方法,另一方面可以将这个和返回值类型相同的变量作为返回值返回出去。

4、final关键字:

final关键字的规范: 字符串的所有字母都必须大写,单词和单词之间用下划线连接

静态常量: static fifinal 修饰 用来存放某些永远不变的量。

final关键字可以用来修饰引用、方法和类。

(1)用来修饰一个引用

  • 如果引用为基本数据类型,则该引用为常量,该值一旦定义就无法修改;
  • 如果引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,但指向该对象或数组的地址的引用不能修改。
  • 如果引用时类的成员变量,则必须当场赋值,否则编译会报错。

(2)用来修饰一个方法

当使用final修饰方法时,这个方法将成为最终方法,无法被子类重写。但是,该方法仍然可以被继承。

(3)用来修饰类

当用final修饰类时,该类称为最终类,无法被继承。简称“断子绝孙类”。

5、打标签:

for循环可已打标签,使用break + 标签名可以 退出 被打标签的循环

flag:for (int i = 0; i < 2; i++) {    
    for (int j = 0; j < 2; j++) {        
        if( j > 0 ){            
            break flag;       
        }        
        System.out.println("===="+j);    
    }
}

4、代码的简化

1、switch简化

switch中当case内的方法体语句一样时,可以简化。

case 1:
case 2:
case 3:
	buyGoods(function);

2、if简化

当判断逻辑中内容里只有一句时,可以省略大括号。

if (i > 0)
    System.out.println("这是简化的");

五、数组️‍

1、数组的定义

数组是存储同一种数据类型多个元素的集合。也可以看成是一个容器

int[] nums = {1,2,3};
int[] nums = new int[3];

类型[] 名字 = new 类型[长度];

2、数组的性质

1、数组一旦建立不能改变长度。

2、每个位置只能存一个值,多了会覆盖。

3、编号从0开始。

4、他有个长度的属性,最后一个位置的编号是 长度-1。

5、数组里边可以是基本类型,也可以是引用类型。

3、数组的简单使用

1、打擂台的形式找最大值

int[] salary = {4,5,0,6,7,8};
int maxIndex = 0 ;
for (int i = 1; i < salary.length; i++) {
    if(salary[i] > salary[maxIndex]){
        maxIndex = i;
    }
}
System.out.println("经过了n轮比赛得到的最大值得下标是:"+maxIndex+"。值是:"+salary[maxIndex]);

2、通循环遍历打印数组的每一个值

for (int i = 0; i < salary.length; i++) {
    System.out.print(salary[i] +  " ");
}

3、查找一个数组里存在的值。

int targetIndex = -1;
for (int i = 0; i < salary.length; i++) {
    if(salary[i] == 9){
        targetIndex = i;
    }
}

4、元素的位移。

int[] salary = {4,5,0,6,7,8};

int temp = salary[0];
salary[0] = salary[1];
salary[1] = temp;

4、数组的排序

1、选择排序

每一轮都是在找一个最小值放在未拍好序的元素的第一个

int[] nums = {4,6,0,8,7};
for (int j = 0 ; j < nums.length -1 ; j++){
    int minIndex = j;
    for (int i = j+1; i < nums.length; i++) {
        minIndex =  nums[i] < nums[minIndex] ? i : minIndex;
    }
    int temp = nums[minIndex];
    nums[minIndex] = nums[j];
    nums[j] = temp;
}

for (int i = 0; i < nums.length; i++) {
    System.out.print(nums[i] + " ");
}

2、冒泡排序

每一轮都是两两相比,会将最大的冒到最后边

int[] nums = {3, 7, 4, 9, 5, 4, 1};

for (int j = 0; j < nums.length - 1 ; j++) {
    for (int i = 0; i < nums.length - 1 -j ; i++) {
        if (nums[i] > nums[i + 1]) {
            int temp = nums[i];
            nums[i] = nums[i + 1];
            nums[i + 1] = temp;
        }
    }
}

for (int i = 0; i < nums.length; i++) {
    System.out.print(nums[i] + " ");
}

六、方法️‍

1、方法的定义及使用

1、方法的定义

Java方法是语句的集合,它们在一起执行一个功能。方法是解决一类问题的步骤的有序组合,方法包含于类或对象中,在程序中被创建,在其他地方被引用。

//权限修饰符 返回值类型(没有返回值写void) 方法名(参数类型 参数名){
//    ...
//    方法体
//    ...
//    return 返回值;(没有返回值可以不写return)
//}

public static void main( String[] args ){
  System.out.println("Hello World!")
}

2、方法的优点

  1. 使程序变得更简短而清晰。
  2. 有利于程序维护。
  3. 可以提高程序开发的效率。
  4. 提高了代码的重用性。

3、方法名的命名规范

  • 第一个单词应以小写字母作为开头,后面的单词用大写字母开头写(驼峰式命名);
  • 不能使用连接符;
  • 下划线可能出现在方法名称中用以分隔名称的逻辑组件;
  • 命名要有意义。

4、方法的调用

但凡是被static修饰的方法或者变量,都会在类加载的时候,就被初始化。都会赋给那个加载到内存的类对象,类对象的名字就是class 后边跟的那个字符串。

所以调用的时候 类的名字.方法名()实现调用,但如果在同一个类里就可以直接使用

方法名() 调用;

//无参数
test();
//有参数
int number = 3;
test(number);
//有参有返回值
int number = 3;
int result = test(number);

5、方法的几种形式

  • 无参数无返回值
  • 无参数有返回值
  • 有参数无返回值
  • 有参数有返回值

6、方法重载

方法名一样,参数数量不一样或者参数类型不一样。和返回值无关。

因为职责不一样,同样的名字往往表示同样的功能。

7、方法中形参和实参的区别

**形参:**方法定义的时候的参数

**实参:**方法调用时传入的参数

8、return的作用

  1. 终止方法:方法中如果没有返回值,使用return可以终止方法,使方法不再继续执行;
  2. 返回所需类型的值:有返回值的话,一方面会终止方法,另一方面可以将这个和返回值类型相同的变量作为返回值返回出去。

2、方法的深入使用

1、方法的使用

功能组成系统,步骤组成功能

当前写方法的步骤:

  1. 首先思考这个系统有什么功能 ,首先肯定是一个功能一个方法。
  2. 每一个功能有多复杂,复杂功能能不能拆开,比如一个功能分三步走,每一步能不能单独定义成一个方法。
  3. 思考整个系统的逻辑顺序,什么情况下会被调用。
  4. 有些小功能能不能独立为方法,很多共同的代码,需要抽离成方法。

2、值传递和引用传递

**值传递:**不改变原来的变量的值

**引用传递:**因为引用传递操作的是地址,会改变内存中的值

public class Test {
  public static void main(String[] args) {
      //依然没有被改变
      //值传递
      int number1 = 3;
      int number2 = 5;
      swap(number1,number2);
      System.out.println("number1 =" + number1);
      System.out.println("number2 =" + number2);
      System.out.println("-------------------------------------");
  
      //数组被改变了
      //引用传递
      int[] numbers = {1,2};
      swap(numbers);
      for (int i = 0; i < numbers.length; i++) {
          System.out.println(numbers[i]+"  ");
      }
      System.out.println("----------------------------------");
  }
  
  public static void swap(int num1,int num2){
      int temp = num1;
      num1 = num2;
      num2 = temp;
  }
  
  public static void swap(int[] nums){
      int temp = nums[0];
      nums[0] = nums[1];
      nums[1] = temp;
  }
}

3、可变参数

**格式:**数据类型…变量名称

**优点:**可以实现不限个数的传入参数,不是无限多,最大个数应该是32个

注意:

  • 传入的参数类型必须一样
  • 参数其实就是个数组
  • 必须是最后一个参数
public class Test {
    public static void main(String[] args) {
        int max = findMax("str",1,2,3,4,5,8,7,5);
        System.out.println(max);
        int max2 = findMax("str",1,2,6,7);
        System.out.println(max2);
        int max3 = findMax("str",1,5);
        System.out.println(max3);
    }

    public static int findMax(String str,int... nums){
        int maxIndex = 0;
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] > nums[maxIndex]) {
                maxIndex = i;
            }
        }
        System.out.println(str);
        return nums[maxIndex];
    }
}

4、方法递归

方法自己调自己,直接或间接调用方法本身。

注意:

  • 递归一定要有终点,终点就是某种情况停止自我调用,负责内存会溢出,就是个死循环
  • 绝大部分的递归可以用循环解决,循环的效率是高于递归的

5、斐波纳契数列

**斐波纳契数列(Fibonacci Sequence):**又称黄金分割数列,指的是这样一个数列:1、1、2、3、5、8、13、21…第一个 为 1 第二个 为1 从第三个开始 都等于前两个之和,第三个 就是 1 + 1 第四个 就是 第二个 + 第三个依次类推。

public class Test {
    public static void main(String[] args) {
        System.out.println("你要看数列的第几个的值:");
        Scanner in = new Scanner(System.in);
        int index = in.nextInt();
        System.out.println("第" + index + "个菲波那切数列的值为:" + fibonacci(index));
    }
    public static int fibonacci(int index){
        if(index == 1 || index == 2){
            return 1;
        }else{
            return fibonacci(index - 2) + fibonacci(index - 1);
        }
    }

斐波纳契数列原理图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pRu3ONuq-1588762657929)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1584377032158.png)]

6、方法内存当中的调用过程

java是一个基于栈的指令集,指令在栈上执行,栈帧

**栈:**先放进去的最后被拿出来,最后放进去的先拿出来,像羽毛球筒一样

Ⅱ、Java面向对象☑️

一、类

1、包

包是用来装类的,就等于文件夹

1、包名

**包名:**公司域名倒着写,com.baidu,全部小写,用点隔开

包名的作用:

  1. 引用其他人写的类的时候保证不重名
  2. 一眼就能看出是哪个公司的作品,起到保护作用
2、类名
简单类名:SuperLinked
全类名:com.xinzhi.util.SuperLinked
3、包的引入
//该包下的内容全部引入
import com.xinzhi.util.*;
//只引入一个类
import com.xinzhi.util.SuperLinked;

2、修饰符

1、权限修饰符
  • **public(公共的):**被修饰的成员,可以在任何一个类中被调用,不管同包或不同包,是权限最大的一个修饰符
  • **protected(受保护的):**被修饰的成员,只能在定义它们的类中使用,在其他类中不能调用。如果有别的包的类想调用它们,那么这个类必须是定义它们的类的子类。
  • **friendly(default)(友好的,默认权限):**默认权限即同包权限,同包权限的元素只能在定义它们的类中使用,以及同包的类中被调用
  • **private(私有的):**被修饰的成员,只能在定义它们的类中使用,在其他类中不能调用。
作用域 当前类 同package 子孙类 其他package
public
protected ×
friendly(default) × ×
private × × ×

注意:

  • 所有权限修饰符都可以修饰数据成员,方法成员,构造方法。但只有public和default可以修饰类(指外部类)。
  • 修饰符修饰的是”被访问”的权限。为了代码安全起见,修饰符不要尽量使用权限大的,而是选择合适的。

修饰符的作用:

  1. 对自己而言,保护代码
  2. 对别人而言,给别人一个干净的接口
2、状态修饰符
  • **static:**静态的,被修饰的变量、方法可以通过类名进行调用
  • **final:**最终的,被修饰的类不能被继承,被修饰的变量是常量,被修饰的方法不能被继承
3、抽象修饰符
  • **abstract:**抽象的,被修饰的类不能被实例化,只能被继承,被修饰的成员方法在子类中必须被重写

3、类和对象、构造方法

1、类

:类是一个模板,它描述一类对象的行为和状态。例如,动物是一个类,

2、对象

对象:对象是类的一个实例,有状态和行为。例如,一只狗狗是一个对象,它的状态有:颜色、名字、品种;行为有:叫、吃等;这只狗的是动物的实例。

3、类和对象的关系

类是对象的类型,对象是类的实例

4、构造方法

每个类都有构造方法。如果没有定义构造方法,Java编译器将会为该类提供一个默认构造方法。

构造方法的名字和类名必须完全一样,目前不能有返回值,一旦你定义了自己的构造方法,系统不会送你空的构造方法

5、new对象

在java中描述类用class,对象是由属性和方法组成,属性是有什么特点,方法是能干什么。new对象其实是调用构造方法,但写的类里并没有构造方法 ,事实上,如果你的类没有构造方法系统会送一个空的构造方法。

4、setter和getter

setting 和 getting 所有属性都加private,所有属性都用getter和setter

每个方法定义的时候都会默认传入两个变量thissuper

this: 代表new出来的那个对象的引用

super: 表示当前类的父类的对象

5、String类型

string是一个引用类型,本来也需要new,但是java给简化了

String name = new String("name");
String name = "name";

既然是个对象就有属性和方法:

他的方法无非就是帮助我们方便的处理这个字符串。

注:使用string一定要注意,必须用一个新的String接受。

常用的String方法:

.contains是否包含,
.substring(1,3)字符串截取,从第2到第3,包前不包后
.split分割字符串
.indexOf查找字符串的位置
.replace 替换字符串中的字符
.toUpperCase将字符串的小写转换成大写
..........
6、基础类型的包装类

因为基础类型没有方法,不好操作,所有java对每一种基础类型都进行了包装,生成包装类。

基本类型基于数值,对象类型基于引用

对象类型的变量需要占用更多的内存空间

int的包装类 Integer

Integer i = 3;

Integer是个对象,本来是要new,但是太常用了,所以简化了定义的方式,和基础类型一样。

**自动装箱:**看见变量是个Integer,而后边没new是自动帮你new了一个。

**自动拆装箱:**看见是个包装类,但这里学要打印的是基础类型,自动转换。

自学其它8种

可以看到,除了 int 和 char 两者的包装类名变化有些大以外,其余六种基本类型对应的包装类名,都是大写了首字母而已。

基本类型 包装类
boolean Boolean
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
7、画图解释了类加载运行过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aksJ6yEl-1588762657934)(E:\Development4\总结\2、Java面向对象\20200207-类加载、超级数组、封装、栈\类加载运行.png)]

代码案例

package com.xinzhi;

/**
 * 画图解释类加载运行
 * @auther 王瑞杰
 * @date 2020/2/9
 */
public class Test {
    public static void main(String[] args) {
        Test test1 = new Test();
        System.out.println("------第一次------");
        System.out.println(test1.num2);
        System.out.println(Test.num1);

        Test test2 = new Test();
        System.out.println("------第二次------");
        System.out.println(test1.num2);
        System.out.println(Test.num1);
    }

    public static int num1 = 0;
    public int num2 = 0;

    public  Test(){
        this.num2++;
        Test.num1++;
    }
}

二、封装

1、封装的定义

**封装(Encapsulation):**是指一种将抽象性函数接口的实现细节部分包装、隐藏起来的方法。

封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。

2、封装的优点

  1. 良好的封装能够减少耦合;
  2. 类内部的结构可以自由修改;
  3. 可以对成员变量进行更精确的控制;
  4. 隐藏信息,实现细节,增强了安全性。
  5. 使用简单的基础数据类型(属性),方法可以被封装成更复杂,更好用的类。

3、封装的作用

  1. 什么东西没有,就封装
  2. 不好用 就封装

4、封装的实现

1、修改属性的权限性

通过修改属性的权限性来限制对属性的访问(一般限制为private)

//将userName和password属性设置为私有的,只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。 
public class User {
    private String userName;
    private int password;
}
2、对每个值属性提供对外的公共方法访问

创建一对赋取值方法,用于对私有属性的访问

public class User {
    private String userName;
    private String password;
    
    public int getUserName(){
      return userName;
    }

    public String getPassword(){
      return password;
    }

    public void setUserName(String userName){
      this.userName = userName;
    }

    public void setPassword(String password){
      this.password = password;
    }
}

三、继承

1、继承的概念

继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

2、继承的实现

  • 继承使用的是extends关键字实现的;
  • java采用的是单继承一个爹可以有多个儿子,一个儿子只能有一个爹,儿子还可以再有孙子
  • 有个顶级父类叫Object,所有的对象都有一个父类叫Object,这是规定,所以所有的对象都能调用Object的所有方法,比如toString();
  • new一个子类,一定会先new一个父类,子类的构造方法中第一句默认是super(),意思就是构造子类一定会先构造一个父类。

思想:一个对象调用方法的时候,首先去自己的类里边找,找不到的话就去父类找,父类也找不到,就去父类的父类找,直到Object,找到为止。

3、继承的图解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZxsTyYrH-1588762657937)(E:\Development4\总结\2、Java面向对象\20200210-队列封装、多太、抽象方法、接口\继承.png)]

四、多态

1、多态的概念

多态是同一个行为具有多个不同表现形式或形态的能力。

2、多态的优点

  • 消除类型之间的耦合关系
  • 可替换性
  • 可扩充性
  • 接口性
  • 灵活性
  • 简化性

3、多态存在的三个必要条件

1、继承

子类继承父类

2、重写

子类重写父类的方法

3、父类引用指向子类对象

使用父类引用指向子类对象时,子类特有的方法就不能再被调用

都是父类引用,指向了不同的子类对象,调用相同的方法,就会有不同的结果,这就叫多态

4、重写(Override)与重载(Overload)

1、重写(Override)

重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心内容重新写!

**重写的好处:**子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。

注意:

  • 当需要在子类中调用父类的被重写方法时,要使用 super 关键字
  • 参数列表必须完全与被重写方法的相同;
  • 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类;
  • 访问权限不能比父类中被重写的方法的访问权限更低;
  • 父类的成员方法只能被它的子类重写;
  • 声明为 final 的方法不能被重写;
  • 声明为 static 的方法不能被重写,但是能够被再次声明;
2、重载(Overload)

重载是在一个类里面,方法名字相同,而参数不同(参数个数或类型不一样)。返回类型可以相同也可以不同。

3、重写和重载的区别:

(1)目的不同

重载用于增加程序的可读性(做法不同,但是做的同一事情)。 重写用于提供其超级类已经提供的方法的特定实现。

(2)范围不同

重载在相同的类范围内内执行。 重写发生在两类具有继承(继承)的关系。

(3)参数不同

重载参数必须不同。 重写参数必须相同。

如图所示:

重写在原来的箭上绑上新的箭,重载是多加了几支箭。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rF0S2ze1-1588762657938)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1584387925697.png)]

五、抽象类

有些类天然的就是为了让子类继承,而不是为了在父类中调用,这类方法存在的目的就是规定了子类,必须要有这些方法,比如动物就规定,你实现了我这个类,就必须有eat方法,而且逆袭必须重写。

对于这种情况,java提出来抽象类,这种类里边可以有一些方法没有方法体,我们称之为抽象方法,抽象方法必须使用abstract修饰,同时,如果有了abstract抽象方法之后,这个类必须被定义成抽象方法,也是用abstract修饰

抽象方法是对子类的约束,不管是猫还是狗还是其它动物,他必须都能吃东西

注意:

  1. 不能new,因为某些方法没有方法体,这些方法就是用来重写的,就是定义子类必须有这些方法;
  2. 他必须被继承才能使用,必须实现所有的抽象方法;
  3. 如果一个类继承了抽象类,要么 把自己申明成一个抽象类,要么 实现抽象类的所有方法。

六、接口

1、接口的概念

当一个类里全是抽象方法时,我们称这类方法叫做接口,省略abstract,class改为interface,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。

注意:

  • 接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
  • 接口里省略权限修饰符,默认为public,一个原因是因为它一定是给子类去实现(继承里叫做重写)的。
  • java是单继承,但是是多实现,一个类可以实现多个接口,但只能继承一个父类。
  • 实现接口,必须实现接口里全部的方法。

2、接口的特性

  • 接口中每一个方法是隐式抽象的,接口中的方法会被隐式的指定为 public abstract
  • 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量
  • 接口中的方法不能在接口中实现,只能由实现接口的类来实现接口中的方法。

3、接口与类的区别

  • 接口不能用于实例化对象。
  • 接口没有构造方法。
  • 接口中所有的方法必须是抽象方法。
  • 接口不能包含成员变量,除了 static 和 final 变量。
  • 接口不是被类继承了,而是要被类实现。
  • 接口支持多继承。

4、接口和抽象类的区别

  • 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行;
  • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的;
  • 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法;
  • 一个类只能继承一个抽象类,而一个类却可以实现多个接口。

Ⅲ、Java高级☑️

一、超级数组、栈、队列

1、自己封装一个超级数组

自己封装一个超级数组,对数组添加增删查改的功能。

package com.xinzhi;

/**
 * 封装超级数组
 * @auther 
 * @date 2020/2/9
 */
public class SuperArray {
    //维护一个数组
    private int[] array;
    //当前最后一个数字的下标,要为-1,因为数组的下标从0开始
    private int currentIndex = -1;

    //构造是初始化
    SuperArray(){
        array = new int[8];
    }

    //添加数据的方法
    public SuperArray add(int data){
        currentIndex++;
        if (currentIndex > array.length - 1){
            array = dilatation(array);
        }
        array[currentIndex] = data;
        //返回当前的对象,把自己返回回去,可以一只调用,方便链式调用,
        return this;
    }

    /**
     * 删除
     * 1、把末位的删除了,没有参数
     * 2、给一个下标删除
     * 3、给值删除
     */
    //Integer是一个包装类,可以返回null
    public Integer delete(){
        currentIndex--;
        if (currentIndex < -1){
            return null;
        }else {
            return array[currentIndex + 1];
        }
    }

    //修改
    public void update(int index,int data){
        boolean flag = validateIndex(index);
        if (flag){
            array[index] = data;
        }else {
            System.out.println("您要修改的数据不存在!!!");
        }
    }

    //查找数组里有几个改数据
    public int findNumber(int data){
        int count = 0;
        for (int i = 0; i < array.length; i++) {
            if (array[i] == data){
                count ++;
            }
        }
        return count;
    }

    //查找这个数据第一次出现的下标
    public int findNumberIndex(int data){
        for (int i = 0; i < array.length; i++) {
            if (array[i] == data){
                return i;
            }
        }
        return -1;
    }

    //根据下表查询数字
    public int get(int index){
        return array[index];
    }

    //查看当前有多少个数字
    public int size(){
        return currentIndex + 1;
    }

    //打印数组
    public void print(){
        System.out.println("当前的数组是: ");
        for (int i = 0; i <= currentIndex; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();
    }

    //排序
    public void sort(){
        for (int i = 0; i < currentIndex; i++) {
            for (int j = 0; j < currentIndex; j++) {
                if (array[j] > array[j + 1]){
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }
    }

    //验证下标是否合法
    private boolean validateIndex(int index) {
        //只要有一个不满足就返回false
        return index <= currentIndex && index >= 0;
    }

    //自动 数组扩容
    private int[] dilatation(int[] oldArray){
        int[] newArray = new int[oldArray.length * 2];
        for (int i = 0; i < oldArray.length; i++) {
            newArray[i] = oldArray[i];
        }
        return newArray;
    }
}

package com.xinzhi;

/**
 * 封装超级数组的执行类
 * @auther 
 * @date 2020/2/9
 */
public class SuperArrayTest {
    public static void main(String[] args) {
        SuperArray superArray = new SuperArray();
        //添加
        superArray.add(3);
        superArray.print();

        //自动扩容
        //因为方法内自己把自己返回了出去,所以能一直调add方法
        superArray.add(4).add(2).add(3).add(4).add(2).add(3).add(4).add(2).add(3).add(4).add(2).add(3);
        superArray.print();

        //删除末位
        int delete = superArray.delete();
        System.out.println("你把末位的【" + delete + "】给删掉了!!");
        superArray.print();

        //修改
        superArray.update(5,9);
        superArray.print();
        superArray.update(22,9);
        superArray.print();

        //查找数据有几个
        int number = superArray.findNumber(3);
        System.out.println("查找的3有" + number + "个");
        superArray.print();

        //查找这个数据第一次出现的下标
        int numberIndex = superArray.findNumberIndex(4);
        System.out.println("4第一次出现的下标是" + numberIndex);
        superArray.print();

        //查询有多少个数字
        int size = superArray.size();
        System.out.println("有【" + size + "】个数字");

        //进行排序
        superArray.sort();
        superArray.print();
    }
}

2、自己封装一个栈

是一种先进后出的数据结构,数组和链表都可以生成栈。

**进栈:**当数据进入到栈时会按照规则压入到栈的底部,再次进入的数据会压在第一次的数据上面,以此类推。

**出栈:**在取出栈中的数据的时候会先取出最上面的数据,所以是先进后出。

package com.xinzhi;

/**
 * 先进后出
 * 封装一个栈
 * @auther 
 * @date 2020/2/9
 */
public class MyStack {
    SuperArray superArray;
    public MyStack(){
        superArray = new SuperArray();
    }

    //压栈 压入栈顶
    public void push(int data){
        superArray.add(data);
    }

    //弹栈
    public Integer pop(){
        Integer number = superArray.delete();
        if (number == null){
            System.out.println("栈已经空了!!");
        }
        return number;
    }
}

package com.xinzhi;

import org.omg.CORBA.MARSHAL;

/**
 * 封装一个栈的执行类
 * @auther 王瑞杰
 * @date 2020/2/9
 */
public class MyStackTest {
    public static void main(String[] args) {
        MyStack myStack = new MyStack();
        myStack.push(3);
        myStack.push(4);

        Integer pop1 = myStack.pop();
        System.out.println(pop1);

        Integer pop2 = myStack.pop();
        System.out.println(pop2);

        Integer pop3 = myStack.pop();
        System.out.println(pop3);
    }
}

3、自己封装一个队列

队列是一种先进先出的数据结构,数组和链表也都可以生成队列。

**进队列:**当数据进入到队列中时是先进入的在下面后进入的再上面。

**出队列:**出队列的时候是先从下面出,然后才是上面的数据出,最晚进入的队列的,最后出。

package com.xinzhi;

/**
 * 封装队列
 * 先进先出
 * @auther 
 * @date 2020/2/10
 */
public class MyQueue {
    private SuperArray superArray;

    public MyQueue(){
        superArray = new SuperArray();
    }

    //入队
    public void put(int data){
        superArray.add(data);
    }

    //出队
    public Integer take(){
        return superArray.delete(0);
    }
}
package com.xinzhi;

import java.util.Scanner;

/**
 * 封装队列的执行类
 * @auther 王瑞杰
 * @date 2020/2/10
 */
public class MyQueueTest {
    public static void main(String[] args) {
        MyQueue myQueue = new MyQueue();
        myQueue.put(1);
        myQueue.put(5);

        System.out.println(myQueue.take());
        System.out.println(myQueue.take());


        System.out.println("---------------银行取票机--------------------");
        for (int i = 0; i < 100; i++) {
            myQueue.put(i + 1);
        }

        while (true){
            System.out.println("请出示您的身份证:");
            Scanner scanner = new Scanner(System.in);
            String name = scanner.next();
            System.out.println(name + "拿到的号码是:" + myQueue.take());
        }
    }
}

二、对象转型、泛型、链表

1、对象转型

**强制转型:**从父类的类型强制转为子类,如果传入的真的是该类型,则强转没有问题;如果不是就会报错

合适的方法是使用instanceof首先进行判断,确定类型之后再处理

//使用instanceof 判断传进来的对象是不是一个Dog类型
//强转成一个子类
if (animal instanceof Dog){
	Dog dog = (Dog)animal;
    dog.enjoy();
}

2、泛型

当某个类不知道自己内部处理的数据的真实类型时,可以使用泛型,

方法是在类后加,不一定是T,其它字母也行,一般写成T或E。

只有当你去new对象时指定了确定的类型时,代码里的T就会变成实际的类型,具体从代码里思考。

3、链表(单向链表)

链表像一跟绳子一样,把节点全链起来,手拉手

查询慢,删除快(查询是从第一个开始,依次往后找)(删除是把要删的上一个和下一个连接起来)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OfJIIaaf-1588762657942)(E:\Development4\总结\2、Java面向对象\20200211-超级数据泛型、链表\链表.png)]

4、数组和链表的区别:

不同点:
  1. 链表是链式的存储结构,数组是顺序的存储结构;
  2. 链表通过 指针来连接元素与元素,数组则是把所有的元素按次序依次存储;
  3. 链表的插入删除元素相对数组较为简单,且较为容易实现长度扩充,但是寻找某个元素较为困难;
  4. 数组寻找某个元素较为简单,但插入与删除比较复杂,由于最大长度需要在编程一开始时指定,所以当达到最大长度时,扩充长度不如链表方便
相同点:

两种数据结构均可实现数据的顺序存储,构造出来的模型是线性结构。

三、集合

1、集合的定义

**集合的概念:**集合是一个动态的数组,长度可以改变。集合存放的都是对象的引用,而非对象本身,出于表达上的便利,我们称集合中的对象就是指集合中对象的引用(reference)

**集合的类型:**set(集)、list(列表)、map(映射)

**集合的接口有:**Collection和Map、List、Set

2、Java集合框架主要结构图:

  1. 集合主要分为CollectionMap两个接口
  2. Collection又分别被ListSet继承
  3. ListAbstractList实现,然后分为3个子类,ArrayListLinkListVector
  4. SetAbstractSet实现,又分为2个子类,HashSetTreeSet
  5. MapAbstractMap实现,又分为2个子类,HashMapTreeMap
  6. MapHashtable实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-te7Jdtjr-1588762657944)(E:\Development4\总结\2、Java面向对象\20200212-集合\Java集合框架主要结构图.png)]

3、集合中常用集合类的继承关系及特点:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Le7VQi0j-1588762657945)(E:\Development4\总结\2、Java面向对象\20200212-集合\集合类特点.png)]

4、List集合

ArrayList和LinkedList分别实现了List,只不过它们的底层一个是数组一个是链表。

5、Map集合

**HashMap组成:**hash散列、数组、链表、红黑树

注意:

任何东西一调用HashCode就能生成一个数字

数组长度16,链表上至少能挂8个,挂到8个时进行树化(红黑树)

Hash数据结构已经定死,一定不能根据key排序

TreeMap直接是一个巨大的红黑树

HashMap集合原理图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AQB5FOb2-1588762657949)(E:\Development4\总结\2、Java面向对象\20200212-集合\HashMap.png)]

6、Set集合

**特点:**不能重复,如果重复直接覆盖

其他集合可以利用set不能重复对象的特性,达到去重的目的

**HashSet:**元素无序,且唯一,允许存储null元素

**TreeSet:**具有Set的属性和方法,基于TreeMap实现,底层的数据结构是红黑树

7、Iterator迭代器

Iterator是一个接口,它是集合的迭代器。集合可以通过Iterator去遍历集合中的元素。

迭代器中常用的方法:
  • **hasNext():**如果迭代器中还有元素,则返回true。
  • **next():**返回迭代器中的下一个元素
  • **remove():**删除迭代器新返回的元素.如果使用Collection中的remove()方法,则会报并发修改异常。但是不是必须的情况下,我们很少使用iterator的remove()方法。

四、java的工具类

1、Object类

object方法:所有类的顶级父类,所有的类都有这个方法

**object里常用的方法:**equals()、hashCode()、toString()、getClass()

方法名 作用 返回值
hashCode() 获取对象hash值 int
toString() 将对象信息变为字符串返回 String
equals(Pbject obj) 判断两个内存地址是否一样 boolean
getClass() 获取类名 Object

注意:

  1. equals在object里的实现就是==就是在比内存地址

  2. 当要比较对象时,要重写equals方法,最好也重写hashCode

  3. hashCode不要自己实现,让人家写,Object.hash()

    toString 把所有的对象转换成字符串,如果不转化:类的全类型名@十六进制的数

2、Date类

java.util 包提供了 Date 类来封装当前的日期和时间。 Date 类提供两个构造函数来实例化 Date 对象。

第一个构造函数使用当前日期和时间来初始化对象。

Date()

第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数。时间戳:英国伦敦1970-1-1 0:0:0到现在的毫秒数,在任何地方都可用

Date (long date)

**使用 SimpleDateFormat 格式化日期:**SimpleDateFormat 是一个以语言环境敏感的方式来格式化和分析日期的类。SimpleDateFormat 允许你选择任何用户自定义日期时间格式来运行。例如: 日期格式化 “yyyy-MM-dd HH:mm:ss”(hh是12小时制,HH是24小时制)

3、Calendar 类

Calendar类的功能要比Date类强大很多,而且在实现方式上也比Date类要复杂一些。

Calendar类是一个抽象类,在实际使用时实现特定的子类的对象,创建对象的过程对程序员来说是透明的,只需要使用getInstance方法创建即可。

创建一个代表系统当前日期的Calendar对象

Calendar c = Calendar.getInstance();//默认是当前日期

创建一个指定日期的Calendar对象

//创建一个代表1998年6月6日的Calendar对象
Calendar c1 = Calendar.getInstance();
c1.set(1998, 6, 6);

Calendar类的常用方法:

方法名 作用 返回值
getInstance() 获取日期 Calendar
get(int field) 获取年/月/日/时/分/秒 int
add(int field,int amount) 计算时间 void
set(int year,int month,int date) 设置时间 void

4、Math类

Math类包含了用于执行基本数学运算的属性和方法,如绝对值、最大最小值、随机数

Math类的方法都被定义为 static 形式,全是静态方法,所以不能new。通过 Math 类可以在主函数中直接调用。

Match常用的方法:

方法名 作用 返回值
abs(int a) 取绝对值 int
ceil(double a) 返回最小值 double
floor(double a) 返回最大值 double
max(int a,int b) 取最大值 int
pow(double a,double b) 求幂 double
random() 随机数 double
round(float a) 四舍五入成整数 int
sqrt(double a) 求double值的正平方根 double

5、Random类

Java提供了更为灵活的用于获得随机数的Random类,该类在java.util包中,使用Random类的如下构造方法,可以创建Random对象,习惯将Random对象称为随机数生成器。

构造方法:

Random() 
创建一个新的随机数生成器。
Random(long seed) 
使用单个指定long种子创建一个新的随机数生成器。

6、Arrays工具类

Arrays是Java.util.Arrays类能方便地操作数组,它提供的方法时静态的

数组Arrays工具类常用方法:

方法名 说明功能
asList 将数组转变成ArrayList,但是ArrayList长度不可变化
sort 对数组进行排序。
binarySearch 用于对已排序的数组进行二分查找
copyOf 数组拷贝,
copyOfRange 指定范围的复制
equals 比较两个数组中对应位置的每个元素是否相等。
toString 打印一维数组的元素

7、Collections工具类

Collections是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。

集合Collections工具类常用方法:

方法名 说明功能
sort 对指定列表按升序进行排序
shuffle 洗牌方法,将当前集合内的数据进行随机排序
reverse 逆序排序,对当前集合的元素按照相反的顺序进行排序
min和 max 分别返回集合中的最小元素和最大元素
indexOfSubList 返回源列表中第一次出现指定目标列表的起始位置
lastIndexOfSubList 返回源列表中最后一次出现指定目标列表的起始位置
rotate 循环移动指定列表中的元素
fill 替换掉源列表中所有的元素为目标元素
copy 拷贝所有元素,目标列表的长度要大于或等于源列表的长度

五、垃圾回收机制

1、概念

**垃圾回收(Garbage Collection,GC):**是释放垃圾占用的空间,防止内存泄露。有效的使用可以使用的内存,对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收。

分析:

1、所有新new的对象会放在伊甸园区,伊甸园区到一定的程度就会触发GC,GC进行标记然后进行垃圾回收,
2、先把不被回收的复制到survive1里,复制比移动快,
3、然后将伊甸园区清空,
4、然后继续往伊甸园区new对象
5、再对伊甸园区和survive1区进行GC,然后将伊甸园区和survive1中不被回收的,复制到survive2区中
6、会对survive2区中的对象标个年龄(刚从survive1中过来的标1,从survive2中过来的标2)
7、再将伊甸园区和survive2清空

8、当对象的年龄达到某个值时 ( 默认是 15 岁)这些对象就会成为老年代。
9、老年代一般不动了,有很少一部分也会进行清除,清除掉后将后面的往前挪
10、永久代一般不进行GC,一般存放class、类对象、元数据

六、File类、IO流

1、File类

1、File类简介:

File 类是 java.io 包中唯一代表磁盘文件本身的对象。

File 类定义了一些与平台无关的方法来操作文件,File类主要用来获取或处理与磁盘文件相关的信息,像文件名、 文件路径、访问权限和修改日期等,还可以浏览子目录层次结构。

File 类表示处理文件和文件系统的相关信息。也就是说,File 类不具有从文件读取信息和向文件写入信息的功能,它仅描述文件本身的属性。

2、File类常用构造方法

不可以空参构造!!

File(String pathname) 
//通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。 
3、File类常用方法
方法 作用 返回值
createNewFile() 创建名称的空文件,不创建文件夹 boolean
isDirectory() 判断是否是目录 boolean
isFile() 判断是否是文件 boolean
exists() 判断文件或目录是否存在 boolean
getAbsolutePath() 返回此对象表示的文件的绝对路径名 String
getPath() 返回此对象表示的文件的相对路径名 String
getName() 返回此对象表示的文件或目录的名称 String
length() 返回文件的长度,单位为字节 long
注意:

路径应该用左斜杠/ 或者 两个右斜杠\ \

/左斜杠在java中表示路径,右斜杠\在java中表示转译符,所有如果要用右斜杠需要给他转译成左斜杠

2、IO流

1、Java中IO流的概念

java的io是实现输入和输出的基础,可以方便的实现数据的输入和输出操作。在java中把不同的输入/输出源(键盘,文件,网络连接等)抽象表述为“流”(stream)。

2、IO流的分类

按照不同的分类方式,可以把流分为不同的类型。常用的分类有三种:

2.1、 按照流的流向分

可以分为输入流和输出流

  • 输入流: 只能从中读取数据,而不能向其写入数据。 InputStream和Reader为基类
  • 输出流:只能向其写入数据,而不能向其读取数据。 OutputStream和Writer为基类
2.2、按照操作单元划分

可以划分为字节流和字符流

字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。

字节流和字符流的区别:

  • 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
  • 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
  • 字节流:一次读入或读出是8位二进制。
  • 字符流:一次读入或读出是16位二进制。

结论:

设备上的数据无论是图片或者视频,文字,它们都以二进制存储的。二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节。意味着,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据。

只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。

2.3、按照流的角色划分

划分为节点流和处理流

  • **节点流:**可以从/向一个特定的IO设备(如磁盘,网络)读/写数据的流,称为节点流。节点流也被称为低级流。 直接使用节点流,读写不方便,为了更快的读写文件,才有了处理流。

这里写图片描述

  • **处理流:**用于对一个已存在的流进行连接和封装,通过封装后的流来实现数据的读/写功能。处理流也 被称为高级流。

这里写图片描述

总结:

  1. Java IO是采用的是装饰模式,即采用处理流来包装节点流的方式,来达到代码通用性。
  2. 处理流和节点流的区分方法,节点流在新建时需要一个数据源(文件、网络)作为参数,而处理流需要一个节点流作为参数。
  3. 处理流的作用就是提高代码通用性,编写代码的便捷性,提高性能。
  4. 节点流都是对应抽象基类的实现类,它们都实现了抽象基类的基础读写方法。其中read()方法如果返回-1,代表已经读到数据源末尾。
3、java输入/输出流体系中常用的流的分类表

**注:**下表中带下划线的是抽象类,不能创建对象。粗体部分是节点流,其他就是常用的处理流。

流分类 使用分类 字节输入流 字节输出流 字符输入流 字符输出流
抽象基类 InputStream OutputStream Reader Writer
节点流 访问文件 FileInputStream FileOutStream FileReader FileWriter
访问数值 ByteArrayInputStream ByteArrayOutStream CharArrayReader CharArrayWriter
访问管道 PipedInputStream PipedOutStream PipedReader PipedWriter
访问字符串 StringReader StringWriter
处理流 缓冲流 BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter
转换流 InputStreamReader OutputStreamWriter
对象流 ObjectInputStream ObjectOutputStream
抽象基类(过滤) FilterInputStream FilterOutputStream FilterReader FilterWriter
打印流 PrintStream PrintWriter
推回输入流 PushbackInputStream PushbackReader
特殊流 DataInputStream DataOutputStream
4、java流类图结构

Java基础详解_第1张图片

七、异常

1、异常的定义

异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止,其实异常本身也是一个类。
注意:异常不是语法错误,语法错误是无法通过编译也就不会产生字节码文件也就不能运行。

2、异常实现及分类

异常类的结构图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1GYd8Ogx-1588762657958)(E:\Development4\总结\2、Java面向对象\20200217-异常、数组集合工具类\异常类的结构图.png)]

所有的异常都是从Throwable继承而来的,是所有异常的共同祖先,Throwable有两个子类,Error和Exception

  • **Error:**java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。Error 用来指示运行时环境发生的错误。例如,JVM 内存溢出。一般地,程序不会从错误中恢复。
  • **Exception:**程序本身可以捕获并且可以处理的异常。异常类有两个主要的子类:IOException 类和 RuntimeException 类
    • **运行时异常(不受检异常)RuntimeException:**该类极其子类表示JVM在运行期间可能出现的错误。编译器不会检查此类异常,并且不要求处理异常,比如用空值对象的引用(NullPointerException)、数组下标越界(ArrayIndexOutBoundException)。此类异常属于不可查异常,一般是由程序逻辑错误引起的,在程序中可以选择捕获处理,也可以不处理。
    • **非运行时异常(受检异常)IOException:**Exception中除RuntimeException极其子类之外的异常。编译器会检查此类异常,如果程序中出现此类异常,比如说IOException,必须对该异常进行处理,要么使用try-catch捕获,要么使用throws语句抛出,否则编译不通过。

3、常见的内置异常类:

异常类型 说明
Exception 异常层次结构的父类
ArithmeticException 算术错误情形,如以零作除数
ArrayIndexOutOfBoundsException 数组下标越界
NullPointerException 尝试访问 null 对象成员(空指针异常)
ClassNotFoundException 不能加载所需的类
IllegalArgumentException 方法参数错误
ClassCastException 对象强制类型转换出错
NumberFormatException 数字格式转换异常,如把"abc"转换成数字

4、异常的处理

  1. 抛出异常:throw,throws
    • **抛出异常throw:**throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。

      使用格式:

      throw new 异常类名(参数)
      
    • **声明抛出异常throws:**运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常

      使用格式:

      修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2 ... { }
      
  2. 捕获异常:try,catch,finally
    • try 和 catch 关键字:
      • 使用 try 和 catch 关键字可以捕获异常,try/catch 代码块放在异常可能发生的地方
      • try/catch代码块中的代码称为保护代码
      • Catch 语句包含要捕获异常类型的声明。当保护代码块中发生一个异常时,try 后面的 catch 块就会被检查。
      • 如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块,这和传递一个参数到方法是一样。
    • 一个 try 代码块后面跟随多个 catch 代码块的情况就叫多重捕获:
      • 可以在 try 语句后面添加任意数量的 catch 块。
      • 如果保护代码中发生异常,异常被抛给第一个 catch 块。
      • 如果抛出异常的数据类型与 ExceptionType1 匹配,它在这里就会被捕获。
      • 如果不匹配,它会被传递给第二个 catch 块。
      • 如此,直到异常被捕获或者通过所有的 catch 块。
    • finally关键字:
      • finally 关键字用来创建在 try 代码块后面执行的代码块
      • 无论是否发生异常,finally 代码块中的代码总会被执行
      • 在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。

注意事项:

  • catch 不能独立于 try 存在。
  • 在 try/catch 后面添加 finally 块并非强制性要求的。
  • try 代码后不能既没 catch 块也没 finally 块。
  • try, catch, finally 块之间不能添加任何代码。
try {   
    ...  //监视代码执行过程,一旦发现异常则直接跳转至catch,        
        // 如果没有异常则直接跳转至finally
} catch (SomeException e) {    
    ... //可选执行的代码块,如果没有任何异常发生则不会执行;
        //如果发现异常则进行处理或向上抛出。
} finally {
        ... //必选执行的代码块,不管是否有异常发生,
            // 即使发生内存溢出异常也会执行,通常用于处理善后清理工作。
}

你可能感兴趣的:(Java基础详解)