Java基础之Java方法

Java 方法

方法

  • 语句的集合,在一起执行一个功能
  • 解决一类问题的步骤的有序组合
  • 包含于类或对象中
  • 在程序中被创建,在其他地方被引用
设计原则

原子性:一个方法只完成一个功能,利于后期扩展

优点:

  1. 使程序变得更简短而清晰
  2. 有利于程序维护
  3. 提高程序的开发效率
  4. 提高了代码的重用性

命名规则

  • 第一个单词应以小写字母作为开头,后面单词则用大写字母开头,不使用连接符。例如:setByName()
  • 下划线可能出现在JUnit的测试方法名称中用以分隔名称的逻辑组件;典型模型:test<MethodUnderTest>_<state>
    例如:testPop_emptyStack

方法的定义

修饰符 返回值类型 方法名(参数类型 参数名){
	方法体
	return 返回值;
}
public static int age(int birthday){
    return birthday;
}
public static int max(int num1, int num2){
    return num1 > num2 ? num1 : num2; 
}

方法包含一个方法头和方法体

  • 主函数

    • main 方法的头部是不变的
      • 带修饰符 public static
      • 返回 void 类型
      • 方法名字是 main
      • String[] 类型参数:String[] 表明参数是字符串数组
  • 其它语言中方法指过程和函数

    • 返回非void类型返回值的方法称为函数
    • 返回void类型返回值的方法叫做过程
  • 方法头

    • 修饰符:可选的,告诉编译器如何调用该方法,定义了该方法的访问类型

    • 返回值类型:方法可能会返回值

      • returnValueType是方法返回值的数据类型
      • 方法执行没有返回值,returnValueType是关键字void
  • 方法名:方法的实际名称;方法名和参数表共同构成方法签名

  • 参数:参数像是一个占位符

    • 当方法被调用时传递值给参数,这个值被称为实参或变量
    • 参数列表指方法的参数类型、顺序和参数的个数
    • 参数是可选的,方法可以不包含任何参数
  • 方法体:包含具体的语句,定义该方法的功能

方法调用

  • main 方法是被 JVM 调用的,此外main 方法和其它方法没区别
  • Java支持两种调用方法的方式,根据是否有返回值选择
  • 程序调用一个方法时程序的控制权交给了被调用的方法
    • 当被调用方法的返回语句执行
    • 或到达方法体闭括号时候交还控制权给程序
  • 当方法返回一个值的时候,方法调用通常被当作一个值
int larger = max(10,20);
  • 如果方法返回值是void,方法调用一定是一条语句
System.out.println("欢迎访问");
public static void main(String[] args) {
    int i = 5; 
    int j = 2;   
    int k = max(i, j);  
    System.out.println(i+"和"+j+" 比较; 最大值是: "+k);} 
/** 返回两个整数变量较大的值 */
public static int max(int num1, int num2){  
    return num1 > num2 ? num1 : num2; 
}
/**
运行结果:
5和2 比较; 最大值是: 5
*/
递归

方法自身调用自身

  • 递归头:必须有结束调用的时候,若没有会陷入死循环
  • 递归体:调用自身方法的时候
  1. 连续调用 → 边界结束 → 值返回

  2. 缺点:深度越大时空复杂度越高;对性能要求很高

void关键字

void类型方法,不返回值

public static void main(String[] args) { 
    printGrade(78.5);
} 
public static void printGrade(double score) {  
    if (score >= 80.0)    
        System.out.println('B');  
    else if (score >= 70.0) 
        System.out.println('C');  
    else      
        System.out.println('F');}
运行结果:C
//一个void方法的调用一定是一个语句; 所以它被在main方法中以语句形式调用:就像任何以分号结束的语句一样

通过值传递参数

如果调用一个方法需要提供参数,必须按照参数列表指定的顺序提供

public static void main(String[] args) {   
    int a = 1;   int b = 2;   
    System.out.println("原a值:"+a+",原b值:"+b);   
    swap(a, b);  // 调用swap方法   
    System.out.println("现a值:"+a+",现b值:"+b);}
/** 交换两个变量的方法 */
public static void swap(int n1, int n2) {  
    System.out.println("交换前n1的值"+n1+",n2的值"+n2); 
    // 交换 n1 与 n2的值   
    int temp = n1; 
    n1 = n2;  
    n2 = temp;  
    System.out.println("交换后n1的值"+n1+",n2的值"+n2); 
}
/**
运行结果:
原a值:1,原b值:2
交换前n1的值1,n2的值2
交换后n1的值2,n2的值1
现a值:1,现b值:2
*/
//传递两个参数调用swap方法,方法被调用后,实参的值并没有改变
  • Java 基本数据类型传递参数时是值传递
    • 传递数值的副本,对原数据无影响
  • 引用类型传递参数时是引用传递
    • 引用 z = null 只是将引用z不指向任何对象 ,并不会对原先指向的对象数据进行修改
      • 但原数据若没有其他引用将无法找回变成垃圾
    • 引用传递的是引用地址,在此对数据进行此操作会影响原数据

重载(Overload)

定义
  • 在一个类里,方法名相同、参数不同,返回类型可相同也可不同
  • 每个重载的方法(构造函数)都必须有独一无二的参数列表
    • 最常用的就是构造器的重载(不同数量的参数)
public static int max(int num1, int num2){ 
    return num1 > num2 ? num1 : num2; 
}
public static double max(double num1, double num2) { 
    return num1 > num2 ? num1 : num2;
}
  • 两个同名 max() 方法,根据实际调用时传递的参数类型判断被调用的方法

    • intdouble 类型参数
    • Java编译器根据方法签名判断哪个方法应该被调用。
  • 方法重载可以让程序更清晰易读

    • 执行密切相关任务的方法应该使用相同的名字
重载规则
  • 重载必须改变参数列表(参数个数或类型不一样)
  • 重载可以改变返回类型、访问修饰符
  • 重载可以声明新的或更广的检查异常
  • 方法能够在同一个类中或者在一个子类中被重载
  • 无法以返回值类型作为重载函数的区分标准
public class Overloading {
    public int test(){
        System.out.println("无参,返回int类型");
        return 1;
    }
 
    public void test(int a){
        System.out.println("一个int类型参数,无返回值");
    }   
 
    //以下两个参数类型顺序不同
    public String test(int a,String s){
        System.out.println("test3");
        return "returntest3";
    }   
 
    public String test(String s,int a){
        System.out.println("test4");
        return "returntest4";
    }   
 
    public static void main(String[] args){
        Overloading o = new Overloading();
        System.out.println(o.test()); // 调用第一个方法
        System.out.println(o.test(1)); // 调用第二个方法
        System.out.println(o.test(1,"test3")); // 调用第三个方法
        System.out.println(o.test("test4",1));  // 调用第四个方法
    }
}

重写(Override)

  • 外壳不变,核心重写
    • 子类对父类的允许访问的方法的实现过程进行重新编写
    • 返回值和形参都不能改变
  • 子类根据需要定义特定于自己的行为
    • 即子类可以根据需要实现父类的方法
  • 面向对象的原则里,重写意味着可以重写任何现有方法
class Anima{
    public void move(){
        System.out.prontln("动物可以动")
    }
}
class Dog{
    public void move(){
        System.out.println("小狗可以跑")
    }
    public void eat(){
        System.out.println("这是一个测试")
    }
}
public class Test{
	public static void main(String[] args){
		Animal a = new Animal();
        Animal b = new Dog();
        a.move;
        b.move;
        b.eat;  //编译错误,因为Animal类中没有eat方法
    }
}
//在编译阶段,只是检查参数的引用类型
//在运行时,Java虚拟机(JVM)指定对象的类型且运行该对象的方法
/**
运行结果:
动物可以动
小狗可以跑
*/
重写规则
  • 参数列表不允许改变

  • 返回类型可以不完全一样

    • 但必须是父类返回值的派生类
    • java5 及更早版本返回类型要一样,java7 及更高版本可以不同
  • 访问权限不能降低

  • 父类的成员方法只能被子类重写

    • 如果不能继承一个类,则不能重写该类的方法
  • 声明为 finalprivate 的方法不能被重写

  • 构造方法不能被重写

  • 声明为 static 的方法不能被重写,但是能够被再次声明

  • 子类和父类在同一个包中

    • 子类可以重写父类所有方法
    • 除了声明为 privatefinal 的方法
  • 子类和父类不在同一个包中

    • 子类只能重写父类的声明为 publicprotected 的非 final 方法
  • 重写的方法能够抛出任何非强制异常,无论原方法是否抛出异常

    • 但不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以
    • 例如: 父类的方法申明了一个检查异常 IOException
      • 重写的时候不能抛出 Exception 异常
      • 因为 Exception IOException 的父类,只能抛出 IOException 的子类异常
super关键字

需要在子类调用父类的方法时,要使用super关键字

class Animal{
   public void move(){
      System.out.println("动物可以移动");
   }
}
 
class Dog extends Animal{
   public void move(){
      super.move(); // super.调用父类的方法
      System.out.println("狗可以跑和走");
   }
}
 
public class TestDog{
   public static void main(String args[]){
      Animal b = new Dog(); // Dog 对象
      b.move(); //执行 Dog类的方法
   }
}
/**
运行结果:
动物可以移动
狗可以跑和走
*/

重写和重载

区别
区别点重载方法重写方法
参数列表必须修改一定不能修改
返回类型可以修改完全一样或原返回值的子类类型
异常可以修改可以减少或删除,一定不能抛出新的或者更广的异常
访问可以修改一定不能做更严格的限制(可以降低限制)

总结:

  • 方法的重写和重载是java多态性的不同表现

    • 重写是父类与子类之间多态性的一种表现
    • 重载可以理解成一个类的多态性表现形式
  • 方法重载:一个类中定义了多个方法名相同,参数不同的方法

    • 根据传入的参数不同,调用不同方法
  • 方法重写:子类方法与父类的方法的名字相同,参数、返回值也相同的方法

    • 重写就是将父类的方法重新实现
重载
  1. 同一方法名的方法
  2. 必须改变参数列表
  3. 返回值类型可以改变
  4. 方法体可以不变
  5. 访问权限可以更改,异常范围可以更改
重写
  1. 需要有继承关系,才可以有子类重写父类的方法
  2. 方法名、参数列表完全相同;返回值类型需要完全一样或父类返回值的的派生类
  3. 访问权限可以放开但不能降低、
  4. 抛出的异常范围可以缩小但不可扩大

参数作用域

变量的范围是程序中该变量可以被引用的部分:

  • 方法内定义的变量被称为局部变量
    • 局部变量的作用范围从声明开始,直到包含它的块结束
    • 局部变量必须声明才可以使用
  • 方法的参数范围涵盖整个方法
    • 参数实际上是一个局部变量
  • for循环的初始化部分声明的变量,其作用范围在整个循环
    • 但循环体内声明的变量其适用范围是从它声明到循环体结束

可以在一个方法里,不同非嵌套块中多次声明一个具有相同名称的局部变量,但不能在嵌套块内两次声明相同名称局部变量

命令行参数

运行一个程序时候再传递给它消息要靠传递命令行参数给main()函数实现

命令行参数是在执行程序时候紧跟在程序名字后面的信息

public static void main(String args[]){   
    int[] a = new int[10];  
    for(int i=0; i<a.length; i++){   
        System.out.println("a[" + i + "]: " + a[i] + "\t");  
    }
}
运行结果:
a[0]: 0	a[1]: 0	a[2]: 0	a[3]: 0	a[4]: 0	a[5]: 0	a[6]: 0	a[7]: 0	a[8]: 0	a[9]: 0	
可变参数

JDK1.5开始Java支持传递同类型可变参数给一个方法

  • 在方法声明中,在指定参数类型后加一个省略号(…)
  • 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数
    • 任何普通的参数必须在它之前声明
  • 对于可变参数,编译器会将其转型为一个数组
    • 所以在函数内部可变参数名即可看作数组名
//声明可变参数typeName... parameterName    类似于 typeName[] parameterName
public class Test {   
    void func(String... args){}  
    void func(String [] args){} //这两个方法的命名是相等的,不能作为方法的重载
    public static void main(String[] args) {   
        Test t = new Test();     
        test.func("Wallen","John","Smith"); 
        test.func(new String[3]);      //可变参数,即可向函数传递 0 个或多个参数   
        //这两种调用方法效果一样   
    }
}
//对于可变参数的方法重载保证参数列表不一样
void func(String... args);
void func(String args1,String args2);
func("Wallen","John");//优先匹配固定参数的方法

finalize()方法

Java 允许定义这样的方法,

finalize( )

  • 在对象被垃圾收集器析构(回收)之前调用
  • 用来清除回收对象
    • Java 的内存回收可以由 JVM 来自动完成
    • 如果手动使用,则可以使用上面的方法

例如:你可以使用 finalize() 来确保一个对象打开的文件被关闭了。

在 finalize() 方法里,必须指定在对象销毁时候要执行的操作。

finalize() 一般格式是:
protected void finalize() {   /* 在这里终结代码 */ }

关键字 protected 是一个限定符,确保 finalize() 方法不会被该类以外的代码调用

构造方法

  • 当一个对象被创建时候,构造方法用来初始化该对象
    • 构造方法和所在类的名字相同,但构造方法没有返回值
  • 通常会使用构造方法给一个类的实例变量赋初值
    • 或者执行其它必要的步骤来创建一个完整的对象。
  • 所有的类都有构造方法,Java 自动提供了一个默认构造方法
    • 默认构造方法的访问修饰符和类的访问修饰符相同
      • 类为 public,构造函数也为 public;类改为 protected,构造函数也改为 protected
    • 但定义了自己的构造方法之后,默认构造方法就会失效
public class Puppy{   
    public Puppy(){	     				//无参构造函数(无构造方法时的默认构造方法)
    }    
    public Puppy(String name){       	//有参构造函数,这个构造器仅有一个参数:name  
    }   
    public static void main(String[] args){    
        Puppy p = new Puppy();			//调用构造方法初始化一个对象                     
        PupPy p1 = new Puppy("张三");		//调用有参构造方法初始化一个对象   
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值