方法
什么是成员方法
某些情况下,我们需要定义一些成员方法(简称方法),来帮助我们加入一些特有的属性以及动作。比如:人类:除了有一些属性外(年龄,姓名…),我们人类还有一些行为比如:可以说话、跑步…通过学习,还可以做算术题。这时就要用成员方法才能完成。
成员方法入门案例
1)添加speak成员方法,输出 我是一只好人
2)添加cal01 成员方法,可以计算从1+…+1000的结果
3)添加cal02 成员方法,该方法可以接收一个数n,计算从1+…+n 的结果
4)添加getSum成员方法,可以计算两个数的和
思路分析与代码实现:
public class fangFa {
//编写main方法
public static void main(String[] args) {
//方法使用
//1.方法写好后,如果不去调用(使用),不会输出
//2.先创建对象,然后调用方法即可
Person p1= new Person();
p1.speak();//调用方法
p1.cal01();//调用cal01方法
p1.cal02(5);//调用cal02方法,同时给 n=5
//调用getSum方法,同时num1 =10; num2=20;
//把 方法getSum 返回的值,赋给 变量 returnSum
int returnSum = p1.getSum(10,20);
System.out.println("getSum方法返回的值 ="+returnSum);
}
}
class Person{
String name;
int age;
//方法(成员方法)
//添加speak成员方法,输出"我是一个好人"
//
//1.public 表示方法是公开
//2.void : 表示方法没有返回值
//3.speak() : speak是方法名,()形参列表
//4.{} 方法体,可以写我们要执行的代码
//5.System.out.println("我是一只好人");表示输出一句话
public void speak(){
System.out.println("我是一只好人");
}
//添加cal01成员方法,可以计算从1+...+1000的结果
public void cal01(){
//循环完成
int num=0;
for(int i=1;i<=1000;i++){
num=+i;
}
System.out.println("cal01方法计算结果="+num);
}
//添加cal02 成员方法,该方法可以接收一个数n,计算从1+..+n的结果
//1.(int n)形参列表,表示当前有一个形参 n,可以接收用户输入
public void cal02(int n){
int sum=0;
for(int i=0;i<=n;i++){
sum=+i;
}
System.out.println("cal02方法计算结果="+sum);
}
//添加getSum成员方法,可以计算两个数的和
//1.public 表示方法是公开的
//2.int : 表示方法执行后,返回一个int值
//3.getSum方法名
//4.(int num1,int num2)形参列表,2个形参,可以接收用户传入的两个数
//5.return sum ;表示把sum的值 , 返回
public int getSum(int num1,int num2){
int sum = num1 + num2;
return sum;
}
}
方法调用机制
以上题的getSum为例子
成员方法
成员方法的好处
1.提高代码的复用性。
2.可以将实现的细节封装起来,以便调用。
成员方法的定义
public 返回数据类型 方法名 (形参列表...){
//方法体
语句;
return 返回值
}
//1.参数列表:表示成员方法输入cal(int n)
//2.数据类型(返回类型):表示成员方法输出,void表示没有返回值
//3.方法主体:表示为了实现某一功能代码块
//4.return 语句不是必须的
注意事项以及使用细节
1)修饰符(作用是控制 方法使用的范围)
如果不写,则为默认访问,有四种:【public、private、protected、默认】
2)返回类型
1.一个方法最多有一个返回值 【如果想要实现返回多个值,则可以使用—数组】
public static void mian(String[] args){
A a = new A();
int[] res = a.getSumAndSub(1,4); //调用数组,返回两个值"和"与"差"
System.out.println("和="+res[0]);
System.out.println("差="+res[1]);
}
}
class A{
public int[] getSumAnSub(int n1, int n2){
int [] resArr = new int[2]; //创建数组
resArr[0] = n1+n2;
resArr[1] = n1-n2;
return resArr;
}
}
2.返回类型可以为任意类型,包含基本类型或引用类型,如:对象、数组。
第一条就使用了数组来实现返回类型
3.如果方法要求有返回数据类型,则方法中最后的执行语句必须为return 值;而且要求返回值类型比如和return 的值类型一致或兼容
public double f1(){
double d1=1,1*3;
return d1; // 返回的值为double的类型
//int n =100;
//return n; //返回的值为100,为int类型,返回类型为double,虽然int与double类型不同,因为double兼容int,则n可以被返回
public int f2(){
double d1=1.1*3;
return n; //若返回类型为int 返回的值为double,则会报错,因为double与int类型不同,并且int不兼容double
}
}
4.如果方法是void,则方法体中可以没有return语句,或者只写return;
public void f2(){
System.out.println("111");
//int n=100;
//return n; 返回类型为void类型,则不能使用return语句来返回
}
方法名
方法名遵循驼峰命名法,最好见名知其意,表达出该功能的意思即可
在实际工作中,我们的方法都是为了完成某个功能,所以方法名要有一定含义
如:得到两个数的和则可以命名为getSum
参数列表
1.一个方法可以有0个参数,也可以有多个参数,中间用逗号隔开
Show(){}
getSum(int n1){}
getSum2(int n1,int n2){}
2.参数类型可以为任意类型,包含基本类型或引用类型
getSum(int n1,int n2){}
printArr(int[][] map){}
3.调用带参数的方法时,一定对应着参数列表传入相同类型或兼容类型的参数
public static void mian(String[] args){
A a = new A();
int[] res = a.getSumAndSub(1,4);
byte b1=1;
byte b2=2;
a.getSumAndSub(b1,b2);
//byte->intint可以兼容byte,所以会自动转换
a.getSumAndSub(1.1,1.8);
//double->int高精度不能转换为低精度,double不能转换为int
}
}
class A{
public int[] getSumAnSub(int n1, int n2){
int [] resArr = new int[2];
resArr[0] = n1+n2;
resArr[1] = n1-n2;
return resArr;
}
}
4.方法定义时的参数称为形式参数,简称形参;方法调用时传入的参数称为实际参数,简称实参,实参和形参的类型要一致或兼容、个数、顺序必须一致
public static void mian(String[] args){
A a = new A();
int[] res = a.getSumAndSub(1,4);
a.getSumAndSub(100);//会报错,形参与实参个数不一致
a.f3(10,"tom")//会报错,因为实参与形参顺序不同
}
}
class A{
public void f3(String str,int n){
}
public int[] getSumAnSub(int n1, int n2){
}
}
方法体
里面写完成功能的具体的语句,可以为输入、输出、变量、运算、分支、循环、方法调用、但里面不能再定义方法。即方法不能再嵌套定义
class A{
public void f4(){
//编译会报错,方法里面不能再嵌套定义方法
//public void f5(){
//}
}
public void f3(String str,int n){
}
public int[] getSumAnSub(int n1, int n2){
}
}
方法调用细节说明
1.同一个类中的方法调用:直接调用即可。如print(参数);
public static void main(String[] args){
A.a=new A();
a.sayOk();
}
}
class A{
public void print(int n){
System.out.println("print()方法被调用 n=" +n);
}
public void sayOk(){ //sayOk调用 print(直接调用即可)
print(10);
System.out.println("继续执行sayOK()");
}
}
输出两句话print() 方法被调用 n=10
继续执行sayOk()
运行结果为:
print()方法被调用 n=10
继续执行sayOk()
主方法里的sayOk运行,则先调用A里的sayOk方法,而sayOk方法里有print方法,则还需要先调用sayOk里面的print方法,再去执行sayOk里的输出语句。
2.跨类中的方法A类调用B类方法:需要通过对象调用。比如print(参数);
public static void main(String[] args){
A.a=new A();
a.sayOk();
}
}
class A{
public void print(int n){
System.out.println("print()方法被调用 n=" +n);
}
public void sayOk(){ //sayOk调用 print(直接调用即可)
print(10);
System.out.println("继续执行sayOK()");
}
//跨类中的方法A类中调用B类方法:需要通过对象名调用
public void m1(){
//创建B对象,然后在调用方法即可
System.out.println("m1()方法调用");
B b = new B();
b.hi();
System.out.println("继续执行sayOk()");
}
}
class B{
public void hi(){
System.out.println("B类中的hi()被执行");
}
}
执行了m1后,先执行输出语句:m1()方法被调用
然后再执行B里hi方法的调用,执行hi方法里的语句:B类中的hi()被执行
然后再到m1里的输出语句执行:m1()继续执行
3.跨类的方法调用和方法的访问修饰符相关,在包类细讲。
方法调用小练习题
- 编写A类方法,判断一个数是奇数还是偶数,返回Boolean
- 根据行、列、字符打印对应行数和列数的字符,比如:行:4,列:4,字符:#,打印对应的效果
编写A类方法,判断一个数是奇数还是偶数,返回Boolean
class A{
//思路
//1.方法的返回类型 boolean
//2.方法的名 pd
//3.方法的形参(int num)
//4.方法体 , 判断
public void pd(int num){
if(num % 2 == 0){
System.out.printf("true");
}else{
System.out.printf("false");
}
}
}
根据行、列、字符打印对应行数和列数的字符,比如:行:4,列:4,字符:#,打印对应的效果
//思路
//1.方法的返回类型void
//2.方法的名字print
//3.方法的形参(int h,int l,char c)
//4.方法体,判断
public void print(int h,int l, char c){
for(int i = 0;i< h;i++){
for(int j=0;j< l,j++){ //输出每一行
System.out.println(c);
}
System.out.println(); //换行
}
}
成员方法传参机制
- 基本数据类型的传参机制
- 引用数据类型的传参机制
1.基本数据类型的传参机制(值传递)
分析一个案例:
public void swap(int a,int b){
int tmp = a;
a = b;
b = tmp;
System.out.println("a=" +a "\tb="+b);
}
加入主方法main分析
public static void main(String[] args){
int a = 10;
int b = 20;
//创建AA对象, 名字为cc
AA cc = new AA();
cc.swap(a,b);//调用swap
System.out.println("main方法的 a="+ a + "b =" +b); //a=10 ,b =20;
}
class AA{
public void swap(int a,int b){
System.out.println("\n a和b交换前的值 \n a="+a "\tb="+b); //a=10 , b =20;
//a与b的交换
int tmp = a;
a = b;
b = tmp;
System.out.println("\n a和b交换后的值 \n a="+a "\tb="+b); //a=20 , b =10;
}
}
Console:
a和b交换前的值
a=10 b=20
a和b交换后的值
a=20 b=10
main方法的 a=10 b=20
结论:
基本数据类型,传递的是值(值拷贝),形参的任何改变都不会影响实参(参考值传递)
2.引用数据类型的传参机制(址传递)
分析另一个案例:
- B类中编写一个方法test1,可以接收一个数组,在方法中修改数组,看看原来的数组是否变化?
- B类中编写一个方法test2,可以接收一个Person(age,sal)对象,在方法中修改该对象属性,看看原来的对象是否变化?
加入主方法main分析:
public static void main(String[] args){
B b = new B();
int[] arr = {1,2,3};
b.test1(arr); //调用方法
System.out.println("main的arr数组");
//遍历数组
for(int i = 0; i<arr.length; i++){
System.out.print(arr[i] + "\t");
}
System.out.println();
}
class B{
//B类中编写一个方法test1
//可以接收一个数组,在方法中修改该数组,看看原来的数组是否变化
public void test1(int[] arr){
arr[0] = 200; //修改元素
//遍历数组
System.out.println("test1的arr数组");
for(int i = 0; i<arr.length; i++){
System.out.print(arr[i] + "\t");
}
System.out.println();
}
}
Console:
test1的arr数组
200 2 3
main的arr数组
200 2 3
结论:
引用类型传递的是地址(传递也是值,但是值是地址),可以通过 形参影响实参
克隆对象
编写一个方法copyPerson,可以复制一个Person对象,返回复制的对象,克隆对象。(要求得到新对象和原来的对象是两个独立的对象,只是他们的属性相同)
//思路
//1.方法的返回类型 Person
//2.方法的名字 copyPerson
//3.方法的形参 (Person p)
//4.方法体,创建一个新对象,并复制属性,返回
public static void main(String[] args ){
Person p = new Person();
p.name = "coco";
p.age = 18;
//创建tools
MyToos tools = new MyTools();
Person p2 = tools.copyPerson(p);
//到此 p 和 p2 是Person对象,但是是两个独立的对象,属性相同
System.out.println("p的属性 age =" + p.age + "name = "+ p.name);
System.out.println("p2的属性 age =" + p2.age + "name = "+ p2.name);
}
class Person(){
int age;
String name;
}
class MyTools{
public Person copyPerson(Person p){
//创建一个新对象
Person p2 = new Person();
p2.name = p.name; //把原来对象的名字赋给p2.name
p2.age = p.age; //把原来对象的年龄赋给p2.age
return p2;
}
}
Console:
p的属性 age = 100 name = coco
p2的属性 age = 100 name = coco