前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java基础面试题 - 总结

Java基础面试题 - 总结

原创
作者头像
用户4893066
修改2020-11-06 11:01:05
6250
修改2020-11-06 11:01:05
举报
文章被收录于专栏:Java面试Java面试

1.hashCode方法会出现相同的hash值吗?

。String类重写了hashCode方法。使用int类型h作为hash值,存在溢出截取问题。

代码语言:txt
复制
public int hashCode() {
        int h = hash; // hash默认值为0
        int len = count;// count是字符串的长度
        if (h == 0 && len > 0) {
            int off = offset; // offset 是作为String操作时作为下标使用的
            char val[] = value;// value 是字符串分割成一个字符数组
            for (int i = 0; i < len; i++) {
                h = 31 * h + val[off++]; // 这里是Hash算法体现处,
                                            // 可以看到H是一个哈希值,每次是将上次一算出的hash值乘以31
                                            // 然后再加上当前字符编码值,由于这里使用的是int肯定会有一个上限,当字符长时产生的数值过大int放不下时会进行截取,一旦截取HashCode的正确性就无法保证了,所以这点可以推断出HashCode存在不相同字符拥有相同HashCode。
            }
            hash = h;
        }
        return h;
}

hashCode值相等的案例。

代码语言:txt
复制
public static void main(String[] args) {

        System.out.println("ABCDEa123abc".hashCode());  // 165374702
        System.out.println("ABCDFB123abc".hashCode());  // 165374702
        System.out.println("ABCDEa123abc" == "ABCDFB123abc");   //false
        System.out.println("ABCDEa123abc".equals("ABCDFB123abc")); //false
}

2.equals()和==的区别

Java当中的数据类型和"=="的含义:

  • 基本数据类型(也称原始数据类型) :byte,short,char,int,long,float,double,boolean。他们之间的比较,应用双等号(==),比较的是他们的
  • 引用数据类型:当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址(确切的说,是堆内存地址)

equals()方法介绍

JAVA当中所有的类都是继承于Object这个超类的,在Object类中定义了一个equals的方法,equals的源码是这样写的:

代码语言:txt
复制
public boolean equals(Object obj) {
    //this - s1
    //obj - s2
    return (this == obj);
}

可以看到,这个方法的初始默认行为是比较对象的内存地址值,一般来说,意义不大。所以,在一些类库当中这个方法被重写了,如String、Integer、Date。在这些类当中equals有其自身的实现(一般都是用来比较对象的成员变量值是否相同),而不再是比较类在堆内存中的存放地址了。

所以说,对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是内存中的存放位置的地址值,跟双等号(==)的结果相同;如果被复写,按照复写的要求来。

我们对上面的两段内容做个总结吧:

?== 的作用:

  基本类型:比较的就是值是否相同

  引用类型:比较的就是地址值是否相同

equals 的作用:

  引用类型:默认情况下,比较的是地址值。

注:不过,我们可以根据情况自己重写该方法。一般重写都是自动生成,比较对象的成员变量值是否相同

3.为什么要重写equals()方法?

因为object中的equals()方法比较的是对象的引用地址是否相等,如何你需要判断对象里的内容是否相等,则需要重写equals()方法。

4. hashcode()方法的作用?

Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。主要是针对HashSet和Map集合类型,比如我们在向HashSet集合里边添加新元素的时候,由于set集合里边不允许元素重复,所以我们在插入新元素之前需要先判断插入元素是否存在,首先根据hashCode()方法得到该对象的hashCode值,如果集合里边不存在该值,可以直接插入进去。如果已经存在,则需要再次通过equals()来比较,这样的话可以提升效率。

5.重写equals()方法为什么要同时重写hashcode()方法?

为了保证当两个对象通过equals()方法比较时,那么他们的hashCode值也一定要保证相等。

6.String、StringBuilder、StringBuffer的区别。

基本区别:

String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。

StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。

在这方面运行速度快慢为:StringBuilder > StringBuffer > String

如何实现扩容

StringBuffer和StringBuiler的扩容的机制在抽象类AbstractStringBuilder中实现,当发现长度不够的时候(默认长度是16),会自动进行扩容工作,扩展为原数组长度的2倍加2,创建一个新的数组,并将数组的数据复制到新数组。

代码语言:javascript
复制
public void ensureCapacity(int minimumCapacity) {
    if (minimumCapacity > 0)
        ensureCapacityInternal(minimumCapacity);
}
 
/**
* 确保value字符数组不会越界.重新new一个数组,引用指向value
*/   
private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value,
                newCapacity(minimumCapacity));
    }
}
 
/**
* 扩容:将长度扩展到之前大小的2倍+2
*/   
private int newCapacity(int minCapacity) {
    // overflow-conscious code   扩大2倍+2
    //这里可能会溢出,溢出后是负数哈,注意
    int newCapacity = (value.length << 1) + 2;
    if (newCapacity - minCapacity < 0) {
        newCapacity = minCapacity;
    }
    //MAX_ARRAY_SIZE的值是Integer.MAX_VALUE - 8,先判断一下预期容量(newCapacity)是否在0<x<MAX_ARRAY_SIZE之间,在这区间内就直接将数值返回,不在这区间就去判断一下是否溢出
    return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
        ? hugeCapacity(minCapacity)
        : newCapacity;
}
 
/**
* 判断大小,是否溢出
*/
private int hugeCapacity(int minCapacity) {
    if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
        throw new OutOfMemoryError();
    }
    return (minCapacity > MAX_ARRAY_SIZE)
        ? minCapacity : MAX_ARRAY_SIZE;
}

7.Object类有哪些方法?

  • clone():获取当前对象的副本
  • hashCode()和equals():equals用于比较两个对象是否相同,hashcode获取对象的hash值。
  • toString():返回一个String对象,用于标识自己
  • getClass():返回一个Class对象,经常用于java反射机制
  • wait(),notify(),notifyAll():多线程机制
  • finalize():用于垃圾回收

8.抽象类与接口

  1. 抽象类和接口都不能直接实例化
  2. 抽象类要被子类extends,接口要被类implements。
  3. 接口里定义的变量只能是public static final,抽象类中的变量是普通变量。
  4. 抽象类里可以没有抽象方法。
  5. 接口可以被类多实现(被其他接口多继承),抽象类只能被单继承。
  6. 接口中没有?this?指针,没有构造函数,不能拥有实例字段(实例变量)或实例方法。
  7. 抽象类不能在Java 8 的 lambda 表达式中使用。

9.反射机制

什么是反射

反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。

哪里用到反射机制?

  1. JDBC中,利用反射动态加载了数据库驱动程序。
  2. Web服务器中利用反射调用了Sevlet的服务方法。
  3. Eclispe等开发工具利用反射动态刨析对象的类型与结构,动态提示对象的属性和方法。
  4. 很多框架都用到反射机制,注入属性,调用方法,如Spring。

如何使用Java的反射?

  1. 通过一个全限类名创建一个对象
    1. Class.forName(“全限类名”); 例如:com.mysql.jdbc.Driver Driver类已经被加载到 jvm中,并且完成了类的初始化工作就行了
    2. 类名.class; 获取Class<?> clz 对象
    3. 对象.getClass();
  2. 获取构造器对象,通过构造器new出一个对象
    1. Clazz.getConstructor([String.class]);
    2. Con.newInstance([参数]);
  3. 通过class对象创建一个实例对象(就相当与new类名()无参构造器)
    1. Cls.newInstance();
  4. 通过class对象获得一个属性对象
    1. Field c=cls.getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段。
    2. Field c=cls.getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的声明字段
  5. 通过class对象获得一个方法对象
    1. Cls.getMethod(“方法名”,class……parameaType);(只能获取公共的)
    2. Cls.getDeclareMethod(“方法名”);(获取任意修饰的方法,不能执行私有)
    3. M.setAccessible(true);(让私有的方法可以执行)
  6. 让方法执行 1). Method.invoke(obj实例对象,obj可变参数);-----(是有返回值的)

10.线程池的核心参数

参数名

参数含义

corePoolSize

核心线程数

maxinumPoolSize

最大线程数

keepAliveTime

空闲线程存活时间

unit

存活时间的单位

workQueue

存放线程任务队列

threadFactory

线程工厂,创建新线程

handler

线程池拒绝处理后的任务

四种拒绝策略

  • AbortPolicy(抛出一个异常,默认的)
  • DiscardPolicy(直接丢弃任务)
  • DiscardOldestPolicy(丢弃队列里最老的任务,将当前这个任务继续提交给线程池)
  • CallerRunsPolicy(交给线程池调用所在的线程进行处理)

11.HashMap的存储结构,什么时候扩容,什么时候转换为红黑树,链表的存储过程是怎么样的。

Hashmap是线程不安全的,在多线程的情况下会出现什么问题。

12.各种查找算法的时间复杂度是多少。

13.mysql在查询中的最左匹配原则。

14.反转链表

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.hashCode方法会出现相同的hash值吗?
  • 2.equals()和==的区别
    • Java当中的数据类型和"=="的含义:
      • equals()方法介绍
        • 哪里用到反射机制?
        • 如何使用Java的反射?
        • 四种拒绝策略
    • 3.为什么要重写equals()方法?
    • 4. hashcode()方法的作用?
    • 5.重写equals()方法为什么要同时重写hashcode()方法?
    • 6.String、StringBuilder、StringBuffer的区别。
    • 7.Object类有哪些方法?
    • 8.抽象类与接口
    • 9.反射机制
    • 10.线程池的核心参数
    • 11.HashMap的存储结构,什么时候扩容,什么时候转换为红黑树,链表的存储过程是怎么样的。
    • 12.各种查找算法的时间复杂度是多少。
    • 13.mysql在查询中的最左匹配原则。
    • 14.反转链表
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
    http://www.vxiaotou.com