本文编写于 118 天前,最后修改于 118 天前,其中某些信息可能已经过时。

附:2019年Java最新面试指南80题*(点击链接进入)

Java 最新面试题大全 11-20 题 http://blog.zh66.club/index.php/archives/109/
Java 最新面试题大全 21-30 题 http://blog.zh66.club/index.php/archives/110/
Java 最新面试题大全 31-40 题 http://blog.zh66.club/index.php/archives/111/
Java 最新面试题大全 41-50 题 http://blog.zh66.club/index.php/archives/112/
Java 最新面试题大全 51-60 题 http://blog.zh66.club/index.php/archives/113/
Java 最新面试题大全 61-70 题 http://blog.zh66.club/index.php/archives/114/
Java 最新面试题大全 71-80 题 http://blog.zh66.club/index.php/archives/115/

问题 #41

用户如果直接关闭浏览器,网站后台能够知道该用户已经断开吗?

共 433 次阅读

答案

如果客户端直接关闭浏览器,服务器不会知道它已经断线。

关闭浏览器时,浏览器并不会发消息来通知服务器,所以服务器怎么会知道呢?

但是,服务器端有一个会话超时的机制。当浏览器与服务器发起一次交互时,服务器会记住最后一次交互的时间。当某个会话长时间(比如,1800秒)未被刷新时,则客户端已经超时(掉线)。

比如,网站后台记录这样的一个结构:

( JessionID, lastAccessTime )

( JessionID, lastAccessTime )

( JessionID, lastAccessTime )

每个会话有一个ID, 一个最后访问时间 lastAccessTime。当浏览器与服务器有交互时,对应会话的lastAccessTime会被刷新了当前时间。服务器只要定时的检查,看哪个会话已经超时,没认为相应的客户端已经掉线。

问题 #42

在Swing里,当鼠标点到子控件的时候,父容器的鼠标事件监听器会不会被触发?

共 213 次阅读

答案

举个例子,

​ JPanel a = new JPanel()

​ JLabel label = new JLabel("xy");

​ a.add ( label )

​ a.addMouseListener ( ... )

那么,当鼠标点到 label 上时,JPanel a 的监听器能够收到这个鼠标事件。

但是,如果在 JPanel 里放一个 JButton ,情况就不同了。当鼠标点到 JButton 上时,父容器 JPanel 的监听器就不起作用。

实际上,只要子控件不接收的事件,都会传到父容器。但是如果子控件里有 addMouseListener() 或者 enableEvents() 了,就代表子控件对此事件感兴趣,父容器就收不到了。

问题 #43

为什么说 Java程序是跨平台的?

共 441 次阅读

答案

所谓跨平台,是指一个程序、或一份代码,可以自动适用于多个平台。在迁移到新平台时不需要改动,便称为具有跨平台特性。

对于Java程序,以.class / .jar 方式发布。在 Windows上运行时,是java.exe -jar YourApp.jar 。在 Linux或iOS上运行时,也是java -jar YourApp.jar ,不需要任何改动。需要Java是一次编译,多平台运行,真正的跨平台。

那么,它是如何做到跨平台运行的呢?

我们注意到,在Windows上用于运行Java程序的是 java.exe ,而在 Linux上是另一个 java。也就是说,不同的平台上 java/bin 下的东西是不一样的,不同的平台有不同的java解释器。

问题 #44

当用户关闭浏览器时,服务器会立刻销毁相应的Session对象吗?

共 265 次阅读

答案

不会,因为当用户关闭浏览器时, Tomcat 后台无法感知。

但是,Session有一个刷新和超时机制。用户每一次访问后台时,无论时访问静态文件,还是访问Servlet,都会刷新Session。

Tomcat会定时检查Session,将长期没有刷新的Session(已超时的)给删掉。所以当用户关闭浏览器后,后台相应的Session不再被刷新,于是一定时间超时之后,该Session会被自己删除。

问题 #46

MySQL 现在还免费吗?它和 mariadb 是什么关系?

共 459 次阅读

答案

MySQL起初是一个免费开源的软件,遵守GPL协议发布。后来MySQL被Oracle收购,之后再越来越倾向于收费了。于是MySQL的创始人觉得不太愉快,他就在MySQL5的基础上,自己开辟了一个分支,仍然走开源路线,并命名为MariaDB。

估计Maria是这个大佬的某个亲人的名字。按照大佬的觉悟,必然是不喜欢商业化,而是觉得自己来领导一个具有全球影响力的项目来得更有成就感。

就我们来说,自然是欢迎大佬的决定的。MariaDB和MySQL的用法完全一致,当然后面会和MySQL越走越远。在CentOS7上,默认的数据库已经变成了mariadb。

关于mariadb的使用说明,参考《数据库篇

问题 #47

APP 端怎么把一个文件传给网站后台?有几种可能的办法?

注:无论桌面GUI还是安卓GUI,均称为APP

共 450 次阅读

答案

1 HTTP POST Multi-Part 方式,即表单文件上传方式

参数《项目应用篇》之连接Web服务器

2 HTTP POST RESTful 方式,即普通文本类消息接口

此时,需要先将文件内容读取出来转成 Hex 或 Base64 的文本传给后台

形如:

{

​ "type": "jpg" ,

​ "name": "some.jpg",

​ "fileSize": "134834",

​ "fileData" : "2asdkjuewefasdfliweuwe" //此处为Hex 或 Base64编码的文件数据

}

后台收接到后,将fileData取出并解码为原始文件数据。

3 FTP 方式

后台需要开设FTP服务器。客户端通过FTP协议,将文件传到后台。

关于FTP的使用,参考《项目应用篇》之连接FTP服务器

4 自定义协议

使用自定义TCP协议,也可以将文件上传到后台。

参考《网络通信篇》中的实例

问题 #48

如何统计一个网站的在线人数?

共 351 次阅读

答案

其实精确的人数是得不到的,但是可能通过监听Session的创建和销毁。

认为一次Session算一个访客。当访问关闭浏览器后,Session在十几分钟后超时然后自动销毁。所以记录一下当前Session的数量,近似为在线人数。

@WebListener

public class SessionCountListener implements HttpSessionListener

{

   public static int currentUserCount = 0;   

   @Override

   public void sessionCreated(HttpSessionEvent ss)

   {      

​      currentUserCount ++;    

​      // System.out.println("Session创建,用户数: " + currentUserCount);

   }



   @Override

   public void sessionDestroyed(HttpSessionEvent ss)

   {   

​      currentUserCount --;

​      // System.out.println("Session销毁,用户数: " + currentUserCount);

   }

}

其中,注意添加注解 @WebListener ,表示这一个Web监听器。全局变量 SessionCountListener.currentUserCount就是当前在线人数。

问题 #49

网站后台如何访问自己的部署目录?

比如,在 server.xml 里配置为:

<Context path="/qianwen" docBase="E:JavaWebaf_qianwenWebRoot" />

则网站应用的目录位置为:E:JavaWebaf_qianwenWebRoot ,那么在后台代码里怎么得到这个目录?

共 316 次阅读

答案

在 Filter 或者 Servlet 里,可以使用 ServletContext 的 getRealPath() 方法来获取

在Filter里,

@Override

public void init(FilterConfig filterCfg) throws ServletException

{

​ String appDir = filterCfg.getServletContext().getRealPath("/");

​ 。。。

}

在 Servlet里,

返回的值就是Webroot所在目录 :E:JavaWebaf_qianwenWebRoot

问题 #50

JDBC的Connection对象,和C3P0的Connection对象有什么区别?

共 360 次阅读

答案

首先要再强调一下,在 JDBC 连接数据库时,连接池支持是必不可少的。

使用JDBC获得的Connection,它代表了一个Socket连接,若关闭了就是Socket关闭了。

使用C3P0获得的Connection,它也代表了一个连接。区别在于,当关闭这个连接的时候,Socket并未关闭,而只是把Connection放回到池子里。这也是连接池技术能提高数据库访问效率的原因。