细评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);}}注:这样写,只有在远程调用时才有必要,如果非远程调用(在同一个虚拟机内),就别这样写了,多余。
这样,远程调用时的值址问题也就解决了。
- 细评Java中的传值、传址及在远程调用时的使用
- java中的远程调用
- 使用Java的RMI完成远程调用
- 使用Java进行远程方法调用的几个方案及比较
- 使用Java进行远程方法调用的几个方案及比较
- JAVA的远程调用
- Java的远程调用
- JAVA的远程调用
- Java的远程调用
- JAVA的远程调用
- BouncyCastle JCE 的安装配置及在java中的使用
- BouncyCastle JCE 的安装配置及在java中的使用
- java 远程调用及动态代理的应用
- 在Android上使用Flamingo进行远程调用的实例
- 【Java进阶】对Java中的传值调用的理解
- Java中的RMI(远程方法调用)
- hessian远程调用的使用
- 使用Akka的远程调用
- iOS中消息的传递机制
- 如何做软件需求分析(个人工作经验总结)
- ICMP
- UVa 550 移位乘法
- 模版匹配
- 细评Java中的传值、传址及在远程调用时的使用
- UML初窥
- Linux与windows的区别
- 寒假训练--训练赛2--小P寻宝记
- hdu1247 Hat’s Words(字典树)
- Linux网络配置1--创建Bond、配置路由和vlan
- POSIX Threads Programming
- HDU 1978 DP水题一枚
- 寒假训练--训练赛2--Good Luck!