从零开始学编程--Java 方法

简介: 从零开始学编程--Java 方法

Java 方法


  • 什么是方法
  • 如何自定义方法
  • 对于有参数的方法传值
  • 基本数据类型作为方法参数和引用数据类型作为方法参数的区别
  • 可变参数方法的定义语法和使用场景
  • 方法重载的使用和意义


1. 什么是方法


Java 程序的入口main()就是一个方法。System.out.println();语句中println()也是一个方法。

IntelliJ IDEA查看代码,可以使用Ctrl + 鼠标左键单击代码中的 println()方法,查看 JDK 源码中对于这个方法的定义:

通过其名称 + 括号运算符()可以调用。我们可以将需要重复编写的代码,封装到一个方法中。提高代码的复用性。


2. 如何定义方法


在 Java 中,定义一个方法的语法为:

访问修饰符 返回类型 方法名(参数列表) {
    若干语句;
    return 方法返回值;
}


  • 访问修饰符有 4 种情况publicprivateprotected,也可以省略(default)。
  • 返回类型:可以是任何的数据类型或 void,如果方法没有返回值,返回类型设置为void
  • 方法名:方法名的命名规范和变量相同;
  • 参数列表:参数是变量的一种类型,参数变量的作用域在方法内部;
  • 方法体:方法内部的一些语句。当方法返回值为 void时,可以省略return语句。


3. 分类


根据方法是否带有参数、是否有返回值,可以分为 4 类:

  • 无参无返回值方法
  • 无参带返回值方法
  • 带参数无返回值方法
  • 带参数带返回值方法


3.1 无参无返回值方法


无参无返回值方法,即参数列表为空,返回值为void的方法。例如,我们经常需要输出一段内容。可以将输出语句封装到方法中:

class MethodDemo1 {
    // 定义无参无返回值方法
    public void printText() {
        // 三条输出语句
        System.out.println("C");
        System.out.println("Java");
        System.out.println("Python");
    }
}

上面代码,在类MethodDemo1中定义了一个方法printText,其中有一些打印语句。那么如何调用这个方法,让其执行呢?

对于非静态方法(即非static关键字修饰的方法),首先要使用new关键字实例化类,生成一个对象,再通过对象名.方法名()的方式去调动方法。

如下是 MethodDemo1 类方法调用的实例:

实例演示

class MethodDemo1 {
    // 定义无参无返回值方法
    public void printText() {
        // 三条输出语句
        System.out.println("C");
        System.out.println("Java");
        System.out.println("Python");
    }
    public static void main(String[] args) {
      // 实例化MethodDemo1类
      MethodDemo1 testDemo = new MethodDemo1();
      // 调用printText方法
      methodDemo1.printText();
  } 
}

Tips:由于我们还没有学习面向对象,此处对于对象的实例化,先记住这种固定写法即可。


3.2 无参带返回值方法


无参带返回值方法,即参数列表为空,返回值不为void的方法,方法体内部要使用return语句返回其声明的返回类型。

我们来自定义一个返回Hello World!字符串的方法:

实例演示


class MethodDemo2 {
    // 定义无参带返回值方法
    public String getHelloStr() {
        // 初始化变量str
        String str = "Hello World";
        // 返回str
        return str;
    }
    public static void main(String[] args) {
        // 实例化MethodDemo2
        MethodDemo2 methodDemo2 = new MethodDemo2();
        // 调用getStr方法,并且使用result变量接收返回值
        String result = methodDemo2.getHelloStr();
        // 打印返回值
        System.out.println(result);
    }
}

运行结果:

Hello World


3.3 带参数无返回值方法


带参数无返回值方法,即带有参数列表,返回值为void的方法。

参数列表可能有一个或多个参数,多个参数使用逗号(,)隔开。定义方式为:DataType 参数名1, DataType 参数名2,DateType 为参数的类型。

下面是一个根据长和宽求长方形面积的方法实例:

实例演示


package com.caq.method;
public class TestDemo {
    public static void main(String[] args) {
        TestDemo test = new TestDemo();
        test.pristr(1.22f,3.8f);
    }
    public void pristr(float width, float height){
        float cube = width * height;
        System.out.println(cube);
    }
}

运行结果:

246.0
25.5


3.3.1 传参方式


在调用带参数方法时,有两种传参方式:

  1. 先初始化变量,再将变量传递给方法:
float a = 12.3f;
float b = 20f;
methodDemo3.printArea(a, b);
  1. 直接传入对应类型字面量:
methodDemo3.printArea(10.2f, 2.5f);

当调用方把参数传递给方法时,调用时传递的值会按参数位置一一绑定,这也比较符合我们正常的思维逻辑。因此,对于有多个参数的方法,一定要注意每个参数的位置。


3.4 带参数带返回值方法


package com.caq.method;public class TestDemo {    public static void main(String[] args) {        TestDemo test = new TestDemo();        int a = test.pristr(5);        System.out.println(a);    }    public int pristr(int n){        int sum = 0;        for (int i = 0; i < n; i++) {            sum += i*i;        }        return sum;    }}

上面有参方法的例子,参数都是简单的基本数据类型,当参数为数组时,我们再来看一个实例:

package com.caq.method;import com.caq.exception.Test;public class TestDemo {    public boolean meetArray(int[] a,int element) {        boolean b = false;        for (int v : a) {            if (v == element) {                b = true;                break;            }        }        return b;    }    public static void main(String[] args) {        TestDemo testDemo = new TestDemo();        int[] intArray = {1,2,3,7,5};        int element = 5;        boolean meetArray = testDemo.meetArray(intArray,element);        System.out.println(meetArray);    }}

代码解析:

上述代码定义了一个查找数组中是否包含指定元素的方法,它将数组指定元素作为方法参数,并且返回了一个布尔型的结果,方法体内部首先声明了一个待返回的布尔变量,默认为false,然后对数组参数进行迭代,只要找到与元素参数相同的元素,即更新返回变量为true,跳出循环;如果数组迭代完成后依旧未找到指定的元素,那么待返回变量依然是false,最后返回这个变量。在方法调用时,以一个布尔变量来接收结果,后续代码根据这个布尔变量做了逻辑判断,以执行不同的语句块。


4. 方法传值


调用方和方法之间有参数的传递时,要注意方法传值问题。


4.1 基本类型的传值


基本数据类型指的是简单的数据段,引用数据类型指的是有多个值构成的对象。

基本类型参数的传递,是调用方值的复制。双方各自的后续修改,互不影响。简单来讲,方法内部对参数变量的任何操作,都不会影响到方法外部的变量。

我们看一个实例:

实例演示

class Car {    public void speedUp(int speed) {        System.out.println("小汽车加速前,速度为:" + speed);        speed ++;        System.out.println("小汽车加速后,速度为:" + speed);    }    public static void main(String[] args) {        // 定义小汽车初始速度变量        int speed = 10;        // 实例化Car类,创建一个car对象        Car car = new Car();        // 调用car对象下的speed方法        car.speedUp(speed);        // 打印调用方法后速度参数的值        System.out.println("调用speedUp方法后,调用方的speed参数为:" + speed);    }}

运行结果:

小汽车加速前,速度为:10小汽车加速后,速度为:11调用speedUp方法后,调用方的speed参数为:10代码块123

我们根据输出的结果验证了以上给出的结论。整型参数speed是一个基本数据类型,在speedUp方法内部进行了自增,但主方法中的speed变量的值并不会受到其影响。


4.2 引用类型的传值


引用类型参数的传递,调用方的变量,和接收方的参数变量,地址指向的是同一个对象。双方任意一方对这个对象的修改,都会影响对方。

我们来看一个实例:

实例演示

package com.caq.method;//引用类型的传值public class TestDemo {    //定义一个代替球员的方法,并传入字符串类的数组和字符串Playname    public void replacePlays(String[] temas, String Playame) {        temas[0] = Playame;    }    public static void main(String[] args) {        System.out.println("引用前:");        String[] teams = {"康熙", "雍正", "乾隆"};        for (String test : teams) {            System.out.println(test);        }        TestDemo plays = new TestDemo();        plays.replacePlays(teams, "张三");        System.out.println("引用后:");        for (String test2 : teams) {            System.out.println(test2);        }    }}

运行结果:

引用前:康熙雍正乾隆引用后:张三雍正乾隆

由运行结果可见:方法replaceFirstPlayer的参数players是数组类型,也就是引用类型。当我们在方法内部对players进行操作,其方法外部(即主方法中)的players变量也受到了影响。不只是数组,对象也是引用类型,其参数传递同样遵循以上结论。我们在日常的编码中,请注意区分基本类型和引用类型的方法传值区别。


5. 可变参数


我们可以使用可变参数列表声明方法的参数。可变参数列表的语法:


参数类型... 参数名

我们可以结合可变参数来实现一个求和方法sum,请阅读下面实例:

实例演示

package com.caq.method;//可变参数public class TestDemo {    public void TestDemo(int... n) {        int sum = 0;        for (int i : n) {            sum += i;        }        System.out.println(sum);    }    public static void main(String[] args) {        TestDemo test = new TestDemo();        test.TestDemo(1);        test.TestDemo(22,33);        test.TestDemo(1,2,3,4,5);    }}

运行结果:

15515

上述实例中,在主方法中给sum方法传参时,可选择一个或多个参数传递。方法体内对可变参数n进行迭代,也可以将可变参数n改为数组:int[] n,得到的效果是相同的。

当方法的参数列表有两个或两个以上参数时,可变参数一定要放在最后,请查看如下实例:

public void search(int element, int... elements) {    boolean existed  = false;    for (int e: elements) {        if (e == element) {            existed = true;            break;        }    }    if (existed) {        System.out.println("找到元素:" + element);    } else {        System.out.println("未找到元素:" + element);    }}

另外,也可以将数组传递给可变参数列表,例如,在主方法中调用上面的search方法:

实例演示

public class VariableParameter1 {    public void search(int element, int... elements) {        boolean existed  = false;        for (int e: elements) {            if (e == element) {                existed = true;                break;            }        }        if (existed) {            System.out.println("找到元素:" + element);        } else {            System.out.println("未找到元素:" + element);        }    }    public static void main(String[] args) {        // 创建对象        VariableParameter1 obj = new VariableParameter1();        // 调用方法        obj.search(2, 1,2,3,4);        // 定义数组参数        int[] arr = {1,2,3,4};        // 将数组传递给可变参数列表        obj.search(2, arr);    }}

运行结果:

找到元素:2找到元素:2

上述两种传参方式都是合法的。


6. 方法重载


方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。

方法重载通常用于创建完成一组任务相似但参数的类型或参数的个数或参数的顺序不同的方法。

免去取名字的烦恼


6.1 自定义方法的重载


例如,在Student类中,有多个study方法:

实例演示

public class Student {    public void study() {        System.out.println("同学真好学!");    }    public void study(String name) {        System.out.println(name + "同学真好学!");    }    public void study(String name, int age) {        System.out.println(name + "同学真好学!" + "他今年" + age + "岁了");    }    public static void main(String[] args) {        // 实例化学生对象        Student student = new Student();        // 调用无参数方法        student.study();        // 调用单参数方法        student.study("Colorful");        // 调用双参数方法        student.study("小蔡", 20);    }}

运行结果:

同学真好学!Colorful同学真好学!小蔡同学真好学!他今年20岁了

代码中的三个study都是重载方法。通常来说,方法重载的返回值类型都是相同的。

如果我们在Student类中再增加一个方法:

public String study() {    return "学习Java语言";}

注意,上述的方法不是重载方法,因为我们已经在Student类中定义了无参方法study

判断一个方法是否是重载方法的原则:方法名相同,参数类型或参数个数不同。


6.2 JDK 中的方法重载


Java语言本身的类也定义了很多方法重载的例子,例如String类的substring方法,用于字符串截取:

public String substring(int beginIndex);               // 截取并返回从beginIndex位置到结束位置的字符串


public String substring(int beginIndex, int endIndex); // 截取并返回从beginIndex位置到endIndex-1位置的字符串

如下为实际应用的实例:

String hello = "Hello, QAQ";String substring1 = hello.substring(7);String substring2 = hello.substring(0, 5);System.out.println(substring1);System.out.println(substring2);

运行结果:

QAQHello


7. 小结


理解方法是一个命名语句块很重要。方法提高了代码的复用性

定义方法时,要理解返回类型方法名参数列表方法体的概念。通过方法的名称 + 括号运算符()可以调用该方法。

方法内部遇到return时返回,返回类型为void表示不返回任何值。

对于方法传值问题,基本数据类型传值:方法中对参数的修改,不会影响到方法调用方传递的变量值;

引用数据类型传值:方法中对参数的修改,会影响到方法调用方传递的对象。

可变参数通常用于参数数量是不确定的、可变化的方法。方法重载提高了程序的兼容性和易用性,为方法提供了多种可能性。

Happy,Fighting!!!!


相关文章
|
1月前
|
Java 程序员
Java编程中的异常处理:从基础到高级
在Java的世界中,异常处理是代码健壮性的守护神。本文将带你从异常的基本概念出发,逐步深入到高级用法,探索如何优雅地处理程序中的错误和异常情况。通过实际案例,我们将一起学习如何编写更可靠、更易于维护的Java代码。准备好了吗?让我们一起踏上这段旅程,解锁Java异常处理的秘密!
|
13天前
|
存储 缓存 Java
Java 并发编程——volatile 关键字解析
本文介绍了Java线程中的`volatile`关键字及其与`synchronized`锁的区别。`volatile`保证了变量的可见性和一定的有序性,但不能保证原子性。它通过内存屏障实现,避免指令重排序,确保线程间数据一致。相比`synchronized`,`volatile`性能更优,适用于简单状态标记和某些特定场景,如单例模式中的双重检查锁定。文中还解释了Java内存模型的基本概念,包括主内存、工作内存及并发编程中的原子性、可见性和有序性。
Java 并发编程——volatile 关键字解析
|
17天前
|
算法 Java 调度
java并发编程中Monitor里的waitSet和EntryList都是做什么的
在Java并发编程中,Monitor内部包含两个重要队列:等待集(Wait Set)和入口列表(Entry List)。Wait Set用于线程的条件等待和协作,线程调用`wait()`后进入此集合,通过`notify()`或`notifyAll()`唤醒。Entry List则管理锁的竞争,未能获取锁的线程在此排队,等待锁释放后重新竞争。理解两者区别有助于设计高效的多线程程序。 - **Wait Set**:线程调用`wait()`后进入,等待条件满足被唤醒,需重新竞争锁。 - **Entry List**:多个线程竞争锁时,未获锁的线程在此排队,等待锁释放后获取锁继续执行。
50 12
|
13天前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
93 2
|
2月前
|
设计模式 Java 开发者
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####
|
2月前
|
缓存 Java 开发者
Java多线程编程的陷阱与最佳实践####
本文深入探讨了Java多线程编程中常见的陷阱,如竞态条件、死锁和内存一致性错误,并提供了实用的避免策略。通过分析典型错误案例,本文旨在帮助开发者更好地理解和掌握多线程环境下的编程技巧,从而提升并发程序的稳定性和性能。 ####
|
30天前
|
安全 算法 Java
Java多线程编程中的陷阱与最佳实践####
本文探讨了Java多线程编程中常见的陷阱,并介绍了如何通过最佳实践来避免这些问题。我们将从基础概念入手,逐步深入到具体的代码示例,帮助开发者更好地理解和应用多线程技术。无论是初学者还是有经验的开发者,都能从中获得有价值的见解和建议。 ####
|
30天前
|
Java 调度
Java中的多线程编程与并发控制
本文深入探讨了Java编程语言中多线程编程的基础知识和并发控制机制。文章首先介绍了多线程的基本概念,包括线程的定义、生命周期以及在Java中创建和管理线程的方法。接着,详细讲解了Java提供的同步机制,如synchronized关键字、wait()和notify()方法等,以及如何通过这些机制实现线程间的协调与通信。最后,本文还讨论了一些常见的并发问题,例如死锁、竞态条件等,并提供了相应的解决策略。
50 3
|
1月前
|
开发框架 安全 Java
Java 反射机制:动态编程的强大利器
Java反射机制允许程序在运行时检查类、接口、字段和方法的信息,并能操作对象。它提供了一种动态编程的方式,使得代码更加灵活,能够适应未知的或变化的需求,是开发框架和库的重要工具。
50 3
|
2月前
|
安全 Java 开发者
Java中的多线程编程:从基础到实践
本文深入探讨了Java多线程编程的核心概念和实践技巧,旨在帮助读者理解多线程的工作原理,掌握线程的创建、管理和同步机制。通过具体示例和最佳实践,本文展示了如何在Java应用中有效地利用多线程技术,提高程序性能和响应速度。
70 1