Java SE 基础知识整理

本文详细介绍了Java语言的核心特性,包括面向对象、数据类型(如基本类型和引用类型)、变量的声明和使用,以及运算符的规则。此外,还涵盖了控制结构(如for、while、do-while循环和switch语句),数组的使用,以及类和对象的概念。文章还深入讨论了方法、构造器、封装、继承、多态等面向对象编程的关键概念,并提到了异常处理、泛型、集合框架和字符串操作。
摘要由CSDN通过智能技术生成

Java语言特性:

1、面向对象(OOP)

2、有健壮的体系,如异常处理、GC、强类型机制

3、跨平台
注:.java源文件不跨,编译后的.class跨,因为JVM的存在

4、解释性语言
注:解释性语言,编译后的代码(如.class),不能被机器直接执行,需要解释器(如JVM)执行;编译性语言,编译后的代码,可被机器直接执行

变量:

1、变量三要素:数据类型+名称+值

2、变量即可以变化的值(要符合定义数据类型)

3、变量在同一个作用域内,变量名不能重复

4、变量要先声明,后使用

+号使用:

1、当+号左右两方全为数值类型时,做加法运算(从左到右相加)

2、当+号左右两方有一方为字符串类型,做拼接运算(从左到右相加)

数据类型:

1、Java中必须指定每种数据的数据类型,不同的数据类型,在内存中分配不同的字节(强类型机制的体现)

2、Java数据类型分为基本数据类型和引用数据类型,具体如图

3、Java各数据类型有固定字节和范围,不受OS影响

4、Java整形常量默认为int类型(通常情况下使用),声明long类型常量须后加’l’或’L’

5、Java浮点数由符号位+指数位+尾数位组成(尾数位可能丢失,造成精度损失)

6、Java浮点型常量默认为double(通常情况下使用),声明float类型常量须加’f’或’F’

7、小类型可以赋给大类型;大类型不可以赋给小类型

8、浮点数相互计算时,可能产生精度损失,如8.1/3,是一个无限接近2.7的小数,而不是2.7,所以对运算结果为小数,进行判断时,要注意判断逻辑

9、科学技术法:如5.12e2表示5.12×10的2次方(e/E前,e/E后必有数,e/E后必须为整数)

10、Java字符型本质是一个整数,即Unicode码(万国码),所以char类型也可以相互运算

11、常用字符编码有:ASCII码(128个字符)、Unicode码(字母和汉字都是2字节)、UTF-8码(字母1字节,汉字3字节,表示汉字多一些)、GBK码(字母1字节,汉字2字节,表示汉字少一些)

12、Java布尔型只允许为true或flase,不允许为null

数据类型转换:

1、精度小转大(自动类型转换);精度大转小(强制类型转换,可能造成溢出和精度损失)

2、在多种数据类型进行混合计算时,Java会首先自动将所有数据类型转换成最大的数据类型,然后再计算

3、byte、short不会和char自动转换,但byte、short、char三者可以进行计算,不管是单种计算,还是混合运算,都会自动转成int

4、boolean不参与转换

5、char类型可以保存int类型常量值,但不能直接保存int类型变量值

6、基本数据类型转成String类型,+""即可;String类型转成基本数据类型需要用到包装类(若格式不正确,如"hello"转int,就会抛出异常)

运算符:

1、i++(i–)、++i(–i),后++后–,即先赋值,再运算;前++前–,即先运算,再赋值

2、/表示整除,如两int型数据相除,4/5结果为0,并不是0.8

3、%表示取模(取余),结果符号和被余数符号相同,公式为a%b=a-a/b×b

4、关系运算符总览


5、&&短路与、||短路或,即当第一个条件满足逻辑关系,后面的就不再执行了

6、&逻辑与、|逻辑或(数字相与、相或按位运算规则执行),没有短路情况,所有判断条件都会执行

7、!非运算,^逻辑异或,两条件相同为0(false),不同为1(true)

8、复合赋值运算时,会自动进行类型转换

9、三元运算符:条件表达式?表达式1:表达式2; 规则:true为1,false为2

10、运算符只有单目运算符和赋值运算符是从右至左的

11、运算符优先级大致排序为:()、. >单目>算数>位移>比较>逻辑>三元>赋值

标识符:

1、标识符规则:可由26个大小写英文字母、数字、下划线、$组成,且数字不能开头,不能使用关键字和保留字

2、标识符规范:包名aaa.bbb.ccc、类接口名XxxYyyZzz、变量方法名xxxYyyZzz、常量名XXX_YYY

进制转换:

1、二进制数据,以0B或0b开头

2、八进制数据,以0开头

3、十六进制数据,以0X或0x开头,a~f不区分大小写

4、十进制转其他进制规律:
假设为A进制,则整数除A、取余、倒排;小数乘A、取整、正排
注意:小数部分转换,乘A,取.前整数数字,然后继续将.后数字乘A,直到结果为0为止

5、其他进制转十进制规律:按位乘权相加

6、二进制转八进制,自右向左,3位变1位,左不够补0;二进制转十六进制,自右向左,4位变1位,左不够补0

7、计算机中二进制有符号数有3种表示方法:原码、反码、补码。
真值:符号+数值位。(真值不是原码)
如+42(十进制真值)=+0101010(二进制真值);-42=-0101010,写全符号位分别为00101010,10101010
X的原码记为[X]原 ,X的反码记为[X]反 ,X的补码记为[X]补
正数(X≥0)的原码、补码、反码相同
负数的反码=符号位不变,数值位按位取反
负数的补码=反码+1(快速方法:原码基础上从后往前,找到第一个1及后面的位不变,前面的除符号位,剩余全部取反)
注意:已知补码,可以反求原码:[X]原=[[X]补]补
Java中没有无符号数,全部都是有符号数,计算机在运算时,都是以补码方式来运算的

8、位运算操作
&按位与(全1为1,有0为0)
|按位或(全0为0,有1为1)
^按位异或(相同为0,不同为1)
~按位取反(1变0,0变1)
>>算数右移(右移n位,÷2的n次方)
>>>逻辑右移(无符号右移)低位溢出,高位补0

分支:

没有需要总结的点

switch:

1、分支可用于区间判断,switch可用于等值判断

2、switch可以进行穿透执行,看break出现位置

3、switch内的表达式返回数据类型必须是byte、short、int、char、enum、String

4、表达式数据类型应和case后常量保持一致,或可以互相转换

5、case后必须为常量或常量表达式,而不能是变量

6、default可以出现在switch的任何位置

7、default和break都不是必须出现的

for:

1、for循环四要素:循环变量初值、循环条件、循环变量迭代、循环语句

2、for中定义的循环变量只在该for大括号内有效,当for结束后,指定变量被释放

3、for(;😉{}也是合法的,若没有其他限制条件,则为死循环,两个分号不可以省略
打印空心金字塔案例:

while:

1、while、do-while循环四要素和for一致,只不过位置不一样

2、do-while先执行再判断,所以无论如何,也会执行一遍循环语句

break:

常用于switch和循环结构中,用语跳出当前结构

continue和return:

1、continue只能用于循环结构,用语跳过本次循环

2、return用在主方法,代表从return处直接跳出程序

数组:

1、数组可以存放多个同一类型的数据(基本类型,引用类型均可),数组是引用数据类型

2、索引下标从0开始

3、数组定义1:数据类型 数组名[] = new 数据类型[大小]; (数据类型[] 数组名也可以,是等价的)

4、数组定义2:数据类型 数组名[] = {元素值,元素值,…};

4、数组使用:数组名[索引下标]

5、数组在默认情况下是引用传递,赋的值是地址

排序与查找:

1、冒泡排序所做的事情:假如有n个数,那么一共进行n-1轮排序(外层循环),而每轮排序都会进行多次相邻比较(内层循环),每多进行一轮排序,每轮排序就会少比较一次。每轮排序都会将该轮最大(最小)的数往后方,当循环完n-1轮后,即可完成排序

2、二分查找所做的事情:假如有一个有序数组,我们假设索引在最中间的数就是我们要查找的数,当索引对应的数与我们要找的数相等,说明我们查找到了,如果不相等,就比较其大小,若大于我们要查找的数,说明在数组左边,反之则在右边,根据情况更新左,右下标索引

二维数组:

1、二维数组定义格式:int[][] arr = new arr[行][列];(int[] arr[]、大括号包大括号也允许)

2、二维数组是一个地址,而在该地址指向的空间,存放的也是若干个一维数组地址,在其下才是真正的数据

3、二维数组列数可以不等(即每个一维数长度小可以不同,可以在创建时动态的new,与C语言不同)

4、杨辉三角程序:

类与对象:

1、对象的创建,建立于类的规定下。如有一个学生类,我们可以将所有学生所具备的共同属性和行为抽象出来,将其在类中规定出来,如姓名,学号,年龄。但具体到每个学生,其属性是不同的,那么就要具体到每一个实例,即对象

2、类是抽象的,概念的;对象是具体的,实际的(类是对象的模板,对象则是类的一个个实例)

3、创建对象格式:类名 对象名 = new 类名();(此处的类就是一个引用数据类型)

方法详解:

1、若方法要求有返回数据类型,必须存在return语句,且返回类型必须与return的值兼容

2、方法若以void定义,可以没有返回值,或者只写return;

3、实参和形参类型要兼容、个数、顺序必须一致

4、Java的值传递,如果传递实参是基本类型,传递的则是基本类型的字面量值的拷贝;如果传递实参是引用类型,那么传递的是实参所引用的对象地址拷贝

递归:

1、递归过深,可能造成栈溢出

2、递归必须有结束条件,且不断逼近,否则就会导致栈溢出

重载:

1、重载:在同一个类下,方法名相同,参数列表不同(与修饰符和返回值无关)

可变参数和作用域:

1、可变参数方法参数列表格式:(数据类型 … 形参名),表示可以接受0~n个指定数据类型的形参,其本质是数组,且一个形参列表只能出现一个可变参数,不可出现多个可变参数

2、局部变量指方法内的变量或形参变量

3、全局变量(属性)指类下直接定义的属性(大括号内不算),作用域是整个类

3、局部变量必须赋值后才能使用,因为没有默认值

4、全局变量(属性)不赋值也可以使用,因为有默认值

5、static方法内不能直接使用非static类型的全局变量(属性)

6、属性伴随着对象创建而创建,销毁而销毁,生命周期长;局部变量随着代码块结束被释放,生命周期短

构造器:

1、构造器是类的一种特殊方法,它的主要作用是完成对新对象的初始化(不是创建对象)

2、构造器名称与类名保持一致、没有返回值部分、创建对象时,系统自动调用完成对象的初始化

3、构造器也可以进行重载

4、若我们没有手动定义构造器,系统会生成一个默认无参构造器(我们看不见)

5、若我们手动定义了构造器,无参构造器就被覆盖了,无法使用,除非我们手动再定义无参构造器

6、对象创建流程分析:加载类信息→在堆中创建对象,分配空间→进行默认初始化→进行显示初始化→进行构造器初始化→将开辟空间的地址赋给栈中的对象变量(引用)

this:

1、this代表当前对象,举一个例子,可以当做“我的”,从不同的对象角度来看,也都是“我的”,当出现this.属性时,就代表我的属性这个意思,谁在调用这个构造器,那么这个this就代表谁

2、this的本质是当前对象的引用地址

3、this可以用来访问本类的属性、方法、构造器(只能在构造器内访问,且要在构造器内第一行语句使用)

4、this可以用来区分当前对象属性和局部变量

IDEA:

没有需要总结的点

包与访问修饰符:

1、包的命名规则:只能包含数字,字母,下划线,小圆点.,不能以数字开头,不能是关键字或保留字

2、包的命名规范:com.公司名.项目名.业务模块名

3、一个类中只能有一个package语句,且必须放在类第一行

4、Java提供4类访问修饰级别,用于控制方法和属性的访问权限
公开级别:public,所有类都可以访问(4个)
保护级别:protected,子类、同类、同包的类可以访问(3个)
默认级别:没有修饰符,同类、同包的类可以访问(2个)
私有级别:private,只有同类才可以访问(1个)
5、只有默认和公开修饰符才可以修饰类

封装与继承:

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

2、封装步骤:将属性私有化、提供一个公共set方法、提供一个公共get方法

3、继承是为了解决代码复用,当多个类存在相同属性和方法时,我们可以抽象出一个父类,然后让所有子类去通过extends继承父类

4、子类继承了父类的所有属性和方法,非私有的属性和方法可以在子类直接访问,私有的属性和方法需要通过父类提供的公共方法访问

5、子类构造器必须调用父类的构造器,完成父类的初始化

6、子类构造器隐藏了super()构造器,默认调用父类无参构造器。若父类有参构造器覆盖了无参构造器,要么去显示定义出父类无参构造器,要么子类构造器去手动调用父类有参构造器

7、super代表父类的引用,用来访问父类的属性、方法、构造器(对比this,但不能访问private修饰的)

方法重写:

1、方法重写就是子类有一个方法和父类的某个方法的名称,返回类型,参数列表完全一致,但是其实现逻辑可能不同

2、子类方法重写不能缩小父类的访问权限

多态:

1、方法和对象具有多种状态,可以做出不同的行为,称为多态

2、方法的重载和重写是多态的体现

3、一个对象的编译类型和运行类型可以不一致

4、编译类型看定义时=号的左边,运行类型看=号的右边

5、编译类型在定义时,就确定了,无法改变,而运行类型是可以改变的

6、对象多态向上转型:用父类引用指向子类对象

7、对象多态向下转型:把父类引用(父类对象不可以)强制转成子类引用(且父类引用原来就是指向该子类类型的对象

8、多态的前提是:两个类存在继承关系

9、instanceof用于判断对象的运行类型是否为XX类型或XX类型的子类型

10、动态绑定机制:当调用对象方法时,该方法会和该对象的运行类型绑定

equals和 = =:

1、==是一个比较运算符,既可比较基本数据类型,又可比较引用数据类型。比较基本数据类型时,比较其值是否相等;比较引用数据类型时,比较其地址是否相等(是否为同一个对象)

2、equals()是Object类下的方法,只能判断引用类型,在源码中也是使用了= =比较运算符,默认比较其地址是否相等。但子类往往重写此方法,用于判断其内容是否相等。比如String和Integer类

hashCode/toString/finalize:

1、hashCode()是Object类下的方法,返回对象的哈希值(一个整数值),提高具有哈希结构容器的效率

2、引用相同的两个对象,则哈希值一定是一样的;引用不同的两个对象,则哈希值是不一样的

3、toString()是Object类下的方法,默认返回格式:全类名+@+哈希值的十六进制

4、finalize()是Object类下的方法,当对象被回收时(根据GC算法判定),系统自动调用该对象的finalize()

断点调试:

没有需要总结的点

类变量与类方法:

1、类(静态)变量与类(静态)方法需要用static修饰,表示被该类的所有对象共享

2、类变量在JDK8前,我们认为存储在方法区内JDK8及后,我们认为其存储在堆中的Class对象里

3、访问格式:类名.类变量名(更推荐)、对象名.类变量名

4、类变量在类加载时就初始化了,其生命周期是随类加载开始,随着类消亡而销毁

5、类方法不能调用成员方法和成员变量,对象方法可以调用类变量和类方法

6、类方法中不允许使用this和super关键字

main方法:

1、Java虚拟机需要调用类的main方法,所以main方法访问权限必须是public

2、Java虚拟机在执行main方法时不必创建对象,所以必须以static修饰为类方法

代码块:

1、代码块只能以static修饰,所以可分为静态代码块和普通代码块

2、普通代码块可以当成对构造器的补充,可以做重复的初始化操作

3、代码块的调用顺序先于构造器

4、静态代码块随着类加载被执行,只会执行一次;普通代码块随着对象创建被执行,创建一次对象,就会执行一次

5、存在继承关系下的初始化顺序:

①父类(静态变量、静态语句块)

②子类(静态变量、静态语句块)

③父类(实例变量、普通语句块)

④父类(构造函数)

⑤子类(实例变量、普通语句块)

⑥子类(构造函数)

单例模式和final:

1、单例模式要点:构造器私有化、创建静态对象、向外暴露一个静态方法返回静态对象

2、饿汉模式:声明静态对象时就创建对象;懒汉模式:调用方法时再创建对象(饿汉与懒汉模式的区别是创建对象的时机不同)

3、final可以修饰属性,方法,类,当我们不希望属性被修改,方法被重写,类被继承,可使用final关键字进行修饰

4、final一般搭配static使用,底层编译做了优化,使用final staic的属性,并不会导致类被加载

5、包装类和String是final类

抽象类:

1、当抽象出的父类,其方法无法确定具体实现时,可以将其设计为抽象类,将方法设计成抽象方法(没有方法体),由其子类继承抽象类,完成方法的具体实现

2、抽象类不能被实例化

3、抽象类可以没有抽象方法

4、一个类继承了抽象类,则必须实现抽象类的所有抽象方法,除非它自己也是抽象类

5、抽象方法不能用private、final、static修饰

6、抽象类的使用场景在设计模式中更多

接口:

1、USB插槽就是现实生活中的接口,厂家规定了统一的尺寸,使各个设备都可以接入;而程序中的接口,规定了需要实现类去实现的方法

2、JDK7前,接口中方法都没有方法体,即都是抽象方法,JDK8后接口可以有静态、默认方法,也就是说接口中方法也可以有具体实现

3、接口中的抽象方法可以省略abstract关键字

4、接口不能被实例化

5、一个普通类实现了接口,则必须实现接口的所有抽象方法

6、抽象类实现接口,可以不用实现接口内的抽象方法

7、一个类可以同时实现多个接口

8、接口内的属性默认都是public static final类型的

9、接口不能继承类,但可以继承多个接口

10、子类继承父类,就拥有了父类功能,并进行重写,按如果子类需要扩展其他功能,就可以通过实现接口来扩展

11、接口和继承解决的问题不同。继承的价值在于复用性和可维护;接口的价值在于设计和规范。继承是is-a的关系(麻雀是鸟),而接口是like-a的关系(麻雀可以像飞机一样飞)

12、接口的多态:接口引用可以指向其实现类的对象

13、接口的父类,同样会被其实现类实现

内部类:

1、一个类的内部又嵌套了另外一个类结构,被嵌套的类称为内部类

2、类的五大成员:属性、方法、构造器、代码块、内部类

3、内部类的分类:若在成员位置(成员内部类、静态内部类)、若在方法内(局部内部类,匿名内部类 )

4、局部内部类可以访问外部类的私有属性,不能添加访问修饰符,但可以被final修饰,其作用域仅仅在定义它的方法或代码块内

5、外部其他类不能访问局部内部类

6、我们在使用匿名内部类时不会定义类名,JVM底层为其分配一个类名,通常是外部类名+$+数字,随后立即创建其对象

7、匿名内部类既是一个类的定义,同时本身又是一个对象

8、匿名内部类要想访问外部类重名属性,可以使用外部类名.this.属性名

9、成员内部类和静态内部类都可以任意添加访问修饰符

10、外部其他类访问成员内部类的语法:外部类名.内部类名 变量名 = new 外部类名().内部类名();

11、静态内部类不能访问外部类非静态成员

枚举:

1、枚举类是一组常量的集合,是一种特殊的类,里面只包含一组有限特定的对象

2、如果使用enum替代class,可直接以常量名(实参列表)进行定义,多个常量之间以,间隔,最后一个常量;结束

3、枚举对象必须放在枚举类首行

4、枚举类内常量默认是public static final的

5、枚举类默认会继承Enum类,而且是一个final类

注解:

1、注解也被称为元数据,用于修饰包、类、方法、属性、构造器、局部变量等数据信息,在JavaEE中使用更为广泛

2、@Target指定注解可以在哪些地方使用,是一种元注解

3、@Override表示指定重写父类的方法

4、@Deprecated表示某个程序元素已经过时

5、@SuppressWarnings表示抑制编译器警告

异常:

1、如果程序员觉得一段代码可能出现问题/异常,可以使用try-catch异常机制来解决,这样出现了异常,程序也可以继续执行

2、执行过程中发生的异常可分为两大类,分别是:Error和Exception,都继承于Throwable

3、Error是JVM无法解决的严重问题,会导致程序崩溃。如栈溢出和OOM

4、Exception是编程错误或外在因素导致的一般性错误,可以使用try-catch进行处理。如空指针异常、数学运算异常、数字格式不正确异常、类型转换异常、类找不到异常、数组越界异常等等

5、Exception又可分为两大类,分别是运行时异常(RuntimeException)和编译时异常

6、运行时异常编译器检测不出来,不要求强制处理,而编译时异常必须处理

7、异常处理方式有两大类,分别是try-catch-finally(代码中捕获后自行处理)和throws(将异常向上抛出,交给调用者,其最顶级的调用者为JVM)

try|catch|throws:

1、在try-catch代码中,若出现异常,try块异常后的代码不会执行,而会进入catch块中,然后向下时顺序执行;若没有出现异常,则不会进入catch块中

2、如果我们希望不管是否出现异常,都执行某段代码(释放资源,关闭连接),我们可以使用try-catch-finally,finally块内代码最终一定会执行

3、可以有多个catch块存在,捕获不同异常,要求子类写在前面,父类放在后面

4、try-finally语法也是允许的,相当于没有捕获异常,若出现异常则会使程序崩溃,主要是想最后执行finally里的代码

5、一般对于编译时异常,我们直接使用try-catch解决;一般对于运行时异常,默认使用的就是throws解决

6、子类重写父类方法时,对抛出异常的规定:子类所抛出异常类型要么和父类一致,要么为父类抛出异常的子类

7、自定义异常需要继承异常类,若我们继承Exception异常,那么其类型为编译时异常;若我们继承RuntimeException,那么其类型为运行时异常

8、throw和throws区别:throw是扔出一个具体的异常对象,用在方法体内;throws是异常处理的一种方式,将异常向上抛出,用在方法声明上

八大包装类:

1、包装类:针对八种基本数据类型相应的引用类型,具有类的特点,可以调用方法。其中Boolean和Character不继承于Number类

装箱和拆箱:

1、装箱:基本数据类型转成包装类型;拆箱:包装类型转成基本数据类型

2、JDK5前只能手动装箱和拆箱(通过new 包装类和调用对应方法),JDK5后就可以自动装箱和拆箱了(底层还是用的valueOf方法)

3、面试题:Object o1 = true?new Integer(1):new Double(2.0); 打印o1是输出1.0,三元运算符将本行当做一个整体,后面有Double包装类,会进行类型提升

4、Integer使用==比较需要注意的点:

当Integer变量和int变量比较时,只要其数值相等,结果一定为true。因为包装类和基本数据类型int比较时会自动拆包,所以是两个int类型在比较

非new生成的Integer变量和new生成的Integer对象比较时,结果一定为false,因为前者变量指向常量池,后者指向堆中对象,地址一定不同。

当两个new生成的Integer变量比较,结果一定为false,因为两个创建的对象地址不可能相同

当两个非new生成的Integer对象比较,其值在-128~127之间,结果为true,反之为false。因为Integer底层源码调用valueOf(),有缓存机制IntegerCache,在这个数值范围内的数值会被缓存,下次使用若数值相同,会直接取相同地址

String:

1、字符串的字符使用Unicode字符编码,一个字符占2个字节

2、String是不可变字符串(地址不可变,内容可变),String被final修饰,其底层的value[]数组也被final修饰

3、String创建对象方式一:String s = “twh”;(先从常量池查看是否有"twh",如果有,直接指向,如果没有则在常量池创建,然后s指向常量池中空间地址

4、String创建对象方式二:String s = new String(“twh”);(先在堆中创建空间,其value数组去指向常量池数据,如果有"twh",则直接指向,如果没有则在常量池创建,然后s指向堆中空间地址

5、String的intern()方法最终返回的是其常量池的地址

6、String s = “hello”+“world”;编译器会做一个优化,发现hello和world若单独创建没有引用,所以只在常量池创建了helloworld一个对象

7、String s = a+b;底层是在堆中创建了StringBuilder对象,并将a和b进行了append,最后toString后,在常量池创建了一个新对象,其value[]指向常量池对象,s指向堆中对象

8、字符串常量相加,指向对象在池中;字符串变量相加,指向对象在堆中

9、String每次更新都需要重写开辟空间

10、String的format方法:对比C语言的打印规则

11、字符串各种方法如果需要起始和结束索引,基本上是前闭后开规则,即[9,11),包含起始索引,不包含结束索引

StringBuffer和StringBuilder:

1、StringBuffer和StringBuilder的父类都是AbstractStringBuilder,虽然StringBuffer和StringBuilder都被final修饰,但其父类的value数组不被final修饰,不用每次都更新地址,且不会产生新的对象

2、StringBuffer和StringBuilder的主要区别在于:StringBuilder不是线程安全的,各种方法上没有synchronized关键字。若在单线程环境下,建议使用StringBuilder,效率更高

3、String、StringBuffer、StringBuilder的比较:

  • String:不可变字符串,效率低,但复用率高
  • StringBuffer:可变字符串,效率高,线程安全
  • StringBuilder:可变字符串,效率最高,线程不安全

其他工具类:

1、Arrays可以使用sort进行定制排序,传入需要排序数组和实现了Comparator接口的匿名内部类两个参数

2、若要处理非常大的数据(超出long表示范围),可以使用BigInteger;若要处理精度要求非常高的数据,可以使用BigDecimal

3、第一代日期类:Date(SimpleDateFormat是其专属的格式化类)

4、第二代日期类:Calendar(构造器私有,通过静态方法获得对象,没有指定的格式化类,自己定义)

5、第三代日期类(DateTimeFormatter是其专属的格式化类):LocalDate(只有日期字段)、LocalTime(只有时间字段)、LocalDateTime(日期和时间字段都有)

集合:

1、集合大体系分为两类,分别是单列集合(List、Set)和双列集合(Map)

2、集合体系图:

3、Iterator:一个集合的迭代器

List|ArrayList|Vector:

1、List下集合是有序的,按加入集合顺序排序,且元素允许重复

2、List集合遍历的三种方式:迭代器、普通for、增强for

3、ArrayList底层是一个Object类型的elementDate数组,如果创建ArrayList对象使用的是无参构造器,初始elementDate大小为0,第一次添加默认扩容elementDate为10,如需再次扩容,则扩容当前elementDate大小的1.5倍进行扩容(原先大小+原先大小右移1位大小,即1+0.5)

4、Vector与ArrayList相比,是线程安全的;且扩容按2倍进行扩容

5、LinkedList底层实现了双向链表和双端队列,底层源码维护了first首节点和last尾节点,每个节点(Node对象)又有preve、next、item三个属性,所以LinkedList元素的添加和删除不是通过数组完成的

6、一般情况下,单线程改查使用ArrayList,增删使用LinkedList

HashSet 与 LinkedHashSet:

1、Set集合和List遍历基本一致,可以使用迭代器和增强for**,但不能使用普通for(Set没有提供get方法,不能通过索引获取)**进行遍历

2、Set集合添加的顺序和取出的顺序不一致,但取出后位置就固定了,且元素不能重复,也可以添加null元素

3、HashSet其底层本质是一个HashMap(数据结构为:数组+单向链表+红黑树)

4、HashSet扩容机制只需要看HashMap源码即可。第一次添加时,Node[] table默认容量扩容到16,加载因子(loadFactor)是0.75,当table容量(不是看数组大小,是看数组内全部的Node节点大小)到达阈值threshold(当前容量×加载因子的大小),table就会扩容到当前容量×2,以此类推

5、HashSet底层调用HashMap的put()得到的hash值并不单纯是通过hashCode()获得的,实际上还与一个右移16位的值进行了异或运算,防止碰撞

6、HashSet调用add()的底层逻辑:当在添加一个元素时,会先得到其对应的hash值,并转成索引值,找到其对应在数组table中应该存放的位置,若没有元素,直接添加;若有元素,则调用equals方法(可由程序员重写,如果没有重写去比较对象,就是单纯调用的Object的equals方法),如果当前链表有一个元素相同,放弃添加;如果对链表元素依次比较后都不相同,则添加到该索引位置链表的最后。从Java8开始,如果一条链表的元素≥8,数组table大小≥64,就会将链表转换成红黑树(TreeNode)。若数组大小没有≥64时,仍然是采用数组扩容机制,不会进行树化

7、当我们使用hash数据结构的集合时,重写equals的同时也要重写hashCode,因为其底层在添加数据时,是根据hashCode()返回的值,去进行计算hash值的,如果不进行重写,不同对象的hash值必然不一样,那么即便我们业务种的equals方法是根据对象属性判断是否相同的,在第一开始的hash值比较也无法过关

8、LinkedHashSet是HashSet的子类,底层是一个LinkedHashMap(数据结构为:数组+双向链表)

9、LinkedHashSet本质也是无序的,不允许元素重复,但由于双向链表的存在,会按插入元素首尾进行相连,这使得插入元素看起来是以插入顺序保存的(实际上还是根据hash值决定存储位置)

10、LinkedHashSet底层数组是Node[]类型,但数组内元素是Entry类型的(Entry和Node都是静态内部类,父子类关系)

HashMap 与 HashTable:

1、Map集合不在Collection体系下,用于保存具有映射关系的数据:Key-Value(键值对,双列数据)

2、Map的键值对可以是任何引用类型,会封装到HashMap$Node中去

3、Map的键不允许重复,若出现键重复,会以新的value替换旧的value

4、为了方便Map遍历,提供了entrySet(),其定义的类型是Map.Entry,但实际存放的还是HashMap$Node对象

5、Map的遍历:
①通过**keySet()取出包含所有key的Set集合,再通过增强for或迭代器对其遍历
②通过
values()取出包含所有value的Collection集合,再通过增强for或迭代器对其遍历
③通过
entrySet()**取出包含所有键值对的Entry集合,再通过增强for或迭代器对其遍历

6、HashMap的put方法分析:同上面HashSet的add()方法分析

7、Hashtable其键值对都不允许为null,且Hashtable是线程安全的

8、Hashtable底层的数据结构是Entry[],其初始容量是11,加载因子是0.75,当其容量≥阈值时,调用rehash()进行扩容(按照当前容量×2+1

Properties:

1、Properties类继承于Hashtable类并且实现了Map接口,是一种属性文件,以键值对格式保存,key和value都不允许为null,一般通过I/O流进行操作,通过Properties对象的load()加载文件,setProperty()方法保存

TreeSet和TreeMap:

1、TreeSet的底层是一个TreeMap

2、当我们使用无参构造器时,两者仍然是无序的;若我们想按照一些规则排序,可以传入一个Comparator匿名内部类

Collections:

没有需要总结的点

泛型:

1、泛型可以对加入到集合中的数据类型进行约束,同时也解决了遍历时需要强制转换的问题

2、泛型又称参数化类型,是JDK5后出现的新特性,可以有效避免ClassCastException异常

3、泛型只能是引用数据类型

4、在给泛型具体类型后,也可以传入该类型的子类型

5、集合不使用泛型,默认其泛型是Object类型

6、自定义泛型:我们可以自己在类或接口上定义泛型,其中属性和方法同样可以使用泛型

7、使用泛型的数组不可以直接初始化

8、静态static不可以和泛型同时出现(类加载时,对象还未创建,我们无法确定泛型类型,就无法开辟空间)

9、泛型方法和方法使用了类声明的泛型不一样,泛型方法会在返回值类型前加泛型符号

10、泛型不具备继承性

11、 <? extends T>表示规定泛型的上限

12、:<? super T>表示规定泛型的下限

很抱歉,我无法回答关于2023年的问题,因为我无法提供未来的信息。但是,如果你对Java基础知识点有兴趣,我可以为你提供一些相关的信息。Java基础知识点包括数据类型、变量、运算符、控制流程、数组、字符串、面向对象编程等。你可以参考Java基础教程系列,其中包含了Java基础知识点、Java8新特性、Java集合、Java多线程等内容,可以帮助你轻松学习Java编程。\[1\]另外,Javac是Java编译器程序的一部分,负责将Java源代码编译成字节码文件,也就是class文件,供Java虚拟机(JVM)执行。\[2\]Java分为三个体系,分别是Java SE(标准版)、Java EE(企业版)和Java ME(微型版),每个体系都有不同的用途和应用领域。\[3\]希望这些信息对你有帮助! #### 引用[.reference_title] - *1* [java基础知识点](https://blog.csdn.net/guorui_java/article/details/120317300)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Java基础知识整理,推荐收藏!](https://blog.csdn.net/weixin_42599558/article/details/114148399)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值