Java面试基础

java创建对象的方式有哪些?

1、使用new关键字 (最常见的方式)

2、使用Class.forName() 配合newInstance():反射机制创建对象

3、使用clone()方法:克隆一个对象

4、使用对象序列化和反序列化:通过读取字节数据恢复为对象

5、使用Constructor.newInstance():反射中的eConstructor创建对象

final有哪些用法?

1、修饰变量:变量成为常量,初始化后不能被修改

2、修饰方法:防范不能被子类覆盖

3、修饰类:类不能被继承

static都有哪些用法?

1、修饰变量:变量变成类的静态变量、所有实例共享

2、修饰方法:方法可以不通过对象而直接通过类来调用

3、静态初始化块:用于初始化类的静态变量,只执行一次

4、静态内部类:不需要外部类的对象就可以创建的内部类

有没有可能两个不相等的对象有相同的hashcode?

存在,两个不相等的对象可以有相同的hashcode。这种情况称为哈希碰撞(Hash Cillision)。又要哈希码的值域(通常是int类型的范围)有限,而实际对象的数量可能远远超出这个范围,理论上不可能为每个不同的对象分配一个唯一的哈希码。因此不同对象产生相同的哈希码是有可能的

深拷贝和浅拷贝的而区别是什么?

浅拷贝:只复制对象以及其基本数据类型的值,对象内的引用类型指向同一地址(共享引用类型)

深拷贝:复制对象以及其内部所有层级的对象,完全独立,无共享引用

3*0.1 == 0.3 返回值是什么?

false

这是因为浮点数的精度问题,计算机在处理浮点数的时候可能不会得到完全精准的结果

a=a+b 与a+=b 有什么区别么?

1、类型转换差异

··a=a+b 需要a和b类型完全匹配,活能够通过类型提升自动匹配

··a+=b 内部包含隐式的类型转换,即如果a和b类型不匹配,b的类型会被自动提升或转换为a的类型,然后再进行赋值。

2、效率和简洁性

··在编写和阅读代码的时候,a+=b更简洁

··在某些编译器优化过程中,a+=b可能会略微高效,尽管这种差异通常非常小,对性能影响不大

try catch finally, try 里有return,finally还执行么?

执行,try的块里有return的时候 finally依旧会执行,在设计之初finally的设计就是确保无论try’块内无论发生什么(包括返回和抛出异常),都能执行清理或者释放资源等操作

说说Excption与Error的区别

Exception 和Error都是Throwable类的子类,它们构成了java异常处理的两大分支

1、Throwable

根类,标识所有可以作为异常被抛出的类

2、Exception

··表示程序中出现的异常情况,可以蓓捕获并由程序处理。

··分为两大类

······Cheched Exception :编译时异常,必须被显式捕获或通过方法签名声明

······Unchecked Exception(RuntimeException):运行时异常,不需要显式捕获或生命

3、Error

··表示严重的错误,通常是程序无法处理的,如虚拟机错误和系统错误

··例如,OutOfMemoryError,StackOverFlowError等

常见的运行时异常有哪些

常见的运行时异常(RuntimeException的子类)

包括:

1、NullPointerException:当尝试使用null对象引用执行操作的时候抛出(空指针异常)

2、ArrayIndexOutOfBoundsException : 当尝试访问数组时使用非法索引(负数或超出数组大小)(数组下标越界异常)

3、ArithmeticException:发生异常算数条件 例如除以零。

4、ClassCastException:尝试将对象强制转换为不是实例的类时抛出

5、IllegalArgumentException:向方法传递了一个不合法或不适当的参数

6、IllegaStateException: 在不合法或不适当的时间调用方法

7、NumberFormatException:尝试将字符串转换为数字格式,但字符串不具有适当的格式

8、IndexOutOfBoundsException:某种类型的索引(如数组、字符串或向量)超出范围时候抛出

9、ConcurrentModificationException:在对集合进行迭代时,除了迭代器自身之外的其他方式修改了集合,就会抛出此异常

常见被检查的异常有哪些?

被检查的异常 (Checked Exception)是那些在编译时必须被显式处理(捕获或通过方法签名声明抛出)的异常,他们直接继承自Exception类,但不包括继承自RuntimeException的异常,常见的而被检查异常包括:

1、IOException:输入或输出操作失败或终端时抛出,如读写文件错误

2、FileNotFoundException: 尝试打开文件失败的时候抛出,文件不存在等情况

3、ClassNotFoundException:找不到类定义时抛出

4、SQLException:处理数据库时发生错误时抛出

5、MalFormedURLException:指定了位置协议或格式错误的URL时抛出

6、InterruptedException:线程被另一个线程中断时抛出

7、NoSuchMethodException:请求方法不存在的时候抛出

8、SAXException:处理XML文件错误的时候抛出

9、ParseException:解析日期时间等格式的时候出错抛出异常

常见Error错误有哪些?

1、OutOfMemoryError:JVM没有足够的内存非陪给对象

2、StackOverflowError:栈溢出,通常是由深度递归调用导致

3、NoClassDefFoundError:找不到类定义,可能是由于类路径问题

4、UnsatisfiedLinkError:当java虚拟机不能找到一个本地方法的声明时候抛出

5、NoSuchMethodError:调用不存在的方法

6、ExceptionInInitializerError:静态初始化器抛出异常或无法加载静态初始化块

7、LinkageError:类依赖性问题,如类的不同版本之间的不兼容

8、ThreadDeath:线程被stop()方法杀死时抛出

9、VirtualMachineEroor:JVM发生内部错误或资源不足时的超类

OOM遇到过哪些情况?SOF遇到过哪些情况?

遇到过OutOfMenoryError(OOM)情况

1、堆内存溢出:对象创建过多,GC无法回收,导致堆内存耗尽

2、永久代(元空间)溢出:加载的类信息太多或大量动态生成类,导致永久代(java8后为原空间)内存不足

3、直接内存溢出:通过ByteBuffer.allocateDirect()分类的直接内存过多

4、线程堆栈溢出:应用创建过多线程,每个线程分配的对战太小(-Xss)导致总体占用空间超过可用内存

5、Tomcat内存溢出:Web应用部署过多或单个应用占用内存过大,超出Tomcat分配的内存限制

遇到过的StackOverflowError(SOF)情况

1、深度递归调用:递归调用层次太深,超出了JVM分配给线程对战的容量

2、大龄局部变量:方法中定义了大量局部变量,增加了每个方法帧的大小,导致堆栈快速耗尽

3、无限循环或递归:(死循环)无终止条件的递归或循环,使得方法不断调用自身或其他方法

面试官追问如何解决,通常这些情况需要通过代码优化、合理配置JVM参数,监控和分析堆栈/内存的使用情况来解决

简述线程、程序、进程的基本概念和关系?

···程序:是指令和数据的集合,存储在磁盘上的文件,是静态的代码

····进程:程序一次执行的过程,是系统资源分配的基本单位。它拥有独立的内存空间,包含代码、数据以及执行的上下文

···线程:是进程的执行单元,是CPU调度的基本单位,一个进程可以包含多个线程,他们共享进程的资源但能够并行执行任务

关系:

··程序是静态的代码和数据的集合,不具备运行的能力

··进程是程序运行的实例,提供必要的资源和环境

··线程是进程内部的自行单元,实现程序的并发执行

简而言之程序是死的,进程是程序的活体表现,线程是进程的执行路径。一个程序可以被多个进程加载执行,一个进程可以包含多个线程共同完成任务实现并发

java序列化中如果有些字段不想进行序列化怎么办?

如果不希望某写字段被序列化,可以将这些字段声明为transient。使用transient关键字修饰的字段不会被序列化到输出流中,因此在反序列化时,这些字段将被忽略,其值会被设置为类型的默认值(例如,数值型为0,对象引用为null)

说说java中的IO流

IO流用于读取和写入数据,主要分为四大类,根据数据类型分为字节流和字符流,根据流向分为输入流和输出流

1、字节流

输入流:InputStream是所有字节输入流的弗雷,用于从源读取字节数据

输出流:OutPutStream是所有字节输出流的父类,用于向目的地写出字节数据

2、字符流

输入流:Reader是所有字符输入流的父类,用于从源读取字符数据

输出流:Writer 是所有字符输出流的父类,用于向目的地写出字符数据

主要流类

··字节流类:FileInputStream、FileOutPutStream、BufferedInputStream、BufferefOutputStream等

··字符流类:fileReader、FileWriter、BufferedReader、BufferedWriter等

特殊流类

··转换流:InputStreamReader和OutPutStreamWriter转换流可以将字节流和字符流进行转换

··序列化流:ObjectInputStream和ObjectOutputStream用于对象的序列化和反序列化

··打印流:PrintStream和PrintWriter提供了打印各种数据值标识的便捷方法

使用场景

··字节流:使用于处理原始文件,如二进制文件、图片、音频视频等。

··字符流:适用于处理文本数据

javaIO和NIO的区别?

区别

1、基本概念

IO:面向流(Stream Oriented),阻塞式IO。每次从流中读取或写入数据时,都会阻塞知道有数据处理

NIO:面向缓冲区(Buffer Oriented),非阻塞式IO。通过通道(Channel)和缓冲区(Buffer)交换数 据,支持非阻塞模式和选择器(Selector)。

2、阻塞和非阻塞

IO:基于流模型实现,进行读写操作会一致阻塞,知道操作完成

NIO:可以设置为非阻塞模式当没有数据刻度或可写的时候,线程可以做其他任务

3、数据处理单位

IO:以流的方式处理数据,直接对流进行读写

NIO:以块(Buffer)的方式进行处理数据,数据首先读取到缓冲区,再从缓冲区进行处理

4、选择器(Selector)

IO:不支持

NIO:支持选择器,一个线程可以管理多哥输入和输出通道

5、使用场景

IO:适用于连接数目比较小且固定的架构,这种方式可以直接对流进行处理

NIO:适用于连接数目多且动态变化的架构,如高性能网络服务器

6、性能和可伸缩性

IO:简单易用,但是在高并发的情况下性能和课伸缩性较差

NIO:在处理并发链接和高速数据读写时具有更高的性能和课伸缩性

java反射的作用和原理

反射的作用

java反射机制允许程序在运行时取得任何类的内部信息,并能操作人与对象的内部属性以及方法,它主要作用包括

1、在运行时判断任意一个对象所属的类

反射机制可以通过对象获得类的信息,如类的方法、字段、构造器等。

2、在运行的时候构造一个类的对象

可以通过反射机制创建对象,而不需要通过new关键字实例化。

3、在运行时判断任意一个类锁具有的成员变量和方法

反射机制可以便利类的字段和方法,甚至调用方法

4、在运行时调用任意一个对象的方法

反射机制允许调用任意对象的方法,而不需要事先知道该对象的类型

5、生成动态代理

利用反射机制生成类或接口的动态代理实现

反射的原理

Java反射时通过类加载机制来实现的,当java程序运行的时,java虚拟机(JVM)会将使用到的类加载到内存中,并为每一个类创建一个Class类型的对象(即类对象),用于存储类的元数据信息(如类的名称、方法信息、字段信息等)。当程序通过反色API(如Class.forName(), obj.getClass(), .class 语法)获取到对应的Class对象后,就可以利用这个对象来访问类的信息和动态操作类或对象

1、类的加载:当程序使用到某个类时,java虚拟机将该类加载到内存中

2、创建Class对象:加载过程中,JVM为每个类创建Class对象,其中包括类的源数据信息

3、使用Class对象:程序可以通过Class对象访问类的元数据,创建实例,访问字段和方法等

说说List、Set、Map三者的区别?

List

··有序集合,按插入顺序存储元素。

··允许重复元素。

··典型实现:ArrayList,LinkedList

Set

··无序集合,不保证存储顺序

··不允许重复的元素

··典型实现 HashSet LinkedHashSet TreeSet

Map

··键值对集合,存储元素为键值对(key-value)

··保证键的唯一性,值可以重复

··不是Collection接口的一部分

··典型实现:HashMap、LinkedHashMap、TreeMap

区别

存储结构:List时序列集合,Set时不重复元素的集合,Map时键值对的映射。

元素唯一性:List允许重复元素,Set不允许重复元素,Map的键不允许重复

存储顺序:List保持元素的插入顺序,Set通常不保证顺序(除LinkedHashSet),Map不保证键值对的顺序(除LinkedHashMap)。

Object有哪些常用方法?大致说一下每个方法的含义

1、public final Class<?> getClass()

返回此对象的运行时的类

2、public int hashCode()

返回对象的哈希码值,用于哈希表

3、public boolean equals(Object obj)

指示其它某个对象是否与此对象“相等”

4、proercted Object clone() Throws CloneNotSupportedException

创建并返回此对象的一个副本

5、public String toString()

返回对象的字符串表示,通常时对象的类名加上其哈希码的无符号十六进制表示

6、public final void notify()

唤醒在此对象监视器上等待的单个线程

7、public final void notifyAll()

唤醒在此对象监视器上等待的所有线程

8、public final void wait(long timeout)throws interruptedException

使当前线程等待知道另一个线程调用此对象的notify()方法或notifyAll()方法,或者超过指定的时间量

9、public final void wait(long timeout,int nanos)throws interruptedException

使当前线程等待知道另一个线程调用此对象的notfy()方法或notifyAll()方法,或者其它某个线程中断当前线程,或者已经过了指定的实际时间

10、protected void finalize()throws Throwable

当垃圾手撕鸡器决定不存在对该对象的更多引用时,由于垃圾收集器调用此方法,用于资源释放等清理操作,一再java9中被标记为过时

获取一个类CLass对象的方式有哪些?

1、使用.Class语法,如String.Class

2、通过对象调用getClass()方法,如"hello".getClass()

3、使用Class.forName()静态方法,如Class.forName(“java.lang.String”)

ArrayList和LinkedList的区别有哪些?

1、内部结构

ArrayList基于动态数组

LinkedList基于双向链表

2、性能

ArrayList优于LinkedList在随机访问数据上

LinkedList优于ArrayList在添加和删除操作上

3、内存占用

ArrayList更紧凑,但是在扩容的时候需要重新分配内存并复制

LinkedList为每个元素使用更多内存(因为节点引用)

ArrayList的特点

1、基于动态数组实现,内部使用可扩容的数组结构,便于索引访问和存储

2、随机访问效率高,提供快速的随机访问性能,通过索引直接访问元素

3、添加、删除成本较高,除了尾部添加之外,插入或者删除元素可能需要移动多个元素,效率低

4、动态扩容,当添加元素草果当前容量的时候,自动扩容,但扩容操作涉及数组复制,可能影响性能

5、不是线程安全的,多线程环境下需要外部同步

为什么有数组还要搞ArrayList?

1、动态扩容:数组大小固定,一旦创建不能改变。ArrayList可以自动扩展和缩减大小,提供了更大的灵活性

2、便捷的操作:ArrayList提供了大量方法来进行元素的插入、删除、遍历等操作,使用起来更加方便。

3、泛型支持:ArrayList支持泛型,可以在编译的时候检查元素类型,提高代码的安全性和可读性

4、集合框架的一部分:ArrayList是Java集合框架的一部分,可以与其它集合类型(如Set、Map)无缝继承,提供了统一的变成接口

说说什么是fail-fast?

Fail-fast是一种错误检测机制,指的是在错做集合(如列表、集合等)时候,如果检测到集合在迭代过程中被结构性修改(例如添加、删除元素),则立即抛出ConcurrentModificationException异常。这种机制旨在快速失败,避免不确定的行为和潜在的错误。Java集合框架中的很多实现(如ArrayList、HashMap)都采用Fail-fast机制。它主要通过在迭代器内部维护一个修改计数器(ModCount)来实现,每次迭代前检查计数器是否有变化,以保证迭代的一致性和安全性

说说HashTable与HashMap的区别

1、线程安全:Hashtable是线程安全的HashMap不是

2、性能:因为线程安全,HashTable性能较HashMap较低

3、空值:HashTable不允许键或值为null,HashMap允许一个键为null和多个值为null

4、遍历:HashTable继承自Dictionary类,HashMap是java Collections Framework的一部分

HashMap中的Key我们可以使用任何类作为Key么?

时刻,可以使用任何类作为HashMap中的key,但是为了确保HashMap正确的存储和检索键值对有两个重要条件需要满足

1、重写equals()方法:确保当两个键对象逻辑上等价时可以返回true;

2、重写HashCode()方法:确保逻辑上等价的键值对象产生相同的哈希码

如果这两个方法没有适当的重写,HashMap可能无法准确的识别键对象,导致数据存取错误

HashMap的长度为什么时2的N次方呢?

HashMap的长度是2的N次方主要是为了优化索引的计算效率。这样设计可以使得索引的计算通过位运算(hash&(length-1))来完成,者比模运算更高效。同时,这种长度能够帮助哈希表中的元素更均匀的分布,减少哈希冲突,提高hashMap的整体性能

HashMap与ConcurrentHashMap的异同

1、相同点

都实现了Map接口,用于存储键值对

内部结构都是用了哈希表

2、不同点

线程安全

HashMap是非线程安全的,适用于单线程环境

ConCurrentHashMap是线程安全的,适用于多线程环境

性能

由于线程安全的实现方式不同ConcurrentHashMap在多线程环境下性能优于使用Collextions.synchronizedMap(new HashMap())包装的HashMap

3、内部实现

HashMap允许一个null键和多个null值

ConcurrentHashMap不允许null键和null值,因为并发区级的时候无法区分返回值null是映射值本身为null还是键不在映射中

4、并发控制

HahsMap 在扩容的时候直接对整个哈希表进行扩容

ConcurrentHashMap使用分段锁(在java8以后是通过分散数组、链表和红黑树的机构,以及CAS操作和Synchronized来保证线程安全),减少锁竞争,提高了效率

红黑树有哪几个特征

红黑树的五个特征

1、每个节点是红色或黑色

2、根节点是黑色

3、所有叶子(NIL节点)都是黑色

4、每个红色节点的两个子节点都是黑色(红色节点不能连续)

5、从任意一个节点到其每个叶子的所有路径都包含相同数目的黑色节点

说说你平常是怎么处理java异常的?

1、明确异常类型:区分检查型异常和运行时异常

2、合理使用try-catch:捕获具体能处理的而一场,避免捕获Exception或Throwable

3、合理的利用finally:确保资源在异常发生的时候也能被正确释放

4、避免空catch块:即使暂时不处理异常,也应该记录或注释说明原因

5、使用throws声明,对于无法立即处理的检查型异常,通过方法签名向上抛出

6、异常链:在捕获异常后抛出新的异常时,保留原始异常信息

7、自定义异常:根据需要合理定义业务异常类提高异常的可识别性

8、避免异常用于控制流程:异常应用于异常情况处理,不应该作为常规控制流程的一部分

JVM 、JDK、JRE之间的关系

JVM(java Virtual Machine):是一个抽象的计算机,提供运行java字节码的环境,使得java程序能够在任何平台上运行不受限制

JRE(java Runtime Environment):包括jvm和运行java程序所需的核心库以及其他组件。他是运行已经开发的Java程序所需要的环境

JDK(java DeveLopment Kit):包括了JRE以及开发java程序所需的编译器、工具和库(比如javac)。JDK适用于开发java应用程序的软件开发工具包

关系:JDK用于开发Java程序,包括JRE来运行编译后的程序,而JRE包含JVM来提供一个平台无关的运行环境,简而言之,JDK>JRE>JVM,其中JDK是包含JRE的,而JRE是包含JVM的

public、protected、default、private的区别?

在java中,public、protected、default(无修饰符)和private关键字用于指定类成员(方法和变量)的访问级别

-public:成员可以被任何其它类访问

-protected:成员可被同一包内的类以及所有子类访问

-default(无修饰符):成员只能被同一包背的类访问

-private:成员只能被其所在类访问

这些修饰符从宽松到严格排序为:public>protected>default>private,他们定义了类成员在不同上下文中的可见性和访问性

多态是什么?如何实现多态?

多态是面向对象百年城中的一个核心概念,指的是统一操作作用于不同的对象时,可以有不同的解释和表现。在Java中,多态可以通过继承(inheritance)和接口interfaces来实现,具体体现为

1、方法重写(Override):子类重写父类中的方法,实现运行时多态

2、接口实现(Implements):类通过实现接口并提供接口方法的具体实现,同样实现运行时多态

3、向上转型(upcasting):子类对象直接复制给父类引用,通过父类引用调用重写方法,实现多态

说说你对Arraylist的了解

ArrayList时Java中一个可以调整大小的数组实现,属于java.util包。它允许存储任意类型的对象(包括null),并且可以动态的增加和减少其容量。arrayList提供了快速的随机访问能力(即按索引访问元素),但在列表中插入或删除元素的速度相对较慢,因为这可能需要移动现在的元素。ArrayList实现了List接口,因此它支持所有的列表操作,如添加、删除、清空列表以及支持迭代器等。由于其内部是通过数组实现的,当元素被添加到ArrayList中而数组容量不足的时候其内部会自动扩容以容纳更多的元素

说说你对LinkedList的了解

LinkedList是java中的一个双向链表实现,属于java.util包。它允许存储任意类型的对象,包括null,与ArrayList相比,LinkedList提供了更高效的元素插入和删除操作,因为这些操作通常只需要改变节点的指针,而不需要移动其他元素。然而LinkedList在随机访问元素的时候性能较低,因为它需要从头或尾开始遍历链表来访问特定索引的元素

LinkedList实现了List接口,因此支持所有列表操作,如添加、删除和遍历元素。此外LinkedList还实现了Deque接口,使其能够被用作双端队列进行元素入队和出队操作。由于其链表的特性,LinkedList在实现栈、队列或双端队列的时候是一个好的选择

说说你对Vector的了解

Vector是java中的一个动态数组实现,属于java.util包。与ArrayList类似,Vector也支持动态扩容,可以根据需要增加和减少容量来存储任意类型的对象。不同之处在于Vector是同步的(Synchronized),这意味着它的线程是安全的,因此在多线程环境中,当多线程环境中,当多个线程同时访问Vector实例的时候,它保证了数据的一致性和完整性

由于其线程安全的特性,Vector的性能可能回避非同步的ArrayList稍低。Vector提供了类似于ArrayList的Api,支持快速随机访问、元素的添加、删除和遍历等操作。然而,在新的java应用中,通常推荐使用Collections.synchronizedList或CopyOnwriteArrayList来获取线程安全的列表而不是直接使用Vector.

谈谈你对Set的了解

Set是java中的一个接口,属于java.util包代表一个不包含重复元素的集合。他是java集合框架(java Collections Framework)的一部分,用于存储一组唯一的元素,不保证元素的顺序,Set接口主要有以下i几个实现:

-HashSet:基于哈希表实现,提供快速的插入查找和删除操作,不保证元素的迭代顺序

-LinkedHashSet:基于哈希表和链表实现,维护元素的插入顺序,性能略低于HashSet

-TreeSet:基于红黑树实现,元素按照自然顺序或自定义比较器排序,提供有序的集合操作

Set接口支持基本操作如添加、删除元素以及判断元素是否已存在。由于Set不允许重复元素,添加已存在的元素会被忽略。Set常用于去除重复数据、集合运算(如并集、交集、差集)等场景

说说你对Map的了解

Map是Java中的一个接口,表示一个键(key)到一个值(value)的映射。他不能包含重复的键,每个键最多只能映射到一个值。这个接口主要用于存储键值对,键和值都可以是任意类型的对象,包括null。Map接口的实现类有多种,包括但不限于:

-HashMap:基于哈希表实现,提供快速的查找、插入和删除操作,不保证映射的顺序

-LinkedHashMap:基于哈希表和链表实现,维护元素的插入顺序或访问顺序

-TreeMap:基于红黑树实现,按照键的自然顺序或者钩爪时提供的Comparator进行排序

-Hashtable:和HashMap类似,但是它是同步的,不允许键或值为null

Map提供的操作包括添加、删除键值对,检查键或值是否存在,以及访问键集、值集或键值对集。他是处理兼职对数据的重要数据结构,广泛应用于需要快速查找数据的场景

Map的遍历方式有哪些

遍历Map的方法主要有以下几种

1、使用KeySet()遍历键集:先获取Map的所有键的集合,然后通过遍历这些键来访问每个键值对的值

2、使用values()遍历值集:直接获取Map中的所有值的集合,遍历这个集合可以访问的所有制,但是无法直接获取对应的键

3、使用entrySet遍历键值对:获取Map中的所有键值对的集合,然后遍历这个集合。每个元素都是Map.Entry对象,可以通过它获取键值对的值

4、使用java8中的forEach方法:利用forEach方法和Lambda表达式直接对兼职对进行操作,更加简洁高效

5、使用迭代器(iterator)遍历:通过keySet()、valus()或entrySet()获取迭代器,然后使用迭代器进行遍历

说说你对HashMap的了解?

HashMap是Java中基于哈希表实现的Map接口的一个类。它存储键值对,并允许使用null值和null键。HashMap不保证映射的顺序,随着时间的推移,这个顺序可能会改变。他不是线程安全的,如果多线程同时访问HashMap且至少有一个线程修改了映射,则必须外部同步。HashMap提供了常数时间的性能(O(1))对于基本操作,如获取和插入元素。假设哈希函数将元素适当地分散在桶中。它通过哈希码为每个键值对分配一个桶来实现快速查找和插入操作

说说你对TreeMap的了解?

TreeMap是java中基于红黑树实现的Map接口的一个类。团出键值对,并且按照键的自然谁徐(或者根据构造TreeMap时提供的eComparator所指定的顺序)对键进行排序,congress保证了元素的有序性。treeMap不允许使用null键(如果使用自然排序),但是允许使用null值。与HashMap相比,TreeMap提供了一致的O(log n)时间性能对于包含n个元素的映射查找、插入、删除操作,因为红黑树是一种自平衡二叉查找树。TreeMap适合于需要按照顺序访问键的场景,如实现范围查找和排序查找

什么是跨平台性?原理是什么?

-跨平台性指的是java程序能够在不同的操作系统上郧西而不需要做任何修改。这种能力基于“编写一次,处处运行”(Write Once,Run Anywhere,WORA)的原则。

-java的跨平台性原理是通过java虚拟机(JVM)实现的,具体来说

1、编译为字节码:java源代码被编译成一种中间形式的字节码(.class文件),而不是直接编译为特定平台的机器码

2、JVM执行字节码:JVM是一个运行在宿主机操作系统上的软件,它能够加载字节码并执行他们。每个平台(如Windows、Linux、macOS)都有适配该平台的JVM实现

3、平台无关性:由于JVM负责字节码与特定平台之间的交互,因此java程序不需要为了在不同平台上运行而做出任何修改

什么是字节码?采用字节码的最大好处是什么?

1、字节码是一种中间代码(intermediate Code)形式,主要用于java和一些其他语言(如Scala)。它介于高级语言带和和机器语言代码之间,是由节哀吧编译器从java源代码编译得到的,存储在.calss文件中.字节码是独立于机器的代码,需要通过java虚拟机(JVM)来解释执行或编译执行(即JIT编译)

2、采用字节码的最大好处就是跨平台性。字节码可以在任何安装了兼容的JVM的平台上运行,实现了“编写一次,处处运行”的目标,这种设计极大的提高了软件的可移植性,开发者无需为了每个目标平台重新编译代码,降低了开发和维护的成本

java和C++的区别

1、内存管理:java具有自动垃圾回收机制,而C++需要手动管理内存

2、平台独立性:java程序编译为平台无关的字节码,通过JVM在不同平台上运行。C++编译为特定平台的机器码,直接由操作系统执行

3、运行环境:java需要在JVM作为运行时环境。C++程序直接在操作系统上运行,无需虚拟机

4、语言特性:C++支持运算符重载、多重继承和指针操作,提供更接近硬件的变成能力。java设计上简化了这些特性,以减少程序复杂性和提高安全性

5、性能:C++通常提供更高的性能,适合系统级开发,如操作系统和游戏引擎。java在跨平台和网络应用中更为流行,牺牲了一定的性能以获取更高的移植性和开发效率

6、错误处理:java使用异常处理机制来处理错误,C++及支持异常处理也支持传统的错误处理代码

7、标准库:java提供了丰富的标准库,尤其是在图形界面和网络编程方面。C++标准库主要集中在容器、算法、和函数对象等

switch是否能作用在byte上?是否能作用在long或者String上?

-byte可以 switch可以作用在byte类型上

-long:不可以

-String 可以 从java7开始 switch可以作用在String类型上

Math.round(11.5)等于多少?Math.round(-11.5)等于多少?

12 -11

float f = 3.4这句代码是否正确

不正确。字面量3.4默认是double类型的,直接赋值给float变量会导致编译错误,应该声明为float类型,方法是在数字后面加上f或F如 float f = 3.4f

short s1 = 1;s1 = s1 + 1;有错么?short s1 = 1;s1+=1;有错么?

-对于short s1 = 1;s1=s1+1 ;有错误,因为 1是int 类型,s1+1的结果也会被提升为int类型,不能直接赋值给short类型的变量s1除非进行强制类型转换

-对于short s1=1;s1 +=1,没有错误,+=操作符会自动处理类型转换的问题,他会将右侧表达式的结果转换为左侧变量的类型,然后再赋值,因此不会有编译错误

java语言采用何种编码方案?有何特点?

java语言采用Unicode编码方案,特点包括:

1、跨平台一致性:确保Java程序在不同平台上字符表示的一致性

2、国际化支持:支持多种语言和字符集,方便构建国际化应用

3、固定长度:在java中,char类型用于表示一个16位的Unicode字符(UTF-16编码)

java有哪些注释

1、单行注释 :使用//、注释从//开始到行末

2、多行注释:使用/* 和*/包围,可以跨越多行

3、文档注释:使用/** 和*/包围,用于生成javaDoc文档

&和&&的区别

-&是位运算符,用于按位与操作;

在布尔逻辑中也可以作为逻辑与操作,但他会对两边的表达式都进行求值

-&&是逻辑与运算符

仅用于不二逻辑中。它具有短路特性,即如果第一个操作数是法拉瑟,则不计算第二个操作数

final有什么用?

final关键字在java中有三种主要用途

1、声明常量:用于变量,表示变量的值一旦被初始化后就不能被改变

2、防止继承:用于类,表示不能被继承

3、防止重写:用于方法,表示方法不能被子类重写

this关键字有哪些用途?

1、引用当前对象:在方法内部,this用来引用当前对象的实例

2、调用其它构造器:在构造器中,this()用来调用同一个类的其他构造器

3、传递当前对象:可以将this作为参数传递给其它方法或构造器

4、解决命名冲突:用this来区分成员变量和局部变量,特别是他们名称相同的时候

super关键字有哪些用途?

1、访问父类的成员:用super来访问父类中被子类覆盖(重写)的方法和变量

2、调用父类的构造器:在子类的构造器中,super()用来调用父类的构造器。如果没有显式调用,java编译器会自动插入对父类无参构造器的调用

3、解决命名冲突:当子类和父类有同名的成员时,可以用supper来引用父类的成员

this与super的区别?

区别

-this引用的是当前对象的实例,用于访问当前类的成员(变量、方法)、调用当前类的其他构造器,或者将当前对象传递给其它方法

-supper引用的是当前对象的父类实例,用于访问父类的成员(变量、方法)和调用父类的构造器,特别是访问被子类覆盖的成员或调用父类的构造器

简而言之,this用于指代当前类的上下文,而super用于指代父类的上下文

static存在的意义是什么?

1、共享:static关键字用于声明类级别的变量和方法,使得他们可以在北邮创建实例的情况下被访问。static变量被类的所有实例共享。

2、工具方法:使用static方法可以创建无需对象实例即可调用的工具方法,例如Math.sqrt(double)

3、内存管理:static变量和方法属于类,而非类的实例,因此他们在内存中只有一份,有助于减少内存的使用

4、初始化代码块:通过static初始化代码块,可以在类被加载的时候执行初始化操作

static的独特之处是什么?

1、属于类:static成员(变量和方法)属于类本身,而非类的实例对象

2、内存共享:所有实例共享同一个static变量,static方法可以再没有类实例的而情况下直接通过类名调用

3、初始化时机:static 变量和static代码块再类加载到jvm的时候仅初始化一次

4、无需实例:可以不创建对象实例而直接使用类名访问static变量

5、全局变量:可以用作跨实例共享的全局变量

6、工具方法:static方法常用作工具或帮助方法,如Math类中的方法

static应用场景有哪些

1、常量定义:使用static final 定义类级别的常量

2、工具/帮助方法:不依赖于对象状态的方法,如数学计算或工具方法,可以声明为static

3、单例模式:使用static变量存储类的单一实例

4、全局状态或资源:共享再所有实例之间的资源或状态,如配置信息

5、静态初始化代码块:用于初始化类级别的资源或执行静态变量的初始化

6、静态内部类:不需要外部类实例就可以创建的内部类,适合作为工具或辅助类

static使用注意事项有哪些?

1、内存管理:static变量存储再静态区,随着类的加载而加载,随着类的消失而消失,过多使用可能增加内存负担

2、线程安全:static变量如果被多个线程访问,需要考虑同步机制避免线程安全问题

3、生命周期:static成员的生命周期长于任何对象实例,他们再程序启动的时候被初始化,程序结束的时候被销毁

4、访问限制:static方法内不能直接访问非静态的成员

5、设计考虑:不应该滥用static,迎丹尽在表示类级别的共享数据或行为的时候使用

6、测试难度:静态方法和静态状态可能增加单元测试的难度,因为他们不易被模拟或重置

break continue renturn 的区别以及作用?

1、break

作用:立即退出最近的循环(for、while、do-while)或者switch语句

区别:只影响一个循环或swutch语句,不会退出方法

2、continue

作用:立即跳过当前迭代,进入下一次循环的迭代

区别:仅用于循环体内,不会影响循环外的代码或退出循环,只是提前结束当前的迭代

3、return

作用:退出当前方法,并可选择返回一个值(对于非void)

区别:return不仅能结束循环还能结束整个方法的执行,并将控制权交回方法被调用的地方。如果方法声明了返

回类型,return后应跟一个返回值

简而言之,break用于完全结束循环或switch语句,contiune用于结束当前迭代进入下一次循环,而return用于结束整个方法的执行

再java中如何跳出当前的多重嵌套循环?

-可以通过使用带标签的break语句来跳出当前的多重嵌套循环

-首先给外层设置一个标签,然后再需要跳出循环的地方使用break语句并指定该标签。示例如下

outerloop;//标签
for(int i = 0;i<10;i++){
    for(int j = 0;i<10;j++){
        if(someCondition){
            break outerLoop;//跳出外层循环
        }
    }    
}

在这个例子中,如果满足someCondition条件,则通过break outerLoop;语句跳出名为outerLoop的外层循环

面向对象的特征有哪些方面?

面向对象变成(OOP)的主要特征包括:

1、封装:隐藏对象的内部细节,质保楼必要的操作接口

2、继承:允许新的类继承现有类的属性和方法。

3、多态性:允许不同类的对象对同一消息做出相应,但表现出不同的行为(例如方法的重载和重写)

4、抽象:将复杂的显示问题抽象成简单的模型,只关注与当前目标相关的部分

什么是多态机制

多态机制是面向对象编程中的一个核心概念,允许不同类的对象对同一消息(方法调用)做出不同的响应。多态主要有两种形式

1、编译时多态(静态方法):通过方法重载实现,同一个类中存在多个同名方法,但参数列表不同

2、运行时多态(动态多态):通过方法重写实现,子类重写父类方法。在程序运行的时候,根据对象的实际类型来调用相应的方法

java中多态的实现方式

Java中多态的实现主要依赖于以下三个机制

1、继承:子类继承父类的方法和属性,提供基础的类层次结构

2、重写(Override):子类可以重写父类中的方法,提供具有相同名称的而参数列表的新实现。运行时多态通过方法重写实现,JVM在运行的时候决定要调用的具体方法

3、向上转型(Upcasting):在多态中,父类引用可以指向子类对象。这使得在运行时,可以通过父类引用调用实际子类的重写方法,而编译器只检查父类引用的方法

说说面向对象编程的五大基本原则

面向对象的五大基本原则,简称为SOLID原则,包括:

1、单一职责原则(Single Responsibility Principle ,SRP):一个类应该只有一个引起它变化的原因。

2、开闭原则(Open/Closed Principle,OCP):软件实体淫荡对扩展开放,对修改封闭

3、里氏替换原则(Liskov Substitution Principle,LSP):子类应该能够替换他们的基类

4、接口隔离原则(Interface Segregation Principle ,ISP):客户端不应该被迫依赖于他们不使用的接口

5、依赖倒置原则(Dependency Inversion Principle,DIP):高层模块不应该依赖低层模块,他们都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象

说说抽象类和接口的异同点

抽象类和接口再java中都用来定义抽象类型,它们有以下的主要异同点:

相同点:

–都不能被实例化

–都可以包含抽象方法,既是没有实现方法。

不同点:

–抽象类

–可以包含具有实现的方法;

–可以包含成员变量;

–一个类只能继承一个抽象类;

–可以有构造方法

–抽象方法可以有任何访问修饰符;

–接口

–java8之前,接口中的方法都是抽象的,不能有实现(java8后,接口可以包含默认和静态方法)

–接口中的变量默认都是public static final的

–一个类可以实现多个接口

–没有构造方法

–接口中的方法默认是public的

抽象类用于表示is-a的关系,用于类的继承;接口更多的用来表示has-a的能力,或特定的行为契约

普通类和抽象类有什么区别?

区别如下

1、实例化:普通类可以被直接实例化,而抽象类不呢个被实例化

2、包含抽象方法:抽象类可以包含抽象方法(即没有具体实现的方法),普通类不能包含抽象方法

3、目的:普通类主要用于创建对象和实现功能,而抽象类主要用于作为其它类的基类,定义共有的抽象方法, 强制子类实现这些方法

4、构造方法:尽管抽象类不能被实例化,他们仍然可以有构造方法,这个构造方法可以被子类通过super关键字调用

5、使用场景:当你有一个包含方法实现的类的时候,使用普通类;当你想要定义一个模板类,其中包含一些方

法声明但是不实现(留给子类实现)时,使用抽象类

抽象类能用final修饰么?

不能,抽象类不能使用final关键字修饰。因为final修饰的类不能被继承,而抽象类的目的是为了被其他类继承并实现其抽象方法。这两个修饰符的目的相互矛盾,所以不能同时使用。

创建一个对象用什么关键字?对象实例与对象引用有何不同?

创建对象使用new关键字。列如,new ClassName()会创建一个ClassName类型的一个对象实例

对象实例与对象引用的区别在于

–对象实例:通过使用new关键字创建的,它在内存中占有实际的空间,保持着对象的状态(属性值)和行为(方法)

–对象引用:是指向对象实例的变量。引用本身并不存储对象实例数据,二十存储了对象实例再内存中的地址。用过引用,我们可以访问和操作对象实例

简而言之,对象实例是具有数据和方法的集合,而对象引用时一个指向那些数据和方法所在内存地址的变量。

成员变量与局部变量有什么区别?

区别在于

1、声明位置:成员变量声明再类中,而局部变量声明再方法内、方法参数或者代码块内;

2、生命周期:成员变量的生命周期与对象的生命周期一致,而局部变量的声明周期随着方法或代码块的执行结束而结束。

3、初始值;成员变量有默认初始值(例如,int的默认值为0,对象引用的默认值为null),局部变量没有默认值,必须先声明、赋值后才能使用

4、访问修饰符:成员变量可以使用访问修饰符(如public,private等),控制其访问级别;局部变量不可以使用访问修饰符

5、作用范围:成员变量的作用范围时整个类内部,局部变量的作用范围限于声明它的方法或代码块内部

再java中定义一个无参的默认构造方法的作用是什么?

主要作用:

1、提供对象实例化的能力:如果一个类中没有显式地定义任何构造方法,Java编译器晖自动提供一个默认地无参构造方法。但是,如果类中定义了至少一个构造方法(无论有参与否),编译器不会提供默认构造方法,因此手动定义一个无参构造方法确保了类可以被实例化,即使类中还有其它带参数地构造方法

2、再子类构造方法中地调用:再继承关系中,子类地构造方法默认会调用父类地无参构造方法,如果父类中没有显示地定义这样的一个构造方法,而且也没有其它构造方法,子类地构造会失败,提供一个无参构造方法可以解决这个问题;

在调用子类构造方法之前先调用父类地无参构造方法地目的时什么?

再调用子类地构造方法之前先调用父类地无参构造方法地目的时为了确保父类地状态被正初始化。这一过程保证了再子类地构造方法执行之前,父类地成员变量和环境已经被设置好,确保继承体系中的对象在使用之前处于一个有效和一致地状态。

类的构造方法地作用是什么?若一个类没有声明构造,程序能正确执行么?

类地构造方法地作用时初始化对象,为对象成员变量设置初始值,并执行任何启动构造对象时必须地步骤。如果一个类没有声明构造方法,程序仍然能正确执行,因为java编译器会自动为这个类提供一个默认地无参构造方法(default constructor),这个构造方法没有参数,体内也没有具体执行语句,这保证了即使没有显示定义构造方法,也能实例化对象

构造方法地特性有哪些?

1、名称和类名相同:构造方法地名称与类名完全一致

2、没有返回值类型:构造方法不定义返回值类型

3、初始化对象:构造方法的而主要作用是初始化新创建的对象

4、自动调用:当通过new关键字创建类的新实例时,构造方法会自动被调用

5、可以重载:一个类可以有多个构造方法,彼此之间通过参数列表的不同区分(这被称为构造方法重载)

6、不可以被static、final、abstract、synchronized修饰:构造方法不能被这些关键字修饰,因为他们与构造方法的目的不兼容

静态变量(也成为类变量)和实例变量有什么区别?

区别在于:

1、存储位置:静态变量存储在类的静态存储区,所有实例共享同一个静态变量;实例变量存储在堆上,每个对象有自己的独立副本

2、访问方式:静态变量可以通过了欸名直接访问,无需创建对象实例;实例变量只能通过对象实例访问;

3、生命周期:静态变量的生命周期从类被加载开始,到类被卸载结束;实例变量的生命周期从对象创建开始,到对象被垃圾回收结束

4、用途:静态变量通常用于类级别的常量或方法(如工具方法)中;实例变量用于存储对象级别的状态信息

静态变量(类变量)和普通变量(实例变量)有什么区别?

1、声明:静态变量使用static关键字声明,普通变量不是用

2、存储:静态变量存储再类的静态存储区,属于类级别,所有实例共享一个静态变量;普通变量存储再堆内存的每个对象实例中,每个对象有自己的一份副本

3、访问:静态变量可以通过类名直接访问,也可以通过对象实例访问(不推荐);普通变量只能通过对象实例访问

4、声明周期:静态变量的生命周期从类被加载到类被卸载;普通变量的生命周期随着对象的创建和垃圾回收

5、用途:静态变量常用于表示类的公共状态或常量;普通变量用于表示对象的属性和状态;

静态方法和实例方法有什么区别?

1、声明:静态方法是用static关键字声明,实例方法不使用

2、调用:静态方法可以通过类名直接调用,不需要创建对象实例;实例方法必须通过对象实例来调用

3、访问变量:静态方法只能直接访问类的静态变量和静态方法;实例方法可以访问类的静态变量、静态方法以及通过对象实例访问非静态变量和方法

4、用途:静态方法通常用于执行不依赖于对象实例的操作;实例方法用于执行与对象实例相关的操作,可以操作和修改对象实例的状态

5、重写:静态方法不能被重写,但是可以被隐藏;实例方法可以被重写

在一个静态方法内调用一个非静态成员为什么是非法的?

在一个静态方法内调用一个非静态成员是非法的,因为静态方法属于类本身,而不依赖于任何特定的对象实例来执行。非静态成员(包括变量和方法)需要依赖于对象的实例,而在静态上下文中没有this实例引用可以指向当前对象,因此无法确定需要操作的具体对象实例。简而言之,静态方法无法确定非静态对象属于那个对象的实例。

什么是方法的返回值?返回值的作用是什么?

方法的返回值是方法完成其操作后提供的输出。

方法执行结束时,可以将一个值传回给调用者。

返回值的数据类型在方法声明时指定,且方法必须返回声明类型的值(特殊情况时void类型,表示方法不返回任何值)

返回值的作用时允许方法将结果床底回给调用者。这使得程序可以利用方法执行的结果进行进一步的操作或决策,增加了程序的模块化和复用性。

例如

一个计算两个数之和的方法会返回这两个数的和,调用者可以使用这个返回值进行其他操作。

内部类是什么?

内部类的定义是在另一类内部的类。

它可以访问外部类的所有成员(包括私有成员),主要用于处理外部类中的某些特定问题,增强封装性。

内部类有哪些类型?

内部类主要有四种类型

1、成员内部类

类似于类的成员变量,可以访问外部类的所有成员

class OuterClass{
    class MemberInnerClass{
        
    }
}

2、静态内部类:

使用static修饰的内部类,不能直接访问外部类的非静态成员

class OuterCLass{
    static class StaticInnerClass{
        
    }
}

3、局部内部类:

在方法或作用域内部定义的类

CLass OuterClass{
    void someMethod(){
        class LocalInnerClass{
            
        }
    }
}

4、匿名内部类

没有类名称,用于创建一次性使用的类实例

new Thread(new Runnable(){
    @Override
    public void run(){
        //code
    }
}).start();

内部类有哪些优缺点

优点

1、封装性:内部类可以直接访问外部类的成员,包括私有成员,提高了封装性

2、逻辑性:如果一个类旨在另一个类的内部使用,将其作为内部类定义可以使用代码组织逻辑性更加强

3、增强可读性和维护性:将内部类放在使用他们的类的内部,可以使代码更加易于理解和维护

4、实现多继承:通过内部类可以实现对多个类的继承,避免了java单继承机制的限制

缺点

1、增加复杂性:内部类增加了代码机构的复杂性,对于初学者来说可能不易理解

2、编辑生成多个.class文件:每个内部类都会编译生成一个单独的.class文件,增加了部署应用的复杂度

3、可能导致内存泄漏:非静态内部类会隐式持有外部类的引用,如果不当使用可能导致内存泄漏的问题

内部类有哪些应用场景

1、封装功能模块:当某个功能只在一个类内部使用的时候,使用内部类可以更好地封装这个功能;

2、实现接口而不暴露给外部:可以创建内部类来实现接口或继承某个类,而不使用外部类地类型发生改变

3、回调函数和事件处理:在图形用户界面(GUI)编程中,匿名内部类常用于事件监听器(listener)和回调函数,使用代码更简洁。

4、迭代器模式:在实现迭代器模式的时候,可以使用内部类来实现Iterator接口隐藏迭代逻辑

5、减少代码冗余:如果多个类有相似地功能,可以通过内部类来共享这部分代码,减少冗余

5、策略模式和工厂模式:在设计模式中,特别是策略模式和工厂模式,使用内部类可以提供更好的封装和数据隐藏

局部内部类和匿名内部类访问局部变量地时候,为什么变量必须要加上final?

局部内部类 和 匿名内部类 访问局部变量地时候,变量必须加上final(在java8及之后版本,即使不显示声明为final,也要求局部变量事实上不被修改,称为”effectively final“)这是因为:

1、声明周期差异:当局部内部类或匿名内部类地对象存在时,方法中地局部变量可能已经退出作用域并销毁。为了使内部类仍然可以访问这些变量,他们地值在创建内部类实例地时候被拷贝到内部类中

2、数据一致性:如果局部变量被允许修改,那么内部类中拷贝地值和原始变量地值可能会不一致。将变量声明为final或确保其为”effectively final“可以避免这种不一致性,确保数据的稳定性和一致性

构造器是否可以被重写?

不能,构造器(constructor)不能被重写(override)。构造器是用于初始化一个新对象的特殊类型的方法,而重写涉及到两个方法间的多态性,这在父类和子类之间的方法中才会发生。不过,构造器可以被重载(overload),即在同一个类中可以有多个构造器,他们的参数列表不同

HashSet如何检查重复?

HashSet检查重复元素主要依赖于元素的HashCode()方法和equals()方法:

1、当向HashSet添加元素的时候,首先调用元素的hashCode()方法计算其哈希码,以此确定元素存储字内部哈希表的那个位置(即哪个桶)

2、如果计算得到的哈希码在哈希表中没有对应的条目,则直接将元素存储在该位置,认为没有重复

3、如果该哈希码对应的位置已经有元素存在(即发生哈希碰撞),则调用元素的equals()方法与改位置上的每一个元素逐一比较。如果equals()方法返回true,则判断为重复元素,不会添加到HashSet中;如果equals()返回false,则将新元素添加到该位置

因此,HashSet检查重复的效率高低直接受到其元素hashCode()方法的实现和equals()方法的实现质量的影响;

两个对象hashCode()相同,则equals()也一定为true么?

不对。两个对象的hasCode()相同,只意味着他们被存在哈希表的同一个桶中,但并不意味着他们通过equals()方法比较的时一定为true. hashCode()下沟通是发生碰撞的情况,需要进一步通过queals()方法来检查两个对象是否真正相等

说说hashCode和equals方法的关系?

hashCode()和equals()方法之间的关系体现在以下两个主要原则上

1、一致性:如果两个对象通过equals()方法比较相等,则这两个对象的hashCode()方法必须返回相同的整数值

2、不一定反向成立:如果两个对象的hashCode()方法返回相同的值,他们通过equals()方法比较不一定相等

这种涉及是为了确保对象可以正确地存储在基于哈希地集合中,如HashSet、HashMap等,保证集合地正确性和性能。

为什么重写equals时必须重写hashCode方法?

重写equals()时必须重写hashCode()方法,以维护hashCode()与equals()方法之间的而一直性约定:如果两个对象相等(即equals()方法返回true),则他们的哈希码(hashCode()方法返回的值)也必须相等。这个约定确保了基于哈希的集合(如HashSet、HashMap)能够正确的处理对象,维护集合的性能和正确性。如果不这样做,相等的对象可能具有不同的哈希码,导致无法在集合操作中正确识别对象,例如,可能会在HashSet中添加重复元素,或在HashMap中找不到键的正确映射。

说说你对hashCode的了解

hashCode()是java中Object类的一个方法,它返回对象的哈希码,即一个整数值。这个方法主要用于优化基于哈希表的集合(如HashMap、HashSet、HashTable)的性能。在这些集合中hashCode()用于确定对象的存储位置(即哈希桶的索引),从而加快搜索、插入和删除操作的速度。每个对象的哈希码是根据对象的内部状态计算出来的,且程序执行期间不应该改变。立项情况下,不同的对象应该有不同的哈希码,但不同的对象产生相同的哈希码的情况也是允许的(哈希冲突)

为什么要有hashCode?

hashCode存在的原因是为了提高基于哈希表的数据结构(如HashSet、HashMap、HashTable)的性能。通过将对象转换成哈希码(一个整数值),hashCode允许快速定位对象应该存储的桶位置,从而实现快速插入、查找和删除操作。立项情况下,不同的对象会产生不同的哈希码,减少哈希冲突,确保数据结构的高效性

对象相等和引用相等有什么不同?

对象的相等通常指的是两个对象的状态或内容相同,这通过重写equals()方法来判断。而引用相等值得是两个引用变量指向内存中的同一个对象地址。简而言之,对象相等关注的是内容是否相等,而引用相等关注的是是否是同一对象

当一个对象被当作阐述传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,呢么这里是值传递还是引用传递?

java中是值传递。当对象作为参数传递给方法的时候,传递的是对象引用的副本(值),这意味着方法内部可以通过这个引用副本改变对象的属性,但不能改变外部引用本身指向的对象

为什么java中只有值传递

java中只有值传递是因为无论是基本数据类型还是对象,方法调用,方法调用时传递的都是变量的副本。对于基本数据类型,这个副本的实际的值;对于对象,这个副本是对应引用的值(即内存地址的副本)。这样设置的目的是为了保护数据,避免原始数据被无意或恶意的修改,从而争抢程序的安全性和可靠性

值传递和引用传递有什么区别?

值传递(Pass by Value):方法调用的时候,实参向形参传递的值的副本。对副本的任何修改不会影响到原始数据

引用传递(Pass by Reference):方法调用的时,实参向行参传递的是引用(或内存地址)的副本。通过这个引用的副本,方法可以修改原始对象所指向的数据

区别在于,值传递不会影响原始数据,而引用传递允许方法修改原始对象。

JDK中常用的包有哪些?

1、java.lang :包含语言基础类 如String、Math、System等

2、java.util :包含集合框架、日期实践类、事件模型、随机数生成等

3、java.io:提供输入输出(I/O)相关的类和接口用于读写数据

4、java.net:包含执行与网络相关的操作的类和接口,如URL处理、套接字编程

5、java.sql:提供了进行jdbc数据库编程的类和接口

6、java.awt:抽象窗口工具包,用于构建图形用户界面(GUI)和图像处理

7、javax.swing:提供了一套更加复杂的GUI组件库,建立在AWT之上

8、java.nio:新输入输出、提供了高速的、可伸缩的I/O操作

java 和javax有什么区别?

java和javax包的区别主要在于他们的历史和用途上。java包是java核心API的一部分,提供了最基础的类和接口,如集合框架、线程、异常处理等。javax包最初被用来作为java核心API的扩展,包含了额外的功能和工具,如Swing GUI工具包、XML处理,javaMai等。随着时间的发展,javaX包中的一些API变得非常重要,但基本上,java包含核心功能,而javax包含扩展功能或补充API

java中IO流分为几种?

分为四种主要类型:字节输入流、字节输出流、字符输入流、字符输出流

Files的常用的方法都有哪些?

1、copy 复制文件或目录

2、move 移动或重命名文件或目录

3、delete 删除文件或目录

4、exists 检查文件或目录是否存在

5、size 返回文件的大小

6、createFIle 创建一个新文件

7、createDirectory 创建一个目录

8、createDirectorys 创建一个目录及其所有父目录

9、newBufferedReader 打开文件进行的读取

10、newBufferedWriter 打开或创建文件以进行写入

11、readAllLines 读取文件的所有行到一个列表

12、write 将多行写入文件

13、isDirectory 检查是否为目录

14、isRegularFIle 检查是否为普通文件

15、setLastModifiedTime 设置文件最后修改时间

什么是反射机制?

java中的反射机制是一种动态机制,允许程序再运行时候访问、检测和修改它本身的类和对象的信息。它使得java程序能够动态加载类、获取类的元数据(如类的方法、字段、构造器等)、调用对象的方法、修改对象的字段,即使在编译时这些类、方法、字段是未知的。反射主要通过java.lang.Class类以及java.lang.reflect包中的Method、Field、Constructor等实现

java反射机制有什么优缺点

优点

1、灵活性

允许程序在运行时动态加载和操作对象,提高了程序的灵活性和扩展性

2、泛型擦除的解决:

可以用于访问在编译十七被泛型擦除的类型信息

3、框架开发

是许多java框架(如Spring,Hibernate)的基础,用于实现依赖注入、ORM等功能

缺点

1、性能开销

反射调用比直接代码调用慢,因为他需要进行类型检查和范文控制检查

2、安全风险

允许运行时修改程序行为可能会引入安全漏洞

3、破坏封装性

可以访问私有成员和方法,破坏了类的封装性

4、代码复杂性

使代码更难理解和维护,尤其是对于非反射机制的使用者

静态编译和动态编译的区别是什么?

区别主要在于编译时机和执行效率

-静态编译:在程序运行前,源代码被编译成机器语言代码。这种编译一次完成,生成的可执行文件直接在硬件上运行,通常提供更高的执行效率和更好的优化,但是缺乏灵活性

–动态编译:在程序运行时,源代码或字节码被即使(JIT)编译成机器语言。这允许更高的灵活性和平台独立性,可以针对当前运行环境进行优化,但是在编译过程中会增加额外的性能开销

反射机制的应用场景有哪些?

1、框架开发

如Spring的依赖注入和Hibernate得到ORM映射,通过反射自动装配对象和管理数据库操作

2、插件化或模块化平台

动态加载和运行第三方开发的插件或模块

3、单元测试框架

如JUtil使用反射来识别和执行测试方法

4、动态代理

在运行时创建代理对象,用于拦截原始对象的方法调用,实现如AOP(面向切面编程)的功能

5、配置解析

解析冰应用配置文件中的设置,如通过反射根据配置实例化类和设置属性

6、泛型类型擦除的补救

通过反射获取和操作泛型类型的实际阐述类型

java获取反射的三种方法?

1、使用Class.forName()方法

传递类的全限定名(包括包名)作为字符串参数,适用于动态加载类

Class<?> c = Class.forName("java.lang.String");

2、通过.class语法

直接在类名后使用.class获取对应的Class对象,适用于编译时已知的类

CLass<?> c = String.class;

3、使用对象的。getClass方法:对于任意对象,调用其.getClass()方法获取其运行时类的Class对象,适用于已有对象实例

String s = "example";
Class<?> c= s.getClass();

字符型常量和字符串常量的区别是什么?

字符型常量(Character Constant)是单个字符,使用单引号(‘)括起来,在java中占用2字节目标是一个单一的Unicode字符

字符串常量(StringConstant)是一系列字符的集合,使用双引号(“”)括起来,如“hello”,在java中String类型的对象,可以包含零个或多个字符,占用的额内存大小取决于字符串中字符的数量

什么是字符串常量池?

字符串常量池

是java堆内存的一部分,用于存储唯一的而字符串常量。这中机制允许JVM节省内存空间,通过确保所有相同的字符串常量都指向内存中的同一个位置。当创建字符串字面量的时候。(例如,通过直接复制 String s = “hello”;),JVM首先检查字符串常量池中是否存在相同的字符串引用;如果不存在,就在池中创建一个新的字符串,并返回引用。这种机制不使用于 new String()创建的字符串对象。

String是最基本的而数据类型么?

不是,String 在java中是一个类,属于引用数据类型,不是基本数据类型。java中的解百纳数据类型包括 byte、short、int、long、float、double、boolean、和char

String有哪些特性?

1、不可变性:字符串一旦创建,其值就不能被改变

2、常量池:字符串常量池帮助节省内存,是的相同内容的字符串共享内存

3、线程安全:由于其不可变性,字符串在java中是线程安全的

4、支持字符串拼接:可以使用+操作符进行字符串拼接,但是每次拼接都会生成新的字符串对象

5、支持intern()方法:可以确保字符串常量池中只有一个唯一的字符串实例

6、实现了Serializable和Comparable接口:是的字符串可以序列化,并且可以自然的排序

String为什么是不可变的?

主要因为以下几个原因

1、安全性:字符串经常作为参数传递给网络连接和文件路径等敏感操作。不可变性保证了值不会被更改,确保安全性

2、同步性:由于不可变,String可以在多线程环境下安全使用,无需额外的同步操作

3、性能:不可变性是的字符串常量池的实现称为可能,相同的字符串字面量可以共享相同的内存地址,节省内存

4、哈希码缓存:由于String的内容不会盖面,其哈希码可以被缓存,这在使用字符串作为HashMap或HashSet的键时可以提高性能

String有什么办法可以变成可变的?

可以通过使用StringBuilder或StringBuffer类使字符串变得可变。这两个类提供了用于修改字符串的API,如追加(append)、插入(insert)、删除(delete)等操作。StringBuilder通常用于单线程环境下,因为它不是线程安全的,但其性能能比StringBuffer更优,后者是线程安全的,适用于多线程环境。使用这些类可以构建和修改字符串,然后通过调用他们的toString()方法将其转为不可变的String对象

String类可以被继承么?

不可以,String类在java中被声明为final,因此不能被继承

String str=“i” 与String str = new String(“i”)一样么?

不一样。

String str = “i”;创建的字符串会检查字符串常量池中是否存在内容为“i”的字符串,如果存在,则直接返回其引用;如果不存在,会在常量池中创建一个然后返回其引用。而String str = new String(“i”);会在堆内存中创建一个新的String对象,即使常量池中已存在内容为“i”的字符串,也会创建新的对象,不会使用常量池中的对象

String s = new String(“xyz”);创建了几个字符串对象?

可能创建了两个字符串对象:一个在字符串常量池中(如果常量池中尚不存在字面量“XYZ”),另一个是通过new String(“syz”)在堆上显式创建的

如何将字符串反转?

可以使用StringBuilder或StringBuffer的reverse()方法来反转字符串

String original = "example";
String reversed = new StringBuilder(original).reverse();

这段代码创建了一个StringBuilder对象,初始化为原始字符串,然后调用reverse()方法将其反转,最后通过toString()方法将其转换回字符串

数组有没有length()方法?String有没有length()方法?

数组没有length()方法,他有一个length属性用来获取数组得到长度

String有一个length()方法用来获取字符串的长度

String类的常用方法都有哪些?

1、length():返回字符串的长度

2、charAt(int index):返回指定索引处的字符

3、substring(int beginindex,int endindex):返回一个新字符串,他是此字符串的一个子字符串

4、concat(String str):将指定字符串连接到此字符串末尾

5、indexOf(int ch),indexOf(String str):返回指定字符或字符串第一次出现的位置

6、lastIndexOf(int ch),lastIndexOf(String str):返回指定字符或字符串最后一次出现的位置

7、equals(Object anObject):比较此字符串与指定对象

8、equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写差异

9、startsWith(String prefix):测试此字符串是否以指定前缀开始

10、endsWith(String suffix)L测试此字符串是否以指定后缀结束

11、toLowerCase():使用默认语言环境的规则将此String中的二左右字符都转换成小写

12、toUpperCase():使用默认语言环境的规则将此String中的所有字符都转换成大写

13、trim():返回字符串的副本,忽略前导空白和尾部空白

14、replace(char oldchar,char new Char),replace(CharSequence target,CharSequence replacement):返回一个新的字符串,他是通过用新字符替换此字符串中出现的所有旧字符或子字符串得到的

15、split(String regex):根据给定的正则表达式的匹配拆分此字符串

16、valueOf(各种类型):返回各种类型数据的字符串表示形式

在使用HashMap的时候,用String做key有什么好处?

1、不可变性:

String的不可变性保证了key的唯一性和一致性,确保了HashMap中key的哈希值不会改变

2、哈希码缓存

String类内部缓存了其哈希码,当再次使用相同的String作为key查找时,可以快速访问,提高了查找效率

3、天然的唯一性和等价性:

String重写了equals()和HashCode()方法,保证了只要内容相同,无论时哪个String实例,都能正确的映射到相同的值,这使得使用String作为key时,HashMap的行为非常直观和可预测

String和StringBuffer、StringBuilder的区别是什么?

String

不可变的字符序列,每次修改都会生成新的String对象,适用于少量的字符串操作

StringBuffer

可变的字符序列,线程安全,适用于多线程环境下的字符串操作,性能略低于StringBuilder 由于同步开销

StringBuilder

可变的字符序列,非线程安全,适用于单线程环境下的字符串操作,性能高于StringBuffer因为省去了同步开销

Integer a = 127 与Integer b = 127相等么?

相等

在java中,整数值在-128到127之间的Integer实例会被缓存,因此a和b引用的时同一个Integer对象

Integer a= 128 与 Integer b=128相等么?

不相等

在java中超过-128到127这个范围的整数不会被缓存,因此Integer a = 128 和Integer b = 128会指向不同的Integer对象实例。使用==比较的时候,比较的是引用,不是值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

忧郁的Mr.Li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值