精选文章 Java面试题全集(上)33 - 64

Java面试题全集(上)33 - 64

作者:NightDW 时间: 2020-08-04 05:17:10
NightDW 2020-08-04 05:17:10

原帖:https://blog.csdn.net/jackfrued/article/details/44921941

个人认为原帖的排版不太好,所以复制过来重新排下版,有少量的修改

本帖主要是给自己看的,有不懂的地方可以看下原帖

33、一个".java"源文件中是否可以包含多个类(不是内部类)?有什么限制?

可以,但一个源文件中最多只能有一个 public 类且文件名必须和公开类的类名完全一致。

 

34、Anonymous Inner Class(匿名内部类)是否可以继承其它类?是否可以实现接口?

都可以,在Swing编程和Android开发中常用此方式来实现事件监听和回调。

 

35、内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?

一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。

 

36、Java 中的final关键字有哪些用法?

  1. 修饰类:表示该类不能被继承;
  2. 修饰方法:表示方法不能被重写;
  3. 修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。

 

37、指出下面程序的运行结果。

class A {
    static {
        System.out.print("1");
    }
    public A() {
        System.out.print("2");
    }
}
class B extends A{
    static {
        System.out.print("a");
    }
    public B() {
        System.out.print("b");
    }
}
public class Hello {
    public static void main(String[] args) {
        A ab = new B();
        ab = new B();
    }
}

执行结果:1a2b2b。创建对象时构造器的调用顺序是:先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器。

 

38、如何将字符串转换为基本数据类型?如何将基本数据类型转换为字符串?

调用基本数据类型的包装类的parseXXX(String)或valueOf(String)方法即可返回相应的基本类型;

将基本数据类型与空字符串连接或调用String类中的valueOf()方法即可返回相应的字符串。

 

39、如何实现字符串的反转及替换?

可以自己写实现也可以使用String或StringBuffer/StringBuilder中的方法。递归实现:

public static String reverse(String originStr) {
    if(originStr == null || originStr.length() <= 1) 
        return originStr;
    return reverse(originStr.substring(1)) + originStr.charAt(0);
}

 

40、怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符串?

new String("Test".getBytes("GB2312"), "ISO-8859-1");

 

41、日期和时间:
- 如何取得年月日、小时分钟秒?
- 如何取得从1970年1月1日0时0分0秒到现在的毫秒数?
- 如何取得某月的最后一天?
- 如何格式化日期?

问题1:通过 java.util.Calendar 或 java.time.LocalDateTimel 对象来获取,代码如下所示:

public class DateTimeTest {
    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();
        System.out.println(cal.get(Calendar.YEAR));
        System.out.println(cal.get(Calendar.MONTH));    // 0 - 11
        System.out.println(cal.get(Calendar.DATE));
        System.out.println(cal.get(Calendar.HOUR_OF_DAY));
        System.out.println(cal.get(Calendar.MINUTE));
        System.out.println(cal.get(Calendar.SECOND));

        // Java 8
        LocalDateTime dt = LocalDateTime.now();
        System.out.println(dt.getYear());
        System.out.println(dt.getMonthValue());     // 1 - 12
        System.out.println(dt.getDayOfMonth());
        System.out.println(dt.getHour());
        System.out.println(dt.getMinute());
        System.out.println(dt.getSecond());
    }
}

问题2:以下方法均可获得该毫秒数:

Calendar.getInstance().getTimeInMillis();
System.currentTimeMillis();
Clock.systemDefaultZone().millis(); // Java 8

问题3:代码如下所示:

Calendar.getInstance().getActualMaximum(Calendar.DAY_OF_MONTH);

问题4:利用java.text.DataFormat 的子类(如SimpleDateFormat类)中的format(Date)方法可将日期格式化。Java 8中可以用java.time.format.DateTimeFormatter来格式化时间日期,代码如下所示:

class DateFormatTest {
    public static void main(String[] args) {
        SimpleDateFormat oldFormatter = new SimpleDateFormat("yyyy/MM/dd");
        Date date1 = new Date();
        System.out.println(oldFormatter.format(date1));

        // Java 8
        DateTimeFormatter newFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        LocalDate date2 = LocalDate.now();
        System.out.println(date2.format(newFormatter));
    }
}

补充:Java的时间日期API一直是被诟病的东西。为了解决这一问题,Java 8引入了新的时间日期API,如Clock、LocalDate、LocalTime、LocalDateTime、Instant等类,它们的设计都使用了不变模式,是线程安全的设计。

 

42、打印昨天的当前时刻。

class YesterdayCurrent {
    public static void main(String[] args){
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, -1);
        System.out.println(cal.getTime());

        //Java 8
        LocalDateTime today = LocalDateTime.now();
        LocalDateTime yesterday = today.minusDays(1);
        System.out.println(yesterday);
    }
}

 

43、比较一下Java和JavaSciprt。

  1. Java 是Sun公司的,前身是Oak语言;而JavaScript是Netscape公司的,前身是LiveScript。
  2. 面向对象和基于对象:Java是面向对象的语言,开发程序前必须设计对象;JS是一种基于对象和事件驱动的脚本语言,它本身提供了许多内部对象供设计人员使用。
  3. 编译和解释:Java的源代码在执行之前必须经过编译;JS是解释性的编程语言,源代码无需编译,可直接由浏览器解释执行(目前的浏览器几乎都使用了JIT(即时编译)技术来提升JS的效率)。
  4. 强类型和弱类型:Java采用强类型变量检查,所有变量在编译之前必须作声明;JS的变量是弱类型的,甚至在使用变量前可以不作声明,JavaScript的解释器在运行时检查推断其数据类型。
  5. 代码格式不一样。

补充:其实Java和JavaScript最重要的区别是一个是静态语言,一个是动态语言。目前的编程语言的发展趋势是函数式语言和动态语言。在Java中是一等公民,而JavaScript中函数是一等公民,因此JavaScript支持函数式编程,可以使用Lambda函数和闭包(closure),当然Java 8也开始支持函数式编程,提供了对Lambda表达式以及函数式接口的支持。

 

44、什么时候用断言(assert)?

断言在软件开发中是一种常用的调试方式。一般来说,断言用于保证程序最基本、关键的正确性。断言检查通常在开发和测试时开启,在软件发布后关闭(为了保证效率)。

断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为true;如果表达式的值为false,那么系统会报告一个AssertionError。断言的使用如下面的代码所示:

assert(a > 0); // throws an AssertionError if a <= 0

断言可以有两种形式:

  1. assert Expression1;
  2. assert Expression1 : Expression2 ;

Expression1 应该总是产生一个布尔值。
Expression2 可以是得出一个值的任意表达式;这个值用于生成显示更多调试信息的字符串消息。

运行时启用/禁用断言:在启动JVM时使用-enableassertions或-ea标记/-disableassertions或-da标记。

在系统类中启用或禁用断言:可使用-esa或-dsa标记。此外还可以在包的基础上启用或者禁用断言。

注意:断言不应该以任何方式改变程序的状态。简单的说,如果希望在不满足某些条件时阻止代码的执行,就可以考虑用断言来阻止它。

 

45、Error和Exception有什么区别?

Error表示系统级的错误和程序不必处理的异常,是很难恢复的严重问题;比如内存溢出,不能指望程序来处理这样的异常;Exception表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题;也就是说,它用于表示如果程序运行正常,就不会发生的情况。

 

46、try{}里有一个return语句,那么紧跟在这个try后的finally{}里的代码会不会被执行,什么时候被执行?

会执行,在方法返回调用者前执行。

注意:在finally中改变返回值的做法是不好的,因为如果存在finally代码块,try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后再向调用者返回其值,然后如果在finally中修改了返回值,并不会返回修改后的值(除非在修改后直接在finally中return了)。

 

47、Java语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?

Java通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java中,每个异常都是一个对象,它是Throwable类或其子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并可以对其进行处理。Java的异常处理是通过5个关键词来实现的:throw、throws、try、catch、finally。

  • try代码块用来存放一段可能抛出异常的代码;
  • catch代码块用来存放捕获到指定的异常时需要执行的一段代码;
  • finally代码块用来存放不管是否出现异常都需要执行的一段代码;
  • throw用来明确地抛出一个异常对象;
  • throws用来声明一个方法可能抛出的各种异常(当然声明异常时允许无病呻吟)。

try语句可以嵌套,每遇到一个try语句,异常的结构就会被放入异常栈中,直到所有的try语句都完成。如果下一级的try语句没有对某种异常进行处理,异常栈就会执行出栈操作,直到遇到有处理该异常的try语句或者最终将异常抛给JVM。

 

48、运行时异常与受检异常有何异同?

异常表示程序运行过程中可能出现的非正常状态。

  • 运行时异常是一种常见的运行错误,表示虚拟机的通常操作中可能遇到的异常。一般来说,只要程序设计得当,就不会发生运行时异常。
  • 受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。

Java编译器要求:方法必须声明抛出可能发生的受检异常,在方法内部捕获到受检异常时需要进行处理或继续抛出。而运行时异常则无需在方法上声明,我们也无需对捕获到的运行时异常进行任何操作。

异常和继承一样,是面向对象程序设计中经常被滥用的东西。异常处理的指导原则:

  • 不要将异常处理用于正常的控制流(设计良好的API不应该强迫调用者为了正常的控制流而使用异常)
  • 对可以恢复的情况使用受检异常,对编程错误使用运行时异常
  • 避免不必要的使用受检异常(可以通过一些状态检测手段来避免异常的发生)
  • 优先使用标准的异常
  • 每个方法抛出的异常都要有文档
  • 保持异常的原子性
  • 不要在catch中忽略掉捕获到的异常

 

49、列出一些你常见的运行时异常?

  • ArithmeticException(算术异常)
  • ClassCastException (类转换异常)
  • IllegalArgumentException (非法参数异常)
  • IndexOutOfBoundsException (下标越界异常)
  • NullPointerException (空指针异常)
  • SecurityException (安全异常)

 

50、阐述final、finally、finalize的区别。

  • final:修饰符(关键字)有三种用法:如果一个类被声明为final,意味着它不能再派生出新的子类,即不能被继承,因此它和abstract是反义词。将变量声明为final,可以保证它们在使用中不被改变,被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取不可修改。被声明为final的方法也同样只能使用,不能在子类中被重写。
  • finally:通常放在try…catch…的后面构造总是执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行,可以将释放外部资源的代码写在finally块中。
  • finalize:Object类中的方法,垃圾收集器在将对象从内存中清除出去之前会先调用其finalize()方法来完成必要的清理工作。通过重写finalize()方法可以整理系统资源或者执行其他清理工作。

 

51、类ExampleA继承Exception,类ExampleB继承ExampleA。请问下面代码的输出是什么?

try {
    throw new ExampleB("b")
} catch(ExampleA e){
    System.out.println("ExampleA");
} catch(Exception e){
    System.out.println("Exception");
}

ExampleA(里氏代换原则)。

 

52、List、Set、Map是否继承自Collection接口?

List、Set 是,Map 不是。Map是键值对映射容器,与List和Set有明显的区别。

Set存储的零散的元素且不允许有重复元素,List是线性结构的容器,适用于按数值索引访问元素的情形。

 

53、阐述ArrayList、Vector、LinkedList的存储性能和特性。

ArrayList 和Vector都是使用数组方式存储数据,此数组大小大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢;和ArrayList相比,Vector是线程安全的,但性能较差。

LinkedList使用双向链表实现存储(将内存中零散的内存单元通过附加的引用关联起来,形成一个可以按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,内存的利用率更高),按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。

Vector属于遗留容器(Java早期版本提供的容器。Hashtable、Dictionary、BitSet、Stack、Properties也是遗留容器),已经不推荐使用。即使需要线程安全的容器,也一般不使用Vector;可通过 Collections 的 synchronizedList() 方法将容器其转换成线程安全的容器后再使用(这是对装潢模式的应用)。

 

54、Collection和Collections的区别?

Collection是一个接口,它是Set、List等容器的父接口;Collections是个一个工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等等。

 

55、List、Map、Set三个接口存取元素时,各有什么特点?

List 以特定索引来存取元素,可以有重复元素。Set 不能存放重复元素(用对象的equals()方法来区分元素是否重复)。Map 保存键值对(key-value pair)映射,映射关系可以是一对一或多对一。

Set 和 Map 容器都有基于哈希存储和排序树的两种实现版本:

  • 基于哈希存储的版本理论存取时间复杂度为O(1);
  • 基于排序树的版本在增删元素时会按照元素或 Key 构成排序树从而达到排序和去重的效果。

 

56、TreeMap 和 TreeSet 在排序时如何比较元素?Collections 工具类中的 sort() 方法如何比较元素?

TreeSet 要求存放的元素所属的类必须实现 Comparable 接口,该接口提供了 compareTo() 方法,当插入元素时会回调该方法比较元素的大小。TreeMap 要求存放的 Key 必须实现Comparable接口。

Collections 工具类的 sort 方法有两种重载的形式:

  1. 要求容器中存放的对象实现 Comparable 接口;
  2. 要求传入 Comparator 接口的子类型来临时定义一个排序规则,通过该接口的 compare() 方法比较元素大小,这是对回调模式的应用(Java中对函数式编程的支持)。

 

57、Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?

sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保持,休眠时间结束后会自动回到就绪状态。

wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),如果线程重新获得对象的锁就可以进入就绪状态。

补充:进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是操作系统进行资源分配和调度的一个独立单位;线程是进程的一个实体,是CPU调度和分派的基本单位,是比进程更小的能独立运行的基本单位。

线程的划分尺度小于进程,这使得多线程程序的并发性高;进程在执行时通常拥有独立的内存单元,而线程之间可以共享内存。多线程编程通常能带来更好的性能和用户体验,但是多线程的程序对于其他程序是不友好的,因为它可能占用了更多的CPU资源。当然,也不是线程越多,性能就越好,因为线程的调度和切换也会浪费CPU时间。

 

58、线程的sleep()方法和yield()方法有什么区别?

  1. sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;
  2. 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;
  3. sleep()方法声明抛出 InterruptedException,而yield()方法没有声明任何异常;
  4. sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性。

 

59、当一个线程进入一个对象的synchronized方法A之后,其它线程能否进入此对象的同步方法B?

不能。其它线程只能访问该对象的非同步方法,同步方法则不能进入。

因为非静态方法上的synchronized修饰符要求执行方法时要获得对象的锁,如果已经进入A方法说明对象锁已经被取走,那么试图进入B方法的线程就只能在等锁池(注意不是等待池哦)中等待对象的锁。

 

60、请说出与线程同步以及线程调度相关的方法。

  • sleep():使当前运行的线程处于睡眠状态,是一个静态方法,需要处理 InterruptedException 异常;
  • wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;
  • notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;
  • notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态;

补充:Java 5通过 Lock 接口提供了显式的锁机制(explicit lock),增强了灵活性以及对线程的协调。Lock 接口中定义了加锁(lock())和解锁(unlock())的方法,同时还提供了 newCondition() 方法来产生用于线程之间通信的 Condition 对象;此外,Java 5还提供了信号量机制(semaphore),信号量可以用来限制对某个共享资源进行访问的线程的数量。在对资源进行访问之前,线程必须得到信号量的许可(调用 Semaphore 对象的 acquire() 方法);在完成对资源的访问后,线程必须向信号量归还许可(调用 Semaphore 对象的 release() 方法)。

 

61、编写多线程程序有几种实现方式?

Java 5 以前有两种实现方法:一种是继承Thread类;另一种是实现Runnable接口。两种方式都要通过重写run()方法来定义线程的行为。后者更加灵活,因为Java中的继承是单继承,如果继承了 Thread 类就无法再继承其他类了。

补充:Java 5后还可以实现Callable接口,其 call() 方法有返回值且可以抛出异常。

 

62、synchronized关键字的用法?

synchronized关键字可以将对象或者方法标记为同步,以实现对对象和方法的互斥访问;

可以用synchronized(对象) { … } 定义同步代码块,或者在声明方法时将synchronized作为方法的修饰符。

 

63、举例说明同步和异步。

同步:一个任务需要等待另一个任务完成可以继续执行;多线程对临界资源的互斥访问是同步的。

异步:一个任务无需等待另一个任务完成可以继续执行;如果应用程序调用了一个耗时很长的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程。

很多情况下,采用异步途径更有效率。事实上,同步就是指阻塞式操作,而异步就是非阻塞式操作。

 

64、启动一个线程是调用run()还是start()方法?

启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由 JVM 调度并执行,这并不意味着线程就会立即运行。run()方法是线程启动后要进行回调(callback)的方法。

勿删,copyright占位
分享文章到微博
分享文章到朋友圈

上一篇:Linux sudo设置

下一篇:libconfig LIST操作

您可能感兴趣

  • 安装SQL Server 2016

    介绍 (Introduction) Microsoft SQL Server 2016 provides faster transactions and queries, deeper insights on any device, advanced analytics, new security technology, and new hybrid cloud scenarios. Alo...

  • mysql 查询最顶级_2018顶级MySQL博客作者

    mysql 查询最顶级 We made a collection of the most popular MySQL bloggers, including a link to each individual blog. The ranking is based on Alexa global score as of April 25, 2019. 我们收集了一些最受欢迎MySQL博客,包括...

  • SQL varchar数据类型深入探讨

    In this article we’ll review the SQL varchar data type including a basic definition and overview, differences from varchar(n), UTF-8 support, Collation, performance considerations and more. 在本文中,我们...

  • 每周全球科技十大新闻(2020.7.20-7.26)

    每周全球科技十大新闻 Weekly Worldwide Top10 Technology News WWTTN 每周发布 新闻摘要: (1)寒武纪成为科创板人工智能芯片第一股,未来可期 (2)富士康拟在青岛建厂造芯片,对我国半导体产业有何贡献? (3)据传:甲骨文中国将N+6再现?再次裁员该消息有待证实 (4)奇安信IPO,未来要与深信服PK,你猜谁会赢? (5)这两个芯片厂商的2020第二...

  • 【收藏】万字综述,核心开发者全面解读PyTorch内部机制

    (给机器学习算法与Python学习加星标,提升AI技能) 选自ezyang博客 作者:Edward Z. Yang 本文由机器之心(nearhuman2014)整理 斯坦福大学博士生与 Facebook 人工智能研究所研究工程师 Edward Z. Yang 是 PyTorch 开源项目的核心开发者之一。他在 5 月 14 日的 PyTorch 纽约聚会上做了一个有关 ,本文是他有关PyTo...

  • 软件测试面试1--软件测试基础理论(持续更新中...)

    1.软件测试工程师的素质: 良好的沟通和表达能力 具有怀疑与破坏的精神 扎实的软件测试基础知识 缜密的业务逻辑分析能力 处在用户的角度进行换位思考 足够的耐心、细心、信心、责任心 积极乐观向上的心态和团队协作能力 要有严谨、敢于承担责任、稳重的做事风格 善于自我总结、自我督促和不断学习的能 2.软件的分类: 软件 = 程序 + 数据 + 文档。   按照功能划分:     系统软件:如操作系...

  • 集合类面试题

    集合类面试题 1.Java集合框架是什么?说出一些集合框架的优点? 每种编程语言中都有集合,最初的Java版本包含几种集合类:Vector、Stack、HashTable和Array。随着集合的广泛使用,Java1.2提出了囊括所有集合接口、实现和算法的集合框架。在保证线程安全的情况下使用泛型和并发集合类,Java已经经历了很久。它还包括在Java并发包中,阻塞接口以及它们的实现。 集合框架...

  • NL 学习资源

    https://github.com/fighting41love/funNLP 在入门到熟悉NLP的过程中,用到了很多github上的包,遂整理了一下,分享在这里。 很多包非常有趣,值得收藏,满足大家的收集癖! 如果觉得有用,请分享并star,谢谢! 长期不定时更新,欢迎watch和fork! 涉及内容包括但不限于:中英文敏感词、语言检测、中外手机/电话归属地/运营商查询、名字推断性别、手...

华为云40多款云服务产品0元试用活动

免费套餐,马上领取!
CSDN

CSDN

中国开发者社区CSDN (Chinese Software Developer Network) 创立于1999年,致力为中国开发者提供知识传播、在线学习、职业发展等全生命周期服务。