现在的位置: 首页 > 综合 > 正文

一些小问题技术笔记(一)–思考是进步的本质

2014年09月14日 ⁄ 综合 ⁄ 共 2669字 ⁄ 字号 评论关闭

(1):String的本质就是一个char[]。String源码是用char[]来存储这个字符串的。

(2):jsp的解析过程是先被转换为servlet。

(3):Tcp是应用层协议,Http是网络层协议,Socket本身并不是协议,可以理解为对tcp/ip协议的封装,是封装好了的对程序员的编程接口。

(4):都知道数据库连接耗时? 可是耗时在哪里? 连接的过程做了一些什么操作?这个问题思考了很久了,一直不知道,我猜想的一些操作:检验用户信息,要打开硬盘文件,创 建内存缓存等,这些操作加起来应该会比较耗时,网上有人说会进行协议交换? 不太了解~

(5):java的打开文件和流之内的东西为什么要关闭?垃圾回收器不能够回收吗?文件和流都不属于虚拟机管理的资源,所以不能通过垃圾回收器回收,不关闭文件就表示虚拟机进程一直占用这个文件,其他进程便不能使用这个文件。

(6):搜索框的即时提示功能是通过ajax发送数据给服务器端,再服务器端通过Trie树来完成,如输入“刘”,在后台Trie树中查找以“刘”开始的trie树子节点,应该还会根据词的热度来排序,然后找出前几个返回客户端。

(7):==和equals()的区别? ==是比较对象的内存地址,equals需要每个类自己重写,所以不太好确定怎么比较大小,比较经典的就是String和StringBuffer的equals()方法,String的equals方法是比较值的,也就是说不管两个String对象是否相同,只要对象里面的值相同这两个对象就一定相等,StringBuffer没有重写equals方法,所以会用Object的equals方法来比较,但是Object的equals方法是比较对象是否相等的,所以就算值相同的StringBuffer也不一定相等。下面的代码一看便明白:

StringBuffer s1 = new StringBuffer("abc");
StringBuffer s2 = new StringBuffer("abc");
System.out.println(s1.equals(s2));//false
System.out.println(s1==s2);//false
String s3 = new String("abc");
String s4 = new String("abc");
System.out.println(s3.equals(s4));//true
System.out.println(s3==s4);//false

(8):String a="a";String b="b";String ab="ab";问:(a+b)==ab?("a"+"b")==ab? 答案:因为a和b是变量,所以a+b会生成临时变量,临时变量的地址跟ab的地址不一样,所以第一个为false,第二个"a"+"b"都是常量,没有生成临时变量,所以第二个相等。思考:如果把a,b的定义都加上final,则a和b变成常量,那么第一个问题会不会相等,答案是会,原因同上。

(9):反射的性能为什么低?关于这题,在 Sun 官方的 The
Reflection API 
明确说明了: 

引用
Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections
of code which are called frequently in performance-sensitive applications.


      大致意思是说因为反射涉及到动态解析类型,以致于某些 jvm 不能够对其进行执行时的优化, 因此使用反射的性能低于非反射的性能..blabla... 
      上面所说的动态解析,意味着对于对象创建的过程、方法调用的过程是动态,通过动态加载字节码在 JVM 中进行执行,并且当使用 Class.forName 或 getMethod 时会执行权限校验检查以及lookup的过程,以至于这些调用操作必定将存在时间成本。 
      另外说的JVM不能进行优化,大致是说的是在对 Class 进行编译时候的优化(如在语义分析过程中会自动拆箱装箱处理),因为编译过程中是无法知道反射代码的真正所需要做的事情, 另外也可能无法发挥 JIT 的最大优化潜力。 

      值一提的是该问题是作者在09年发出,到目前为止,JDK反射提升越来越好了,从1.6版本后基本上与非反射方法调用相差无几了。当然,最好能在反射的代码进行缓存 Class 或 Method 对象,避免重复调用 getMethod 和 Class.forName,从而减少访问检查及lookup 的过程。 


(10) int a=3;Long b=3;问b==a? b.equals(a)? 答案:第一个等于,第二个不等于,因为第一个a向上转型为long型并进行了自动装箱,第二个是因为equals方法并不会进行转型,equals它的源代码如下:

   public boolean equals(Object obj) {
	if (obj instanceof Long) {
	    return value == ((Long)obj).longValue();
	}
	return false;
    }

对不属于Long类型的都返回false。

(11)如下所示,输出结果:

Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
System.out.println(c==d);
System.out.println(e==f);

输出为:  true

                 false

值在-128到127之间的值,在装箱后,对象会重用,而不再这个范围的装箱,对象不会重用,会新建一个对象,所以e和f不相等。如果把Integer改成Long,同样适用。

(12)字符串转换是非常耗时的操作,因为要讲字符串解析成数字,如Double d = new Double(“2.34”);比Double d = new Double(2.34)要快,测试新建10w个Double,第一种情况要441ms,第二种10ms;

参考:http://www.iteye.com/topic/1119390

抱歉!评论已关闭.