41、== 和 equals 的区别?
==: 如果比较的对象是基本数据类型,则比较的是数值是否相等;如果比较的是引用数据类型,则比较的是对象的地址值是否相等;
equals方法: 用来比较两个对象的内容是否相等;注意:equals 方法不能用于比较基本数据类型的变量。如果没有对 equals 方法进行重写,则比较的是引用类型的变量所指向的对象的地址。(很多类重新了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等)
42、两个对象的 hashCode() 相同,则 equals() 也一定为true 吗?
两个对象的 hashCode() 相同,equals() 不一定为 true。因为在散列表中,hashCode() 相等即两个键值对的哈希值相等,然而哈希值相等,并不一定能得出键值对相等。
43、为什么重写 equals() 就一定要重写 hashCode() 方法?
这个问题应该是有个前提,就是你需要用到 HashMap、HashSet 等 Java 集合。用不到哈希表的话,其实仅仅重写 equals() 方法也可以吧。而工作中的场景是常常用到 Java 集合,所以 Java 官方建议重写 equals() 就一定要重写 hashCode() 方法。
对于对象集合的判重,如果一个集合含有 10000 个对象实例,仅仅使用 equals() 方法的话,那么对于一个对象判重就需要比较 10000 次,随着集合规模的增大,时间开销是很大的。但是同时使用哈希表的话,就能快速定位到对象的大概存储位置,并且在定位到大概存储位置后,后续比较过程中,如果两个对象的 hashCode 不相同,也不再需要调用equals() 方法,从而大大减少了 equals() 比较次数。
所以从程序实现原理上来讲的话,既需要 equals() 方法,也需要 hashCode() 方法。
那么既然重写了 equals(),那么也要重写 hashCode() 方法,以保证两者之间的配合关系。
1、如果两个对象相等,则 hashCode 一定也是相同的;
2、两个对象相等,对两个对象分别调用 equals 方法都返回 true;
3、两个对象有相同的 hashCode 值,它们也不一定是相等的;
4、因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖;
5、hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)
44、& 和 && 的区别?
Java中 && 和 & 都是表示与的逻辑运算符,都表示逻辑运输符 and,当两边的表达式都为 true 的时候,整个运算结果才为 true,否则为 false。
&&:有短路功能,当第一个表达式的值为 false 的时候,则不再计算第二个表达式;
&:不管第一个表达式结果是否为 true,第二个都会执行。除此之外,& 还可以用作位运算符:当 & 两边的表达式不是 Boolean 类型的时候,& 表示按位操作。
45、Java 中的 Math.round(-1.5) 等于多少?
等于 -1,因为在数轴上取值时,中间值(0.5)向右取整,所以正 0.5 是往上取整,负0.5 是直接舍弃。
46、Error 和 Exception 的区别?
Error 类和 Exception 类的父类都是 Throwable 类。主要区别如下:
Error类:一般是指与虚拟机相关的问题,如:系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢出等。这类错误将会导致应用程序中断,仅靠程序本身无法恢复和预防;
Exception 类:分为运行时异常和检查时异常。运行时异常:【如空指针异常、指定的类找不到、数组越界、方法传递参数错误、数据类型转换错误】可以编译通过,但是一运行就停止了,程序不会自己处理;
检查时异常:要么用 try … catch… 捕获,要么用 throws 声明抛出,交给父类处理。
47、throw 和 throws 的区别?
throw:throw 在方法体内部,表示抛出异常,由方法体内部的语句处理;throw 是具体向外抛出异常的动作,所以它抛出的是一个异常实例;
throws:throws 在方法声明后面,表示如果抛出异常,由该方法的调用者来进行异常的处理;表示出现异常的可能性,并不一定会发生这种异常。
48、常见的异常类有哪些?
NullPointerException:当应用程序试图访问空对象时,则抛出该异常。
SQLException:提供关于数据库访问错误或其他错误信息的异常。
IndexOutOfBoundsException:指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。
FileNotFoundException:当试图打开指定路径名表示的文件失败时,抛出此异常。
IOException:当发生某种 I/O 异常时,抛出此异常。此类是失败或中断的 I/O 操作生成的异常的通用类。
ClassCastException:当试图将对象强制转换为不是实例的子类时,抛出该异常。
IllegalArgumentException:抛出的异常表明向方法传递了一个不合法或不正确的参数。
49、主线程可以捕获到子线程的异常吗?
线程设计的理念:“ 线程的问题应该线程自己本身来解决,而不要委托到外部 ”。
正常情况下,如果不做特殊的处理,在主线程中是不能够捕获到子线程中的异常的。
如果想要在主线程中捕获子线程的异常,我们可以用如下的方式进行处理,使用 Thread的静态方法。
Thread.setDefaultUncaughtExceptionHandler( new XxxExceptionHandle() );
50、Java 的泛型是如何工作的 ? 什么是类型擦除 ?
泛型是通过类型擦除来实现的,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。例如:List<String> 在运行时仅用一个 List 来表示。这样做的目的,是确保能和 Java 5 之前的版本开发二进制类库进行兼容。
类型擦除:泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。在泛型类被类型擦除的时候,之前泛型类中的类型参数部分如果没有指定上限,如 <T> 则会被转译成普通的 Object 类型,如果指定了上限如 <T extends String> 则类型参数就被替换成类型上限。
List<String> list = new ArrayList<String>();
1、两个 String 其实只有第一个起作用,后面一个没什么卵用,只不过 JDK7 才开始支持List<String>list = new ArrayList<>; 这种写法。
2、第一个 String 就是告诉编译器,List 中存储的是 String 对象,也就是起类型检查的作用,之后编译器会擦除泛型占位符,以保证兼容以前的代码。
看完如果对你有帮助,感谢点击下面的一键三连支持下!
我的个人订阅号(大叔学Java/dashu_java),文章第一时间在公众号发布,感兴趣的可以关注下,谢谢!