您的位置:首页 > 编程语言 > Java开发

学了Java 你未必知道这些

2015-12-18 16:03 302 查看
作为一个正奔跑向编程完美天堂的朝圣者,本人觉得在平常的编程中,应该要做到以下几点:

    一:汝应注释,这样做既方便别人,也方便自己去读懂代码的逻辑

    二:注重细节,为自己写的每行代码负责,比如,在并发编程的过程中,应该给那些可变的共享单元加“同步锁”或把可变的共享变量的粒度降到每个线程的级别

    三:注重效率,由于本人的学校比较重视算法这一块,于是不知不觉中就对程序执行效率这一块比较执着,假如你和你的同事们都写了一个相同功能的程序,然后老板给你们 各100万条数据,你的同事的程序很快就把这100万条数据执行完了,然后去喝了杯咖啡,回来时如果你的代码还在跑,这不是......(后面的话你们都懂的)

    四:注重代码的整洁性和尽力让代码的冗余降到最低,这在代码的重构上是要注意的地方。

  后续本人会写一些本人读到的比较好的算法例子,读这些例子有利于我们思维活跃开来,当然,相信你也会像本人一样为这些算法解法的巧妙性而啧啧称奇,以致使自己在以后的编程中更加注重这一块,这些例子大家以后可以查看这个网址 http://www.cnblogs.com/wanggangjia/来看看(后续会补上这些算法序列)   好吧!前菜已了,正餐现在来了

1.请你完善下列函数来实现这个功能:交换下面例子中A、B的值 

public class TestAdd {
public static void main(String[] args) {
int A = 100;
int B = 10;
.....   //在这里写下你的代码,使A,B的值交换
System.out.println("A:" + A + "\t" + "B:" + B);  //输出  A:10   B:100
}

}


    (1)大多数的我们都会定义一个临时变量temp,然后就如下面代码一样

int temp = A;
A = B;
B = temp;


    (2)又有人会说,定义一个变量多奢侈啊!看我的

A = A + B;
B = A - B;
A = A - B;


    (3)这确实比(1)解法好了一点,但我们知道系统处理数据最快的是位操作,我们能不能从这方面下手使我们的程序更快呢?而且,把A+B赋值给A可能会产生越界,这不是不安全吗?那怎么办才能兼顾安全、快速、简洁呢?看码如下(采用“异或”操作符):

A = A ^ B;
B = A ^ B;
A = A ^ B;


说明:异或运算是按照二进制位进行异或运算的,这个运算是最低级的CPU位运算,运行速度快,而且不会产生进位。

拓展:位操作符由于它们具有运行速度快的特点(思考一下它们快的原因),所以经常被使用,特别是“>>”或“<<”位运算符,这点读者可以看看jdk中有关hashcode这一块的源码

拓展例子:编程实现2 * 8,直接给码如下:

2<<3;  //假设每个变量的存储是8位,则2的二进制是0000 0010,向左偏移3位后,可得0001 0000,转换成十进制为16,不就是2 * 8,数3是因为2的3次方为8


  2.这条语句:float i = 3.3;能编译通过吗?

float i = 3.3;不能通过编译,因为常数 3.3 Java默认是double类型,而float类型的范围是比double小的,把3.3赋值给i 是向下转型,会损失精度,如果真的需要赋值给i,需强制转型float i = (float)3.3;


拓展:short i = 1,i = i + 1;这也是不能通过编译的,因为Java默认常数1位int类型,理由同上,但是short i = 1,i += 1;却是可以的,这是因为jdk在编译的时候,会隐式的将类型强制转换成i = (short)(i + 1);

  3.Java中int类型和Integer类型有什么区别?

首先,int类型是Java的基本数据类型,而Integer是一个对象,是一个引用,它们在内存逻辑就不同,关于内存逻辑,可以看看本人所写的“一个大三学生的学习之悟”这篇文章,下面给出这两个类型的内存结构,既然Integer是一个对象,那么它相对于int这基本类型来说就有很多额外的方法,具体可自查Java的API,要特别说明的是:在jdk1.5引入了“自动拆箱和装箱”,使得基本数据类型和其对应的封装对象能够隐式的转换。



综合例子:涵盖的知识点包括自动装箱和拆箱、内存结构分析、自动装箱和拆箱背后的类似“对象池”的思想

public class BoxingTest {
public static void main(String[] args) {
Integer i = new Integer(300);
Integer j = 300;  //自动装箱,内部机制是调用Integer的valueOf(int)方法
int z = 300;
System.out.println(i == j);  //false  因为它们的内存地址不同
System.out.println(z == j); //true  因为j自动拆箱,内部机制是调用Integer的intValue()方法,它们比较的都是数值300
}

}


读到这里,如果你没有一种去读Integer的valueOf(int)方法的源码的冲动,那么你将失去挺多东西的,因为它里面包含着Java在性能优化的一些蛛丝马迹,算了,我还是讲讲吧!如果你没有去看这个方法的源码,相信把下面这道题完全做对的应该不太可能,先炫代码:

public class ValueOfTest {   //使用驼峰形式命名

public static void main(String[] args) {
Integer i = 50;
Integer j = 50;
Integer x = 200;
Integer y = 200;

System.out.println(i == j);  //true
System.out.println(x == y); //false
}

}


分析如下:

public static Integer valueOf(int i) {   //注意这里是静态方法,隶属于类,所以可以直接使用 “Integer.方法名” 来调用该方法

if (i >= IntegerCache.low && i <= IntegerCache.high)  //这里的IntegerCache.low默认值为-128   IntegerCache.high默认值为127
return IntegerCache.cache[i + (-IntegerCache.low)];  //这些Integer对象,默认范围在[-128~127],已经被创建,被放在常量池里

return new Integer(i);

}


由于Java的操作不外乎是创建对象---使用对象----销毁(回收)对象,因为创建对象比较耗时间,损失了系统的性能,所以我们一般都会在程序开始时对一些比较耗时但在我们的程序又经常使用的对象先会初始化一些实例,对象池的对象是如此,线程池的线程是如此,数据库连接池的Connection对象也是如此,供我们在程序中调用,以达到对象的重用及快速引用,这是优化程序功能的一个方法。好吧!回归本题,范围在[-128~127]的Integer对象已经被初始化在常量池里了,所以在这区间的Integer对象创建时都会指向常量池中相对应的对象,这也是上面代码中为什么第一个输出为true的原因,在这个范围之外的,它会自己创建一个Integer对象,所以根据内存逻辑可知它们并不相等,所以为false

  其实,有空读读Java源代码也是有好处的,在这里,本人只是希望编程者们在平常的代码编辑中,要时刻注重自己程序的安全性、代码运行的效率性及项目的性能的优化等等
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: