`
沙漠绿树
  • 浏览: 425281 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

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趋于完整的那一天,恐怕没有人会再以简单形容它了。

3
0
分享到:
评论
4 楼 沙漠绿树 2014-08-11  
yanwushu 写道
学习java也有两年了, 但是一直没有注意到参数传递的这个问题,挺惭愧的。
建议楼主在详细解释下什么叫做按值传递。不然传递object的那一段还是不容一定懂。



请看下面的代码及注释:

public class T
{
    public void test(TT a, TT b)
    {
        TT c = a;
        a = b;
        b = c;
    }

    public void test(TT a, RR b)
    {
        a.a = 11;
        b.b = 22;
    }

    public static void main(String[] args)
    {
        TT a = new TT();
        a.a = 4;

        TT b = new TT();
        b.a = 6;

        T t = new T();
        t.test(a, b);
        //这里打印的:4   6;如果不是传值引用则是:6   4
        System.out.println(a.a + "\t" + b.a);

        RR r = new RR();
        t.test(a, r);
        //这里打印:11   22;体现了out参数,a和r对象属性的值被方法改变,会影响外部使用其属性,变通的成为了out参数。
        System.out.println(a.a + "\t" + r.b);
    }
}

class TT
{
    int a = 2;
}

class RR
{
    int b = 1;
}
3 楼 yanwushu 2014-07-31  
学习java也有两年了, 但是一直没有注意到参数传递的这个问题,挺惭愧的。
建议楼主在详细解释下什么叫做按值传递。不然传递object的那一段还是不容一定懂。
2 楼 avi9111 2011-10-26  
写了5年程序,只是在笔试的时候会碰到这个问题

还真没碰到这种需求,要换了2个数据的
   void swap(int &a, int &b) {
        int temp = a;
        a = b;
        b = temp;
    }

第一,真的没这种应用需求
第二,自己不好控制, 到底换了没,怎么判断,DEBUG?LOG?
第三,人家接手改你程序,也太难了吧,谁看的懂
1 楼 lancezhcj 2010-12-04  
肯钻研,而且文笔很好

相关推荐

    RSA算法Java实现

    // 获取私钥参数及解密 BigInteger n = prk.getModulus(); System.out.println("d= " + d); System.out.println("n= " + n); BigInteger m = c.modPow(d, n); // 显示解密结果 System.out.println(...

    K-Means 聚类算法 java实现

    k-means 的java实现,用解压缩打开可以看到源码, 有图形界面可以做测试,可以自定参数。 具体信息运行程序有会有system.out

    AIC的Java课程1-6章

    (System.out对象封装了这两个方法)。 第10章 基本数据结构 4课时  了解和比较静态分配内存空间和动态分配内存空间,能够选择数组或链表表示线性结构。  掌握通过引用同类型对象(指针)实现...

    中文分词工具word-1.0,Java实现的中文分词组件多种基于词典的分词算法

    word分词是一个Java实现的中文分词组件,提供了多种基于词典的分词算法,并利用ngram模型来消除歧义。 能准确识别英文、数字,以及日期、时间等数量词,能识别人名、地名、组织机构名等未登录词。 同时提供了Lucene...

    JAVA阶段模拟试题

    18关于Java类中带参数的方法,下列选项中的说法错误的是( )。 (选择一项) A使用带参数的方法分为两步:1.定义带参数的方法:2.调用带参数的方法 B带参数方法的返回值不能为void C带参数方法的参数个数可以为一个...

    完全免费的Java/jsp开发编辑工具FirstJava2

    列表框中双击某一个函数名,代码编辑区将会自动输入"函数名()",如果这个函数有参数光标定位于 括号中,否则定位到括号外. 3.输入"this."时,会显示当前类和超类的所有相关函数和属性. 4.输入"new "时,会显示当前类...

    java基础入门教程

    工 业 界 不 少 人 预 言 :"Java 语 言 的 出 现 ,将 会 引 起 一 场软 件革 命 ",这 是 因 为 传统 的 软 件 往 往 都 是 与 具 体 的 实现 环 境 有 关 ,换 了 一 个 环 境 就需 要 作 一 番 改 动 ,耗时 费 力 ,...

    java常用工具类的使用

    “工欲善其事,必先利其器”,在Java程序开发过程中,很多算法(比如:MD5加密算法)、很多数据结构(比如链表LinkedList)已经实现并且大多放在类库的java.util包中,程序员只需要了解各种工具的功能就可以直接调用...

    Java 加减乘除工具类(解决精度损失问题)

    import java.math.BigDecimal; import java.text.DecimalFormat; public class Calculation { public static final DecimalFormat df = new DecimalFormat("######0.00"); /** * @methodName format2point * @...

    java 面试题 总结

    但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,通常Java Bean还要实现Serializable接口用于实现Bean的持久性。Java Bean实际上相当于微软COM模型中的本地...

    键盘录入和方法调用例题.rar_java_numeralxnd_out_storeerr

    1.开发中要实现人机互动,所以首先要学习键盘录入,可以让程序...2.打印调用,格式:System.out.println(方法名称(参数));3.赋值调用,格式:数据类型 变量名称=方法名称(参数);4.单独调用:方法名称(参数);

    Java复习题及答案

    6、在异常处理中,若try中的代码可能产生多种异常则可以对应多个catch语句,若catch中的参数类型有父类子类关系,此时应该将父类放在前面,子类放在后面。 ( ) ..... 二、单项选择题(每题2分,共30分) 1、若在某...

    java初学者必看

    最近正在学习Java,也买了很多的有关Java方面的书籍,其中发现《跟我学Java》这本书,都的很不错啊,所以顺便拿电脑把这本书的目录敲了下来,与大家分享。尤其是那些和我一样初学Java的朋友们,看看哪一节对你有用,...

    JAVA复习题及答案

    在Java中一个类不能同时继承一个类和实现一个接口 D. 在Java中接口只能单一继承 7、对于下列Cat类,哪个叙述是错误的?( ) A.Cat类只有 2 个构造方法,而且没有无参数的构造方法 B.Cat类有 4 个构造方法 C.Cat ...

    FirstJava2完全教材

    列表框中双击某一个函数名,代码编辑区将会自动输入"函数名()",如果这个函数有参数光标定位于 括号中,否则定位到括号外. 3.输入"this."时,会显示当前类和超类的所有相关函数和属性. 4.输入"new "时,会显示当前类所有...

    最全java考试编程题

    用 java 程序实现三角形的输出。要求:(1)能从命令行参数读取三角形的高度 (2)使用“*“作为 三角形的外框(例如: * *1* *222* *33333* *4444444* *555555555*)(3)实现至少一处自定义 Exception(4)进行 Exception ...

    java发送短信之AT指令

    // 下面是初始化COM口的传输参数,如传输速率:9600等。 try { serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); setCOMname(portId.getName())...

    Java 语言基础 —— 非常符合中国人习惯的Java基础教程手册

    (5) implements 子句用于说明类中将实现哪些接口,接口是 Java 的一种引用类 型。 (6) 类体包含了变量和方法。在类体中定义的数据、变量和方法称为类的成员, 或称为实例变量和实例方法。 (7) 例如: 下例定义...

    达内 coreJava 习题答案

    1,编写程序,判断给定的某个年份是否是闰年。 闰年的判断规则如下: ... System.out.println("参数错误!"); return; } if(n){ sum = 1; }else{ for(int i=3;i;i++){ sum = n1+n2; n1 = n2; ...

    java实验报告:实验六.doc

    输入参数(IN):Java.sql.PrepareStatement接口提供了一系列setXXX方法向SQL语句 传递输入参数,实现动态的SQL语句。在传递参数时,必须满足数据类型一致的要求. 6.输出参数(OUT):在调用一个存储过程时,可用setXXX...

Global site tag (gtag.js) - Google Analytics