方法是类或对象的行为特征的抽象:它描述的是这个方法能干什么(具有操作性);如传 入什么参数、 完成什么操作、 返回什么结果;方法类似于过去结构化程序设计中的函 数,比如 C 语言里的函数、 C++里的函数。
-
方法的定义:
[ 修饰符 ] 方法返回值类型 方法名 (形参列表){ //方法体 }
例如:
public class Monkey { /** * 修饰符 返回什么类型 方法名称(传入什么参数) { * 这个方法 负责做什么 * 如果返回类型不是void ,则需要 用 return 语句来带回来一个值 ( 类型是明确的) * } */ public int add( int a , int b ){ int c = a + b ; return c ; // 返回 c ( c 是int 类型,其中存储的值是 a 与 b 的和 ); } public void subtract ( int a , int b){ int c = a - b ; // return c; //如果返回类型是 void ,则不需要返回数据 System.out.println(a + " - " + b + " = "+c); } }
当然,这里是自己写的东西,以下是官方文档中的描述:
Here is an example of a typical method declaration: public double calculateAnswer(double wingSpan, int numberOfEngines, double length, double grossTons) { //do the calculation here } The only required elements of a method declaration are the method's return type, name, a pair of parentheses, (), and a body between braces, {}.
这里说的就是 : 一个方法的定义仅仅需要 方法的返回类型、方法的名字、一对小括号和在花括号之间的身体 这些元素 组成。
-
方法的命名
Although a method name can be any legal identifier, code conventions restrict method names. By convention, method names should be a verb in lowercase or a multi-word name that begins with a verb in lowercase, followed by adjectives, nouns, etc. In multi-word names, the first letter of each of the second and following words should be capitalized. Here are some examples: run runFast getBackground getFinalData compareTo setX isEmpty Typically, a method has a unique name within its class. However, a method might have the same name as other methods due to method overloading.
以上是官方文档中所说的,虽然方法名可以是任何法定标识符,但代码约定限制方法名。按照惯例,方法名应该是小写的动词或以小写的动词开头的多单词名,后面跟着形容词、名词等。在多单词名中,每个单词的首字母和后面的单词都应该大写。
-
方法的属主
Java 里的方法必须有属主,也就是说这个方法是属于谁的。 方法不能独立存在, 一般定义在类体内 方法只能定义在类体内 方法不可以定义在方法内(语法要求) 从逻辑上看, 方法或者属于类, 或者属于对象 被 static 修饰的方法属于类, 它将被该类的所有对象所共享 没有被 static 修饰的方法, 只能属于类的某一对象(各对象不共享) 方法不能独立运行, 必须通过类或者对象调用它 不可能直接使用诸如 rename() 直接运行 只能通过 类名.方法名 或者 对象名.方法名 的形式调用方法 被 static 修饰的方法, 可以通过 类名.方法名 和 对象名.方法名 调用 没有被 static 修饰的方法, 只能通过对 象名.方法名 调用
例子:
public class Sheep { // 实例属性,属于具体的某个实例所拥有 public String name; // 静态属性(类属性):这个属性的拥有者是当前这个类,而不是具体的某个个体 public static String school;// 静态属性被所有实例 共享 // 实例方法,基于那个实例去调用,就表现那个实例的行为特征 比如:s2.showName(); public void showName(){ // this 是当前类 的一个实例,与汉语中的 “我” 对应 System.out.println("My name is "+ this.name); } // 静态方法(类方法):这个方法的拥有者是当前这个类,而不是 具体 的 某个 个体 public static void showSchool(){ System.out.println("My school id " + school); } }
访问的例子:
public class TestSheep{ public static void main(String[] args) { // 访问静态属性(类属性)用 “类名.属性名” 的形式访问 // Sheep 的 school Sheep.school = "大肥羊学校"; // 创建Sheep类的对象(实例) Sheep s1 = new Sheep();// 实例化 一个Sheep 对象 s1.name = "喜羊羊"; s1.showName(); // s1 的 showName() // The static method showSchool() from the type Sheep should be accessed in a static way // 那个静态属性 Sheep.school 应该访问 用静态的方式 // Sheep类中的静态属性 school 应该用 静态的方式 去访问 s1.showSchool();;// 应该用“类名.属性名”的形式访问 Sheep s2 = new Sheep(); s2.name = "懒羊羊"; s2.showName();// s2 的 showName() } }
-
参数传递机制
- 形参和实参
形参 - 形式上的参数 在方法名之后, 紧跟的小括号内部, Java 里管它叫形参列表 形参是相对于实参而言的 对于一个不被调用的方法来说, 它的参数就是个摆设, 不具实际意义 只有当调用一个方法, 传入了具体的值, 这个参数才有意义 实参 - 实际的参数 调用一个方法时, 给方法传入的具体的参数的值 这个具体的参数的值是具有实际意义的 Java 里的方法只有被调用, 传入参数, 方法体才有意义
- 基本数据类型的参数传递机制
public class Dog { /** * 注意:这里的int a 和 int b 都是该方法的形式参数 */ public int add(int a,int b){ int c = a+b; return c; } // 相当于 i = 100 public void increment(int i) { System.out.println("i = "+ i); i++; System.out.println("i = "+ i); } }
测试函数:
public class TestDog { public static void main(String[] args) { int a = 100; int b = 200; // Dog.class 会加载,创建这个类型的对象(只要运行,就会被加载) Dog wangcai = new Dog(); // 注意,这里的 a 和 b 是 add 方法执行时传入的实参 int c = wangcai.add( a, b ); System.out.println("运算结果是:"+ c); System.out.println("*********************************************"); int i =100; System.out.println("在i increment执行之前 i = "+ i); // 将 i 作为实参 传递给 wangcai 引用的对象的 increment 方法 // 注意:这里仅仅是将 i 变量存储的值 传递个 increment 方法 // 这个时候可以举例子:身份证原件与身份证复印件的关系 wangcai.increment(i);// int i = i; // 意思是 将前面声明的i 变量的值 赋给 形参 i System.out.println("在i increment执行之后 i = "+ i);// 说明方法内部的 i 与 声明的i 不是同一个i } }
- 引用类型的参数传递
// 声明一个类 public class Person { public String name; // 姓名 public char gender;// 性别 // 对参数 传入的 对象 P 实施变性操作(男--->女;女--->男) public void changeGender(Person p) { // 顺着 p 变量内存储的地址,找到堆区域中的对象 if (p.gender == '男') { p.gender = '女'; } else if (p.gender == '女') { p.gender = '男'; } } }
测试方法:
public class TestPerson { public static void main(String[] args) { // 创建一个大夫,用来给“顾客”做手术 Person doctor = new Person(); doctor.gender = '男'; doctor.name = "朱天佑"; Person customer = new Person(); customer.gender = '男'; customer.name = "金星"; System.out.println(customer.gender); System.out.println(customer); // doctor 的 changeGender 方法 为 customer 变性 doctor.changeGender( customer ); System.out.println(customer.gender); } }
数据结果:
男 methods.Person@15db9742 女
图解:
这里是声明了两个 Person 对象,一个是 doctor,另一个是 customer,分别存放在main 方法的栈中,分别指向了堆中存放的东西,但是在调用 doctor.changeGender 的方法的时候,就会产生一个 doctor.changeGender 的方法栈。
通过doctor.changeGender( customer );这一行代码,就会将main方法栈中的customer地址传到changeGender的方法栈中,并赋予了相应的值,也就是customer的地址。那么在changeGender的方法栈中,对应的P也就是有了相应的地址,那么通过相应的地址就可以找到在堆中存放的数据。
那么通过 changeGender 方法就可以将 customer 的 gender 的值改变掉。
-
方法的返回值
返回值,一般理解为方法被调用、执行完成后,向它的调用者返回的一个数值或对象。 谁调用了方法,方法就把其返回值返回给谁,在哪里调用了方法,方法就把其返回值返 回到哪里。就是相当于,你早上买早餐,你调用买早餐这个方法,那么这个方法就给你 返回了你所需要的早餐,那么这个早餐是你需要的么?是的,因为你是调用买早餐这个方法。 Java 是强类型语言,因此必须指定返回类型。函数是可以有返回值的,也是可 以没有的,当有返回值的时候,那么返回什么类型就写什么类型,如果不需要返回值的时候,那么就是void关键字,表示不需要返回,如果不需要返回,那么也可以写return,只不过 return 后边什么都不写就可以了。当方法需要返回的时候,一般使用 return 语句,方法运行中,一旦遇到 return 语句便立即返回,方法执行到 return 语句就结束运行(调用)。
-
方法的重载
- 方法的重载定义:
同一个类中有两个或两个以上方法同名不同参的方法,称为方法重载。注意,重载发生在:本类的方法之间(前提条件),有继承关系的,还有继承来的方法与本类方法之间。
- 重载发生的条件:
同名:至少有两个方法同名(也可以是两个以上); 不同参:同名的方法中,其参数类型、个数、顺序至少有一个不同 可选的条件:方法的返回类型可以不相同,方法的修饰符可以不相同。
例如 :
public class TraversalArray { public static void main(String[] args) { int[] array = {1,4,68,1234,0,89}; traversal( array ); } public static void traversal(short[] array) { for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } public static void traversal(int[] array) { for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } public static void traversal(byte[] array) { for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } public static void traversal(long[] array) { for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } public static void traversal(float[] array) { for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } public static void traversal(double[] array) { for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } public static void traversal(char[] array) { for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } public static void traversal(boolean[] array) { for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } }
那么在这里需要注意 : 使用方法重载的时候,可能会降低代码的阅读性。(Overloaded methods should be used sparingly, as they can make code much less readable.)
-
可变长参数 JDK 1.5 以后, 允许定义形参长度可变的参数,即允许为方法指定数量不确定的形参。 具体格式如下:
[ 修饰符 ] 方法返回值类型 方法名 ( 其它形参, 形参类型... 形参名){ //方法体 }
解释:
形如 形参类型... 形参名 的参数叫做可变长参数 注意其中的三个 . 可变长参数必须放在整个参数列表的最后边 下面的写法是错误的: [ 修饰符 ] 方法返回值类型 方法名 ( 形参类型... 形参名 , 其它形参 ) { //方法体 } 一个方法中至多只能有一个可变长参数!
举例说明:
/** * 可变长参数,是指一个方法的实参个数是可以变化的,根据需要传入参数 * 可变长参数 在同一个方法的参数列表中,至多出现一次,并且必须放在所有参 数的最后边 */ public class ChangeParameter { // 当作一个"数组"来对待 public static int add(int... a){ // 就算什么都没有传入,这个数组也是存在的只是它的长度是0而已 int sum = 0; for (int i = 0; i < a.length; i++) { sum+=a[i]; } return sum; } public static void main(String[] args) { int sum1 = add(); int sum2 = add(1,2,3,4); System.out.println(sum1+sum2); } }
注意 : 如果在可变长参数的方法中没有传入任何参数,那也没有什么影响,也就是说数组的长度为0。
转载于:https://my.oschina.net/lujiapeng/blog/2249976