细评Java中的传值、传址及在远程调用时的使用

来源:互联网 发布:java手机色游戏破解版 编辑:程序博客网 时间:2024/06/09 23:33

        在编程中,传值和值址的不同,那么我们相应的代码就有可能会发生变化。对于VB、C#、C++在传值和值址的时候,都会在方法的形参上有所区别(具体什么样子自己搜下吧)。但我学Java也快一年了吧,却还没有见过这个东西。于是查了一下,原来在Java中,值类型的是按址传递的,而对于像自定义类、String这样的类型,是按址传递的。

        下面就来看一下吧,首先先看一下按值传递,只列一个int,其它的也类似是这样的:

public static void main(String[] args){int a=1,b=2;System.out.println("====before swap====");System.out.println("a:"+a);System.out.println("b:"+b);swap(a, b);System.out.println("====after swap====");System.out.println("a:"+a);System.out.println("b:"+b);}public static void swap(int a,int b){a=a+b;b=a-b;a=a-b;}


输出结果如下,可以看出形参的改变,没有影响到实参,故是按值传递;

====before swap====
a:1
b:2
====after swap====
a:1
b:2
        下面来看一个按址传递的例子:

public class TestSwap {public static void main(String[] args){Container con=new Container();System.out.println("====before swap====");System.out.println("con.a:"+con.a);System.out.println("con.b:"+con.b);swap(con);System.out.println("====after swap====");System.out.println("con.a:"+con.a);System.out.println("con.b:"+con.b);}public static void swap(Container container){container.a=container.a+container.b;container.b=container.a-container.b;container.a=container.a-container.b;}}class Container{int a=1,b=2;}

输出结果如下,可以看出,形参的改变导致了实参的改变,所以为按址传递

====before swap====
con.a:1
con.b:2
====after swap====
con.a:2
con.b:1

==================================华丽的分割线====================================

下面来说远程调用时的参数的传递方式

        上面的测试都是用的main函数测试的,也就是说这些是在一个虚拟机里的,如果不在一个虚拟机里,例如EJB远程调用,那么如果我传一个对象会怎样进行传递呢?

        在EJB里,形参的类型是要求实现Serializable接口,这样这个参数就可以序列化了(具体序列化成什么在这里不进行说明),那么在进行本地调用时(Local),测试结果会与上面的相同。

        如果是远程调用(Remote),不论是不是调用的本地计算机,那么它都会将这些个参数序列化,传到对方的虚拟机里进行运行,这个对象在对面不论进行什么样的操作都不会影响到实参。

        那么在如下的系统结构中就会出现问题(EJB的实体部分与Hibernate如出一辙,所以我就写了个Hibernate):

        

        会出现什么问题呢?我在业务逻辑层有一个类Student,我通过远程调用将其保存到了数据库,那么按照ORM中对象状态,此时Student应该是有Id的才对。可是执行完后却意外的发现Student的Id依然为空,再看数据库,已经存进去了。

        Why?!

        这就是前面说到的,逻辑层通过远程调用将Student传了过去,在封装操作的EJB中,对Student进行了操作,并且对Id进行赋值,但此时它获取到的Student只是逻辑层的Student序列化反序列化的结果。

        难道在EJB中我们就不能传引用了么

        个人感觉是的,不过我们可以自己做到和传址一样的结果:我们用传址是为了干嘛,不就是想获取一个那边修改后的对象嘛,我们再把它传回来不就可以了。事实上,这也是在远程调用方面的一个解决方式,下面我简单说明一下,

业务逻辑层{public void addStudent(Student student){student=封装Hibernate操作类.add(student);//对student的id进行应用}}封装Hibernate操作类{public Student add(Student student){EntityManager.persist(student);}}
注:这样写,只有在远程调用时才有必要,如果非远程调用(在同一个虚拟机内),就别这样写了,多余
        这样,远程调用时的值址问题也就解决了。


3 0
原创粉丝点击