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

附: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/

问题 #11

什么叫反编译?你把java程序(jar)交给别人,会被人看到源码吗?

次阅读

答案

※ 编译 Compile

将一个 .java文件编译成 .class 文件的过程,称为编译。

比如,HelloWorld.java 被编译后得到 HelloWorld.class

※ 反编译 Decompile

在.class文件里包含了完全的信息,包含类名、方法、属性、注解,除了注释文字之外的所有信息。所以从.class文件可以恢复得到原来的*.java文件,而且一丝不差!

.class 逆向得到 .java 的过程,称为反编译。

反编译之后,得到的.java和原始代码文件几乎完全相同,除了注释文字。所以,当你把.class或者 *.jar 交到别人手里时候,别人可以很容易的得到原始代码。

具体的反编译效果展示,可以参考《项目应用篇》之“反编译"一章。

* 如何防止别人反编译?

没有办法。就好比一个C程序可以反编译为汇编代码一样,*.class可以反编译得到Java代码。

但是,并不是完全没有办法,在业界普遍采用proguard混淆技术来对抗反编译,具体可以参考《项目应用篇》之“proguard混淆技术"一章。


问题 #12

HTTP GET与POST的区别什么? HTTP GET可以用来执行增删改操作吗?

共 455 次阅读

答案

HTTP GET 和 POST 的区别,很容易,也很明显,只要你用Wireshark抓包看过,就能很直观地看到区别。

GET: HTTP头部第一行为GET,参数放在URL里上传,通常没有HTTP内容体。

POST: HTTP头部第一行为POST字样,参数放在HTTP内容区。

这个区别,在 《网站入门篇》里有详细演示,相信学过的同学都是知道的。那么,下面的问题是,可以在响应HTTP GET请求时执行增删改操作吗?

可以的!后台怎么做,想做什么,完全由你自己决定!

一般来说,在定义后台接口时,查询类接口规定用GET方式,增删改类的接口用POST方式访问。但这是只是一个习惯性的做法,并不是什么硬性规定。

如果你喜欢,你也可以响应一个GET请求,在后台执行什么删除操作,都是可以的,技术上完全行得通。

这就好比,一般男人们留短发,女人们扎鞭子。但是这没有强制规定,你一个老爷们扎个鞭子、穿个裙子也完全可以。你自己喜欢就好,虽然别人会觉得怪怪的。


问题 #13

什么叫系统后门?后门与漏洞有什么区别?

去年爆发的勒索病毒案例中,被黑客利用的是Windows的后门、还是漏洞?

共 585 次阅读

答案

后门,是一个系统的作者故意留下的、只有作者自己知道的机关。

比如,一个洞府看起来是铜墙铁壁,但是若在它前面前念一声"芝麻开门!"便会在墙壁上凭空打开一个门。这便是一个后门,这是系统的作者故意留下的机关。

再比如,打开手机拨号键盘,正常使用的话就可以拨打电话。但是,若连续输入 *#06# ,变进入了特殊的处理程序: 显示当前手机序列号。这也是一个后门,是系统作者故意留下的手段。

可见,普通人无法看到后门的存在,但系统的作者知道后门在哪里。在输入特殊的指令后,便打开了后门,进入特殊的处理分支。注意重点: 只有作者自己知道这个指令!

如果让我们自己建立一个系统,是不是也可以留一些后门呢?当然可以!

比如,我们建了一个大楼,并在门口安装一个智能识别器。

当普通人进门时,识别器会发生声音:欢迎你!

但是,如果有一穿着红衣服的、进门时发出 "1..3..9..0..5..1" 的声音的人时,识别器会启动自毁程序、令大楼倒塌。显然,这个规则很复杂,普通人在进门时不会满足这个规则。但是我们是系统的作者,我们在认别器内写下了这么一段:

if ( 衣服 is red )

{

if ( 声音 == 1 . 3 . 9 .0 . 5. 1 )

{

进入自毁程序

}

}

这便是作者留下的后门,显然,除了作者自己,别人无法测出这个后门逻辑的存在。在别人看来,这就是一个普通的门,可以正常通讯!

同样的,如果我们自己来设计一个操作系统,比如叫 Doors 系统。这个系统上运行一些正常的服务,在普通人看来,这些服务很安全,比如就是FTP服务,可以在指定的目录下传递文件。

然而,身为作者的我们,只要发一段特殊的指令这个服务器,这个服务器在接收到指令后就会令系统崩溃。

因为,服务器是我们写的,我们在服务器中留下了这么一段:

public void doService( ... input )

{

if( input == 08 21 A8 89 12 38 98 )

{

进入自毁程序

}

.... 正常路径,提供正常服务

}

显然,我们只要把这段特殊指令 08 21 A8 89 12 38 98 发给服务器,便可以轻松攻破系统。为什么能这么轻松?因为你就是这个系统的作者啊!这个指令除了你,没有人知道它的存在!

那么,后门和漏洞有什么区别呢?其实也没什么区别了。。如果这个机关是故意留下的,那就是后门;如果是作者不小心留下来的,那便是漏洞。所以,倒底是后门还是漏洞,只凭作者一张嘴了!

对于一个不开源的系统,没有任何理由相信它是安全的。因为它里面的后门,技术上不可能测出。

对于一个开源的系统,如Linux,只要我们能吃透它的所有服务代码,那么它就可以是足够安全的。


问题 #14

网站后台如何判断客户端是来自手机、还是来自电脑?

共 486 次阅读

答案

在浏览器打开一个网址时,此时浏览器为客户端,你的网站后台tomcat为服务器,客户端向服务器传了一个HTTP请求。

在HTTP请求的头部,有一个字段 User-Agent,用于表示客户端浏览器的类型、及操作系统的类型。以下是一 以个真实的HTTP请求抓包(客户端:小米浏览器)

GET /qianwen/ HTTP/1.1

Host: 192.168.1.109:8080

Connection: keep-alive

Cache-Control: max-age=0

User-Agent: Mozilla/5.0 (Linux; U; Android 7.1.2; zh-cn; MI 5X Build/N2G47H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.128 Mobile Safari/537.36 XiaoMi/MiuiBrowser/10.4.5

Accept: text/html

Accept-Language: zh-CN,en-US;q=0.8

所以,在服务器端只需要从请求里取这个User-Agent,看看里面有没有 Mobile 字样

HttpServletRequest request = ...

String userAgent = request .getHeader("User-Agent");

然后,分析这个UserAgent即可以判断出客户端是出自手机、还是电脑

String guessDevice(String userAgent)
{
if(userAgent == null)
return "pc";

if(userAgent.indexOf("Mobile")>=0)
return "phone";

if(userAgent.indexOf("Andr")>=0)
return "phone";

if(userAgent.indexOf("iPhone")>=0)
return "phone";

//MiuiBrowser
if(userAgent.indexOf("Miui")>=0)
return "phone";

return "pc";
}
当然,这个分析的方法需要自己去优化,它能覆盖大多数情况。

另外,一般的浏览器也都支持模拟手机版或桌面版来访问。


问题 #15

网站开发中,什么是过滤器,什么是拦截器,有什么区别?

共 411 次阅读

答案

Java Web有3种自带机制,Servlet,Filter,Listener。

其中,Filter称为过滤器,也可翻译为拦截器。它们是同一个东西。


问题 #16

面试时,面试官问你怎么看待加班,你会怎么回答?

共 604 次阅读

答案

面试的基本思路:说对方想听到的话。你的回答首先应符合对方的利益,然后应符合对方公司的利益。

所以,你这可以这么回复:

"愿意加班。我觉得应该以公司的利益为优先考虑,如果公司不赚钱的,个人也是没有奖金发的。而且市场有时效性,每个产品都有它的市场时机,如果错过了时机,那么再加班也是没有用的。所以在必要的时候,必须加班加点以保证产品的准时发布上线。"

其实这里面有几层意思。

第一层,态度问题。在你表示愿意时,不应该附加任何前提条件。

第二层,对利益关系的把握。越有钱的公司,员工工资越高;公司不景气,员工别想过得舒服。

第三层,对加班背景的把握。一般来说,就是项目急了才需要加班。在时间点之前加班,使产品即时上线,你的加班才有意义。过了这个时机,等市场都被别家占了,你再加班也是徒劳。所以,加加班其实是正常状况。

第四层,对职场规则的理解。其实你的小领导也是人,也有家庭,他也不过是个打工仔,他比你更不想加班。但是没办法,身在其位,必谋其政。拿了别人的钱,必定要为人办事,这是基本的游戏规则。老板有着急的事情,他必须为老板分忧;他着急,你作为下属也不能优哉游哉。


问题 #17

一个中文字符对应几个字节?

共 558 次阅读

答案

这个和字符编码有关。所谓字符编码,就是规定了如何将字符串转成byte[]。

同一个汉字,在不同的字符编码下,得到的结果也不同。

例如,"中国"

GBK 编码: D6 D0 B9 FA

UTF-8 编码:E4 B8 AD E5 9B BD

以GBK编码时,一个汉字得到2个字节。

以UTF-8编码时,一个汉字得到2~3个字节。


问题 #18

浏览器里输入 http://afanihao.cn/abc.jpg ,可以打开显示一张图片。那么是否意味着服务器后台里有一个名为abc.jpg的图片文件?

共 459 次阅读

答案

不一定。

后台可能存在这个文件,也可能是一个伪静态实现。关于伪静态技术,参考『网站中级篇』。

比如,创建一个Servlet,映射路径设置为"/abc.jpg",返回一个图片的内容即可。Content-Type设置为"image/jpeg"。

在客户端浏览器看来,它得到的是一个图片的内容。它语法区分这个图片是来自一个静态文件,还是来自一个Servlet的输出。


问题 #19

用户绑定了一个email地址,网站后台如何验证这个邮箱是这个用户的、而不是别人的邮箱呢?(即邮箱验证)

共 355 次阅读

答案

当用户指定一个邮箱进行注册或者绑定时,后台需要验证该邮箱是否属于用户。

例如,小明 以注册用户时使用 xiaozhang@163.com ,而这个email是 小张 的,后台要避免这种情况的发生。

通常有两种方式:验证码方式,验证链接方式。

第1种方式:验证码

(1) 用户在页面上输入邮箱 xiaoming@163.com

(2) 后台在当前 Session记录一个验证码,如 5420

(3) 后台向 xiaoming@163.com 发送一封邮件,邮件内容为”你的验证码为 5420"。(后台如何发送邮件? 请参考《项目应用篇》之邮件发送)。

(4) 用户到mail.163.com 上以登录自己的邮箱,查看验证码。拷贝验证码,填写到我们的网站界面。

(5) 前端将验证码传到后台,后台将其与Session中的值比较。如果相同,则验证通过;否则,说明 用户冒用了别人的email地址 进行注册。

第2种方式:验证链接

(1) 用户在页面上输入邮箱 xiaoming@163.com

(2) 后台向 xiaoming@163.com 发送一封邮件,邮件内容为:

"请点此链接进行确认:http://your.com/userEmailConfirm?code=xxxxxxxxxxxxxxxxxxxxxxxx"

其中,xxxxxxxxxxxxxxxxxxxxxxx 为AES加密后的内容,原文为 user=1928089&email=xiaoming@163.com

( 关于如何进行AES加密,请参考《项目应用篇》之数据的加密 )

(3) 用户到mail.163.com 上以登录自己的邮箱,发现一封验证邮件

(4) 用户在浏览器访问上述超链接

(5) 后台收到请求,对数据URL里的数据进行解密,解得 user=1928089&email=xiaoming@163.com 。于是,后 端确认 user为1928089 的 email 为 xiaoming@163.com。

完成绑定。


问题 #20

如何理解开发效率和运行效率,哪个更重要?

共 466 次阅读

答案

效率分两种语义: 开发效率,运行效率。

开发效率,是指用最短的把代码写好,功能实现。

运行效率,是指程序的性能,运行的越快,所耗费的CPU越好,内存越少越好。

简单的说,开发效率是节省人的时间,而运行效率是节省机器的时间。那么,是人的时间重要、还是机器的时间更重要呢?结论似乎显而意见。

从老板角度看 : 如果要提高运行效率,那么就得雇佣薪资更高的程序员,花更多的开发时间,,,而这个代价就是员工的薪资成本。

运行效率低的话,多花钱买点硬件,就能解决吗?如果能解决,则需要衡量是cpu内存更贵,还是人工成本更贵。

在硬件成本降低,而人工成本不断攀升的今天,老板或许更倾向于多买点硬件。