Java方法及传递参数到方法中

时间:2019-04-29 03:17:57  来源:igfitidea点击:

在 Java 中,方法定义对象行为或在类级别实现不同的功能(对于静态方法)。如果变量(值类型或引用)表示 Java 编程的静态部分,则方法表示动态部分,因为方法等效于执行和处理某些变量的代码块。

如何定义方法

用于定义方法的一般语法是

[access_modifier] [non-access modifier] return_type method_name (type parameter1, type parameter2, …, type parameterN)
[访问修饰符] [非访问修改符] 返回值 方法名称 (类型参数 1, 类型参数 2, ..., 类型参数N) 

其中:

[access_modifier] [ 定义该方法的可见性;可能的值包括:

[default] = 当你不写任何东西;
[public] 方法在其他类中可见;
[private] 方法在其他类中不可见;
[protected] = 方法仅在子类中可见。

[non-access modifier] [定义其他属性的方法,如:
[static] (该方法在类级别定义 = 它不是对象方法),
[final] (该方法不能在子类中重写),
[abstract] (该方法不能实例化,因为包含抽象方法 = 虚拟纯方法)

[return_type] [任何基元或参考类型;如果该方法不返回值,则返回类型为 [void];如果定义返回类型,则该方法必须以 返回值/变量语句结束,其中值/变量类型是定义的返回类型:

public class Test {

  public static void main(String[] args) {

      int vb1 = 10;

      int vb2 = 20;

      //调用doSum 方法

      int sum = doSum(vb1, vb2);

      System.out.println("The sum is "+sum);

  }

  public static int doSum(int a, int b)

  {

      int result = a + b;

      return result;

  }

}

[method_name] [ 必须尊重变量使用的相同命名约定;Java 建议使用 camelCase 命名约定(第一个单词以小写字母开头);此外,名称应该是动词名词对,如getNamedoSum;

[参数] = 表示方法的输入值(原始值或引用值);关于参数,你必须知道这一点:

  • 方法声明中变量称为形式参数parameters简称形参;调用 方法时,输入值称为实际参数arguments简称实参;
  • 方法输入的参数是该方法的局部变量;
  • 我们可以使用var-arg 方法定义可变数量的输入参数 ;

参数的重要规则

  • 方法参数始终按其值传递;方法参数始终是参数的副本(可能是最重要的规则);
  • 基元参数表示调用参数的值副本;
  • 引用参数表示调用引用参数的值副本(引用值不是对象,而是对象地址)

如何传递参数并返回多个值

在我们描述这个概念之前,请记住一个重要的Java规则:

方法的实参argument总是按其值传递;方法形参parameters始终是实参的副本

有 2 种类型的参数:值类型对象引用。它们之间的区别在于合乎逻辑的,因为引用就像具有重要特征的数字变量:它们的值表示存储在 Heap 中的对象的地址。

在C++,则是不同的,因为我们有参数通过它们的值和它们的地址传递(当我们使用指针时)。此外,在 C# 中:我们有参数通过其值或指针(不安全)传递,或者使用 [ref] 作为输入参数属性。

因为 在 Java 中,方法的实际参数argument始终由其值传递,这意味着方法局部变量的值与调用参数的值相同。当我们想要编写返回多个值的方法时,这可能表示一个问题(对于一个值,可以使用方法返回类型)。

例如,让我们编写一个用于交换 2 个基元变量的值的方法。如果我们这样写:

public class Main {

  public static void main(String[] args) {

      int vb1 = 10;

      int vb2 = 20;

      doInterchange(vb1, vb2);

      System.out.println("vb1 = "+vb1+", vb2 = "+vb2);

  }

  public static void doInterchange(int a, int b)

  {

      int temp = a;

      a = b;

      b = temp;

  }

}

那么输出将会是:

vb1 = 10, vb2 = 20

尽管 [doInterchange)] 方法正在实现正确的算法,但结果并不是预期的,因为根据以前的规则,该方法正在交换其自身局部变量 [a] 和 [b] 的值。

因此,我们必须编写一个更好的方法,它将交换2个主要变量的值。让我们尝试通过将 2 个整数装箱到其相应的对象中的引用,像这样:

public class Main {

  public static void main(String[] args) {

      int vb1 = 10;

      int vb2 = 20;

      doInterchange2(vb1, vb2);	//the values are boxed by default

      System.out.println("vb1 = "+vb1+", vb2 = "+vb2);

  }

  public static void doInterchange2(Integer ra, Integer rb)

  {

      int temp = ra;	//default unboxing

      ra = rb;

      rb = temp;	//boxing

  }

}

但是, 令人惊讶的是, 输出还是一样

vb1 = 10, vb2 = 20

在这种情况下,原因更微妙,因为默认boxing机制正在创建一个具有基元变量值的新对象。
另请注意,Integer对象是不可变的。

正确解决方案是使用我们自己的类的引用,例如:

class MyValue

{

  public int value;

  public MyValue(int input)

  {

      value = input;

  }

}

public class Main {

  public static void main(String[] args) {

      int vb1 = 10;

      int vb2 = 20;

      MyValue value1 = new MyValue(vb1);

      MyValue value2 = new MyValue(vb2);

      doInterchange3(value1, value2);

      vb1 = value1.value;

      vb2 = value2.value;

      System.out.println("vb1 = "+vb1+", vb2 = "+vb2);

  }

  public static void doInterchange3(MyValue aValue, MyValue bValue)

  {

      int temp = aValue.value;

      aValue.value = bValue.value;

      bValue.value = temp;

  }

}

结果:

vb1 = 20, vb2 = 10

因为来自主堆栈和 doInterchange3 堆栈的引用引用在堆中引用相同的对象。
因为,在Java中,方法参数总是由它们的值(也是引用)传递的。[不要]错误地认为这行得通:

public static void doInterchange4(MyValue aValue, MyValue bValue)

  {

	//interchange references VALUES and NOT objects values

      MyValue temp = aValue;

      aValue = bValue;

      bValue = temp;

  }

请记住,aValue参考值是 *value1 * 参考值的副本。

另一个解决方案是使用数组作为基元值的包装器,如下:

public class Main {

  public static void main(String[] args) {

      int vb1 = 10;

      int vb2 = 20;

      int[] anArray = {vb1,vb2};

      doInterchange5(anArray);

      vb1 = anArray[0];

      vb2 = anArray[1];

      System.out.println("vb1 = "+vb1+", vb2 = "+vb2);

  }

  public static void doInterchange5(int[] values)

  {

      int temp = values[0];

      values[0] = values[1];

      values[1] = temp;

  }

}

方法的一些规则

  • 方法输入参数parameters由基元和/或引用表示;

  • 定义方法时,声明的变量称为参数parameters;

  • 调用方法时,输入值称为参数arguments;

  • 方法输入参数是方法的局部变量;

  • 方法实际参数arguments始终按其值传递;方法形式参数parameters始终是实际参数arguments的副本(可能是最重要的规则);

  • 基元参数表示调用实参argument的值副本;

  • 引用参数表示调用引用参数的值副本(引用值不是对象,而是对象的地址);

  • 当输入参数与局部变量或实例变量具有相同的名称时,将发生阴影(由于这是逻辑错误,因此很难调试);例如,变量使用 this.表示法来区分输入参数和对象属性;对于类静态变量,则使用类名来区分;

  • 方法可以具有变量数参数(var-args 方法);

  • var-arg 方法只能有一个 var-arg 参数;

  • var-arg 必须是最后一个参数(如果该方法具有其他参数);