- 我将跳过与本系列文章 重叠的问题,以免不必要地重复信息。我建议阅读这些文章,因为它们涵盖了最常见(流行)的 Java Core 面试问题。
- 我可以更详细地描述答案,但我不会,因为这样每个答案都可能拖累整篇文章。在任何工作面试中,没有人会要求您提供如此详细的信息。
11. 命名Object类的所有方法
Object类有11个方法:-
Class<?> getClass() — 获取当前对象的类;
-
int hashCode() — 获取当前对象的哈希码;
-
boolean equals(Object obj) — 将当前对象与另一个对象进行比较;
-
Object clone() — 创建并返回当前对象的副本;
-
String toString() — 获取对象的字符串表示形式;
-
void notify() — 唤醒在此对象监视器上等待的一个线程(线程的选择是随机的);
-
void notifyAll() — 唤醒在此对象监视器上等待的所有线程;
-
void wait() — 让当前线程在当前监视器上等待(冻结当前线程),直到notify或notifyAll调用唤醒线程(仅适用于同步块);
-
void wait(long timeout) — 使当前线程在当前监视器上等待(在当前同步块上),但退出等待状态超时(或者再次,直到notify或notifyAll调用唤醒线程);
-
void wait(long timeout, int nanos) — 此方法与之前的方法类似,但超时时间更精确;
-
void Finalize() — 在垃圾收集器删除对象之前(最终)调用此方法。它用于清理获取的资源。
12. 使用资源时,try-with-resources 和 try-catch-finally 有什么区别?
通常,当使用try-catch-finally时,final块用于关闭资源。Java 7 引入了新的try-with-resources语句。它类似于释放资源的 try-catch-finally ,但更紧凑和可读。让我们回想一下try-catch-finally是什么样子的:String text = "some text......";
BufferedWriter bufferedWriter = null;
try {
bufferedWriter = new BufferedWriter(new FileWriter("someFileName"));
bufferedWriter.write(text);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
现在让我们重写这段代码,但使用try-with-resources:
String text = "some text......";
try(BufferedWriter bufferedWriter =new BufferedWriter(new FileWriter("someFileName"))) {
bufferedWriter.write(text);
} catch (IOException e) {
e.printStackTrace();
}
现在这有点简单了,你不觉得吗?除了更简单的代码之外,还有其他几点需要注意:
-
在try-with-resources中,括号中声明的资源(将被关闭的资源)必须实现AutoCloseable接口及其唯一的close()方法。
close 方法在隐式的finally块中执行,否则程序如何确定如何关闭资源?
但是您可能很少会编写自己的资源实现及其关闭方法。
-
块按以下顺序执行:
- try块。
- 隐式的finally块。
- catch块,捕获前面步骤中发生的异常。
- 显式的finally块。
通常,列表中较低位置抛出的异常会中断较高位置抛出的异常。
13.什么是按位运算?
位运算是对位序列的运算。它们包括逻辑运算和按位移位。 逻辑运算符:-
按位AND — 比较位值。任何设置为 0 (假) 的位都会将结果中的相应位设置为 0。也就是说,如果两个比较值中的某个位均为 1 (真),则结果位也将为 1。
表示为AND或&
示例:10111101 & 01100111 = 00100101
-
按位或— 此操作与前一个操作相反。任何设置为 1 的位都会将结果中的相应位设置为 1。因此,如果两个比较值中该位均为 0,则结果位也将为 0。
表示为OR或|
示例:10100101 | 01100011 = 11100111
-
按位NOT — 该运算符应用于单个值。它翻转(反转)位。即原来为1的位变为0;那些原本为 0 的变成了 1。
表示为NOT或~
示例:~10100101 = 01011010
-
按位异或— 比较位值。如果两个位均为 1,则结果位为 0。如果两个位均为 0,则结果位为 0。换句话说,为了使结果位为 1,只有其中一位必须为 1,并且另一位必须为 0。
表示为XOR或^
示例:10100101 ^ 01100011 = 11000110
- 01100011 >> 4 = 00000110
- 01100011 << 3 = 00011000
14. Java中有哪些标准的不可变对象?
如果一个对象不允许其原始值改变,则该对象是不可变的。它可能具有返回具有不同值的相同类型的新对象的方法。一些标准的不可变对象包括:- 毫无疑问,Java 最著名的不可变类型是 String;
- 包装标准类型的包装类的实例:Boolean、Character、Byte、Short、Integer、Long、Double、Float;
- BigInteger 和 BigDecimal 对象,通常用于特别大的数字;
- 组成堆栈跟踪的 StackTraceElement 对象(例如,异常的堆栈跟踪);
- File 类的对象——它可以修改文件,但同时对象本身保持不变;
- UUID,通常用于唯一标识元素;
- java.time包中类的所有对象;
- Locale 对象,用于标识地理、政治或文化区域。
15. 不可变对象相对于普通对象有什么优点?
-
不可变对象可以安全地在多线程环境中使用。他们这样做是为了让您不必担心由于竞争条件而导致的数据丢失。这与处理普通对象时不同。在这种情况下,在并行环境中使用对象时,您必须思考并想出良好的机制。
-
不可变对象非常适合作为映射中的键。如果您使用可变对象作为 HashMap 键,然后该对象的状态发生变化,那么数据结构可能会变得混乱:该对象仍然存在,但如果您使用 containsKey(),您可能找不到它。
-
不可变对象非常适合存储在程序运行时永远不应更改的不可变(常量)数据。
-
另一个优点是失败原子性。如果不可变对象抛出异常,它不会处于不需要的(损坏的)状态。
-
这些类很容易测试。
-
您不需要任何额外的机制,例如复制构造函数或对象克隆的实现。
关于面向对象编程的问题
16. 与过程式编程相比,OOP 总体上有哪些优点?
好吧,OOP 的优点:-
使用 OOP 比过程式编程更容易编写复杂的应用程序,因为所有内容都被分解为小模块(彼此交互的对象),因此,编程被简化为对象之间的关系。
-
使用 OOP 编写的应用程序更容易修改(当正确遵守设计原则时)。
-
由于数据和数据操作都形成一个实体,因此它们不会遍布整个应用程序(过程式编程中经常出现这种情况)。
-
封装的原则可以保护用户最关键的数据。
-
相同的代码可以与不同的数据重用,因为类允许您创建许多对象,每个对象都有自己的值。
-
继承和多态性还允许您重用和扩展现有代码(而不是重复类似的功能)。
-
扩展应用程序比使用过程方法更简单。
-
OOP 方法使得抽象实现细节成为可能。
17.告诉我们OOP有哪些缺点
不幸的是,它们也存在:-
OOP 需要大量的理论知识,在编写任何东西之前必须先掌握这些知识。
-
OOP 思想并不那么容易理解并在实践中应用(你需要内心成为一个小哲学家)。
-
由于系统复杂性增加,OOP 会稍微降低程序的性能。
-
OOP 方法需要更多的内存,因为一切都由类、接口、方法组成,它们比普通变量占用更多的内存。
-
初始分析所需的时间比程序方法所需的时间长。
18.什么是静态多态与动态多态?
多态性允许同一类或接口的对象有不同的行为。多态性有两种类型,也称为早期结合和晚期结合。静态多态性,或早期结合:- 发生在编译时(程序生命周期的早期);
- 决定在编译时执行哪个方法;
- 方法重载是静态多态性的一个例子;
- 早期绑定包括私有、静态和最终方法;
- 早期绑定不涉及继承;
- 静态多态性不涉及特定对象,而是涉及出现在变量名称左侧的类类型信息。
- 发生在运行时(程序运行时);
- 动态多态性决定了方法在运行时将具有哪种具体实现;
- 方法重写是动态多态性的一个例子;
- 后期绑定意味着分配一个特定的对象、其类型的引用或其超类;
- 继承与动态多态性相关。