一文让你深入了解JavaSE的知识点

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱
ʕ̯•͡˔•̯᷅ʔ大家好,我是xiaoxie.希望你看完之后,有不足之处请多多谅解,让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客
本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如需转载还请通知˶⍤⃝˶
个人主页:xiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客
系列专栏:xiaoxie的JAVA系列专栏——CSDN博客●’ᴗ’σσணღ*
我的目标:”团团等我💪( ◡̀_◡́ ҂)” 

( ⸝⸝⸝›ᴥ‹⸝⸝⸝ )欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​+关注(互三必回)!

 本文将会系统的详细的介绍关于JAVASE的所有内容,里面也会掺杂一些面试题,希望能够对同样在学习的Java的你带来帮助

目录

一.初始Java 

1.准备工作

首先我们在学习Java时需要提前准备好编译器,博主建议大家使用idea,最主要的原因就是它功能强大,很合适新手使用,但在使用之前我们需要提前准备好配置环境,在这里博主推荐博主之前总结好的教程初识JAVA-CSDN博客

2.Java的口号

Write once, Run anywhere”,一次编译到处运行

3.JAVA的基础知识

JDK:JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境(JVM+Java系统类库)和JAVA工具。

JRE: 

Java运行环境(Java Runtime Environment,简称JRE)是一个软件,由太阳微系统所研发,JRE可以让计算机系统运行Java应用程序(Java Application)。

JRE的内部有一个Java虚拟机(Java Virtual Machine,JVM)以及一些标准的类别函数库(Class Library)。

JVM:

JVM即Java虚拟机,是一种抽象计算机,它有一个指令集,在运行时操作各种内存区域。

而它们三者的关系为下图

2.一些注意事项

1.注意:在一个源文件中只能有一个public修饰的类,而且源文件名字必须与public修饰的类名字相同。
2.一个文件里我们可以写多个类,一个类就对应着一个字节码文件
3.main函数有且只有一个

4.标识符

1.标识符中可以包含:字母、数字以及下划线和$符号等等。

2.命名规则

标识符不可以使用数字,关键字开头,并且大小写也要严格区分。

5.关键字

1.关键字有哪些

JAVA关键字

abstract

assert

boolean

break

byte

case

catch

char

class

const

continue

default

do

double

else

enum

extends

final

finally

float

for

goto

if

implements

import

instanceof

int

interface

long

native

new

package

private

protected

public

return

strictfp

short

static

super

switch

synchronized

this

throw

throws

transient

try

void

volatile

while

2.关键字的含义

关键字

含义

abstract

表明类或者成员方法具有抽象属性

assert

断言,用来进行程序调试

boolean

基本数据类型之一,声明布尔类型的关键字

break

提前跳出一个块

byte

基本数据类型之一,字节类型

case

用在switch语句之中,表示其中的一个分支

catch

用在异常处理中,用来捕捉异常

char

基本数据类型之一,字符类型

class

声明一个类

const

保留关键字,没有具体含义

continue

回到一个块的开始处

default

默认,例如,用在switch语句中,表明一个默认的分支。Java8 中也作用于声明接口函数的默认实现

do

用在do-while循环结构中

double

基本数据类型之一,双精度浮点数类型

else

用在条件语句中,表明当条件不成立时的分支

enum

枚举

extends

表明一个类型是另一个类型的子类型。对于类,可以是另一个类或者抽象类;对于接口,可以是另一个接口

final

用来说明最终属性,表明一个类不能派生出子类,或者成员方法不能被覆盖,或者成员域的值不能被改变,用来定义常量

finally

用于处理异常情况,用来声明一个基本肯定会被执行到的语句块

float

基本数据类型之一,单精度浮点数类型

for

一种循环结构的引导词

goto

保留关键字,没有具体含义

if

条件语句的引导词

implements

表明一个类实现了给定的接口

import

表明要访问指定的类或包

instanceof

用来测试一个对象是否是指定类型的实例对象

int

基本数据类型之一,整数类型

interface

接口

long

基本数据类型之一,长整数类型

native

用来声明一个方法是由与计算机相关的语言(如C/C++/FORTRAN语言)实现的

new

用来创建新实例对象

package

private

一种访问控制方式:私用模式

protected

一种访问控制方式:保护模式

public

一种访问控制方式:共用模式

return

从成员方法中返回数据

short

基本数据类型之一,短整数类型

static

表明具有静态属性

strictfp

用来声明FP_strict(单精度或双精度浮点数)表达式遵循IEEE 754算术规范

super

表明当前对象的父类型的引用或者父类型的构造方法

switch

分支语句结构的引导词

synchronized

表明一段代码需要同步执行

this

指向当前实例对象的引用

throw

抛出一个异常

throws

声明在当前定义的成员方法中所有需要抛出的异常

transient

声明不用序列化的成员域

try

尝试一个可能抛出异常的程序块

void

声明当前成员方法没有返回值

volatile

表明两个或者多个变量必须同步地发生变化

while

用在循环结构中

3.关键字一律用小写字母标识,按其用途划分为如下几组。

(1)用于数据类型

用于数据类型的关键字有 boolean、byte、char、 double、 float、int、long、new、short、void、instanceof。

(2)用于语句

用于语句的关键字有break、case、 catch、 continue、 default 、do、 else、 for、 if、return、switch、try、 while、 finally、 throw、this、 super。

(3)用于修饰用于修饰的关键字

abstract、final、native、private、 protected、public、static、synchronized、transient、 volatile。

(4)用于方法、类、接口、包和异常。用于方法、类、接口、包和异常的关键字

class、 extends、 implements、interface、 package、import、throws。还有些关键字,如 future、 generic、 operator、 outer、rest、var等都是Java保留的没有意义的关键字。

[4]另外Java还有3个保留字

goto、const、null。它们不是关键字,而是文字。包含Java定义的值。和关键字一样,它们也不可以作为标识符使用。

4.说明

以上就是Java中的一些关键字,需要注意的是,这些关键字不需要刻意的去背诵它们,在之后的学习之中我们都会使用到他们,随着学习的深入我相信大家都会记住它们并且灵活的使用它们

二.数据类型与变量

1.八大基本数据类型

1.int
1.定义

使用最广泛的整数类型,占4个字节

2.包装类型

int的包装类型为Integer

3.取值范围

int的取值范围为 -2^31—(2^31)-1

2.byte
1.定义

用于处理文件和网络传输等字节级别的数据,占1个字节

2.包装类型

byte的包装类型为Byte

3.取值范围

byte的取值范围为 -128—127

3.short
1.定义

可以用于节约内存空间的需求,占2个字节

2.包装类型

short的包装类型为Short

3.取值范围

byte的取值范围为 -2^15—-(2^15)-1

4.long
1.定义

用于处理需要较大值的整数计算,占8个字节

2.包装类型

long的包装类型为Long

3.取值范围

long的取值范围为 -2^63–(2^63)-1

5.float
1.定义

用于科学计算和需要高精度计算的场景,占4个字节

2.包装类型

float的包装类型为Float

3.取值范围

float的取值范围为 -2^31–(2^31)-1

6.double
1.定义

使用最广泛的浮点数类型,占8个字节

2.包装类型

double的包装类型为Double

3.取值范围

double的取值范围为 -2^63–(2^63)-1

7.char
1.定义

可以表示任何字符,占2个字节

2.包装类型

char的包装类型为Charzcter

3.取值范围

char的取值范围为 -2^15–(2^15)-1

8.boolean
1.定义

是一种只能取两个值(true或false)的数据类型,它主要用于条件判断和布尔运算

2.包装类型

boolean的包装类型为Boolean

3.取值范围

boolean的取值范围为只能为true或者是falase

2.基本数据类型之间的赋值和运算

1.例子
  1. int a=10;

  2. byte b=15;

  3. b=a;

像上图,要把int类型的a赋值给byte类型的b,编译器会报错,不能把数据类型大的赋值给数据类型小的,如果是 a=b;那就可以。

2.强制类型转换

假如你想强行把a赋值给b,可以通过强制类型转换,但一般不建议用,因为可能会造成数据泄露

  1. int a=10;

  2. byte b=15;

  3. b=(byte)a;

3.整形提升
  1. int a=10;

  2. byte b=15;

  3. int c=a+b;

小于四个字节的数据会被提升成4个字节再运算

4.字符串类型

1.说明

在Java中并没有字符串的基本数据类型,只有字符串这个类,其中有包含许多库函数方法,十分简便,在这里就先不过多赘述,在之后的知识点中博主会为大家详细介绍

三.运算符和逻辑运算符

1.说明

关于运算符博主就不过的的叙述了,主要需要注意以下几个注意事项以及位运算符,和移位运算符就足够了

2.注意事项

  1. 除零错误:在进行除法运算时,需要注意被除数是否为零,以避免出现除零错误。

  2. 优先级:不同的运算符有不同的优先级,需要根据运算符的优先级来确定运算的顺序。

  3. 溢出:在进行运算时,需要注意运算结果是否会溢出,尤其是在使用整数进行运算时。

3.位运算符

1.什么是位运算符

位操作表示 按二进制位运算. 计算机中都是使用二进制来表示数据的(01构成的序列), 按位运算就是在按照二进制位 的每一位依次进行计算。

2.位运算符有哪些 

位运算符主要有四个: & | ~ ^ ,除 ~ 是一元运算符外,其余都是二元运算符。

3.按位与 &: 如果两个二进制位都是 1, 则结果为 1, 否则结果为 0.

举例:

int a = 10;
int b = 20;
int c = a & b;
c =0;

4.按位或 |: 如果两个二进制位都是 0, 则结果为 0, 否则结果为 1.

举例:

int a = 10;
int b = 20;
int c = a|b;
c = 30  

 5.按位取反 ~: 如果该位为 0 则转为 1, 如果该位为 1 则转为 0

 此运算符位一元运算符,博主就不举例说明,并且在之后的学习中,几乎不怎么使用

6..按位异或 ^: 如果两个数字的二进制位相同, 则结果为 0, 相异则结果为 1.

如果两个数相同,则异或的结果为0

3.位移运算符

1.左移 <<: 最左侧位不要了, 最右侧补 0.

2.右移 >>: 最右侧位不要了, 最左侧补符号位(正数补0, 负数补1)

3.无符号右移 >>>: 最右侧位不要了, 最左侧补 0

4.注意:

1. 左移 1 , 相当于原数字 * 2. 左移 N , 相当于原数字 * 2 N次方. 2. 右移 1 , 相当于原数字 / 2. 右移 N , 相当于原数字 / 2 N次方. 3. 由于计算机计算移位效率高于计算乘除, 当某个代码正好乘除 2 N次方的时候可以用移位运算代替. 4. 移动负数位或者移位位数过大都没有意义.

5.位移运算符和位运算符的妙用

写一个函数返回参数二进制中 1 的个数 比如: 15 0000 1111 4 1
public static void main(String[] args) {
  int a = 15;
  System.out.println(countOnes(num));
}
public static int countOnes(int num) {
 int count = 0;//计数器
  while(num != 0) {
   count += num & 1;// 检查最低位是否为1
   num >>= 1;// 右移一位,继续检查下一位
  }
}

 结果如下:

6.逻辑运算符

注意的地方

在逻辑运算符的表达式后面必须是布尔表达式,以及注意逻辑短路的问题

四.方法

1.什么方法

方法就是一个代码片段. 类似于 C 语言中的函数。方法存在的意义(不要背, 重在体会): 1. 是能够模块化的组织代码(当代码规模比较复杂的时候). 2. 做到代码被重复使用, 一份代码可以在多个位置使用. 3. 让代码更好理解更简单. 4. 直接调用现有方法开发, 不必重复造轮子.

2.实参和形参的关系

Java中方法的形参就相当于sum函数中的自变量n,用来接收sum函数在调用时传递的值的。形参的名字可以随意 取,对方法都没有任何影响,形参只是方法在定义时需要借助的一个变量,用来保存方法在调用时传递过来的值Java中,实参的值永远都是拷贝到形参中,形参和实参本质是两个实体,如果想要和c语言一样传的地址,就需要传引用类型参数,例如数组等等

3.递归

关于递归的知识点可以参考博主之前的博客一种艺术般的问题解决办法—–递归-CSDN博客在这里就不过多的赘述了,需要注意的一点是,要想熟练的使用递归还需要大家在平常的学习中多使用多感悟

五.数组

1.一维数组

数组(Array)是有序的元素序列。 [1]  若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按有序的形式组织起来的一种形式。 [1]  这些有序排列的同类数据元素的集合称为数组。数组是用于储存多个相同类型数据的集合

1.下标

数组的下标是从0开始,使用下标可以访问数组里的元素

2.表示形式

和c/c++:int arry[]不同的是 Java的表示方式如上图。注意中括号中不可以写上任何数字

3.Java中使用导Arays包

和c/c++ 不同的是使用IDEAJava可以使用导Arrays包的方法简化很多关于数组中的一些常规操作现在博主就为大家总结以下几个常用的方法

1.遍历数组
import java.util.Arrays;//导Arrays包时我们要先导入java.util.Arrays类,以便在代码中使用该类提供的方法和功能

public class Study {

public static void main(String[] args) {

int[] arry = {1,5,9,6,7,9};

System.out.println(Arrays.toString(arry));

}

}

输出结果如下

只需要Array.toString()就可以做到遍历数组的作用

2.排序数组
import java.util.Arrays;//导Arrays包时我们要先导入java.util.Arrays类,以便在代码中使用该类提供的方法和功能

public class Study {

public static void main(String[] args) {

int[] arry = {1,5,10,6,7,9};

Arrays.sort(arry);

System.out.println(Arrays.toString(arry));

}

输出结果如下

只需要Array.sort()就可以做到排序数组的作用

3.指定的值填充数组的所有元素
import java.util.Arrays;//导Arrays包时我们要先导入java.util.Arrays类,以便在代码中使用该类提供的方法和功能

public class Study {

public static void main(String[] args) {

int[] arry = {1,5,10,6,7,9};

Arrays.fill(arry,1);

System.out.println(Arrays.toString(arry));

}

}

输出结果如下

Arrays.fill()的作用是用指定的值填充数组的所有元素。它接受四个参数:数组,要填充的元素,起始索引和结束索引。起始索引是要填充的起始位置,结束索引是要填充的结束位置(不包括结束位置)。如果不提供起始索引和结束索引,则默认填充整个数组。

如果我们需要填充到指定位置可以如下图

import java.util.Arrays;//导Arrays包时我们要先导入java.util.Arrays类,以便在代码中使用该类提供的方法和功能

public class Study {

public static void main(String[] args) {

int[] arry = {1,5,10,6,7,9};

Arrays.fill(arry,2,5,11);//参数分别为数组名,起始位置,终点位置,填充的元素

System.out.println(Arrays.toString(arry));

}

}

输出结果如下

需要注意的一点是:起始位置到终点位置的下标是左闭右开

4.二分查找法

这里也有博主之前整理的二分查找的模板二分查找之红蓝二分查找-CSDN博客

比如我们经常使用的二分查找法也可以通过Arrays类里的方法快速实现

import java.util.Arrays;//导Arrays包时我们要先导入java.util.Arrays类,以便在代码中使用该类提供的方法和功能

public class Study {

public static void main(String[] args) {

int[] arry = {1,2,3,4,5,6,7,8,9};

int k = 7;

int ret = Arrays.binarySearch(arry,k);

System.out.println(ret);

}

}

输出结果如下

5.复制指定的数组
import java.util.Arrays;//导Arrays包时我们要先导入java.util.Arrays类,以便在代码中使用该类提供的方法和功能

public class Study {

public static void main(String[] args) {

int[] arry1 = {1,2,3,4,5,6,7,8,9};

int[] arry2 = Arrays.copyOf(arry1,9);//参数为指定的数组名和数组长度

System.out.println("arry1 ="+Arrays.toString(arry1));

System.out.println("arry2 ="+Arrays.toString(arry2));

}

}

输出结果如下

当然我们也可以指定输出数组的长度,可以复制不同长度的新数组,注意:如果指定的长度大于要复制的对象的数组长度,多出来的元素将会被赋初始值即“0”

如图:

mport java.util.Arrays;//导Arrays包时我们要先导入java.util.Arrays类,以便在代码中使用该类提供的方法和功能

public class Study {

public static void main(String[] args) {

int[] arry1 = {1,2,3,4,5,6,7,8,9};

int[] arry2 = Arrays.copyOf(arry1,13);//参数为指定的数组名和数组长度

System.out.println("arry1 ="+Arrays.toString(arry1));

System.out.println("arry2 ="+Arrays.toString(arry2));

}

}

输出结果如下

6.说明

以上五个就是博主总结的一些常用的使用Arryas类的一些书写代码格式以及一些注意事项

2.二维数组

Java中的二维数组是由多个一维数组组成的数组。它可以被认为是一个表格,其中的每个元素都有两个索引,一个用于指定行号,另一个用于指定列号。他的一些注意事项和一维数组差不多除了

  1. 数组长度:二维数组的长度是指行数,可以使用数组名.length来获取二维数组的行数。要获取每一行的列数,可以使用数组名[行索引].length

  2. 不规则二维数组:Java中的二维数组可以是不规则的,即每一行的列数可以不同。在声明和初始化不规则二维数组时,需要为每一行指定具体的列数。

  3. 声明和初始化:要声明一个二维数组,需要指定数组的行数和列数

  4. 别的博主就不过多的赘述了

六.面向对象三巨头

ava是一门纯面向对象的语言(Object Oriented Program,简称OOP),面向对象是一种编程范式,它将程序的组织方式从过程化的思维方式转变为以对象为中心的思维方式。在面向对象编程中,程序被组织成一组相互协作的对象,每个对象都有自己的状态和行为,并且可以通过消息传递来进行交互。面向对象的编程语言提供了类和对象的概念,通过定义类来创建对象,并通过对象之间的交互来实现程序的功能,Java面向对象有三大巨头——封装,继承,多态 。下文博主将一一介绍它们的语法以及优点等等。

一.封装

1.什么是封装

封装是面向对象编程中的一个重要概念,指的是将抽象出来的数据和对数据的操作封装在一起,形成一个类(或对象),使其只能通过类(或对象)提供的接口来访问和操作数据,同时隐藏了数据的实现细节,从而达到保护数据的安全和完整性的目的。通过封装,程序员可以将复杂的系统简化并提高代码的可维护性和可扩展性。

2.为什么要封装

封装的目的是保护数据的安全和完整性,同时隐藏数据的实现细节,提高代码的可维护性和可扩展性,具体有以下几个方面的好处:

  1. 保护数据的安全和完整性:封装可以将数据隐藏起来,使得外部代码无法直接访问和修改数据,从而防止数据被意外修改或篡改,提高数据的安全性和可靠性。

  2. 隐藏实现细节:封装可以隐藏数据的实现细节,将复杂的实现逻辑封装到类的内部,对外部代码来说,只需要关心调用类的接口即可,不必关心类的内部实现,降低了代码的耦合度,提高了代码的可维护性和可读性。

  3. 提高代码的可维护性和可扩展性:封装可以将数据和操作进行分离,使得修改数据的实现细节并不会影响对外部接口的调用方式,从而提高了代码的可维护性和可扩展性,方便系统的后续维护和升级。

3.该如何实现封装

Java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,更符合人类对事物的认知,而访问权限用来控制方法或者字段能否直接在类外使用。Java中提供了四种访问限定符:

访问限定符
NO范围privatedefault(默认)protectedpublic
1同一个包中的同一类☑️☑️☑️☑️
2同一个包中的不同类☑️☑️☑️
3不同包中的子类☑️☑️
4不同包中的非子类☑️

说明:访问限定符不仅可以限制成员属性的访问权限也可以限制类的访问权限;一般成员变量由private 所修饰 成员方法由 public所修饰;default :表示的是没有写访问限定符就默认为default所修饰

4.实例举例

  1. public class Employee {
    
    private String name; // 将属性进行封装
    
    private String department; // 将属性进行封装
    
    private int age; // 将属性进行封装
    
    
    public String getName() {
    
    return name; // 只暴露出了获取属性的接口
    
    }
    
    
    public void setDepartment(String department) {
    
    this.department = department; // 只暴露出了设置属性的接口
    
    }
    
    
    public void increaseAge() {
    
    age++; // 只暴露出了对属性进行修改的接口
    
    }
    
    }

在这个例子中,将员工的姓名、部门和年龄进行了封装,只在外部暴露了获取姓名和设置部门、增加年龄的接口,从而保护了属性的安全和完整性,同时隐藏了实现细节。

5.说明

当然以上举得例子只是封装一个小小的优点之一,等和继承与多态结合起来一起使用,你就会发现封装的妙用了

二.继承

1.什么是继承

继承是面向对象编程中的一个概念,它指的是一个类可以派生出新的类,新的类可以继承原来类的属性和方法,同时可以在原有基础上增加自己的属性和方法,从而达到代码复用的目的。继承可以通过子类来扩展或者修改父类的功能,提高代码的可维护性和可复用性。在继承关系中,被继承的类被称为父类或基类,继承的类被称为子类或派生类。

2.为什么要继承呢

首先让我们看一下下面的例子  

class Animal {

public String name;

public int age;

public void eat() {

System.out.println(this.name+"正在吃");

}

}

class Dog {

public String name;

public int age;

public void eat() {

System.out.println(this.name+"正在吃");

}

public void Bark() {

System.out.println(this.name+"汪汪叫");

}

}

class Bird {

public String name;

public int age;

public void eat() {

System.out.println(this.name+"正在吃");

}

public void Bugu() {

System.out.println(this.name+"布谷布谷叫");

}

}

从以上代码可以看出我们设计出的了三个类,相信细心的读者们可以发现这三个类有很多共性的地方,代码有很多的重复使用了,而继承就是为了解决这个问题

3.继承的使用

上述图示中,Dog和Bird都继承了Animal类,其中:Animal类称为父类/基类或超类,Dog和Bird可以称为Animal的子类/派生类,继承之后,子类可以复用父类中成员,子类在实现时只需关心自己新增加的成员即可。
从继承概念中可以看出继承最大的作用就是:实现代码复用,还有就是来实现多态

4.继承的语法

在Java中如果要表示类之间的继承关系,需要借助extends关键字,具体如下

class Animal {

public String name;

public int age;

public void eat() {

System.out.println(this.name+"正在吃");

}

}

class Dog extends Animal {


public void Bark() {

System.out.println(this.name+"汪汪叫");

}

}

class Bird extends Animal {


public void Bugu() {

System.out.println(this.name+"布谷布谷叫");

}

}

5.继承中的一些注意事项

1.Java只能单继承,不可以实现多继承
2.成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找。
3.子类要想访问父类中的成员属性可以使用关键字 super()来访问如下图
class Animal {

public String name = "小黑";

public int age;

public void eat() {

System.out.println(this.name+"正在吃");

}

}

class Dog extends Animal {

public String name = "旺财";

public void Bark() {

System.out.println(this.name+"汪汪叫");

}

public void func() {

System.out.println(super.name);

}


}

public class Main {

public static void main(String[] args) {

Dog dog = new Dog();

dog.func();

}

}

结果如下

4.父子父子,先有父再有子,即:子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法。
class Animal {

public String name;

public int age;


public Animal(String name, int age) {

this.name = name;

this.age = age;

}

public void eat() {

System.out.println(this.name+"正在吃");

}

}

class Dog extends Animal {


public Dog(String name, int age, String sex) {

super(name, age);

this.sex = sex;

}

public String sex;

public void Bark() {

System.out.println(this.name+"汪汪叫");

}

public void func() {

System.out.println(super.name);

}


}

因为:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整 。

注意:
1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构造方法
2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
3. 在子类构造方法中,super(…)调用父类构造时,必须是子类构造函数中第一条语句。
4. super(…)只能在子类构造方法中出现一次,并且不能和this同时出现

5. super和this

super和this是两个关键字,都是用来引用对象或类的,但是它们有不同的作用和用法。

this关键字用于在一个类的方法中引用该类的成员变量、方法或构造函数。通常用于区分成员变量和方法名相同的情况。例如:

public class Person{

private String name;


public Person(String name){

this.name = name;

}


public String getName(){

return this.name;

}

}

在上述代码中,this.name引用了该类的成员变量name,而非方法中的参数name。

super关键字用于在子类中引用父类的成员变量、方法或构造函数。通常用于在子类中重写父类的方法时,调用父类的方法或调用父类的构造函数。例如:

public class Person{

private String name;


public Person(String name){

this.name = name;

}


public String getName(){

return this.name;

}

}

在上述代码中,super(name)调用了父类Animal的构造函数,而super.eat()调用了父类Animal的eat方法。

6.封装在继承中的使用

1.private 即只能在自己类中被访问,父类中private成员变量虽然在子类中不能直接访问,但是也继承到子类中了

2.default 即默认在同一个包内父类的default成员变量子类可以访问

3.protected 即在同一个包或者不同包的父类成员变量被protected修饰的子类可以访问

4.public 即都可以被访问

7.final的使用

在继承中,final关键字通常用于类、方法或属性上,用来表示其不能被子类继承或重写。

  1. 对于类,如果使用了final关键字修饰,则该类不能被其他类继承。

  2. 对于方法,如果使用了final关键字修饰,则该方法不能被子类重写。

  3. 对于属性,如果使用了final关键字修饰,则该属性不能在子类中被重新赋值。

使用final关键字有以下几个好处:

  1. 可以提高程序的安全性,避免子类对父类的重要方法或属性进行更改。

  2. 可以提高程序的性能,因为编译器可以对final修饰的方法或属性进行优化,减少运行时的开销。

  3. 可以使程序的设计更加灵活,因为final关键字可以限制子类的行为,从而保证代码的正确性和稳定性。 

8. 继承和组合

继承和组合是面向对象编程中常用的两种关系。它们的区别如下:

  1. 继承是一种“is-a”(是一个)的关系,即子类是父类的一种具体化,子类可以继承父类的属性和方法。而组合是一种“has-a”(拥有一个)的关系,即一个类拥有另一个类的对象作为自己的属性或成员。

  2. 继承是静态的关系,即子类在编译期已经确定了继承关系,而组合是动态的关系,即一个类可以在运行时动态地组合其他类的对象。

  3. 继承可以方便地实现代码的重用,减少了代码的冗余。但是过多的继承会导致类之间的耦合性增加,影响代码的灵活性。组合能够更灵活地组合各种对象,但是需要更多的代码来处理对象之间的关系。

  4. 继承可以直接访问父类的属性和方法,但是如果父类的实现发生改变,子类也需要相应地做出调整。组合需要通过调用对象的方法来访问其属性和方法,但是更容易适应变化。

三.多态

1.多态发生的前置条件

Java发生多态的条件包括:

  1. 继承:多态是通过父类和子类之间的继承关系实现的。

  2. 重写:子类必须重写父类的方法,才能实现多态。

  3. 向上转型:使用父类的引用指向子类的对象,从而实现多态。

  4. 运行时绑定:多态的方法调用在运行时进行绑定,而不是在编译时确定。这意味着程序在运行时才能确定调用的是哪个类的方法。

2.什么是向上转型呢

从上文中我们可以知道发生多态的条件之一就是发生向上转型,那什么是向上转移呢?

向上转型是指将一个子类对象转换为其父类对象的过程,即子类对象赋值给父类类型的变量。这种转型是安全的,因为子类对象具有父类对象所有的属性和方法,因此可以在父类类型的变量中使用。通常向上转型是多态性的基础之一。

举个例子,如果有一个动物类 Animal,和一个子类狗类 Dog,可以这样转型:

Animal animal = new Dog(); // 向上转型,将子类对象赋值给父类对象

//分解写就是

Dog dog = new Dog();

Animal animal = dog;

在这个例子中,Dog 对象 animal 实际上是一个 Animal 类型的变量,但是它仍然可以调用 Dog 类中定义的方法,因为 Dog 类继续了 Animal 类,所以 Dog 类对象拥有 Animal 类的所有属性和方法。

3.什么是重写

重写(override)是指在子类中实现一个与父类中同名、同参数列表的方法,并且这个方法的访问修饰符不能低于父类中的方法,目的是覆盖父类中的方法实现。在运行时,调用该方法时将优先执行子类中的实现。重写方法可以改变父类中的行为,实现多态性和动态绑定。

class Animal {

public String name;

public int age;

public Animal(String name, int age) {

this.name = name;

this.age = age;

}

/* 4.private*/ /* 1.final*/ /*2.static*/ public void eat() {

System.out.println(this.name+"正在吃....");

}

}

class Dog extends Animal {

public Dog(String name,int age ) {

super(name,age);

}


@Override//重写,建议加上@Override编译器就会检测是否符合重写的语法

public void eat() {

System.out.println(this.name+"正在吃狗粮....");

}

}

class Bird extends Animal {

public Bird(String name, int age) {

super(name, age);

}


@Override//重写

public void eat() {

System.out.println(this.name + "正在吃鸟粮....");

}

}

public class text {

public static void func(Animal animal){

animal.eat();

}

public static void main(String[] args) {

func(new Dog("旺财",2));

func(new Bird("布谷",1));


}

}

4.多态,继承,封装的实现

// Animal 类定义

public class Animal {

private String name;


public Animal(String name) {

this.name = name;

}


public void makeSound() {

System.out.println("动物发出叫声");

}

}


// Dog 类继承 Animal 类

public class Dog extends Animal {

public Dog(String name) {

super(name);

}


@Override

public void makeSound() {

System.out.println("汪汪汪");

}

}


// Cat 类继承 Animal 类

public class Cat extends Animal {

public Cat(String name) {

super(name);

}


@Override

public void makeSound() {

System.out.println("喵喵喵");

}

}


// 测试类

public class Main {

public static void main(String[] args) {

Animal dog = new Dog("旺财");

Animal cat = new Cat("咪咪");


dog.makeSound(); // 输出:汪汪汪

cat.makeSound(); // 输出:喵喵喵

}

}

5.多态的一些注意事项

1.如果加上了方法上了关键字 final 就不可以发生重写

2.如果是被stastic 修饰的方法也不可以发生重写

3.被private修饰的方法也不可以被重写

4.注意被除private修饰的方法,子类的权限范围大于父类的权限范围

5.不要把构造方法中方法重写

6.重写,建议加上@Override编译器就会检测是否符合重写的语法

七.抽象类和接口

1.抽象类的定义

Java中的抽象类是一种特殊的类,它不能被实例化,只能被继承。抽象类用于定义一些通用的属性和方法,但是这些方法并没有具体的实现,需要子类去实现。抽象类的定义使用关键字abstract来修饰,可以包含抽象方法和非抽象方法。

2.抽象类的语法

public abstract class Animal {

//和普通的类一样可以创建成员变量,静态成员变量

public String name;

private int age;

protected String sex;

public static int a;

//和普通的类一样可以创建成员方法,静态成员方法

public void func1() {


}

public static void func2() {


}

//和普通类不一样的是抽象类还可以创建抽象方法

//抽象方法要在方法的前面加上关键字abstract 并且没有具体的实现

public abstract void func3();


}
  • 使用关键字abstract来修饰类,表示这是一个抽象类。
  • 抽象类可以包含成员变量、构造方法、抽象方法和非抽象方法。
  • 抽象方法的声明以及没有方法体。
  • 非抽象方法有具体的实现,可以直接调用。
  • 抽象类不能被实例化,只能被继承。

3.抽象类的注意事项

1.抽象类不能被实例化:抽象类不能被直接实例化,因为它包含未实现的抽象方法。只能被用作其他类的父类,子类必须实现抽象方法才能被实例化。

2.子类必须实现抽象方法:如果一个类继承了一个抽象类,它必须实现抽象类中所有的抽象方法,除非子类也声明自己为抽象类。

3.抽象类可以包含非抽象方法:抽象类中可以包含非抽象方法,这些方法有具体的实现。子类可以直接继承这些非抽象方法,也可以选择性地重写它们。

4.抽象类可以包含成员变量和构造方法:与普通类一样,抽象类可以包含成员变量和构造方法。子类可以通过super关键字调用父类的构造方法。

5.抽象类可以被继承:一个抽象类可以被另一个抽象类继承,子类可以继续定义更多的抽象方法,或者实现所有的抽象方法。

4.对抽象类的看法

抽象类是一种不能被实例化的类,它主要用于定义一些共性的属性和方法,以供其子类继承和实现。抽象类本身并不具备完整的实现,而是通过其子类来完善其方法和属性。因此,抽象类可以被看作是一种模板或者规范,用来约束其子类的行为和结构。

抽象类的存在可以帮助程序员更好地进行代码的组织和设计,通过抽象类可以定义出一些通用的行为和属性,减少了代码的重复性,提高了代码的可维护性和扩展性。同时,抽象类也能够在一定程度上约束了子类的行为,使得程序更加健壮和可靠。

总的来说,抽象类是xiaoxie的JAVA系列专栏——CSDN博客●’ᴗ’σσணღ*编程中非常重要的概念,它能够帮助程序员更好地进行代码的组织和设计,提高代码的复用性和可维护性。因此,对于抽象类的使用,程序员需要深入理解其特性和用法,合理地应用到实际的程序设计中。

二.接口

1.接口的定义

接口是指软件系统中不同组件之间互相传递信息的规范和协定。在面向对象编程中,接口用来定义一个类的行为,是类的一种规范化或规范模式。接口中定义了一些方法,但是并不实现,而是由实现该接口的类去实现。

在具体应用中,接口可以描述两个不同的组件之间的交互方式,包括数据格式、协议、参数、返回值等方面的规范。接口可以帮助不同的系统或组件进行互操作,提高软件的可维护性、可扩展性和灵活性。同时,接口的定义还可以帮助开发人员进行模块化的设计和开发,提高代码的复用和可读性。

2.接口的语法

public interface IFly {

//接口也可以创建成员变量

//不过成员变量 默认的形式为 public static final

//并且需要初始化 因为接口不能实例化对像

String name = " ";

//接口可以创建成员方法

//成员方法被 public abstract 修饰 也可以不写,并且没有方法实现

//实现这个接口的类需要重写接口的这个方法

public void work();

//要写具体的方法实现 需要被 public static 所修饰

public static void work1() {


}

}

其中,InterfaceName是所定义的接口的名称,// 接口成员指的是在接口中定义的方法和属性。在接口中定义的方法和属性不包含函数体和实现细节,只是提供了一个对实现类的约束,即定义了实现类必须实现哪些方法和属性。

3.接口的注意事项

1. 确保接口的命名具有描述性,能够清晰地表达其功能和用途。
2. 接口的方法和属性应该按照功能进行分组和命名,以便于理解和使用。
3. 接口的设计应该尽量简洁和易于理解,避免过度复杂或冗余的设计。
4. 在设计接口时,需要考虑到未来可能的扩展和变化,以便接口能够灵活地适应需求的变化。
5. 接口的文档应该清晰地描述每个方法和属性的作用和用法,以便其他开发人员能够正确地使用接口。
6. 在实现接口时,需要确保按照接口定义的要求进行实现,以确保接口的一致性和可靠性。
7. 接口的版本管理也是一个重要的考虑因素,需要确保接口的变化不会对已有的实现造成影响。
8. 在使用接口时,需要遵循接口的规范和约定,以确保接口的正确使用和调用。

4.父类和接口的区别

1.在Java中子类只能继承一个父类,子类却可以实现多个接口

2.抽象类的成员属性和方法和普通类一样 可以创建成员变量和成员方法,而接口的成员属性是被 public stasic final 和 public abstract 所修饰的

5.对接口的看法

接口是一种非常重要的编程概念,它可以帮助开发人员实现代码的模块化和复用,提高代码的可维护性和可扩展性。

接口提供了一种规范化的方式来定义类之间的交互和通信方式,使得不同的类可以通过实现同一个接口来实现相同的功能。这种方式可以大大减少代码的重复和冗余,同时也可以提高代码的可读性和可理解性。

另外,接口还可以帮助开发人员实现代码的解耦和模块化,使得不同的模块之间可以独立开发和测试,从而提高代码的质量和可靠性。同时,接口的使用也可以促进团队合作和代码复用,使得开发效率得到提高。

总之,作为一种重要的编程概念,接口在软件开发中具有非常重要的作用,它可以帮助开发人员实现代码的复用和模块化,提高代码的可维护性和可扩展性,促进团队合作和开发效率的提高。

三.接口和抽象类的结合运用

接口和抽象类都是面向对象编程中的重要概念,它们可以用于实现多态和封装。在某些情况下,将接口和抽象类结合起来使用可以达到更好的效果。

接口和抽象类的区别在于,接口只能定义方法和常量,而抽象类可以定义具体方法和成员变量。因此,可以使用抽象类来实现接口中的某些方法,然后在子类中重写剩余方法。

例如,假设我们有一个图形接口 Shape,其中定义了一个计算面积的方法 getArea()。我们可以将该接口改为抽象类,并提供一个具体方法 getPerimeter() 来计算周长。这样,子类就可以继承抽象类并只需要实现计算面积的方法。

示例代码如下:

public abstract class Shape {

public double getPerimeter() {

return 0;

}


public abstract double getArea();

}


public class Circle extends Shape {

private double radius;


public Circle(double radius) {

this.radius = radius;

}


@Override

public double getArea() {

return Math.PI * radius * radius;

}


@Override

public double getPerimeter() {

return 2 * Math.PI * radius;

}

}


public class Rectangle extends Shape {

private double length;

private double width;


public Rectangle(double length, double width) {

this.length = length;

this.width = width;

}


@Override

public double getArea() {

return length * width;

}


@Override

public double getPerimeter() {

return 2 * (length + width);

}

}

在上面的示例中,我们将 Shape 接口改为抽象类,并添加了一个具体方法 getPerimeter()。子类 Circle 和 Rectangle 继承自 Shape,并实现了 getArea() 方法和重写了 getPerimeter() 方法。

通过这种方式,我们可以在抽象类中实现一些通用的方法,同时还能保留接口的灵活性。这种结合运用可以使代码更加简洁和易于扩展。

八.String类

String类是Java中非常重要的一个类,它代表字符串。String类是Java中唯一不用new关键字就可以创建对象的类。在Java中,字符串是使用Unicode字符编码表示的。String类有许多方法可以用来操作字符串,例如连接字符串、截取字符串、查找字符串等等。在Java中,字符串是不可变的,这意味着一旦创建了一个字符串,它就不能被修改。如果需要修改字符串,需要创建一个新的字符串对象。字符串具有很高的使用频率,也是Java中非常重要的数据类型之一。

1.说明

字符串类的相关知识很重要,在面试题或者是笔试题里出现的频率很高,所以需要我们熟练的掌握它。

2.String的构造方法

  String s = "hello";
  String s1 = new String("hello");
  char[] arr = {'h','e','l','l','o'};
  String s2 = new String(arr);

3.Sting类的常用方法

方法功能
char charAt(int index) 返回index位置上字符,如果index为负数或者越界,抛出 IndexOutOfBoundsException异常
int indexOf(int ch) 返回ch第一次出现的位置,没有返回-1
int lastIndexOf(int ch)从后往前找,返回ch第一次出现的位置,没有返回-1
String replaceAll(String regex, String replacement) 替换所有的指定内容
String replaceFirst(String regex, String replacement) 替换指定内容
String[] split(String regex, int limit)将字符串以指定的格式,拆分为limit
String[] split(String regex)将字符串全部拆分
String substring(int beginIndex)从指定索引截取到结尾
String substring(int beginIndex, int endIndex)截取部分内容
String trim()去掉字符串中的左右空格,保留中间空格
String toUpperCase() 字符串转大写
String toLowerCase()字符串转小写

以上就是字符串常用的库函数了,但需要注意的是String是一种不可变对象. 字符串中的内容是不可改变。字符串不可被修改。 

 九.异常

ava异常是指在程序运行过程中出现的错误或异常情况,如空指针异常、数组越界异常等。Java异常处理机制可以使程序在出现异常时不会立即崩溃,而是能够通过异常处理机制来捕获异常并进行处理,从而提高程序的健壮性和可靠性。

Java异常处理机制主要包括以下几个方面:

  1. 异常类的继承关系:Java中所有异常类都继承自Throwable类,其中又分为Error和Exception两个子类,其中Error表示程序无法处理的错误,Exception表示程序可以处理的异常。

  2. 异常处理语句:Java中提供了try-catch-finally语句来处理异常,其中try块中放置可能出现异常的代码,catch块中捕获异常并进行处理,finally块中放置无论是否出现异常都需要执行的代码。

  3. 抛出异常:当程序出现异常时,可以通过throw语句手动抛出异常,并在catch块中进行处理。

  4. 自定义异常:Java中允许自定义异常类,可以根据业务需求来定义自己的异常类,并在程序中使用。

  5. 异常链:Java中的异常可以形成异常链,即一个异常引发另一个异常,可以通过getCause()方法获取异常链中的前一个异常。

总之,Java异常处理机制是保证程序健壮性和可靠性的重要机制之一,掌握好异常处理机制可以帮助程序员更好地处理异常情况,提高程序的稳定性和可维护性

十.关于JavaSE阶段的一些需要注意的点

1.【面试题】JDKJREJVM之间的关系?

Java Development Kit (JDK): JDK 是 Java 开发工具包,是整个 Java 平台的核心组成部分。它包含了用于开发 Java 应用程序所需的软件开发工具,包括:

  • Java Runtime Environment (JRE): JRE 是 Java 运行环境,它是运行 Java 应用程序所必需的组件。它包含了:
    • Java Virtual Machine (JVM): JVM 是 Java 虚拟机,它是实现 Java 语言跨平台特性的关键部分。JVM 负责解释和执行字节码(.class 文件),并为 Java 程序提供了一个独立于具体操作系统和硬件平台的运行环境。

总的来说即:JDK包含JRE,而JRE又包含JVM如果你需要编写和编译 Java 代码,你需要安装 JDK;如果你只需要运行 Java 程序,则只需要安装 JRE 即可。而所有的 Java 程序都需要在 JVM 上运行,这就是所谓的“一次编写,到处运行”(Write Once, Run Anywhere, WORA)的特性。 

2.浅拷贝和深拷贝的区别

 

浅拷贝和深拷贝是两种不同的复制对象的方法,它们的主要区别在于是否创建了原始对象中所引用的对象的新副本。以下是它们之间的主要差异:

浅拷贝

  1. 定义:浅拷贝是指重新分配一块内存,创建一个新的对象,但这个新对象中的元素是原对象中各个子对象的引用。
  2. 行为:当对可变类型的子对象进行操作时,修改会影响到原对象,因为它们共享同一份数据。
  3. 示例
    • 对于列表(list)来说,浅拷贝会创建一个新列表,但是其中的元素仍然是原来列表中元素的引用。
    • 对于字典(dict)来说,浅拷贝会创建一个新字典,但是其中的键值对仍然是原来字典中键值对的引用。

深拷贝

  1. 定义:深拷贝是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联。
  2. 行为:即使对可变类型的子对象进行操作,也不会影响到原对象,因为它们各自拥有独立的数据副本。
  3. 示例
    • 对于列表(list)来说,深拷贝会创建一个新列表,并且其中的元素也都是原始元素的完整副本。
    • 对于字典(dict)来说,深拷贝会创建一个新字典,并且其中的键值对也是原始键值对的完整副本。

 3.重载和重写的区别

重载(Overloading)和重写(Overriding)是面向对象编程中的两个重要概念,它们都与方法的定义和使用有关。下面是两者的区别:

1. 定义不同

  • 重载:在同一类中,允许存在多个同名的方法,但这些方法的参数列表必须不同(即参数的数量、类型或顺序至少有一个不相同)。这样,编译器可以根据调用时提供的参数类型和数量来决定具体执行哪个方法。
  • 重写:在子类中重新实现父类的方法,且方法名称、返回类型和参数列表必须与被覆盖的方法完全一致。这意味着当子类对象调用该方法时,会执行子类中定义的代码而不是父类中的代码。

2. 范围不同

  • 重载:仅在一个类内部发生。
  • 重写:发生在继承关系中,涉及父类和子类之间的关系。

3. 多态性不同

  • 重载:属于静态多态,也称为编译时多态。在编译阶段就已经确定了要调用哪个方法。
  • 重写:属于动态多态,也称为运行时多态。只有在程序运行时才会根据实际的对象类型确定调用哪个方法。

4. 参数不同

  • 重载:要求参数列表不同,可以有不同的参数个数、类型或者顺序。
  • 重写:不能改变参数列表,必须保持与父类中被覆盖方法的参数列表完全一致。

5. 返回值类型

  • 重载:返回值类型可以不同,也可以相同。
  • 重写:返回值类型必须与被覆盖的方法一致,或者为其子类型。

6. 修饰符

  • 重载:对方法的访问修饰符没有特定的要求。
  • 重写:要求重写方法的访问修饰符大于等于被重写的父类方法。

7. 目的不同

  • 重载:为了解决同一功能的不同实现方式,通过不同的参数列表来区分。
  • 重写:为了在子类中提供一种不同于父类的行为,通常是为了扩展或修改父类的功能。

总结起来,重载是在同一个类内提供多种实现方式以适应不同的参数类型,而重写则是在继承体系中使得子类能够替换父类的某些行为,从而实现多态性。

4.this 和 super 的区别

this 关键字

  1. 作用this关键字用于引用当前类的对象实例。它可以用来调用当前对象的方法或访问当前对象的成员变量。
  2. 使用场合
    • 在非静态方法中(包括构造函数),可以使用this来区分局部变量与成员变量。
    • 在构造器中,可以用this调用另一个重载的构造器。
  3. 限制:不能在类的静态方法、静态代码块或声明为静态的变量中使用this关键字。

super 关键字

  1. 作用super关键字用于引用父类对象实例。它可以用来调用父类的方法或者访问父类的成员变量。
  2. 使用场合
    • 在子类中覆盖了父类的方法时,可以通过super关键字调用父类的方法实现。
    • 在子类的构造器中,通过super调用父类的构造器初始化父类的成员变量。
  3. 限制:同this一样,不能在类的静态方法、静态代码块或声明为静态的变量中使用super关键字。

总结起来,this关键字是用来引用当前类的对象实例,而super关键字则是用来引用父类的对象实例。两者都可以用于访问和操作对象的属性和方法,但是分别对应的是当前类和父类。

5.继承和接口的区别

继承

  1. 定义:继承是指一个类(子类)从另一个类(父类)中继承属性和方法的过程。
  2. 语法:在Java中使用extends关键字来表示继承关系。
  3. 特点
    • 单继承:一个类只能直接继承一个父类(不考虑多层继承时的间接父类)。
    • 多级继承:一个类可以间接地继承多个类。
    • 父类的私有成员变量和方法不能被子类访问或覆盖。
  4. 作用:通过继承,子类可以直接获得父类的所有非私有的属性和方法,无需重新编写相同的代码。

接口

  1. 定义:接口是一种契约,它定义了一组行为规范。实现接口的类必须提供接口所要求的功能。
  2. 语法:在Java中使用interface关键字来声明接口。
  3. 特点
    • 接口没有构造器,不能实例化。
    • 接口中所有方法默认为抽象的,并且不允许包含任何实现。
    • 一个类可以实现多个接口。
  4. 作用:接口提供了统一的行为标准,使得不同类型的对象能够共享相同的行为方式。

区别总结

  • 继承关注的是“是什么”的关系,即子类是一个特殊的父类;而接口关注的是“能做什么”的能力,即实现了接口的类具有某种功能。
  • 子类继承自父类后,自动拥有父类所有的非私有属性和方法;实现接口的类则需要手动提供接口中所定义的方法的实现。
  • 类与类之间的继承关系是单向的,而类与接口的关系则是多对一或多对多的。
  • 类只能单一继承,但可以实现多个接口。
  • 在设计上,通常推荐优先使用组合、委托和接口而不是继承,因为继承容易导致耦合度过高,不利于系统的维护和扩展。

6.StringStringBufferStringBuilder的区别  

  1. 不可变性

    • String:是不可变的。一旦创建了一个String对象,就不能更改其内容。每次对String进行修改都会创建一个新的String对象。
    • StringBuffer 和 StringBuilder:这两个类的对象可以被多次修改。
  2. 线程安全性

    • String:由于它的不可变性,因此它是线程安全的。
    • StringBuffer:是线程安全的,在多线程环境下使用时不需要额外同步。
    • StringBuilder:是非线程安全的,它在单线程环境下比StringBuffer更快,因为它不需要执行同步操作。
  3. 性能

    • String:由于每次修改都需要创建新的对象,所以频繁修改字符串时可能会导致大量内存分配和垃圾回收,影响性能。
    • StringBuffer 和 StringBuilder:它们内部维护一个字符数组,可以通过动态扩展来适应字符串的变化,所以在频繁修改字符串时效率更高。
  4. 应用场景

    • String:适合于那些不会改变的字符串常量,或者字符串操作不频繁的情况。
    • StringBuffer:适用于多线程环境下的字符串操作,比如在一个服务器应用程序中处理用户请求。
    • StringBuilder:适用于单线程环境下的字符串操作,特别是当需要频繁修改字符串且不需要考虑线程安全的时候。

总结起来,当你需要处理不变的字符串或只读字符串时,应使用String;如果你需要频繁地修改字符串,并且是在多线程环境中,应使用StringBuffer;如果你在单线程环境中并且希望提高字符串操作的速度,则应使用StringBuilder。

十一.结语

以上就是博主这一个多月学习JAVASE的所有的内容了,希望你能够对你有所帮助,感谢阅读,祝你一天愉快

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
扎眼的阳光的头像扎眼的阳光普通用户
上一篇 2023年12月1日
下一篇 2023年12月1日

相关推荐