【面试】Java(低频)

一、Java基础

1、谈谈你对Java平台的理解?【第1讲】

答:

  • 1、相较C语言,Java面向对象,有GC(垃圾收集),不用关心内存分配和回收;
  • 2、JVM(跨平台)、JRE(Java基础运行环境)、JDK(Java开发工具包)
    1)JVM + 【Java类库、某些模块等】= JRE
    2)JRE + 【编译器、诊断等工具】 = JDK

1

  • 3、拓展
    1
    ……
追问1:面向过程和面向对象有什么区别?
角度面向过程面向对象
特点以分步骤解决问题,用方法组织代码以分类解决问题,用类组织代码。
优点性能好工程更加模块化,实现更低耦合和高内聚
缺点适应性差、可拓展性与可维护性差类调用需要实例化,开销大
特征步骤封装、继承、多态

关系:细节用面向过程解决,整体面向对象把控,相辅相成。

追问3:Java和Python的区别
角度JavaPython
类型静态类型,变通实现运行时修改全动态
语法面向对象结合函数式编程与面向对象
开发周期有丰富库,快
执行效率性能稳定,扩展性好较差
领域服务器、Web、安卓脚本处理、AI、图形图像
追问5:“Java 是解释执行”,这个说法正确吗?

答:不太准确。 Java 的源代码首先通过 Javac 编译成为字节码(bytecode),在运行时,JVM内嵌的解释器将字节码转换成为最终的机器码。

但常见 JVM(如 Hotspot JVM)都提供了 JIT(Just-In-Time)编译器,即动态编译器,能在运行时将热点代码编译成机器码,这种情况下部分热点代码就属于编译执行,而不是解释执行了。

2、Java提供了哪些IO方式(*2)? NIO如何实现多路复用?【第11讲】

Java IO 方式有很多种,基于不同的 IO 抽象模型和交互方式,可以进行简单区分。

首先,传统的 java.io 包,它基于流模型实现,提供了我们最熟知的一些 IO 功能,比如 File 抽象、输入输出流等。交互方式是同步、阻塞的方式,也就是说,在读取输入流或者写入输出流时,在读、写动作完成之前,线程会一直阻塞在那里,它们之间的调用是可靠的线性顺序。

java.io 包的好处是代码比较简单、直观,缺点则是 IO 效率和扩展性存在局限性,容易成为应用性能的瓶颈。

很多时候,人们也把 java.net 下面提供的部分网络 API,比如 Socket、ServerSocket、HttpURLConnection 也归类到同步阻塞 IO 类库,因为网络通信同样是 IO 行为。

第二,在 Java 1.4 中引入了 NIO 框架(java.nio 包),提供了 Channel、Selector、Buffer 等新的抽象,可以构建多路复用的、同步非阻塞 IO 程序,同时提供了更接近操作系统底层的高性能数据操作方式。

第三,在 Java 7 中,NIO 有了进一步的改进,也就是 NIO 2,引入了异步非阻塞 IO 方式,也有很多人叫它 AIO(Asynchronous IO)。异步 IO 操作基于事件和回调机制,可以简单理解为,应用操作直接返回,而不会阻塞在那里,当后台处理完成,操作系统会通知相应线程进行后续工作。

3、Java有几种文件拷贝方式?哪一种最高效?【第12讲】

Java 有多种比较典型的文件拷贝实现方式,比如:

利用 java.io 类库,直接为源文件构建一个 FileInputStream 读取,然后再为目标文件构建一个 FileOutputStream,完成写入工作。


public static void copyFileByStream(File source, File dest) throws
        IOException {
    try (InputStream is = new FileInputStream(source);
         OutputStream os = new FileOutputStream(dest);){
        byte[] buffer = new byte[1024];
        int length;
        while ((length = is.read(buffer)) > 0) {
            os.write(buffer, 0, length);
        }
    }
 }

或者,利用 java.nio 类库提供的 transferTo 或 transferFrom 方法实现。


public static void copyFileByChannel(File source, File dest) throws
        IOException {
    try (FileChannel sourceChannel = new FileInputStream(source)
            .getChannel();
         FileChannel targetChannel = new FileOutputStream(dest).getChannel
                 ();){
        for (long count = sourceChannel.size() ;count>0 ;) {
            long transferred = sourceChannel.transferTo(
                    sourceChannel.position(), count, targetChannel);            sourceChannel.position(sourceChannel.position() + transferred);
            count -= transferred;
        }
    }
 }

当然,Java 标准类库本身已经提供了几种 Files.copy 的实现。

对于 Copy 的效率,这个其实与操作系统和配置等情况相关,总体上来说,NIO transferTo/From 的方式可能更快,因为它更能利用现代操作系统底层机制,避免不必要拷贝和上下文切换。

4、写正则表达式进行手机号匹配(*2)
# 号码规则:
1、第 1 位: 1
2、第 2 位: 39
3、第 3 到第 11 位只要是数字就行.


答案: /^[1]([3-9])[0-9]{9}$/

(1) /^ - 表示文本开始;
(2) () - 子表达式的开始与结束;
(3) [] - 要匹配里面内容,[0-9]匹配数字范围为0/1/2/3/4/5/6/7/8/9(4) {n} - 匹配n次,{9}是匹配9次;
(5) ^ - 字符串开始,\^ - 匹配 ^ 字符本身; $ - 字符串结束。
5、什么情况下Java程序会产生死锁?(*2)如何定位、修复?(*2)【第18讲】(死锁处理办法)

死锁是一种特定的程序状态,在实体之间,由于循环依赖导致彼此一直处于等待之中,没有任何个体可以继续前进。死锁不仅仅是在线程之间会发生,存在资源独占的进程之间同样也可能出现死锁。通常来说,我们大多是聚焦在多线程场景中的死锁,指两个或多个线程之间,由于互相持有对方需要的锁,而永久处于阻塞的状态。

你可以利用下面的示例图理解基本的死锁问题:
9

定位死锁最常见的方式就是利用 jstack 等工具获取线程栈,然后定位互相之间的依赖关系,进而找到死锁。如果是比较明显的死锁,往往 jstack 等就能直接定位,类似 JConsole 甚至可以在图形界面进行有限的死锁检测。

如果程序运行时发生了死锁,绝大多数情况下都是无法在线解决的,只能重启、修正程序本身问题。所以,代码开发阶段互相审查,或者利用工具进行预防性排查,往往也是很重要的。

追问1:Java调试命令。看线程运行状态用什么?看堆栈信息用什么?

……

6、如何终止一个正在运行的线程?

stop():一剑封喉,被终止线程没机会料理后事,不建议使用。
interrupt():可以将休眠线程转换为RUNNAVBLE状态,设置中断位,然后判断是否中止。
……

追问1:如何优雅终止线程池?

方法:shutdown()和shutdownNow()
shutdown():保守,执行后,不接收新任务,但会等待正在执行和阻塞任务执行完,才最终关闭。
shutdownNow():激进,拒绝新任务,同时强制停止正在执行与阻塞队列任务,优雅结束需要正确处理线程中断。

三、JVM

1、Java内存模型中的happen-before是什么?【第29讲】

真正含义即关闭所有的编译器、操作系统和处理器的优化,所有指令顺序全部按照程序代码书写的顺序执行。 去掉CPU高速缓存,让CPU的每次读写操作都直接与主存交互。

……

补充:Happen-before规则内容

程序次序规则:在单线程中,代码的执行是有序的,虽然可能会存在运行指令的重排序,但最终执行的结果和顺序执行的结果是一致的;

锁定规则:一个锁处于被一个线程锁定占用状态,那么只有当这个线程释放锁之后,其它线程才能再次获取锁操作;

volatile 变量规则:如果一个线程正在写 volatile 变量,其它线程读取该变量会发生在写入之后;

线程启动规则:Thread 对象的 start() 方法先行发生于此线程的其它每一个动作;

线程终结规则:线程中的所有操作都先行发生于对此线程的终止检测;

对象终结规则:一个对象的初始化完成先行发生于它的 finalize() 方法的开始;

传递性:如果操作 A happens-before 操作 B,操作 B happens-before 操作 C,那么操作 A happens-before 操作 C;

线程中断规则:对线程 interrupt() 方法的调用先行发生于被中断线程的代码检测到中断事件的发生。

2、你用过哪些JVM参数?

JVM参数作用
-Xms堆的最小空间大小
-Xmx设置堆最大空间大小
-XX:NewSize设置新生代最小空间大小
-XX:MaxNewSize设置新生代最小空间大小
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值