在编程中,传值和值址的不同,那么我们相应的代码就有可能会发生变化。对于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):
vcHLyv2+3b/io6zEx8O0sLTV1U9STdbQttTP89e0zKyjrLTLyrFTdHVkZW5006a4w8rH09BJZLXEssW21KGjv8nKx9a00NDN6rrzyLTS4s3itcS3os/WU3R1ZGVudLXESWTSwMi7zqq/1aOs1Nm/tMr9vt2/4qOs0tG+rbTmvfjIpcHLoaM8YnI+CjwvcD4KPHA+IAogICAgICAgV2h5o7+joTxicj4KPC9wPgo8cD4gCiAgICAgICDV4r7NysfHsMPmy7W1vbXEo6zC37ytsuPNqLn91LazzLX308O9q1N0dWRlbnS0q8HLuf3IpaOs1Nq34tewstnX97XERUpC1tCjrLbUU3R1ZGVudL340NDBy7LZ1/ejrLKix9K21ElkvfjQ0LizJiMyMDU0MDujrLWrtMvKscv8u/HIobW9tcRTdHVkZW501rvKx8LfvK2y47XEU3R1ZGVudNDywdC7r7e00PLB0LuvtcS94bn7oaM8YnI+CjwvcD4KPHA+IAogICAgICAgxNG1wNTaRUpC1tDO0sPHvs2yu8TctKvS/dPDwcvDtKO/PGJyPgo8L3A+CjxwPiAKICAgICAgILj2yMu40L71yse1xKOssru5/c7Sw8e/ydLU19S8utf2tb26zbSr1rfSu9H5tcS94bn7o7rO0sPH08O0q9a3ysfOqsHLuMnC76Ossru+zcrHz+u78cih0ru49sTHsd/Q3rjEuvO1xLbUz/PC76OsztLDx9TZsNHL/LSru9jAtLK7vs2/ydLUwcuho8rCyrXJz6Os1eLSssrH1NrUtrPMtffTw7e9w+a1xNK7uPa94r72t73KvaOsz8LD5s7SvPK1pcu1w/fSu8/Co6w8L3A+CjxwPjxwcmUgY2xhc3M9"brush:java;">业务逻辑层{ public void addStudent(Student student){ student=封装Hibernate操作类.add(student); //对student的id进行应用 } } 封装Hibernate操作类{ public Student add(Student student){ EntityManager.persist(student); } }注:这样写,只有在远程调用时才有必要,如果非远程调用(在同一个虚拟机内),就别这样写了,多余。
这样,远程调用时的值址问题也就解决了。