Java技术——Java中的参数传值方式

0. 前言  

昨天10号晚上迎来了今日头条视频面试三连击(Android开发实习生),每场都50都分钟,而且问的问题有些确实有点难(头条的工程师水平确实有点高,面BAT的时候都没这么大压力),不过今日头条是我见过招聘效率最高的公司,第一场面试结束后面试官会让你不要离开视频间,等待HR通知,一般HR10分钟你就会打电话告知你一面过了,马上开始第二场面试。就这样进行了三轮视频面试,结果差强人意,三面都通过了,并且获得了秋招终面直通卡。不废话了,这篇文章主题就是一面中的一道面试题。

 

1.  你觉得下面程序会输出什么

public static void change(String s) {   
    s = “123”;  
}   
  
public static void main(String args[]) {   
    String s = “abc”;   
    change(s);   
    System.out.println(s);
}

面试官写下了这段代码,问我s会输出什么。

我想起了各种排序算法直接把一个int数组array,通过参数传递给一个方法,在方法里完成数据的移动后,直接在main()函数中输出array[]中的值就是修改过的。所以我回答说,那应该输出123吧。

然后面试官说,不对,是输出abc,你觉得原因是什么。

我想了想回答说,Stringfinal的,所以值是不变的。

接着面试官写下了如下代码:

public static void main(String[] args) {
	MyClass myClass = new MyClass();
	change(myClass);
	System.out.println(myClass.val);
}

private static void change(MyClass myClass) {
    myClass = new MyClass();
	myClass.val = 2;
}
public static class MyClass{
	int val = 1;
}

问我MyClass类不是final的,但为什么这里还是会输出1。我有点被问懵了,其实后来面试结果又仔细看一下,是自己忽略掉了第八行代码,其实把第八行代码注释掉,肯定就输出2了。

2.  Java参数传值

2.1  值传递

先从一个例子说起:

public static void change(int i, int j) {  
      int temp = i;  
      i = j;  
      j = temp; 
}  
 
public static void main(String[] args) {  
      int a = 3;  
      int b = 4;  
      change(a,b);  
      System.out.println(a);  
      System.out.println(b); 
}  

输出为:

3
4

值传递是指方法调用时,实际参数把它的值传递给对应方法的形参,如change()方法中ij,也在内存空间中分配了存储单元,这样形参在change()方法中的改变不会影响实际参数的值。

值传递的数据类型包括,八种基本数据类型和String

2.2  引用传递

值传递的数据类型包括,八种基本数据类型和String,八种数据类型还比较好理解,比如2.1中的int,但是String并不是基本数据类型,这要怎么理解呢。比如下面这个例子。

public class Example {  
    String str = new String("abc");  
    char[] ch = { 'a', 'b', 'c' };  
    public static void main(String args[]) {  
        Example ex = new Example();  
        ex.change(ex.str, ex.ch);  
        System.out.println(ex.str);  
        System.out.println(ex.ch);  
    }  
    public void change(String str, char ch[]) {
        //ch = new char[]{'a','b','c'};  
        str = "change";  
        ch[0] = 'c';  
    }  
}  

这个例子的输出为:

abc
cbc

要知道String和char数组都是引用类型,不是基本类型。

当我们把str作为参数传入方法后,会新建另一个变量,已经不是原来的变量了,但是他们指向的数据区域都一样,所以如果你在方法中改变了str指向的数据区域,即执行str = "change",那也只是改变新建的另一个变量所指向的数据区域,即指向一个新对象"change"str仍然指向原来的数据区域。所以会输出abc

 

但是对于char数组的例子呢,即对象类型,也就是Object的子类(除了String,是把ch的引用传递进来,即引用传递。这样里面和外面的ch都指向了相同的数据区域,执行ch[0] = 'c',就会把这个数据区域里的第一个字符改成c,并没有改变内部ch的数据地址,所以这个修改也会反映到外部的ch。所以会输出cbc。如果你改变了内部ch所指向的数据区域,即把上面代码中注释的那一行打开,即执行ch = new char[]{'a','b','c'},这样ch已经指向一个新的数据区域。输出的结果肯定也就是abc了。

 这样在1中面试官给的两段代码也就很容易解释了。

两种数据传递总结

值传递和引用传递的本质区别在于是否在传递的时候进行对象的内存拷贝

基本类型是由于在JVM中存储区域不同于普通对象所以传递前会拷贝,传递的是拷贝后的值,但是对象在传递的时候不拷贝,直接传“引用值”,指向同一片对象堆内存区域,当然要注意String这种特殊情况。

### JSP 和 Java 代码间的数据递方法 #### 使用 `request` 对象参数 在 Web 应用程序开发中,`request` 对象用于封装客户端请求的信息。通过该对象可以方便地从前端表单或其他来源接收数据并将其递给处理逻辑。 ```java // 假设有一个登录表单提交到服务器 String username = request.getParameter("username"); String password = request.getParameter("password"); if ("admin".equals(username) && "123456".equals(password)) { // 处理成功情况... } else { // 处理失败情况... } ``` 此段代码展示了如何利用 `request.getParameter()` 方法读取来自 HTML 表单的输入字段[^3]。 #### 利用 Servlet 进行预处理并将结果转发至 JSP 页面显示 当需要执行复杂的业务逻辑时,通常会先由一个专门负责此类工作的Servlet完成必要的计算工作之后再转向相应的视图层组件——即JSP文件来进行最终呈现: ```java protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 执行某些操作... // 将所需数据显示变量设置为请求属性 req.setAttribute("message", "Hello from servlet!"); // 转发控制权给指定路径下的目标资源 RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/result.jsp"); dispatcher.forward(req, resp); } ``` 上述例子说明了怎样把信息附加到当前HTTP请求上以便稍后能在展示模板里访问它们;同时也体现了基于MVC架构模式下不同职责分离的设计理念[^1]。 #### Application Scope 的全局作用域共享机制 对于那些在整个应用程序生命周期内都需要保持一致性的配置项或是统计类别的计数器来说,则更适合采用 application scope 来实现跨多个用户会话之间的持久化存储需求: ```jsp <!-- 设置 --> <% application.setAttribute("siteName", "Example Site"); %> <!-- 获取 --> <p>Site name is <%= application.getAttribute("siteName") %>.</p> ``` 这里给出了具体的应用场景以及相应代码片段来解释如何借助于 application object 实现这一目的[^2]。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值