栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java 基础面试题

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java 基础面试题

重写和重载
不同点重载重写
发生范围同一个类子类
参数列表必须修改不可修改
返回类型随便修改子类要比父类小(void 不可改)
抛出异常随便修改子类要比父类小
修饰符随便修改可降低限制
发生阶段编译器运行期
泛型擦除

泛型提供了编译期间类型安全检测机制,该机制允许程序员在编译期间检测到非法的类型。

Java 的泛型是伪泛型,在编译后的字节码,所有的泛型信息都会被擦掉。但是为了反编译时识别泛型 LocalVariableTable 中的 Signature 会保留泛型信息。

List l1 = new ArrayList<>();
List l2 = l1;
l2.add('a');

上述代码编译后再反编译可得下面的代码

List l1 = new ArrayList();
l1.add('a');

扩展阅读

深入探索Java泛型的本质 | 泛型

== 和 equals

基本数据类型:== 比值

引用数据类型:== 比地址

对于没有重写的类,其 equals 继承自 Object,而 Object 的 equals 用的是 ==

hashCode 和 equals

对于 HashMap、HashSet 这类容器而言,需要先使用 hashCode 判断在容器中是否存在 hashCode 相同的元素,如果存在再使用 equals 比较是否是相同元素。

hashCode 相同,可能是因为 hash 碰撞导致的。所以 equals 判断相等的两个对象,其 hashCode 也相等。而 hashCode 相等的对象,equals 判断未必会相等。

hashCode 的作用是降低所需要比较的成本。如果不使用基于 Hash 的容器,无需重写 hashCode。

扩展阅读

Java hashCode() 和 equals()的若干问题解答

包装类常量池

Byte、Short、Integer、Long 常量池中缓存了 − 128 ~ 127 -128 ~ 127 −128~127 ,而 Character 缓存了 0 ~ 127 0~127 0~127。

Boolean、Float、Double 无常量池。

自动装拆箱

装箱:将基本类型用它们对应的引用类型包装起来。调用包装类的 valueOf 方法拆箱:将包装类型转换为基本数据类型。调用了 xxxValue 方法

频繁的自动装拆箱会严重影响性能。

构造方法能否被重写(override)

构造方法不能重写。因为重写必须发生在继承的基础上,而构造方法又无法被继承,所以不能重写。

虽然构造方法不能重写,但可以重载。

被 final 修饰的方法同理,还有被 private 修饰的方法会隐式加上 final。

String、Stirng Builder 和 String Buffer

String 不可变性

String 不可变指的是对 String 二次赋值不是在原内存地址上修改数据,而是重新指向一个新对象。

    底层字符数组是 final,导致数组引用不可变,但数组元素是可变的。底层字符数组是 private,也没提供暴露出去修改的方法。所以就杜绝了数组元素可变的情况。上述两点足以保证 String 不可变,但是仍然在类上加了 final 完全杜绝被子类破坏。

不可变性带来的好处

    多线程安全:在多线程环境下,只有写操作才会引起安全问题,然而 String 是不可写的所以在多线程下是安全的。字符串常量池:字符串不可变,所以可以利用常量池公用一个串,从而节省内存空间。

扩展:反射改变 Stirng 底层字符数组

    所有引用相同字符串常量池的 String,都会发生变化String 的 hashCode 只会计算一次,所以不会出现改变前后 hashCode 对不上的问题。

不可变性带来的弊端

由于 String 不可变,每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象,开销较大。

从而引入了 StringBuilder 和 StringBuffer 来解决频繁修改字符串时带来的开销问题。StringBuilder 是线程不安全的,StringBuffer 是线程安全的。

综上所述:

    对字符串修改不频繁,使用 String对字符串修改频繁且在单线程环境下,使用 StirngBuilder对字符串修改频繁且在多线程环境下,使用 StringBuffer

扩展阅读

如何理解 String 类型值的不可变? - 知乎提问

反射能否改变 final 字段

final 修饰的字段代表该字段引用不能改变,但引用对象本体可以改变,所以 final 能够被反射改变。

但对于基本数据类型和 String 来说,在编译时会做内联优化,所以从结果上来说就失效了。

public class A {
    final String s = "a";
    final int i = 1;
    public String getS() {
        return  s;
    }

    public int getI() {
        return i;
    }
}

编译后再反编译可得

public class A {
    final String s = "a";
    final int i = 1;

    public A() {
    }

    public String getS() {
        return "a";
    }

    public int getI() {
        return 1;
    }
}
深拷贝、潜拷贝、引用拷贝

深拷贝:堆内新创建的对象里的所有字段都是新创建的。

潜拷贝:堆内新创建的对象里的所有字段都是引用旧对象的字段。

引用拷贝:压根没在堆内创建新对象,而是直接引用了老对象。

这里所说的字段是引用类型

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/720885.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号