问题一、java的by value而非by reference传递方式
java中的数据类型分为两大类:基础类型和引用类型,基础类型的值传递很容易理解,它被作为参数传递并修改后,并不会影响它原来的值,而引用类型,它传的是它引用的地址,即使被传到方法内被修改后,直接会影响这个对象本身的值。举例如下
public static void modifyPoint(Point p,int x){
pt.setLocation(5,5);
x=15;
System.out.println("during modifypoint"+ "pt = " + pt +" and j = " +j);
}
public static void main(String [] args){
Point p = new Point(1,2);
int i = 10;
System.out.println("before modifypoint"+ "p = " + p +" and i = " +i);
modifyPoint(p,i)'
System.out.println("after modifypoint"+ "p = " + p +" and i = " +i);
}
上述程序中输出modifyPoint方法调用前后的值,p是对象的引用(值传递,传的是引用的地址值),方法会修改其坐标值,最后的结果会直接影响对象的值,i是一个基础类型的变量,把它作为参数传给方法并修改它的值,因为是值传递,所以不会改变它的值。
问题二、JAVA 泛型-类型擦除
正确的使用Java泛型需要深入的了解Java的一些概念,如协变,桥接方法,以及这篇笔记记录的类型擦除。Java泛型的处理几乎都在编译器中进行,编译器生成的bytecode是不包涵泛型信息的,泛型类型信息将在编译处理是被擦除,这个过程即类型擦除。
通常情况下,一个编译器处理泛型有两种方式:
1.Code specialization。在实例化一个泛型类或泛型方法时都产生一份新的目标代码(字节码or二进制代码)。例如,针对一个泛型list,可能需要针对string,integer,float产生三份目标代码。
2.Code sharing。对每个泛型类只生成唯一的一份目标代码;该泛型类的所有实例都映射到这份目标代码上,在需要的时候执行类型检查和类型转换。
C++中的模板(template)是典型的Code specialization实现。C++编译器会为每一个泛型类实例生成一份执行代码。执行代码中integer list和string list是两种不同的类型。这样会导致代码膨胀(code bloat),不过有经验的C++程序员可以有技巧的避免代码膨胀。
Code specialization另外一个弊端是在引用类型系统中,浪费空间,因为引用类型集合中元素本质上都是一个指针。没必要为每个类型都产生一份执行代码。而这也是Java编译器中采用Code sharing方式处理泛型的主要原因。
Java编译器通过Code sharing方式为每个泛型类型创建唯一的字节码表示,并且将该泛型类型的实例都映射到这个唯一的字节码表示上。将多种泛型类形实例映射到唯一的字节码表示是通过类型擦除(type erasue)实现的。
类型擦除的主要过程如下:
1.将所有的泛型参数用其最左边界(最顶级的父类型)类型替换。
2.移除所有的类型参数。
下面代码经过擦除(参数签名一样)是无法通过编译的:
- public class Erasure{
- public void test(List<Long> ls){
- System.out.println("Long");
- }
- public void test(List<Integer> li){
- System.out.println("Integer");
- }
- }
问题三、几段比较有意思的代码
try
{
if (you.believe(it) == true || you.believe(it) == false)
{
I.believe(it);
}
}
catch (Exception ex)
{
throw new Exception("It's a miracle!");
}
finally
{
it.justHappened();
}
you.believe(it) 此方法可能会有副作用,开始为true,后为false,所以 I.believe(it);可以执行。
if (you.believe(it) || !you.believe(it))
{
I.believe(it);
}
优化了一下,关注怎么做而不是做了什么
if (true || you.believe(it))
让编译器优化
if (you.believe(it) || true)
装个样子,其实结果已经确定
if (you.Love(me) || !you.Love(me))
{
love++;
love--;
}
同样由于副作用,语句不会被优化。