zoukankan      html  css  js  c++  java
  • java入门(3)--函数

    函数和方法

    如果我们经常要进行一些相似的处理过程,就可以把这个处理过程封装为函数

    函数可以被多次重复调用,从而实现代码重用和隔离的目的。

    在面向对象的语言中,函数经常和对象绑定在一起,为区分起见,这时它被称为方法

    因为java是完全面向对象的,函数必须从属于某个类。所以java中的函数都被称为方法。

    如果方法前以 static 修饰,则称为静态方法,可以粗略地认为,它与 c 语言的函数的概念大致相等了。

    方法可以在其括号中列出调用它时需要准备的参数,叫形式参数

    方法也可以有一个返回值(或没有,此时写void)。

    下面,我们调用方法 f,求两个整数的末位是否相同。

     1 public class A0403
     2 {
     3     static boolean f(int a, int b){
     4         int a1 = a % 10;
     5         int b1 = b % 10;
     6         return a1==b1;
     7     }
     8     
     9     public static void main(String[] args){
    10         System.out.println(f(101,12));
    11         System.out.println(f(65432,12));        
    12     }
    13 }

    这个方法接受两个参数,都是整数,它进行一系列的处理后,返回一个布尔值。

    return 语句结束 f 方法的执行,并返回一个指定的值。

    在遇到 return 语句后,f 方法的其它代码就不再执行,而是要返回调用它的那个方法中。当然,在此方法中,return 语句后恰好没有更多的语句了。

    如果一个方法定义了返回值,它在结束执行之前就一定会遇到 return 语句,否则会引发编译错误。

    形参独立原理

    如果在被调函数中改变了形参的值,会不会影响调用的一方呢? 不会!

    我们看这个例子:

     1 public class A0404
     2 {
     3     static void f(int x){
     4         int sum = x % 10;
     5         x /= 10;
     6         sum = sum * 10 + x % 10;
     7         x /= 10;
     8         sum = sum * 10 + x % 10;
     9         System.out.println(sum);
    10         System.out.println("x=" + x);
    11     }
    12     
    13     public static void main(String[] args){
    14         int a = 368;
    15         f(a);
    16         System.out.println("a=" + a);    
    17     }
    18 }

    这里的函数f的功能是:把传给它的3位数 x 的数位反转并输出。

    为了观察,我们额外输出了 a 的值,以及 x 的值。

    通过结果可以看到,虽然 x 的值在计算过程中发生了变化,但这并不会影响 a 的值。

    实际上,在调用 f 之前,要为它准备需要的参数,这些参数必须新创建,所以才称为形式参数。

    也就是说,在没有调用 f 函数的时候,这些形参变量是不存在的,在多次调用 f 的时候,这些形参就会被创建多次。

    创建形参后,把实参的值(这里就是 a 的值)拷贝给它,然后才开始 f 的执行。

    当 f  执行结束后,形参变量会被自动释放掉。

    从更底层的机制看,这个形参的分配与释放的过程是通过栈来完成的。

    函数调用前,要把返回的位置,需要的参数等信息压栈,在函数执行完毕后,自动弹栈,恢复执行前的样子。

    如果被调用的函数还会去调用其它函数,这个过程还会继续上演。

    这样,栈可能就会越涨越高,但函数的执行总有结束的时候,那时栈就会落回来。

    如果由于某种设计失误,导致函数调用一直没能正确返回,而是不断地调用其它的函数,就会导致栈的溢出,这是很常见的程序错误。

    从参数传递的原理上我们看到,实参与形参是各自独立的变量,除了开始的时候,实参拷贝给形参外,它们再不会有任何联系。这叫做

    "形参独立原理"。

    这种设计为我们省去了许多麻烦,但有时我们可能会想让被调方与主调方共享一个变量,而不是各自独立,这怎么办呢?

    答案是传指针,在java中叫做:引用。

    引用作为参数

    引用的本质是持有另一个对象的地址。

    如果对一个引用进行复制,只不过是两个引用指向了同一个对象,并没复制对象本身。

    引用与面向对象的体系紧密联系在一起,所以要等到学了初步的面向对象的知识后我们才能更好地理解它。

    但这里,我们可以先看看数组的行为,来窥其端倪。

    数组就是一种对象类型,我们定义的数组变量,实际上是指向实际数组对象的指针,或说:引用。

     1 public class A0404
     2 {
     3     static void f(int[] x){
     4         for(int i=0; i<x.length; i++){
     5             if(x[i] < 0) x[i] = -x[i];
     6         }
     7     }
     8     
     9     public static void main(String[] args){
    10         int[] a = {5, -3, 6, 10, 0, -15};
    11         f(a);
    12         System.out.println(java.util.Arrays.toString(a));
    13     }
    14 }

    这里的形参 x,实参 a 都不是数组本身,它们是指向数组的引用。

    虽然  x 和 a 也是按照同样的规则,不会相互影响,但由于它们指向了同一个对象,这就引起了复杂的现象。

    从结果上,我们可以观察到,在 f 方法中修改了数组对象的值,在主调方打印数组时也看到了这些变化。

    其原理图:

    引用是一种在主调函数和被调函数间共享数据的常用手段。

    在上面的这个例子中,引用变量本身并没有发生变化。发生变化的是引用所指向的对象,所以“形参独立性原理”并没有因此而破坏。

    我们可能会看到某些材料上写着: java 有两种传递参数的方式,一种是传值(传拷贝),另一种是传引用。

    这可能会产生一些误导。实际上Java只有一种传递参数的方式,就是传值。

    而这个被传递的值有可能会恰好是一个引用类型,就会引起一些类似共享变量的效果,其实并没有什么特殊的秘密,也不应该算是“另一种”传递方式。

  • 相关阅读:
    iBatisnet 1.5版本的配置文件的几个变化
    使用Trace时要注意
    无刷新转页面?
    无刷新“页面跳转”问题一:与AtlasToolKit协同工作
    Assembly的Release与Debug
    iBatis.Net系列(四) iBatisNet API基础
    Atlas 调用web service
    无刷新“页面跳转”
    iBatis.Net系列(六) ResultMap
    在GridView中格式化时间字段
  • 原文地址:https://www.cnblogs.com/gyhang/p/8728389.html
Copyright © 2011-2022 走看看