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

        在编程中,传值和值址的不同,那么我们相应的代码就有可能会发生变化。对于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);
	}	
}
注:这样写,只有在远程调用时才有必要,如果非远程调用(在同一个虚拟机内),就别这样写了,多余
        这样,远程调用时的值址问题也就解决了。


  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 30
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值