专栏首页Java面试Java基础面试题 - 总结
原创

Java基础面试题 - 总结

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

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

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值相等的案例。

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的源码是这样写的:

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,创建一个新的数组,并将数组的数据复制到新数组。

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.反转链表

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

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java集合类

    hash()方法将key的hashcode值(由native方法计算得到)再与该值的高16位进行异或运算得到最终的hash值。这样做的目的作者也给出了解释,就是...

    用户4893066
  • 做网站-推荐3种CSS,JS合并的方式

    在Web项目的开发中,js,css文件会随着项目的开发变得越来越多,越来越大,这就给给性能方面带来一些问题,如,页面引入的的js,css越多的话,那么对就增加了...

    企鹅号小编
  • 其他篇之操作系统——文件管理

    文件管理是操作系统的功能之一,由于系统的内存有限并且不能长期存储,故平时总是把数据以文件的形式存储在外存中,需要时再将其调入内存。文件管理的主要内容有:

    一半是我
  • JDK之synchronized字节码分析 原

        之后用在命令行输入javap -v -p Example2_synchronizer,得到如下片段:

    克虏伯
  • 将超过5000万行JS代码迁移到TypeScript,我们得到的10大见解

    几年前,彭博工程公司决定采用 TypeScript 作为一等语言。本文分享了我们在这一旅程中学到的一些见解和教训。

    深度学习与Python
  • 十分钟了解 TypeScript 是如怎样工作的

    本文概述了 TypeScript 的工作原理:典型的 TypeScript 项目的结构是什么?什么被编译以及怎样编译?我们如何使用 IDE 编写 TypeScr...

    疯狂的技术宅
  • SpringCloud 2.x学习笔记:5、Config(Greenwich版本)

    版权声明:本文为博主原创文章,欢迎转载。 ...

    程裕强
  • Node + Selenium使用小结

    可参考网上的步骤进行操作。例如这篇文章:https://wangheng3751.github.io/2018/01/17/selenium/

    meteoric
  • getline();和reserve();

    getline() 语法: istream &getline( char *buffer, streamsize num ); istre...

    小二哥
  • VC工程中后缀为.cpp,.h,.rc,.dsp,.dsw

    (其它.clw .opt .aps等后缀文件,见下面说明) .opt 工程关于开发环境的参数文件。如工具条位置等信息;

    阳光岛主

扫码关注云+社区

领取腾讯云代金券