4.2 方法所属性、方法参数传递机制、形参个数可变的方法

一、方法的所属性

  方法由传统的函数发展而来,方法与传统的函数显著不同:在结构化编程中,函数是一等公民,这个程序由一个个函数组成;在面向对象编程语言里,类才是一等公民,整个系统由一个个类组成。因此在Java语言里,方法不能独立存在,方法必须属于类或对象。

方法的所属性:
(1)方法类似于函数。但与函数不同的是,方法不能存在,方法必须定义在类里面。
(2)方法一定要有执行者,必须通过类或对象来调用方法。从逻辑上来看,该方法属于类本身,应该用类来调用
    如果该方法有static修饰,该方法属于类本身,应该用类调用;
    如果该方法无static修饰,该方法属于对象本身,应该用对象调用
【规则】如果调用同一个类中方法,可以省略调用者,此时系统会默认添加调用者。如果方法是无static方法,添加this作为默认调用者;如果方法是static方法,添加类作为调用者。

 1 class Method_attribute
 2 {
 3     //定义一个普通方法
 4     public void nonStaticMethod()
 5     {
 6         System.out.println("这是一个普通方法");
 7     }
 8
 9     //定义一个static方法
10     public static void StaticMethod()
11     {
12         System.out.println("这是一个类方法");
13     }
14
15     //在同一个类中一个方法调用另外一个方法
16     public void test()
17     {
18
19         this.nonStaticMethod();
20         this.StaticMethod();
21         StaticMethod();//省略的是主调类
22     }
23     public static void main(String[] args)
24     {
25         var p=new Method_attribute();
26         //此时test()方法中的两个this代表对象p
27         p.test();
28     }
29 }
30 ---------- 运行Java捕获输出窗 ----------
31 这是一个普通方法
32 这是一个类方法
33 这是一个类方法
34
35 输出完成 (耗时 0 秒) - 正常终止

二、方法参数的传递机制

Java里方法是不能独立存在的,调用方法时必须使用类或对象作为主调者。如果声明方法时,包含了形参声明,则调用方法时必须给这些形参指定参数值,调用参数时传给形参参数值也称为实参。

Java里面参数传递方式只有一种:值传递。所谓值传递,就是将实际参数的副本(复制品)传入方法内,而参数本身不会受到影响。

class ParamTransferTest
{
    public static void swap(int a,int b)
    {
        //实现变量a和b的值交换
        //定义一个临时变量来保存a的值
        var temp=a;
        a=b;
        b=temp;
        System.out.println("swap方法里,a的值为:"+a+",b的值为:"+b);
    }
    public static void main(String[] args)
    {
        int a=6;
        int b=9;
        swap(a,b);
        System.out.println("交换结束后,a的值为:"+a+",b的值为:"+b);
    }
}
---------- 运行Java捕获输出窗 ----------
swap方法里,a的值为:9,b的值为:6
交换结束后,a的值为:6,b的值为:9

输出完成 (耗时 0 秒) - 正常终止

Java程序从main()方法开始执行,main()方法开始定义了a、b两个局部变量,如图所示:

程序从main()函数开始执行,当程序进入swap()方法时,系统分配了两个栈区,将mian()方法中的变量a、b的副本传入swap()方法,而不是a、b本身。

程序在swap()方法中,进行变量a、b交换的值,交换结束后,内存中的存储情况:

两个示意图可以发现,mian()方法栈区中a、b值并未发生改变,程序只改变swap()栈区中的变量a、b。这就是值传递的实质:当系统开始执行方法时,系统为形参初始化,就是把实参变量的值赋给方法的形参变量,方法里操作的并不是实参变量。

再看一个例子:

 1 class DataWrap
 2 {
 3     int a;
 4     int b;
 5 }
 6
 7 public class ReferenceTransferTest
 8 {
 9     public static void swap(DataWrap dw)
10     {
11         //下面实现的dw的两个成员的变量值的交换
12         var temp=dw.a;
13         dw.a=dw.b;
14         dw.b=temp;
15         System.out.println("swap()方法里,a成员变量的值是:" + dw.a + ",b成员变量的值是:"+dw.b);
16     }
17
18     public static void main(String[] args)
19     {
20         var dw=new DataWrap();
21         dw.a=6;
22         dw.b=9;
23         swap(dw);
24         System.out.println("swap()方法里,a成员变量的值是:"+dw.a+",b成员变量的值是:"+dw.b);
25     }
26 }
27 ---------- 运行Java捕获输出窗 ----------
28 swap()方法里,a成员变量的值是:9,b成员变量的值是:6
29 swap()方法里,a成员变量的值是:9,b成员变量的值是:6
30
31 输出完成 (耗时 0 秒) - 正常终止

上面结果swap()方法里和mian()方法里的两个变量a、b都发生了改变。这很容易产生错觉:调用swap()方法时,传入的时dw本身,而不是它的复制品。

下面分析一下程序执行的过程:

(1)程序从mian()方法开始执行:

var dw=new DataWrap();
dw.a=6;
dw.b=9;

这里创建了一个DataWrap对象,并赋给引用变量dw。堆内存保存该对象本身,栈内存保存的该对象的引用变量。

(2)执行swap(dw);

接下来main()方法开始调用swap()方法,mian(0方法并未结束,系统会为main()和swap()开辟两个栈区,用于存放mian()和swap()方法里的局部变量。调用swap(0方法时,dw作为实参传入swap()方法,同样采用值传递:把main()方法里的dw变量赋值给swap()方法里的dw形参,从而完成swap()方法的dw形参初始化。下图显示main()方法中实参dw传入swap()方法后的存储示意图:

系统只复制了dw变量,但未复制DataWrap对象。

  不管程序在swap()方法中还是在mian()方法的操作dw变量时,实际操作的都是堆内存中的DataWrap对象,他们引用的是同一个变量。因此在swap()方法中交换了dw所引用的a、b两个成员变量后,可看到在main()方法中dw引用变量引用的a、b变量的值也发生了改变。

实际上,我们在创建swap()方法时,将

 public static void swap(DataWrap dw);中的dw换个符号表示理解起来就更容易,不易混淆。

三、形参个数可变的方法

Java允许定义形参个数可变的参数,从而允许为方法指定数量不确定的形参。如果在定义方法时,在最后一个形参的类型后增加三点(...),则表示该形参可以接受多个参数值,多个参数被当作数组传入。

 1 class  VarArgs
 2 {
 3     public void test(int a,String... names)
 4     {
 5         System.out.println("a参数:"+a);
 6         System.out.println("names数组的长度:"+names.length);
 7         for(int i=0;i<names.length;i++)
 8         {
 9             System.out.println(names[i]);
10         }
11     }
12     public static void main(String... args)
13     {
14         VarArgs va=new VarArgs();
15         va.test(2,"efdf","fdfs","fjgd");
16         va.test(34,new String[]{"孙悟空","猪八戒"});
17     }
18 }
19 class  VarArgs
20 {
21     public void test(int a,String... names)
22     {
23         System.out.println("a参数:"+a);
24         System.out.println("names数组的长度:"+names.length);
25         for(int i=0;i<names.length;i++)
26         {
27             System.out.println(names[i]);
28         }
29     }
30     public static void main(String... args)
31     {
32         VarArgs va=new VarArgs();
33         va.test(2,"efdf","fdfs","fjgd");
34         va.test(34,new String[]{"孙悟空","猪八戒"});
35     }
36 }
37 ---------- 运行Java捕获输出窗 ----------
38 a参数:2
39 names数组的长度:3
40 efdf
41 fdfs
42 fjgd
43 a参数:34
44 names数组的长度:2
45 孙悟空
46 猪八戒
47
48 输出完成 (耗时 0 秒) - 正常终止

va.test(2,"efdf","fdfs","fjgd");   va.test(34,new String[]{"孙悟空","猪八戒"});
这两种多形参传入方法都可以,但是第一种方法更加简洁。

类型[] 形参名

类型...写法的好处是:
调用方法时更加方便,即可直接传入多个元素,系统会自动将它们封装为数组
也可直接传入数组
确定:类型... 这种写法只能作为形参列表的最后一个形参
【暗示】一个方法只能由一个形参个数可变的形参

再看一个例子:

 1 class VarIntTest
 2 {
 3     public int add(int... num)
 4     {
 5         int result=0;
 6         for (int i=0;i<num.length;i++)
 7         {
 8             result+=num[i];
 9         }
10         return result;
11     }
12     public static void main(String[] args)
13     {
14         var p=new VarIntTest();
15         System.out.println(p.add(1,2,3,4));
16     }
17 }
18 ---------- 运行Java捕获输出窗 ----------
19 10
20
21 输出完成 (耗时 0 秒) - 正常终止

原文地址:https://www.cnblogs.com/weststar/p/12341091.html

时间: 2024-10-13 18:33:39

4.2 方法所属性、方法参数传递机制、形参个数可变的方法的相关文章

linux下java环境变量的设置,形参个数可变的方法

首先我们执行jdk二进制文件: 生成一个jdk目录,将这个目录mv到/usr/loca/jdk # vim /etc/profile export JAVA_HOME=/usr/local/jdkexport CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/libexport PAT# vim Varargs.java #source /etc/profile 例子: #vim test.java 这个例子中test方法形参个数可变,在形参列表中,最后一个形参

iOS学习笔记(5)形参个数可变的方法

如果在定义方法时,在最后一个形参明后增加逗号和三点(,...),则表明该形参可以接受多个参数值. 为了在程序中获取个数可变的形参,需要使用如下关键字 · va_list:这是一个类型,用于定义指向可变参数列表的指针变量 · va_start:这是一个函数,该函数指定开始处理可变形参的列表,并让指针变量指向可变形参列表的第一个参数 · va_end:结束处理可变形参,释放指针变量 · va_arg:该函数返回获取指针当前指向的参数的值,并将指针移动到指向下一个参数 例子 Varargs.h #im

java中形参个数可变的方法使用

public class Varargs { public static void main(String[] args) { test(3,"java","C++","PHP"); } public static void test(int num,String... books) { System.out.println(num); for(String book : books) { System.out.println(book); }

用C#中的params关键字实现方法形参个数可变

个人认为,提供params关键字以实现方法形参个数可变是C#语法的一大优点.在方法形参列表中,数组类型的参数前加params关键字,通常可以在调用方法时代码更加精练. 例如,下面代码: [csharp] view plaincopy class Program { static void Main(string[] args) { Console.WriteLine(Sum(1)); Console.WriteLine(Sum(1, 2, 3)); Console.WriteLine(Sum(1

疯狂java学习笔记之面向对象(三) - 方法所属性和值传递

方法的所属性: 从语法的角度来看:方法必须定义在类中 方法要么属于类本身(static修饰),要么属于实例 -- 到底是属于类还是属于对象? 有无static修饰 调用方法时:必须有主调对象(主语,调用者) 1 public class MathTest{ 2 public static void main(String[] args){ 3 System.out.println(Math.sin(1.57)); 4 System.out.println(Math.sin(Math.PI/2))

UITableView UITableDataSource UITableViewDelegate的基本方法和属性

1.1 UITableView的基本方法和属性 选中的行号 - (NSIndexPath *)indexPathForSelectedRow; // returns nil or index path representing section and row of selection. 表格编辑模式设置 // Editing. When set, rows show insert/delete/reorder controls based on data source queries @prop

python--把一个方法变成属性调用

# coding=utf-8 ''' 装饰器(decorator)可以给函数动态加上功能,对于类的方法,装饰器一样起作用.Python内置的@property装饰器就是负责把一个方法变成属性调用的: @property:把一个getter方法变成属性 @score.setter:负责把一个setter方法变成属性赋值 ''' class Screen(object): #读属性 @property def width(self): return self.value_of_width #写属性

Java中的参数传递机制

通过前一篇文章的介绍,我们从整体上明白了,Java类中变量的差异性.不同变量在内存中的存储位置,以及变量的生命周期等.今天,我们来看一下Java中参数传递的机制. 形参:方法声明时包含的参数声明 实参:调用方法时,实际传给形参的参数值 Java方法的参数传递机制: Java方法的参数传递只有一种:值传递.所谓值传递,就是将实际参数值的副本,传入方法内,而参数本身不会收到任何影响. PS:传入方法的时实际参数值的复制品,不管方法中对这个复制品如何操作,实际参数本身不会受到任何影响. 基本类型的参数

Java:参数数量可变的方法

许多Java新人在看到下面的这段代码的时候,都会问一个问题:dealArray方法里那三个小点点是什么啊? [java] view plaincopy public class TestVarArgus { public static void dealArray(int... intArray){ } public static void main(String args[]){ } } 可变的参数类型,也称为不定参数类型.英文缩写是varargus,还原一下就是variable argume