Java实现OUT参数

引用
    在java函数中只有一种类型的返回值,但是当我们要一个函数有多个类型的返回值时,我们该怎么办呢,有办法吗,答案是肯定的,向其他语言一样使用OUT参数(就是能作为函数的输出使用的参数)。下面先看个例子,看那些参数实现了OUT功能。


/**
 * 
 * 这个类是用来测试Java中如何实现OUT参数。
 * 
 * @author LoongHua
 *
 */
class B{
	
	String cnt=null;
	
	public static void main(String[] args) {
		B t=new B();//实例化一个对象
		
		String a=null;
		String[]s=new String[1];
		B b=new B();
		Object o=null;
		
		t.test1(a);
		System.out.println("原子类型实现的结果:"+a);
		
		t.test2(b);
		System.out.println("引用类型实现的结果:"+b.cnt);
		
		t.test3(s);
		System.out.println("数组类型实现的结果:"+s[0]);
		
		t.test4(o);
		System.out.println("数组类型实现的结果:"+String.valueOf(o));
	}
	
	public void test1(String a){
		a="aaaaaaaa";
	}
	
	public void test2(B b){
		b.cnt="bbbbbb";
	}
	
	public void test3(String[] s){
		s[0]="sssssssss";
	}
	
	public void test4(Object o){
		o="sssssssss";
	}
}
运行结果:

原子类型实现的结果:null
引用类型实现的结果:bbbbbb
数组类型实现的结果:sssssssss
数组类型实现的结果:null

引用

用Java写一个交换两个数的程序,这还不简单,下面是很容易写出的一个:
    void swap(int a, int b) {
        int temp = a;
        a = b;
        b = temp;
    }
熟悉Java的你轻而易举的就看出了问题所在,在Java语言中,基本类型作为参数是通过传值(pass by value)的方式进行传递的,所以,这里改变的是传过来的“值”,而非我们实际的参数。

改一下我们的目标,交换两个对象,照搬上面的模式:
    void swap(Object a, Object b) {
        Object temp = a;
        a = b;
        b = temp;
    }
这个方法可以正常执行吗?这是一个比较让初学者糊涂的问题。乍看之下,对象传递过来的是引用(pass by reference),改变引用的结果应该可以作用到外部。实际上,调用这个函数前后,作为实际参数的对象不会有任何改变,也就是说,这只是一个浪费时间的方法。这种pass by reference实际上也是一种pass by value,不同的是,这里的value是reference而已。所以,对传入的reference重新赋值只是对副本进行操作,而本尊没有受到任何影响。

设计方法的时候,大多数的参数是作为IN参数出现,也就是向方法传入一个值,但有时候,我们也需要参数作OUT参数——从方法内取回一个值,就像前面swap希望做的那样。如果你了解IDL(Interface Definition Language)的话,这些内容应该会让你有一丝亲切感。

在C++中,如果希望一个参数作为OUT参数,我们可能会想到指针和引用。为了让调用代码少写几个‘&’,我们可能会选择引用。
    void swap(int &a, int &b) {
        int temp = a;
        a = b;
        b = temp;
    }

但到了Java中,面对这样简单的一个需求,我们却很难通过最简单的方式完成,原因上面已经说得很清楚了。难道我们只能束手就擒了吗?显然不是。虽然我们不能把引用如何,但我们仍然可以对引用指向的内容痛下狠手,于是有了这样的解决方案,提供一个对象封装类,简单起见,这里把内部成员置成了public:
    class ObjectHolder {
        public Object object;
    }

用它改写我们的swap:
    void swap(ObjectHolder a, ObjectHolder b) {
        Object temp = a.object;
        a.object = b.object;
        b.object = temp;
    }

不过调用端代码会显得复杂许多,需要把对象封装到ObjectHolder,这样执行完swap之后,ObjectHolder中所放的对象便已经是修改之后的对象。若要原有对象也受到影响,那还需要把ObjectHolder的值取出,重新给原有对象赋值。Apache的Axis就是用这种方案解决了OUT参数的问题。

Java语言从C++简化而来,一切本着简单的原则,但有些地方实在也太简单了,这样造成的结果就是有时为了完成一个简单的功能而绕很大的弯子。正是因为这样,Java语言这些年才会处于一个不断发展的过程中。也许等Java趋于完整的那一天,恐怕没有人会再以简单形容它了。

你可能感兴趣的:(java,apache,设计模式)