snake168
2010-03-25 13:20
浏览 411
已采纳

HashSet中的反序列化的问题

[code="java"]
map = (((HashSet)this) instanceof LinkedHashSet ?
new LinkedHashMap(capacity, loadFactor) :
new HashMap(capacity, loadFactor));
[/code]
这是jdk中HashSet中的readObject中的一段代码

为什么这里的this要先强制转换成HashSet类呢?
昨天已问过该问题,昨天是小弟的误解,该this应该是反序列化时的object类,为何要强制转换呢?
Object类难道不能用instanceof识别是哪个类?或者说在readObject类的内部不能识别呢?

所以小弟做了以下尝试
[code="java"]
package test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class CharsetTest {

public static void main(String[] args) throws Exception {
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("D:" + File.separator + "objectFile.obj"));
    // 序列化对象
    Customer customer = new Customer();
    TestCustomer test = new TestCustomer();
    out.writeObject(customer);
    out.writeObject(test);
    out.close();
    // 反序列化对象
    ObjectInputStream in = new ObjectInputStream(new FileInputStream("D:" + File.separator + "objectFile.obj"));
    Object obj1 = in.readObject();
    Object obj2 = in.readObject();
    System.out.println(obj1 instanceof Customer);
    System.out.println(obj1 instanceof TestCustomer);
    System.out.println(obj2 instanceof Customer);
    System.out.println(obj2 instanceof TestCustomer);
    in.close();
}

}

class Customer implements Serializable {

private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {

}

}

class TestCustomer extends Customer implements Serializable
{}
[/code]

结果很明显的:
true
false
true
true

然后基本确定该强制转换的使用基本唯一的可能性是位于readObject中this不能用instanceof识别
再次尝试代码如下
[code="java"]
package test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class CharsetTest {

public static void main(String[] args) throws Exception {
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("D:" + File.separator + "objectFile.obj"));
    // 序列化对象
    Customer customer = new Customer();
    TestCustomer test = new TestCustomer();
    out.writeObject(customer);
    out.writeObject(test);
    out.close();
    // 反序列化对象
    ObjectInputStream in = new ObjectInputStream(new FileInputStream("D:" + File.separator + "objectFile.obj"));
    Object obj1 = in.readObject();
    Object obj2 = in.readObject();      
    in.close();
}

}

class Customer implements Serializable {

private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
    System.out.println(this instanceof Customer);
    System.out.println(this instanceof TestCustomer);
}

}

class TestCustomer extends Customer implements Serializable
{}
[/code]

结果依然是
true
false
true
true

这下小弟糊涂了,总觉得java源码中所写的都是有必要的,既然用了强制转换,必然有其道理
难道是性能问题?
然后又做了如下尝试
[code="java"]
package test;

public class Test {

public static void main(String[] args) {
    Test test = new Test();
    long beforeTime,nextTime,thisTime,totalTime1,totalTime2;
    totalTime1 = 0;
    totalTime2 = 0;
    int count = 1<<30;
    //测试20次取平均值,两种方法间隔开以消除系统资源导致的时间差
    for(int i = 1;i<=20;i++)
    {
        //不强制转换
        beforeTime = System.currentTimeMillis();
        //执行1<<30次
        for(int m = 1;m<=count;m++)
            test.test();            
        nextTime = System.currentTimeMillis();
        System.out.println(thisTime = nextTime-beforeTime);
        totalTime1 += thisTime;

        //强制转换
        beforeTime = System.currentTimeMillis();
        //执行1<<30次
        for(int m = 1;m<=count;m++)
            test.test2();
        nextTime = System.currentTimeMillis();
        System.out.println(thisTime = nextTime-beforeTime);
        totalTime2 += thisTime;
    }
    System.out.println(totalTime1);
    System.out.println(totalTime1/20);
    System.out.println(totalTime2);
    System.out.println(totalTime2/20);
}

public void test()
{
    if(this instanceof Test)
    {}
}
public void test2()
{
    if((Test)this instanceof Test)
    {}
}

}

[/code]
测试结果如下
3922
3328
3922
3203
3938
3219
4234
4281
3969
3422
4187
3188
4047
3328
4031
3438
4266
3297
4000
3453
4203
3422
4203
3422
4453
3297
4109
3735
4312
3266
3984
3266
3969
3218
3938
3203
3937
3219
3953
3188
81577
4078
67393
3369
看到这结果,原来如此,心想jdk的编写者真是厉害,这点时间都计算得那么精准
但记起上次测试(代码已不见了),没有连续着的,似乎时间是一样的,于是有点怀疑地做了以下测试
[code="java"]
package test;

public class Test {

public static void main(String[] args) {
    Test test = new Test();
    long beforeTime,nextTime,thisTime,totalTime1,totalTime2;
    totalTime1 = 0;
    totalTime2 = 0;
    int count = 1<<30;
    //测试20次取平均值,两种方法间隔开以消除系统资源导致的时间差
    for(int i = 1;i<=20;i++)
    {
        //不强制转换
        beforeTime = System.currentTimeMillis();
        //执行1<<30次
        for(int m = 1;m<=count;m++)
            test.test();            
        nextTime = System.currentTimeMillis();
        System.out.println(thisTime = nextTime-beforeTime);
        totalTime1 += thisTime;

        //强制转换
        beforeTime = System.currentTimeMillis();
        //执行1<<30次
        for(int m = 1;m<=count;m++)
            test.test2();
        nextTime = System.currentTimeMillis();
        System.out.println(thisTime = nextTime-beforeTime);
        totalTime2 += thisTime;
    }
    System.out.println(totalTime1);
    System.out.println(totalTime1/20);
    System.out.println(totalTime2);
    System.out.println(totalTime2/20);
}

public void test2()
{
    if(this instanceof Test)
    {}
}
public void test()
{
    if((Test)this instanceof Test)
    {}
}

}

[/code]
其实也就是把上一段代码Test中的两个方法换个位置,结果却很崩溃~
3890
3219
3844
3125
3844
3156
3781
3125
3844
3109
3813
3094
3781
3125
3828
3125
3844
3125
3875
3140
3828
3141
3828
3125
3860
3140
3844
3125
3797
3140
3829
3140
3797
3078
3797
3156
3828
3125
3829
3140
76581
3829
62653
3132
结果基本完全一样~意外地引发出另一个奇怪的问题来了
但之前的问题尚未解决,只能暂且放下了
于是改了下方法测
[code="java"]
package test;

public class Test2 {

public static void main(String[] args) {
    Test2 test = new Test2();
    long beforeTime,nextTime,thisTime,totalTime1,totalTime2;
    totalTime1 = 0;
    totalTime2 = 0;
    int count = 1<<30;
    //测试20次取平均值
    //不强制转换
    for(int i = 1;i<=20;i++)
    {           
        beforeTime = System.currentTimeMillis();
        //执行1<<30次
        for(int m = 1;m<=count;m++)
            test.test();            
        nextTime = System.currentTimeMillis();
        System.out.println(thisTime = nextTime-beforeTime);
        totalTime1 += thisTime;
    }

    //测试20次取平均值
    //强制转换
    for(int i = 1;i<=20;i++)
    {       
        beforeTime = System.currentTimeMillis();
        //执行1<<30次
        for(int m = 1;m<=count;m++)
            test.test2();
        nextTime = System.currentTimeMillis();
        System.out.println(thisTime = nextTime-beforeTime);
        totalTime2 += thisTime;
    }
    System.out.println(totalTime1);
    System.out.println(totalTime1/20);
    System.out.println(totalTime2);
    System.out.println(totalTime2/20);
}

public void test2()
{
    if(this instanceof Test2)
    {}
}
public void test()
{
    if((Test2)this instanceof Test2)
    {}
}

}
[/code]
结果:
3797
3797
3781
3922
3797
3813
3812
3797
3812
3797
3797
3813
3812
3797
3813
3796
3797
3813
3781
3844
3109
3110
3109
3094
3109
3141
3093
3110
3094
3125
3125
3093
3110
3109
3094
3109
3125
3110
3125
3125
76188
3809
62219
3110
继续把两个方法互换(这里不贴代码了),再试
3796
3813
3781
3781
3797
3844
3813
3796
3797
3813
3781
3797
3812
3797
3828
3782
3797
3796
3797
3782
3109
3094
3109
3109
3110
3109
3094
3109
3110
3093
3125
3094
3110
3109
3094
3109
3109
3079
3109
3109
76000
3800
62093
3104
忽然有了种想死的感觉
继续
[code="java"]
package test;

public class Test2 {

public static void main(String[] args) {
    Test2 test = new Test2();
    long beforeTime,nextTime,thisTime,totalTime1,totalTime2;
    totalTime1 = 0;
    totalTime2 = 0;
    int count = 1<<30;
    //测试20次取平均值
    //不强制转换
    for(int i = 1;i<=20;i++)
    {           
        beforeTime = System.currentTimeMillis();
        //执行1<<30次
        for(int m = 1;m<=count;m++)
            test.test();            
        nextTime = System.currentTimeMillis();
        System.out.println(thisTime = nextTime-beforeTime);
        totalTime1 += thisTime;
    }

    /*//测试20次取平均值
    //强制转换
    for(int i = 1;i<=20;i++)
    {       
        beforeTime = System.currentTimeMillis();
        //执行1<<30次
        for(int m = 1;m<=count;m++)
            test.test2();
        nextTime = System.currentTimeMillis();
        System.out.println(thisTime = nextTime-beforeTime);
        totalTime2 += thisTime;
    }*/
    System.out.println(totalTime1);
    System.out.println(totalTime1/20);
    /*System.out.println(totalTime2);
    System.out.println(totalTime2/20);*/
}

public void test()
{
    if(this instanceof Test2)
    {}
}
public void test2()
{
    if((Test2)this instanceof Test2)
    {}
}

}

[/code]
结果
3797
3875
3813
4156
3797
3797
3812
3828
3829
3796
3813
3828
3812
3797
3813
3812
3828
3797
3828
3813
76641
3832
again:
[code="java"]
package test;

public class Test2 {

public static void main(String[] args) {
    Test2 test = new Test2();
    long beforeTime,nextTime,thisTime,totalTime1,totalTime2;
    totalTime1 = 0;
    totalTime2 = 0;
    int count = 1<<30;
    //测试20次取平均值
    //不强制转换
    for(int i = 1;i<=20;i++)
    {           
        beforeTime = System.currentTimeMillis();
        //执行1<<30次
        for(int m = 1;m<=count;m++)
            test.test2();           
        nextTime = System.currentTimeMillis();
        System.out.println(thisTime = nextTime-beforeTime);
        totalTime1 += thisTime;
    }

    /*//测试20次取平均值
    //强制转换
    for(int i = 1;i<=20;i++)
    {       
        beforeTime = System.currentTimeMillis();
        //执行1<<30次
        for(int m = 1;m<=count;m++)
            test.test2();
        nextTime = System.currentTimeMillis();
        System.out.println(thisTime = nextTime-beforeTime);
        totalTime2 += thisTime;
    }*/
    System.out.println(totalTime1);
    System.out.println(totalTime1/20);
    /*System.out.println(totalTime2);
    System.out.println(totalTime2/20);*/
}

public void test()
{
    if(this instanceof Test2)
    {}
}
public void test2()
{
    if((Test2)this instanceof Test2)
    {}
}

}
[/code]
结果
3812
3891
3828
3813
3828
3843
3813
3812
3797
3828
3813
3797
3828
3844
3812
3828
3813
3828
3812
3797
76437
3821
终于得到了理想中的结果~
然而强制转换的问题仍然没有答案,两个的时间几乎完全一样
到底强制转换为何用?
然后又引发了另一个问题:
为何会在前两次测试中会出现时间差?而且间隔开或者连在一起都会出现这时间差,这又是什么原因?
小弟学java还没多久,请教高手了

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

6条回答 默认 最新

  • iteye_13500 2010-03-25 16:02
    已采纳

    刚才又测试了一下,把test函数改成:

    [code="java"] public void test() {
    int j;
    for (int i = 0; i < 5; i++)
    j = 9;
    }[/code]

    三个测试的时间几乎一样了。

    结论:

    1 强制转换和不强制转换时间差不多,没有明显差别
    2 如果是普通语句,放在第一个位置和不放在第一个位置执行时间差不多
    3 如果是你提供的test函数,放在第一个位置执行的时间明显要长,个人觉得可能和instance 操作符有关,因为看不到源码,暂时也不好找原因了,总之是比较奇怪的。

    评论
    解决 无用
    打赏 举报
  • 查看更多回答(5条)

相关推荐 更多相似问题