java面试-java基础(下)


一、==和equals区别?

  • ==:如果比较的对象是基本数据类型,则比较的是数值是否相等;如果比较的对象是引用数据类型,则比较的是对象的地址值是否相等
  • equals方法:没有重写相当于==,重写后比较两个对象的内容是否相等。String、Integer重写了

二、hashcode方法作用?两个对象的hashCode方法相同,则equals方法也一定为true吗?

  • hashCode 方法主要用来获取对象的哈希码,哈希码是由对象的内存地址或者对象的属性计算出来的,它是⼀个int类型的整数,重复率低,因此可以用来作为键值对的键,以提高查询效率。
  • 不一定。因为存在哈希冲突,不同的对象可能会有相同的哈希值,所以哈希值相等,并不一定能equals方法相等。为了解决哈希冲突的问题,在判断对象是否相等时,不仅会比较键对象的哈希码,还会使用 equals 方法。如果两个对象的哈希码相同,但通过equals方法比较结果为 false,那么这两个对象就不被视为相等。

三、为什么重写equals方法就一定要重写hashCode方法?

  • 保证在equals相同的情况下hashcode值必定相同:如果只重写equals方法,那么被认为相等的对象可能会有不同的哈希码(默认是对象的地址,因此所有对象都是不同的哈希码),存储在集合不同的位置,导致集合出现重复元素或者无法找到对应元素(因为equals是根据对象的特征进行重写)
  • 提升性能:hashCode能提高hashmap等集合去重的性能,如果没有重写hashCode()方法,那么集合每次添加元素都要遍历已有元素调用equals方法,性能太差,重写hashcode能减少equals方法调用次数

四、Java中的参数传递时传值呢还是传引用?

  • java基本类型作为参数被传递时是值传递;引用类型作为参数被传递时也是值传递,参数值是对象的引用。

五、深拷贝和浅拷贝?

  • 浅拷贝仅拷贝被拷贝对象的基本数据类型变量的值和引用数据类型变量的地址值,而对于引用类型变量指向的堆中的对象不会拷贝
  • 深拷贝完全拷贝一个对象,拷贝被拷贝对象的成员变量的值,堆中的对象也会拷贝一份。
  • 浅拷贝需要实现Cloneable接口并重写Object类中的clone()方法;
  • 深拷贝需要实现Serializable接口,通过对象的序列化和反序列化,或者使所有引用类型属性实现Cloneable接口

六、Java中创建对象的几种方式?

  • 使用new关键字
A a = new A();
  • 使用Class类的newInstance方法,Class.forName.newInstance()
Class clazz = Class.forName("A");
A a = (A) clazz.newInstance();
  • 使用clone方法
A a = new A();
A a2= (A) a.clone();
  • 反序列化,比如调用ObjectInputStream类的readObject()方法
A a= new A();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
oos.writeObject(a);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt"));
A a2 = (A) ois.readObject();

七、Java对象初始化过程?(笔试)

  • 父类静态属性
  • 父类静态代码块
  • 子类静态属性
  • 子类静态代码块
  • 父类非静态属性
  • 父类构造代码块
  • 父类构造方法
  • 子类非静态属性
  • 子类构造代码块
  • 子类构造方法

八、怎么精确表示任意精度的整数和任何精度的定点数或者货币?

  • BigInteger任意精度的整数
  • BigDecimal任何精度的定点数->货币
  • 转成分用int运算

九、String是Java基本数据类型吗?可以被继承吗?

  • 引用类型,String被final修饰不能被继承

十、String是不可变类吗?字符串拼接是如何实现的?

  • String是不可变的,1.8以前+的拼接操作,如果字符串在常量池中不存在,则会生成新的对象。1.8时被优化为基于StringBuilder的append方法进行处理

十一、不同String创建方法分别创建了几个对象?

String str1 = "abc";//1
String str2 = new String("abc")//2 
  • 1在内存的字符串常量池中存储abc字符串对象
  • 2在内存的字符串常量池中找abc字符串对象,没有则创建;在堆中创建str2对象,引用指向abc字符串对象

十二、String为什么是不可变的?设计原因?

  • 不可变:一旦String对象被创建,它所包含的字符串内容是不可改变的。
  • 不可变是因为引用的char数组(jdk1.9后改为byte数组)被final修饰。字符串的值本身不能改变,但引用字符串的变量中记录的地址值是可以改变的。每次修改操作(如拼接、替换等)都会产生新对象。
  • 避免内存浪费:当创建一个String对象时,如果字符串值在常量池中已经存在则不会创建,只是引用已经存在的对象
  • 性能优化:字符串不变性保证了hash码的唯一性,允许String对象缓存频繁使用的HashCode(如HashMap),不必每次都去计算新的哈希码
  • 安全性:String被许多的Java类用来当做参数,例如:网络连接地址URL、文件路径path、反射机制的String参数等, 如果String不是固定不变的,将会引起各种安全隐患。

十三、String、StringBuilder、StringBuffer 的区别?

  • String:类的对象是不可变的;适用于字符串内容不经常改变的场景。在使用字符串常量或进行少量的字符串操作时使用。每次对String对象进行修改操作(如拼接、替换等)实际上都会生成一个新的String对象,而不是修改原有对象。大量字符串连接情况下,产生太多对象浪费内存。线程安全
  • StringBuilder:适用于单线程环境下需要频繁修改字符串内容的场景,比如在循环中拼接或修改字符串,使用字符数组char[]保存字符串,可变类,每次对String对象进行修改操作(如拼接、替换等)都是直接在原有字符串对象的底层数组上进行,不产生新对象,线程不安全;效率高
  • StringBuffer:适用于多线程环境下需要频繁修改字符串内容的场景,使用字符数组char[]保存字符串,可变类,方法加同步锁synchronized,线程安全;效率低
  • 多线程强制使用StringBuilder()
public class StringBuilderHolder {
    private final StringBuilder sb;
    
    public StringBuilderHolder(int capacity) {
        sb = new StringBuidler(capacity);
    }
    //3.避免重复构造String,重用StringBuilder
    public StringBuilder resetAndGetStringBuilder() {
        sb.setLength(0);
        return sb;
    }
}
//2.ThreadLocal避免多线程冲突
private static final ThreadLocal<StringBuilderHolder> threadLocalStringBuilderHolder = new ThreadLocal<StringBuilderHolder>() {
    protected StringBuilderHolder initialValue() {
        //1.设置好初始长度,超过char[]默认16调用System.arraycopy成倍复制扩容太浪费资源
        return new StringBuilderHolder(256);
    }
}

StringBuilder sb = threadLocalStringBuilderHolder.get().resetAndGetStringBuilder();

总结

本文介绍了的java面试之java基础(下),如有问题欢迎私信和评论

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

编程岁月

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

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

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

打赏作者

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

抵扣说明:

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

余额充值