了解基本的Java特定面试问题

7

昨天我参加了一次面试,他们问了我一些Java相关的问题,其中有一些问题我不知道答案。我很好奇这个问题的答案。面试官没有告诉我答案。我在这里提出这些问题:

  • Java是否提供任何构造来查找对象的大小?
  • 给出一种最简单的方法来查找一个方法执行所需的时间,而不使用任何分析工具?
  • 什么是已检查异常和运行时异常?
  • 如果我在try块结束时写return语句,finally块是否仍会执行?
  • 如果我在try块结束时写System.exit (0);语句,finally块是否仍会执行?

想要知道上述问题的答案,这将对我下次的面试有所帮助。

解释、注释或与规范相关的链接将比简单的回答更加受欢迎——以及学习这些东西的好方法是什么?


5
很抱歉,我之前期待会有一些有趣的问题,但我认为这不是一个好问题(例如,相关信息很容易被研究和测试,而且很可能非常重复),但是我希望能从中得到一些好的详细回答。 - user166390
8
既然你现在可以访问编译器/运行时和谷歌,那么你认为答案是什么?(注意,“你”指的是询问者本人) - Andrew Thompson
8个回答

17

我认为所有这些问题都可以通过搜索现有的Stack Overflow问题来回答。 我认为值得用链接回答这个问题的原因是,你问了很多不同的问题,每一个问题都有其自身的趣味。 当你一起问这些问题时,不太可能得到关于它们的深入讨论,但在此前的问题的答案和评论中,你会发现很多细节和讨论,这些细节和讨论 (a) 可能很有趣,(b) 可能有助于进一步的面试。(可能会有更好的选择-这些只是我找到的第一个合理的SO答案。)

Java提供任何结构来查找对象的大小吗?

给出一种最简单的方法,不使用任何分析工具就能找出一个方法执行所需的时间?

什么是已检查异常和运行时异常?

如果我在try块的末尾写了return语句,finally块仍然会执行吗?

如果我在try块的末尾写了System.exit(0);语句,finally块仍然会执行吗?


有时候答案的规模很小,但是要获取那个内容需要大量的研究和努力。这是一种需要花费很多时间去搜索的答案类型,而你成功地做到了。非常感谢你,@Mark Longair,你的回答非常好。 - zeeshan

3

Java提供了任何构造来查找对象的大小吗?

没有。

提供一种简单的方法来查找方法执行所需的时间,而不使用任何分析工具?

long t0 = System.nanoTime();
// code to profile
long timeTaken = System.nanoTime() - t0;

什么是已检异常和运行时异常?
已检异常是指任何Throwable,它没有扩展自java.lang.Error或java.lang.RuntimeException。如果您不处理或明确传播已检查的异常,则Java编译器将给出错误。
如果我在try块的末尾写了return,finally块仍然会执行吗?
是的
如果我在try块的末尾写了System.exit(0); finally块仍然会执行吗?
可能。如果存在SecurityManager,则它可以抛出SecurityException而不是退出,这将触发finally块。
如果堆栈太大,则调用System.exit可能导致堆栈溢出异常,从而触发finally块。

3

Java提供了什么构造来查找对象的大小吗?

据我所知没有。

不使用任何分析工具,给出一种最简单的方法来查找方法执行所需的时间?

使用System.currentTimeMillis()System.nanoTime()来测量时间。

什么是已检异常和运行时异常?

有关详细说明,请查看此线程

如果在try块末尾写return语句,finally块仍会执行吗?

是的。

如果在try块末尾写System.exit(0);语句,finally块仍会执行吗?

不会。


1
Java提供了什么结构来查找对象的大小吗? 我所知道的没有跨平台/跨VM的方法。
给出一种最简单的方法,以找出一个方法的执行时间而不使用任何分析工具? 通过在执行前后创建新的Date()。
什么是已检查异常和运行时异常? 您应该将已检查异常包装在try/catch块中。
如果我在try块的末尾写return,finally块仍会执行吗? 是的。
如果我在try块的末尾写System.exit(0);,finally块仍会执行吗? 不会。

0

1.

不,通常不适用于对象。.length 适用于数组和字符串...

2.

final long startTime = System.nanoTime();
final long endTime;
try {
  methodToTime();
} finally {
  endTime = System.nanoTime();
}
final long duration = endTime - startTime;

如何在Java中计时方法的执行时间?

3.

未经检查的异常是错误,参见http://download.oracle.com/javase/tutorial/essential/exceptions/runtime.html

已检查的异常例如无效的用户输入,可以处理的异常。

4.

finally块仍然会执行

5.

finally块不会执行


2
如何使用.length测量对象的大小。在java.lang.Object中没有这样的字段。 - Alex Nikolaenkov
我认为OP想要的是比数组.length更通用的东西。 - Michael Lloyd Lee mlk
endTime 赋值放在 finally 块中是没有意义的,因为只有当 methodToTime 正常完成时才会使用它。 - Mike Samuel

0
Java提供了任何构造来查找对象的大小吗?
实际上并没有。您可以创建一个对象并记录内存差异,或者阅读规范以了解对象由什么组成。
给出一种最简单的方法来查找方法执行所需的时间而不使用任何分析工具?
像这样:
long start = System.currentTimeMillis();
// do something
System.out.println("Time: " + (System.currentTimeMillis() - start));

什么是已检查异常和运行时异常?
已检查异常是在例程的throws部分中声明的异常。同样,未经声明的异常是那些未经声明的异常,例如RuntimeException的子类。
如果我在try块的末尾写了return,finally块是否仍会执行?
是的,在sun/oracle jvm上至少如此。虽然不太好看...
如果我在try块的末尾写了System.exit(0);,finally块是否仍会执行?
不会。

http://download.oracle.com/javase/6/docs/api/java/lang/instrument/Instrumentation.html getObjectSize? - Andrey
@Andrey,这是一个不错的方法,但根据Javadoc它提供的是一个估计值,而不是大小。 - Alex Nikolaenkov
@Alex Nikolaenkov 至少值得一提。 - Andrey
@Andrey,@Alex:至少我们可以使用getObjectSize()来说一些关于对象大小的事情。 - Harry Joy

0
Java提供了任何构造来查找对象的大小吗?
不,它没有。
有没有一种最简单的方法可以找出一个方法执行所需的时间,而不使用任何分析工具?
long begTime = System.currentTimeInMillis();
x.method();
long endTime = System.currentTimeInMillis();
System.out.println("method running time: " + (endTime-begTime));

什么是已检查异常和运行时异常?
已检查异常必须被捕获,否则编译器会标记;运行时异常不需要catch块。
如果我在try块的末尾写return语句,finally块仍然会执行吗?
会的。
如果我在try块的末尾写System.exit(0);语句,finally块仍然会执行吗?
不会。http://download.oracle.com/javase/tutorial/essential/exceptions/finally.html

“System.exit”不能保证一定会运行。它可能会被安全管理器取消,更普遍的情况是,如果堆栈接近溢出,任何涉及方法调用的操作都有可能失败。 - Mike Samuel
不是一般情况,但你肯定是正确的。谢谢你的教导,Mike。 - duffymo

0

(可序列化的)对象的大小可以相对容易地找到。

import javax.swing.*;
import java.io.*;

class HowLongIsAPieceOfString {

    public static int getObjectSize(Object object) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(object);
        return baos.toByteArray().length;
    }

    public static void main(String[] args) throws IOException {
        Object object = "string";
        System.out.println( "String size: \t" + getObjectSize(object) );

        object = new JButton("Click Me!");
        System.out.println( "Button size: \t" + getObjectSize(object) );

        object = new JTree();
        System.out.println( "Tree size: \t" + getObjectSize(object) );

        object = new Object();
        System.out.println( "Object size: \t" + getObjectSize(object) );
    }
}

输出:

String size:    13
Button size:    4347
Tree size:      5628
Exception in thread "main" java.io.NotSerializableException: java.lang.Object
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156)
        ...

1
这不是对象的大小,而是序列化形式中对象的大小。我认为这些值只对DTO和其他传输对象更或多少有效,而不适用于复杂对象。它与对象使用多少内存没有太大关系。 - Andrey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接