此学绵绵无绝期(java面试题)

         一.Java语言中的基本数据类型是指不包含对象和方法的数据类型。Java中有八种基本数据类型,分别为:

  1. byte:字节型数据类型,占用1个字节(8位),取值范围为 -128 到 127。

  2. short:短整型数据类型,占用2个字节(16位),取值范围为 -32768 到 32767。

  3. int:整型数据类型,占用4个字节(32位),取值范围为 -2147483648 到 2147483647。

  4. long:长整型数据类型,占用8个字节(64位),取值范围为 -9223372036854775808 到 9223372036854775807。

  5. float:单精度浮点型数据类型,占用4个字节(32位),取值范围为 1.401298E-45 到 3.4028235E38,精度为小数点后7位。

  6. double:双精度浮点型数据类型,占用8个字节(64位),取值范围为 4.9E-324 到 1.7976931348623157E308,精度为小数点后15位。

  7. char:字符型数据类型,占用2个字节(16位),用来表示单个字符。

  8. boolean:布尔型数据类型,用于表示 true 和 false 两个值。

在Java中,基本数据类型是按值传递的,也就是说,当将一个基本数据类型赋值给另一个变量时,会复制该值。相反,Java中的引用类型则是按引用传递,也就是说,实际传递的是对象的引用,而非对象本身。

        二.String类能被继承吗

在Java中,String类是被final关键字修饰的,因此不能被继承。final修饰的类表示该类是最终的,不允许其他类继承它。

String类是Java中用于表示字符串的类,在Java中广泛使用。由于String类在设计上考虑了安全性和不可变性,为了确保字符串对象的内容不会被修改,String类被设计为不可变类(Immutable Class),即一旦创建了String对象,其内容就不可更改。

通过将String类设置为final,可以防止其他类对其进行继承和修改,确保了字符串对象的内容不会被意外或恶意地修改,保证了程序在使用字符串时的安全性和稳定性。

虽然不能直接继承String类,但可以使用String类提供的方法和操作符来处理和操作字符串,例如连接、截取、比较等操作。

        三.String、StringBuffer和StringBuilder都是Java中用于操作字符串的类,它们之间的主要区别如下:

  1. 可变性:

    • String类是不可变的,一旦创建了String对象,就无法修改其内容。每次对String进行操作(拼接、替换等),都会生成一个新的String对象。
    • StringBuffer和StringBuilder类是可变的,可以对其内容进行修改。每次对StringBuffer和StringBuilder进行操作时,在原有对象上进行修改,不会生成新的对象。
  2. 线程安全性:

    • String类是线程安全的,多个线程同时操作同一个String对象是安全的。
    • StringBuffer类是线程安全的,多个线程同时操作同一个StringBuffer对象是安全的,因为StringBuffer的方法都是同步的(synchronized)。
    • StringBuilder类是非线程安全的,多个线程同时操作同一个StringBuilder对象可能会导致数据不一致,因为StringBuilder的方法没有进行同步。
  3. 性能:

    • 在单线程环境下,由于String是不可变的,每次对String进行操作都会产生一个新的String对象,频繁的字符串拼接操作会产生大量的临时对象,对性能会有一定的影响。
    • StringBuffer在进行字符串操作时,不会生成新的对象,而是在原有的对象上进行操作,因此在频繁的字符串拼接场景下,使用StringBuffer比String性能更好。
    • StringBuilder与StringBuffer类似,也是在原有的对象上进行操作,但不保证线程安全,因此在单线程环境下,使用StringBuilder比StringBuffer性能更好。

基于以上区别,一般情况下推荐如下使用场景:

  • 需要频繁进行字符串拼接和修改,并且在多线程环境下使用:使用StringBuffer。
  • 需要频繁进行字符串拼接和修改,但在单线程环境下使用:使用StringBuilder。
  • 不需要频繁进行字符串修改时,可以使用String,因为String具有不可变性,更加安全可靠。

        四.ArrayList和LinkedList是Java集合框架中List接口的两个实现类,它们之间的主要区别如下:

  1. 内部实现机制:

    • ArrayList底层使用数组来存储元素,通过索引位置可以快速访问和修改元素。
    • LinkedList底层使用双向链表(每个节点都包含前后两个指针)来存储元素,每个节点只存储自身的值和前后节点的引用。因此,LinkedList在增删操作时具有更好的性能。
  2. 随机访问和定位效率:

    • ArrayList通过索引位置可以进行高效的随机访问,时间复杂度为O(1)。
    • LinkedList需要从头节点或尾节点开始遍历链表,直到找到目标元素,时间复杂度为O(n)。
  3. 插入和删除操作效率:

    • ArrayList在插入和删除元素时,涉及到元素的移动,特别是在列表的中间位置进行插入和删除操作时,需要将后续的元素进行位移,因此时间复杂度为O(n)。
    • LinkedList在插入和删除元素时,只需要修改节点的前后指针,不需要移动其他节点,因此在列表的任何位置都可以高效地执行插入和删除操作,时间复杂度为O(1)。
  4. 内存占用:

    • ArrayList需要预先分配一块连续的内存空间来存储元素,因此在创建时需要占用较多的内存空间。
    • LinkedList由于是基于链表的实现,每个节点只需存储自身的值和前后节点的引用,因此内存占用相对较少。

根据以上特点,一般情况下建议使用:

  • 需要频繁进行随机访问或按索引位置操作元素:使用ArrayList。
  • 需要频繁进行插入、删除或操作列表的首尾元素:使用LinkedList。

当然,具体选择哪种实现取决于具体的场景和需求。

        五.      在Java中,当使用new关键字实例化一个对象时,以下是类的实例化顺序:

  1. 父类的静态代码块:如果存在父类,并且父类有静态代码块,在子类实例化之前会首先执行父类的静态代码块。父类的静态代码块只会在类加载的过程中执行一次。

  2. 子类的静态代码块:紧接着会执行子类的静态代码块。和父类的静态代码块类似,子类的静态代码块也只会在类加载的过程中执行一次。

  3. 父类的实例变量和代码块:父类会按照在类中定义的顺序执行实例变量和代码块。

  4. 父类的构造函数:然后会调用父类的构造函数来完成父类对象的初始化。

  5. 子类的实例变量和代码块:接着执行子类的实例变量和代码块。

  6. 子类的构造函数:最后调用子类的构造函数来完成子类对象的初始化。

需要注意的是,静态成员(静态变量和静态代码块)的初始化仅在类加载阶段进行一次,而实例成员(实例变量、实例代码块、构造函数)则在每次实例化对象时都会执行。

总结起来,类的实例化顺序是:父类静态代码块 -> 子类静态代码块 -> 父类实例变量和代码块 -> 父类构造函数 -> 子类实例变量和代码块 -> 子类构造函数。

        六.用过哪些Map类,都有什么区别,HashMap是线程安全的吗,并发下使用的Map是什么,他们内部原理分别是什么,比如存储方式;

Java中常用的Map类有HashMap、TreeMap、LinkedHashMap、ConcurrentHashMap等。

HashMap

HashMap是基于哈希表实现的Map,它采用了数组+链表(或红黑树)的数据结构。HashMap中的键值对没有固定的顺序,允许存在一个null键和多个null值。HashMap的性能较好,在大多数场景下都能满足需求。HashMap是非线程安全的,因此在并发场景下需要进行同步处理。

TreeMap

TreeMap是基于红黑树实现的Map,它对键进行排序,因此在遍历时会按照键的自然顺序或者自定义的顺序进行遍历。TreeMap的性能相对较低,适合在键需要排序的场景下使用。

LinkedHashMap

LinkedHashMap是基于哈希表和链表实现的Map,它可以维护键值对的插入顺序,或者按照最近访问的顺序进行遍历。LinkedHashMap是非线程安全的。

ConcurrentHashMap

ConcurrentHashMap是Java并发包中提供的线程安全的Map,它采用了锁分段技术,将整个Map分成若干个段,每个段都可以被一个线程独立访问,从而实现了高并发下的安全性和效率。ConcurrentHashMap在并发场景下的性能远优于HashMap和Hashtable,但在单线程场景下会略逊于HashMap。
在并发场景下,除了ConcurrentHashMap之外,还可以使用Java8中新增的ConcurrentHashMap的替代品ConcurrentHashMapV8、Google Guava中的ConcurrentHashMultimap等并发Map类。

这些Map的内部原理大多基于哈希表实现,其中HashMap是最常用的一种,其底层数据结构是一个数组加上链表(或红黑树),通过计算键的hashCode来确定其在数组中的位置,并通过链表或红黑树解决哈希冲突。HashMap的默认容量为16,加载因子为0.75,当Map的大小超过容量*加载因子时,会进行扩容。HashMap在多线程并发访问时不是线程安全的,因此需要进行同步操作,或者使用线程安全的ConcurrentHashMap。同时,HashMap和其他哈希表实现的Map,在键的hashCode相等时,还需要通过equals方法来比较键的值是否相等。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值