面试技巧
Java中高级面试题总结

时间:2021年5月17日 09时19分


 1、说出几条 Java 中方法重载的最佳实践?

  下面有几条可以遵循的方法重载的最佳实践来避免造成自动装箱的混乱。

  a、不要重载这样的方法:一个方法接收 int 参数,而另个方法接收 Integer 参数。

  b、不要重载参数数量一致,而只是参数顺序不同的方法。

  c、如果重载的方法参数个数多于 5 个,采用可变参数。

  2、在多线程环境下,SimpleDateFormat 是线程安全的吗?

  不是,非常不幸,DateFormat 的所有实现,包括 SimpleDateFormat 都不是线程安全的,因此你不应该在多线程序中使用,除非是在对外线程安全的环境中使用,如 将 SimpleDateFormat 限制在ThreadLocal 中。

  如果你不这么做,在解析或者格式化日期的时候,可能会获取到一个不正确的结果。因此,从日期、时间处理的所有实践来说,我强力推荐 joda-time 库。

  3、Java 中如何格式化一个日期?如格式化为 ddMMyyyy的形式?

  Java 中,可以使用 SimpleDateFormat 类或者 joda-time 库来格式日期。DateFormat 类允许你使用多种流行的格式来格式化日期。

  4、Java 中,怎么在格式化的日期中显示时区?

  使用SimpleDateFormat来实现格式化日期,但是DateFormat 的所有实现,包括 SimpleDateFormat 都不是线程安全的,因此你不应该在多线程序中使用,除非是在对外线程安全的环境中使用,如将SimpleDateFormat 限制在 ThreadLocal 中。

  如果你不这么做,在解析或者格式化日期的时候,可能会获取到一个不正确的结果。因此,从日期、时间处理的所有实践来说,强力推荐 joda-time 库。

  5、如何测试静态方法?

  可以使用 PowerMock 库来测试静态方法。

  6、怎么利用 JUnit 来测试一个方法的异常?

  对需要测试异常的代码使用try,catch语句块。比如:public void testException(){try{Long.parseLong(null);} catch(NumberFormatException expected){}}然后使用Junit的fail函数,对于没有抛出预期异常的代码。

  7、@Before 和 @BeforeClass 有什么区别?

  @Before :在每个测试方法之前都执行一次, 方法需要声明为public

  @beforeclass :只在类中执行一次, 必须声明为public static

  8、怎么检查一个字符串只包含数字?

  用Java自带的函数、用正则表达式、用ascii码判断。

  9、Java 中如何利用泛型写一个 LRU 缓存?

  这是一种混合的数据结构,我们需要在哈希表的基础上建立一个链表。但是Java已经为我们提供了这种形式的数据结构-LinkedHashMap!它甚至提供可覆盖回收策略的方法。

  唯一需要我们注意的事情是,改链表的顺序是插入的顺序,而不是访问的顺序。但是,有一个构造函数提供了一个选项,可以使用访问的顺序。

  10、Java 中,怎么获取一个文件中单词出现的最高频率?

  a、将文件内容存入String字符串中

  b、利用split()函数分割字符串,因为直接替换英文空格或者,逗号分隔就可以了,中文类似,分隔得到一个数组。

  c、遍历数组中所有的单词,统计结果Map 中,key=单词,value=单词出现的次数。

  d、使用TreeSet类型,对Map中的结果进行排序,依据统计次数。

  e、输出最高的排序的前N名结果

  11、如何检查出两个给定的字符串是反序的?

  思路主要是,从开始字符,和另外一个从末尾字符比较,先判断长度是否相同,不同直接不可能反文。然后再比较。

  12、Java 中如何将字符串转换为整数?

  String s="123";

  int i;

  第一种方法:i=Integer.parseInt(s);

  第二种方法:i=Integer.valueOf(s).intValue();

  13、在没有使用临时变量的情况如何交换两个整数变量的值?

  加减法、乘除法、异或法。

  14、接口是什么?为什么要使用接口而不是直接使用具体类?

  接口用于定义 API。它定义了类必须得遵循的规则。同时,它提供了一种抽象,因为客户端只使用接口,这样可以有多重实现,如 List 接口,你可以使用可随机访问的 ArrayList,也可以使用方便插入和删除的 LinkedList。接口中不允许写代码,以此来保证抽象。

  15、Java 中,抽象类与接口之间有什么不同?

  Java 中,抽象类和接口有很多不同之处,但是最重要的一个是 Java 中限制一个类只能继承一个类,但是可以实现多个接口。抽象类可以很好的定义一个家族类的默认行为,而接口能更好的定义类型,有助于后面实现多态机制。

  16、除了单例模式,你在生产环境中还用过什么设计模式?

  这需要根据你的经验来回答。一般情况下,你可以说依赖注入,工厂模式,装饰模式或者观察者模式,随意选择你使用过的一种即可。不过你要准备回答接下的基于你选择的模式的问题。

  17、你能解释一下里氏替换原则吗?

  首先,这是编译器的要求,如果不这么做,无法通过编译。其次,面向对象的编程,其中继承有个大原则,任何子类的对象都可以当成父类的对象使用。

  18、什么情况下会违反迪米特法则?为什么会有这个问题?

  迪米特法则建议“只和朋友说话,不要陌生人说话”,以此来减少类之间的耦合。

  19、适配器模式是什么?什么时候使用?

  适配器模式提供对接口的转换。如果你的客户端使用某些接口,但是你有另外一些接口,你就可以写一个适配去来连接这些接口。

  20、什么是“依赖注入”和“控制反转”?为什么有人使用?

  控制反转(IOC)是 Spring 框架的核心思想,用我自己的话说,就是你要做一件事,别自己可劲 new 了,你就说你要干啥,然后外包出去就好~依赖注入(DI) 在我浅薄的想法中,就是通过接口的引用和构造方法的表达,将一些事情整好了反过来传给需要用到的地方。

  21、抽象类是什么?它与接口有什么区别?你为什么要使用过抽象类?

  a、接口用于规范,抽象类用于共性。

  b、声明方法的存在而不去实现它的类被叫做抽象类。

  c、接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。

  22、构造器注入和 setter 依赖注入,那种方式更好?

  每种方式都有它的缺点和优点。构造器注入保证所有的注入都被初始化,但是setter 注入提供更好的灵活性来设置可选依赖。如果使用 XML 来描述依赖,Setter 注入的可读写会更强。经验法则是强制依赖使用构造器注入,可选依赖使用 setter 注入。

  23、依赖注入和工程模式之间有什么不同?

  虽然两种模式都是将对象的创建从应用的逻辑中分离,但是依赖注入比工程模式更清晰。通过依赖注入,你的类就是 POJO,它只知道依赖而不关心它们怎么获取。使用工厂模式,你的类需要通过工厂来获取依赖。因此,使用 DI 会比使用工厂模式更容易测试。

  24、适配器模式和装饰器模式有什么区别?

  虽然适配器模式和装饰器模式的结构类似,但是每种模式的出现意图不同。适配器模式被用于桥接两个接口,而装饰模式的目的是在不修改类的情况下给类增加新的功能。

  25、适配器模式和代理模式之前有什么不同?

  这个问题与前面的类似,适配器模式和代理模式的区别在于他们的意图不同。由于适配器模式和代理模式都是封装真正执行动作的类,因此结构是一致的,但是适配器模式用于接口之间的转换,而代理模式则是增加一个额外的中间层,以便支持分配、控制或智能访问。

  26、什么是模板方法模式?

  模板方法提供算法的框架,你可以自己去配置或定义步骤。例如,你可以将排序算法看做是一个模板。它定义了排序的步骤,但是具体的比较,可以使用Comparable 或者其语言中类似东西,具体策略由你去配置。列出算法概要的方法就是众所周知的模板方法。