集合类参数的传递.doc_第1页
集合类参数的传递.doc_第2页
集合类参数的传递.doc_第3页
集合类参数的传递.doc_第4页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

对于传参,从计算机的本质而言是传值.因为从数据模型而言计算机只认识数学值.但是不同的数学值代表的意义不同,有的数学值表示的是另一个数据的地址.所以根据这个数学值能访问到它表示的数据,我们就把这样的操作称为传址.其实就是某个数据所在的地址的数学表示.其本质还是传值. 从应用层而言我们所说的地址当然是指虚拟地址.而对于中间语言(java的byteCode/.NET的IL)而言是托管地址.我们不必关心实际的内存地址如何和它们对应,这由作业系统和应用环境来决定,你想关心也关心不了.我们要关心的是理解作业系统和应用环境提供给我们的可访问地址的内存布局.对于集合类参数,如果传入方法后在方法外重新赋值参数本身,这和其它引用参数一样不会影响方法内的参数.但如果对集合中元素重新赋值则改变了方法内的集合中的元素,因为方法外和方法内的集合就是本身是同一对象.class MyRun public static void exec(String args) for(int i=0;iargs.length;i+) try check(args i ); catch(Exception e) invoke(args i ); static void check(String str) throws Exception if(str.equals(s2) throw new Exception(error1); static void invoke(String str) System.out.println(执行的语句是+str); 这段程序设计是否有错?如果有错,如何修改?这是我在bea论坛上贴出来的一段程序,最初没有一个人能说明有什么错,更别说如何修改.(我知道有很多水平很高的高手根本不去bea论坛所以没有看到这个问题)更可悲的是我把问题展示了很多根本看不懂的人说我在胡说八道,这就是中国程序员的现状,他没有能力理解和不知道的东西都叫胡说八道,当他上小学时他说初中,高中,大学,研究生的知识是胡说八道的.这个问题的展示很简单:当你设计了上面的类以后, 那么我作为调用者,我可以任何方式调用你的类,你都应该是安全的.好,我现在这样调用:先设计一个用来改变数据的线程:class ModifyThread extends Thread private String arr; public ModifyThread(String arr) this.arr = arr; public void run() try Thread.currentThread().sleep(20); catch(Exception e) arr0 = s2; 为了说明问题,我在你设计的类中插入一段sleep来模拟线程运行到那里时被切换到其它线程运行,然后又切换回来到本线程运行的情况:class MyRun public static void exec(String args) for(int i=0;iargs.length;i+) try check(args i ); /为了说明问题,在这儿sleep(100)来模拟运行到这里时线切换到其它线程去运行 Thread.currentThread().sleep(100); catch(Exception e) /然后又回到这个这线程继续运行. invoke(args i ); static void check(String str) throws Exception if(str.equals(s2) throw new Exception(error1); static void invoke(String str) System.out.println(执行的语句是+str); 然后调用:public class Main /* Creates a new instance of Main */ public static void main(String args) / TODO code application logic here String strs = s1; new ModifyThread(strs).start(); MyRun.exec(strs); 试试看,我利用一个辅助线程就把s2传进去执行了.好,有人说要同步:class MyRun public static void exec(String args) for(int i=0;iargs.length;i+) synchronized(args) try check(args i ); /为了说明问题,在这儿sleep(100)来模拟运行这里时线切换到其它线程去运行了. /然后又回到这个这线程继续运行. Thread.currentThread().sleep(100); catch(Exception e) invoke(args i ); static void check(String str) throws Exception if(str.equals(s2) throw new Exception(error1); static void invoke(String str) System.out.println(执行的语句是+str); 再调用看看,s2仍然越过了check.因为同步只能保证明多个MyRun.exec()方法在执行时只有一个线程能访问方法内的args数组,根本无法保证从方法外修改strs, 因为方法外的代码没有和方法内共同竞争同一对象锁,.我用sleep来模拟线程间执行的切换.其实只要我用足够多的ModifyThread线程在不同时刻运行起来,和MyRun.exec一起运行,产生这种切换的可能性就非常大.简单说我只要用足够多的辅助线程就能绕过你设计的check.其实要解决问题非常容易:class MyRun public static void exec(String args) /将传入变量复制为方法内的本地变量,打断与方法外的联系. /然后只能本地变量操作 Stringtemp = new Stringargs.length; System.arraycopy(args, 0,temp, 0, args.length); for(int i=0;itemp.length;i+) /synchronized(temp) /然后根本不需要同步. try check(temp i ); /为了说明问题,在这儿sleep(100)来模拟运行这里时线切换到其它线程去运行了. /然后又回到这个这线程继续运行. Thread.currentThread().sleep(100); catch(Exception e) invoke(temp i ); / static void check(String str) throws Exception if(str.equals(s2) throw new Exception(error1); static void invoke(String str) System.out.println(执行的语句是+str); 如果你还不能理解或者不相信我,我们来看看JDK(1.6)是如何处理的.Runtime.exec最终调用了ProcessBuilder的start()方法.在ProcessBuilder中,外部命令可以通过command(List command)这样的方法将一个List传进来,而本地用全局的List command保存也就是command(List command)的实现是: mand = command;这样外部传入一个保存了多个命令的List后,从外部仍然可以访问方法内的List中的内容.所以在start()方法中JDK这样处理,而且加上了这样的注释:/ Must convert to array first - a malicious user-supplied/ list might try to circumvent the security check.String

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论