Java面向对象(二)

Java面向对象(二)

五、方法

5.1 方法的重载(overload)

  1. 定义:在 同一个类中,允许定义多个 相同名字的方法,只要 参数列表(参数类型或者参数个数)是不同的
  2. 判断是否为方法重载:
    (1) 同一个类,同样的方法名,不同的参数列表! (2) 与方法修饰符、方法返回值、形参名、方法体无关
public class OverloadTest{

    public void getSum(int a,int b){}

    public void getSum(int a,int b,int c){}

    public void getSum(double a,double b){}

    public void getSum(int a,double b){}

    public void getSum(double a,int b){}

/*  不属于方法重载:与方法返回值类型无关
    public int getSum(int a,int b){
        return 0;
    }
*/

/*  不属于方法重载:与形参名称无关
    public void getSum(int m,int n){}
*/

/*  不属于方法重载:与方法修饰符无关
    private void getSum(int a,int b){}
*/

}
  1. 方法重载中一些特殊情况:

情况一:

public class OverloadTest {
    public static void main(String[] args){
        OverloadTest o = new OverloadTest();

        System.out.println(o.getSum(1,2));      // 输出3
        System.out.println(o.getSum(1.0,2.0));  // 输出3.0
        System.out.println(o.getSum(1.0,2));    // 输出3.0

    }
    public int getSum(int a,int b){
        return a + b;
    }
    public double getSum(double a,double b){
        return a + b;
    }

}

/*  可以看到,我们并没有定义 getSum(double,int)类型的方法,但是 getSum(1.0,2)还是正常输出,没有报错。
    这里getSum(1.0,2)是调用了getSum(double a,double b)的方法,原因是实参2被自动转换为double类型并传递给这个方法。

    那为什么getSum(1,2)调用时不会使用getSum(double a,double b)方法?
    原因:
    其实 getSum(int a,int b) 和 getSum(double a,double b) 都是 getSum(1.0,2) 可能的匹配。调用方法时,Java编译器会查找最精确匹配的方法,因为方法 getSum(int a,int b) 比 getSum(double a,double b) 更精确,所以调用 getSum(1,2) 时使用的是getSum(int a,int b)。

*/

情况二:

public class OverloadTest {
    public static void main(String[] args){
        OverloadTest o = new OverloadTest();

        System.out.println(o.getSum(1,2));

    }
    public double getSum(int a,double b){
        return 1.0;
    }
    public double getSum(double a,double b){
        return 2.0;
    }

}

/*  输出 1.0
    根据调用方法时,Java编译器会查找最精确匹配的方法。
    所以 getSum(1,2)调用时使用的是 public double getSum(int a,double b)方法
*/

情况三:

有时调用一个方法时会有两个或多个可能的匹配,但编译器无法判断哪个是最精确的匹配。这就称为”歧义调用”(ambiguous invocation),会产生编译错误。

public class OverloadTest {
    public static void main(String[] args){
        OverloadTest o = new OverloadTest();

        System.out.println(o.getSum(1,2));

    }
    public double getSum(int a,double b){
        return 1.0;
    }
    public double getSum(double a,int b){
        return 2.0;
    }

}

/*  编译报错:
    Error:(9, 29) java: 对getSum的引用不明确
    javase.OverloadTest 中的方法 getSum(int,double) 和 javase.OverloadTest 中的方法 getSum(double,int) 都匹配
*/

5.2 可变参数的形参

  1. JavaSE 5.0 中提供了 Varargs (variable number of arguments)机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参。
//JDK 5.0以前:采用数组形参来定义方法,传入多个同一类型变量
public class Test {
    public static void main(String[] args){
        Test o = new Test();
        o.test(new String[]{"aa","bb","cc"});   //调用时必须new String[]数组

    }

    public static void test(String[] books){
    for (int i = 0; i < books.length; i++) {
            System.out.println(books[i]);
        }
    }
}

//JDK5.0:采用可变个数形参来定义方法,传入多个同一类型变量
public class Test {
    public static void main(String[] args){
        Test o = new Test();
        o.test(new String[]{"aa","bb","cc"});   //同样可以用
        o.test("aa","bb","cc");                 //更加简单
    }

    public static void test(String ... books){
        for (int i = 0; i < books.length; i++) {
            System.out.println(books[i]);
        }
    }
}

/*  输出:
    aa
    bb
    cc
*/
  1. 说明:
  2. 声明格式:方法名(参数的类型名 … 参数名) 。
  3. 可变参数: 方法参数部分指定类型的参数个数是可变多个:0个,1个或多个
  4. 可变个数形参的方法与同名的方法之间,彼此构成重载
  5. 可变参数方法的使用与方法参数部分使用数组是一致的故两个不能构成方法重载
  6. 方法的参数部分有 可变形参,需要放在形参声明的最后
public static void test(int a ,String ... books);

/*  报错,Java编译器不知道可变参数什么时候结束
    public static void test(String ... books,int a);
*/
  • 在一个方法的形参位置,最多只能声明一个可变个数形参

5.3 方法参数的值传递机制

  1. Java 里方法的参数传递方式只有一种: 值传递。 即将 实际参数值的副本(复制品)传入方法内,而参数本身不受影响
  2. 形参是基本数据类型:将实参基本数据类型变量的”数据值”传递给形参
  3. 形参是引用数据类型:将实参引用数据类型变量的”地址值”传递给形参
  4. 例子:
//  针对基本数据类型:
public class Test {
    public static void main(String[] args) {
        int num1 = 1;
        int num2 = 2;
        System.out.println("在调用 swap 方法前,变量 num1 的值为:" + num1 + ",变量 num2 的值为:" + num2);

        swap(num1, num2);
        System.out.println("在调用 swap 方法后,变量 num1 的值为:" + num1 + ",变量 num2 的值为:" + num2);
    }

    public static void swap(int n1, int n2) {
        System.out.println("在进行交换前,变量 n1 的值为:" + n1 + ",变量 n2 的值为:" + n2);
        int temp = n1;
        n1 = n2;
        n2 = temp;
        System.out.println("在进行交换后,变量 n1 的值为:" + n1 + ",变量 n2 的值为:" + n2);
    }

}

/*  输出结果:
    在调用 swap 方法前,变量 num1 的值为:1,变量 num2 的值为:2
    在进行交换前,变量 n1 的值为:1,变量 n2 的值为:2
    在进行交换后,变量 n1 的值为:2,变量 n2 的值为:1
    在调用 swap 方法后,变量 num1 的值为:1,变量 num2 的值为:2

    可以看到,num1 和 num2 的值并没有因为调用 swap 方法而进行交换。
*/

Java 内存分析:

Java面向对象(二)
//  针对引用数据类型:
public class Test {
    public static void main(String[] args) {

        Data data = new Data();

        data.m = 10;
        data.n = 20;

        System.out.println("m = " + data.m + ", n = " + data.n);

        Test test = new Test();
        test.swap(data);

        System.out.println("m = " + data.m + ", n = " + data.n);

    }

    public void swap(Data d){
        int temp = d.m;
        d.m = d.n;
        d.n = temp;
    }

}

class Data{
    int m;
    int n;
}

Java内存分析:

Java面向对象(二)

所以,在写交换数组元素位置方法时:

//错误的:交换数组中指定两个位置元素的值
//  public void swap(int i,int j){
//      int temp = i;
//      i = j;
//      j = temp;
//  }
    //正确的:交换数组中指定两个位置元素的值
    public void swap(int[] arr,int i,int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
  1. 特殊的,String类型
public class Test {
    public static void main(String[] args) {

        String s1 = "hello";

        Test test = new Test();
        test.change(s1);

        System.out.println(s1);

    }

    public void change(String s){
        s = "hi";
    }
}

//  输出:hello

Java内存分析:

Java面向对象(二)

结论: String 属于引用类型变量,形参仍然接收的是实参变量的地址值,只是字符串在常量池是一个 char[] 型的一个字符数组,新赋值 hi 时会在常量池新创建一个字符数组,再将 hi 字符串的地址赋值给 s 变量。

5.4 递归方法

  1. 递归方法:一个方法体内调用它自身。
  2. 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
  3. 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
  4. 典型使用场景:
  5. 求 n 的阶乘
//  求 n!方法
public int f(int n) {

    if (n == 1) {
        return 1;
    } else {
        return n * f(n - 1);
    }
}
  • 斐波那契数列
public int f(int n) {

    if (n == 1 || n == 2) {
        return 1;
    }
    if (n > 2) {
        return f(n-1) + f(n-2);
    }
    return -1;
}
  • 快速排序

Original: https://www.cnblogs.com/xiaozhao01/p/16461395.html
Author: 小钊丶
Title: Java面向对象(二)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/593519/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • GTID主从配置后的主库数据迁移到从库操作

    在不停止主库、主库不锁库的情况下进行数据库主从复制,主库的数据导入给从库,并且从库开启同步功能。 windows环境下mysql线上数据库需要做主从备份,线上的数据库已经开启bin…

    Java 2023年6月8日
    073
  • Elasticsearch 入门实战(2)–安装

    本文主要介绍 Elasticsearch 的安装,使用到的环境及软件信息如下:CentOS 7.6.1810、Elasticsearch 8.2.2。 1、主机参数调整 安装 El…

    Java 2023年6月16日
    084
  • 常用正则表达式

    一、校验数字的表达式 数字:^[0-9]*$ n位的数字:^\d{n}$ 至少n位的数字:^\d{n,}$ m-n位的数字:^\d{m,n}$ 零和非零开头的数字:^(0|[1-9…

    Java 2023年6月7日
    074
  • fastHttp服务端处理请求的过程

    主要代码 设置监听地址 server.go func (s *Server) ListenAndServe(addr string) error { ln, err := net….

    Java 2023年5月30日
    0107
  • 多线程顺序运行的 4 种方法,面试随便问!

    文章介绍4种方法,简单易懂,通过4个demo抛砖引玉。 通过 join()方法使当前线程”阻塞”,等待指定线程执行完毕后继续执行。 举例:在线程thread…

    Java 2023年5月29日
    086
  • 手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(七)-Elasticsearch 8.2 集成与配置

    Elastic Stack 是一个可以帮助我们构建搜索体验、解决问题并取得成功的搜索平台。核心产品包括 Elasticsearch、Kibana、Beats 和 Logstash(…

    Java 2023年6月8日
    086
  • rabbitmq 安装

    rabbitmq 安装 官网地址 https://rabbitmq.com/download.html 前言 RabbitMQ是一个开源的遵循 AMQP协议实现的基于 Erlang…

    Java 2023年6月9日
    093
  • SQL中那么多函数,Java8为什么还要提供重复的Stream方法,多此一举?

    有个同学提出一个这样的疑问; 在业务系统中,数据一般都从sql中查询,类似使用where,order by,limit,聚合函数等,为什么还要用java8的Stream方法? 对这…

    Java 2023年6月5日
    080
  • 关于我的博客图片失效问题

    我的博客图片全部是储存在我的 Github图床中,因为某些不可抗拒原因,加速节点失效了导致我的博文图片全部失效,我也是今天才发现,单独对每篇博文的图片链接进行更换的时间成本过高,目…

    Java 2023年6月5日
    066
  • screw-数据库文档生成器

    文档地址:https://gitee.com/leshalv/screw cn.smallbun.screw screw-core 1.0.5 import cn.smallbun…

    Java 2023年6月9日
    072
  • Day5

    package scanner;import java.util.Scanner;public class Demo4 { public static void main(Stri…

    Java 2023年6月5日
    0112
  • 【力扣】82. 删除排序链表中的重复元素 II

    存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字。返回同样按升序排列的结果链表。 示例 …

    Java 2023年6月8日
    0108
  • 公众号资料分享

    在公众号分享两份资料一份是面试资料整理,面试资料针对Java方向,从JVM虚拟机到机器学习,云计算都有涉及,虽然机器学习有些内容比较简单,但是整体的知识框架还是列出来了,总结的非常…

    Java 2023年5月30日
    063
  • 同一台电脑生成多份ssh私钥和公钥,映射多个GitHub账号

    当我们使用 Git 进行代码版本控制时,经常出现一台电脑需要连接多个Git 账号的情况,此时需要在一台电脑上生成多份 ssh 私钥和密钥,同时映射多个 Git 账号;这里我们需要同…

    Java 2023年6月5日
    065
  • Spring核心之Ioc容器

    spring框架 Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服…

    Java 2023年6月5日
    068
  • Spring 常见面试题

    Spring 常见面试题 Spring 常见面试题 Spring 八股文 说说你对Spring的理解? 你觉得Spring的核心是什么? 说一下Spring的优势? Spring是…

    Java 2023年5月30日
    077
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球