struts int参数没法传string_对JAVA参数传递的理解

刚开始接触JAVA的时候,从书上看到的JAVA中参数的传递机制,包括了很多概念,比如:形参,实参,传值调用,传引用调用等等,花了很长时间弄明白这其中的关系.直到我看了一本叫《JAVA编程的逻辑》的书,里面这样写的:

关于参数传递,简单总结一下,定义函数时声明参数,实际上就是定义变量,只是这些变量的值是未知,调用函数时传递参数,实际上就是给函数中的变量赋值.

既然调用函数时传递参数,实际上就是给函数中的变量赋值 ,那我们不妨先来看看在JAVA中给变量赋值的原理,再来对照理解参数传递.

1.基本类型

int a = 10;
int b = a;
b = 5;
a = ?    

毫无疑问,这里a = 10,值不会被改变,画个简单的图示意一下:

38f97138b6322ee8ae6abd98d15a577f.png

这里a赋值给b,是把a的值(10)给了b,a和b同样是分别保存在栈上,互相不影响,所以改变b的值,a并不会被改变.

那么同样的道理,基本类型的参数传递,也不会改变原来的值:

    public static void main(String[] args) {
        int a = 10;
        System.out.println("a:before = "+a);
        reset(a);
        System.out.println("a:after = "+a);
    }

    public static  void reset(int b){
        System.out.println("b:before = "+b);
        b = 5;
        System.out.println("b:after = "+b);
    }

输出结果:

a:before = 10

b:before = 10

b:after = 5

a:after = 10

2.数组

int[] a = {1, 2};
int[] b = a;
b[1] = 3;
a[1] = ?

在这里,a[1] = 3.这是因为一个数组变量有两块空间,一块用于存储数组内容本身,另一块用于存储内容的位置,变量a记录的就是这个存储内容的位置.这里a对b赋值,就是把这个内容的位置信息交给了b,所以a和b都保存了这么一个相同的位置,而数组内容本身只有一份数据.所以当b去修改数组内容的时候,a也会同样受到影响.

int[] a = {1, 2}

73c75dd8a2b50e9df8a93af2f8b26e5d.png

int[] a = {1, 2};

0121d994ec31f3b886e5e3e155197341.png

b[1] = 3;

5ca55de3dad8f5afcfcd93f760eda6b7.png

这样再来看数组作为参数时的情况就很清楚了

public static void main(String[] args) {
    int[] arr = {10,20,30,40};
    reset(arr);
    for(int i=0; i<arr.length; i++){
        System.out.println(arr[i]);
    }
}

public static void reset(int[] arr){
    for(int i=0; i<arr.length; i++){
        arr[i] = i;
    }
}

输出:

0

1

2

3

main方法中的数组arr被修改了.

3.对象

因为数组本身就是一种对象,所以如果是传入一个对象到方法中,然后再修改这个对象,那么和数组没有什么区别,变量保存的内容和参数传递的内容同样是对象在堆中的位置,所以在方法中的修改同样会影响到方法外.我就不再重复讲也不画图了.

这个地方我们讲点别的情况

public static void main(String[] args) {
        User teacher = new User();
        teacher.name = "cxk";
        changeUser(teacher);
        System.out.println("teacher = " + teacher);
}

public static void changeUser(User user){
      //user.name = "Owen"; //如果在这里修改后直接返回的话, 那么显然main方法中的teacher.name是会被改变的
        user  = new User();
        user.name = "Owen";
}

 static class User{
        public String name;

        @Override
        public String toString() {
            return name;
        }
 }

这里打印出来的结果是:

teacher = cxk

这是因为changeUser方法中的new User() 在堆上重新创建了一个User对象 , user = new User() 则把这对象的地址赋值给了变量user.但是这仅仅是修改了changeUser方法内的引用指向,对main方法中的teacher的引用指向没有任何影响.

731cd35231de0abe98764180b029be72.png

user =newUser();

user.name ="Owen";

ce5eb7903d0c88c0f603a5e42742f195.png

可以看到,main方法中的teacher此时是不会被changeUser方法中的user影响了,因为他们已经指向了不同的对象.

在这种情况下,如果我们就是需要将另外的对象赋值给传递进来的参数,或者有时候,我们想把这个对象置为null,改怎么办呢?我们可以时候Holder类,他的源码非常简单,就是一个对泛型value的包装:

package javax.xml.ws;

import java.io.Serializable;

/**
 * Holds a value of type <code>T</code>.
 *
 * @since JAX-WS 2.0
 */
public final class Holder<T> implements Serializable {

    private static final long serialVersionUID = 2623699057546497185L;

    /**
     * The value contained in the holder.
     */
    public T value;

    /**
     * Creates a new holder with a <code>null</code> value.
     */
    public Holder() {
    }

    /**
     * Create a new holder with the specified value.
     *
     * @param value The value to be stored in the holder.
     */
    public Holder(T value) {
        this.value = value;
    }
}

还是用刚才老师和学生的例子来测试一下:

public static void main(String[] args) {
        User teacher = new User();
        teacher.name = "cxk";
        Holder<User> teacherHolder = new Holder<>();
        changeUser(teacherHolder);
        System.out.println("teacher = " + teacherHolder.value.name);
    }
public static void changeUser(Holder<User> holder){
        User student  = new User();
        student.name = "Owen";
        holder.value = student;
}

static class User{
        public String name;

        @Override
        public String toString() {
            return name;
        }
}

输出是:teacher = Owen

相信看到这里上面的原理大家应该很清楚了,我就不再画图了(好的好的,我就是懒O(∩_∩)O)

4.String

String稍微有点特殊,他本身是一个引用类型,那么我们先来看看String在赋值的时候会发生什么:

String teacher = "cxk";
String student = teacher;
student = "Owen";
System.out.println("teacher = "+teacher);
System.out.println("student = "+student);

输出为:

teacher = cxk

student = Owen

虽然teacher 和 student 都同时指向了"cxk",但是在修改student的时候,并不会影响到teacher.那么同样的道理,在把String作为参数传递时,也不会影响到函数外原本的变量的值.

这是因为String虽然是引用类型的数据,但是它的底层是一个字符数组,String被设计为不可变的,每次改变他的值,都是会重新生成一个新的String,然后把这个新String的地址指给变量.所以当执行student = "Owen"时,其实是产生了一个新的String,然后student指向了这个新的地址.

String teacher = "cxk";

8caa2cb3294937718a2acf570805959d.png

String student = teacher;

5cb20642b9ff60c93a75158de16e097d.png

student = "Owen";

8d08aa54f9558c018527fb83b29a8598.png

总结

这里大致讲了一下对JAVA参数传递的理解,但是有的地方沒有展开或者深入的去说.比方说,String的底层是一个字符数组和String不可变有什么关系?String为什么要设计成不可变的?还可以了解数组扩容会改变地址,字符串常量池等等引申出去很多内容.希望大家可以对不太了解的点去深入的学习.这样才能形成自己的知识体系.其实很多时候面试官在问问题时也是这样一个逻辑,当一个问题你回答的不错时,他就会顺着这个问题的某一个点继续去深入挖掘,所以在平时学习时也保持这样一个习惯是非常好的.


扯淡内容又开始了:

其实我想过是不是应该把标题改为《JAVA的参数传递,看这一篇就够了!》或者《再有人问你JAVA的参数传递,就把这一篇丢给他!》,后来觉得还是算了.因为我也只能算个初学者,这个专栏也是我自己在学习的过程中有什么感想,就随手记录一下.所以我不会写一些系列文章,那种在网上一搜就会有一大把,我只会在自己对某些知识点真的有些自己的思考的时候才会写下来.如果能偶然帮助到一些和我一样在学习JAVA的同学,帮助大家在某一个小的知识点上产生了自己的理解,而不是把它简单的背下来,那我就非常开心了.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值