前言:
对于一个刚接触编程或只学过C语言的“小白”来说,相信大家和我一样或多或少地对“方法”、“类”和“对象”这几个名词感觉陌生,本文我将对这几个概念谈谈我的理解,如有遗漏或者错误,欢迎在评论区中进行补充或指出错误,谢谢大家的理解。
文中目录带有!!!后缀的为文章重点理解内容。



文章目录

  • 一. 方法
  • 1. 什么是方法?
  • 2. 方法的定义
  • 3. 实参和形参的关系 !!!
  • 3.1 形参改变不影响实参
  • 3.2 形参操作影响实参
  • 3.3 形参操作不影响实参
  • 4. 方法重载 !!!
  • 4.1 方法重载是什么?
  • 4.2 为什么要进行方法重载,怎样重载?
  • 二. 对象
  • 1. 面向对象与面向过程
  • 2. 什么是对象?
  • 三. 类
  • 1. 简单认识类
  • 2. 类的定义格式
  • 3. 类的实例化
  • 4. 类和对象的说明
  • 5. 对象的初始化和使用
  • 5.1 对象的使用
  • 5.2 对象的初始化 !!!
  • 5.2.1 构造方法
  • 5.2.2 未初始化的变量的使用?
  • 5.3 this引用 !!!
  • 5.3.1 为什么要有this引用?
  • 5.3.2 什么是this引用?
  • 5.3.3 this引用的特性


一. 方法

举个例子:
在学习的过程中,我们学了一个新的知识点并做了相关的练习,在一个问题百思不得其解的时候,我们会去请教老师,而老师经验丰富,一眼就看出了题中的“门道”,在老师的引导下,你一步步有了解决此类问题的思路,下次遇到换汤不换药的问题后,你凭借上次的思路很快解决了该问题,这里的思路可以称为一个“方法”
随着班上同学询问次数的增加,老师心想:不如把解决此类问题的方法录制成一个视频,下次只要同学有疑惑,直接打开视频的链接即可解惑。这里的录制的视频也可以称为一个“方法”
总结:方法的作用有:能够解决同一类问题,并减少大量重复性的工作。

1. 什么是方法?

方法就是一个代码片段. 类似于 C 语言中的 “函数”。方法存在的意义是:

  1. 是能够模块化的组织代码(当代码规模比较复杂的时候)。
  2. 做到代码被重复使用, 一份代码可以在多个位置使用。
  3. 让代码更好理解更简单。
  4. 直接调用现有方法开发, 不必重复造轮子。

2. 方法的定义

方法定义的语法格式:

修饰符 返回值类型 方法名称(参数类型 形参,……) {
方法体代码
return 返回值;
}

public static int add(int x, int y) {
	方法体代码
	return 返回值;
}

注意事项:

  1. 在Java中,方法必须写在类中
  2. 在静态方法中,无法使用非静态变量或方法。(用关键字“static”修饰的变量或方法即静态变量或方法)
  3. 在Java中,方法不能嵌套定义。方法没有声明一说,即方法可随意写在main()方法的前后位置。
  4. 方法可有多个参数,参数之间用逗号隔开;对于无参方法,( )中什么不写。
  5. 对于有返回值的方法,方法体中返回的实体类型必须与返回值类型一致;无返回值必须写成void。

3. 实参和形参的关系 !!!

方法的形参相当于以下函数的自变量 x 与 y ,用来接收函数被调用时实际传入的值。在调用方法时,操作系统会内存中重新开辟参数类型对应大小的空间,用于保存传递过来的值。(形参名字没有强制要求)
因此,在Java中,形参的值永远是实参的一份临时拷贝。它们分别拥有独立的内存空间

public class Main {

    public static int multiply(int x, int y) {		//x, y是形式参数
        return x * y;
    }

    public static void main(String[] args) {
        int n = multiply(3, 4);						//3,4是实参
        System.out.println(n);
    }
}

下面谈谈形参的变化对实参的影响:

3.1 形参改变不影响实参

public static void swap(int x, int y) {
    int tmp = x;
    x = y;
    y = tmp;
}

public static void main(String[] args) {
    int a = 1;
    int b = 3;
    System.out.println("交换前:");
    System.out.print("a = "+a);
    System.out.print(", b = "+b);
    swap(a, b);
    System.out.println();
    System.out.println("交换后:");
    System.out.print("a = "+a);
    System.out.print(", b = "+b);
}

//程序运行结果
交换前:
a = 1, b = 3
交换后:
a = 1, b = 3

原因:形参只是接收了方法调用时传入的整数的值,在内存中拥有独立的空间,在函数调用过程中虽然交换了x、y的值,但等到函数调用完成后,形参的内存空间被收回,对实参的值不会产生任何影响。
总结:对于基础数据类型(整型,浮点型,字符型,布尔类型)作为形式参数,形参只接收实参本身内容,对其做任何操作都不会影响实参的内容。可以理解为“传值调用”。

3.2 形参操作影响实参

public static void doubleArr(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            arr[i] *= 2;
        }
    }
    public static void main(String[] args) {
        int[] arr = {1,3};
        System.out.println("操作前:");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();

        doubleArr(arr);
        System.out.println("操作后:");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }

操作前: //程序运行结果
1 3
操作后:
2 6

JAVA方法的五要素 及基本作用_笔记


原因:形参接收的是整型数组的引用,即数组的地址,虽然该地址仍然是实参的一份临时拷贝,但形参 str 同样指向该整型数组,因此形参通过地址对数组进行操作,就会起到影响实参的效果。

总结:对于引用数据类型作为形式参数,假如通过引用对其指向的对象的内容进行操作,则会对实参产生影响。(对象这个概念后面会讲到)

3.3 形参操作不影响实参

public static void doubleArr(int[] arr) {
    int[] arr2 = new int[arr.length];
    for (int i = 0; i < arr.length; i++) {
        arr2[i] = arr[i] * 2;
    }
    arr = arr2;
}

public static void main(String[] args) {
    int[] arr = {1,3};
    System.out.println("操作前:");
    for (int x:arr) {
        System.out.print(x + "  ");
    }
    System.out.println();

    System.out.println("操作后:");
    doubleArr(arr);
    for (int x:arr) {
        System.out.print(x + "  ");
    }
}

程序运行结果:
操作前:
1 3
操作后:
1 3

JAVA方法的五要素 及基本作用_笔记_02


原因:形参是临时开辟的一块空间,将整型数组的引用arr2给arr1(形参),在方法调用完成后,arr1(形参)会被销毁,而操作后的结果不影响arr(实参)。

总结:引用变量作为实参传给形参,不一定会改变实参所指对象的内容,是否影响要看对形参做了什么操作。

4. 方法重载 !!!

4.1 方法重载是什么?

举个例子:在现实生活中,我们经常会碰到一词多义的情况,比如你在别人遇到困难时伸出援手,别人会对你说一句:“谢谢你,你真的是一个好人!”;而当你对一个暗恋已久的女生表白后,本以为是一场双向奔赴,实际上却只是你一个人疯狂脑补各种“恋爱细节”,因此,这个女生也对你说了一句:“我感觉你是一个好人,谢谢你的喜欢,你会遇到一个更好的女生。”

方法重载与上面的多义词相类似,能够使一个方法在不同的适用条件上表现出不同的作用。
在Java中,假如多个方法的名字相同,参数列表不同,则称这几种方法被重载了

4.2 为什么要进行方法重载,怎样重载?

方法重载的原因不难想象:

对于一个简单的两数相加的 add 方法,我们可能实际上不单单要实现2个整数求和、也可能需要2个浮点数进行求和、2个以上的整数求和,甚至于让多个整数和浮点数混合相加求和。

那么怎么解决这个问题呢?

答:要解决这个问题十分简单,无非对每个需求重新再写一个对应的方法就行了。

因为方法的命名一般需要与实际实现的功能相联系,那么这么多方法该怎么命名呢?

答:解决命名问题也十分简单,无非在每个方法名后面加上一点后缀,如数字1,2,3等等来加以区别。

虽然有方法后缀来区分每个方法,但是时间长了,用的次数少了,大家都会或多或少地给混淆了,这又该如何解决呢?

JAVA方法的五要素 及基本作用_System_03


这时候很多人可能开始犯难了,这确实是一个不好解决的问题(当然,不排除少部分人拥有超强的记忆力)。

这时候,方法重载的优势就体现出来了,只需要一个相同的方法名,在使用时传入不同的参数,就能轻松实现一个需要频繁调用的方法。


方法怎样进行重载呢?

  1. 方法名称必须相同。
  2. 参数的类型、个数与顺序,这三个影响方法重载的因素至少有一个存在不同。

二. 对象

1. 面向对象与面向过程

众所周知,Java是一门纯面向对象的语言(Object Oriented Program,简称OOP)。在一个面向对象的世界里,所有事物皆对象,人是一个对象、笔是一个对象,电脑是一个对象……

面向对象是解决问题的一种思维,主要依靠对象的交互来完成一件事情,每个对象有一定的属性和方法,面向对象就是通过给对象赋予一些方法,然后对象通过执行各自的方法让问题得到解决。

面向过程顾名思义更注重完成事情的过程,它通过将一件大的事情拆解成一个个小问题,通过思考并解决每个小问题来完成一个事情。

举个例子:

假如一个独自在外打工的人,晚上工作完回到家后,他的肚子饿了,他怎样得到一份晚餐来充饥呢?

解决这个问题有两个方法:① 点外卖。②自己动手做饭。前者明显面向对象,而后者面对过程。

① 点外卖:首先,我们需要寻找完成这件事情的对象:自己,手机,外卖骑手,电动车,一份从餐馆已经做好的食物;接下来为对象赋予属性和方法(如下图);最后通过利用对象属性和调用对象的方法,通过对象之间的相互协作共同完成这件事情。

JAVA方法的五要素 及基本作用_System_04


②自己动手做饭:思考做什么食物–>出门购买食材–>挑选合适的食材–>考虑食物的烹饪方式以及烹饪的时间–>对食材进行前处理–>烹饪–>考虑调味料的添加比例并进行添加–>等待既定的时间–>完成食物的制作

总结:面向对象是通过调用对象方法,通过对象之间的协作去解决问题的一种方法;面向过程更注重解决问题的每一个过程,通过对问题进行拆解,思考并解决每一个小问题从而完成整件事情。

2. 什么是对象?

通过第1小点,相信大家对对象有了一个初步的认识。
对象是某一个具体的实体,它具有某些属性和方法。简而言之,对象就是类的实例

三. 类

1. 简单认识类

类是用来描述某一实体(对象)的,它由实体的特性(属性)和功能(方法)组成。
例如,描述一台洗衣机,我们需要知道洗衣机有哪些属性?如产品品牌、型号、尺寸、产品重量、颜色……
洗衣机有哪些功能(方法)?如:浸洗、洗涤、漂洗、脱水、烘干……

2. 类的定义格式

java中用class关键字来定义一个类,具体的语法格式如下:

class 类名 {
成员变量(可以没有,也可以有多个)

成员方法(可以没有,也可以有多个)
}

例:		
class Dog {
	String name;
	String species;
	String colar;
	int age;

	public void bark() {
		方法体
	}
	public void eat() {
		方法体
	}
}

一个类由属性(成员变量)和行为(成员方法)组成,其中成员变量又可分为普通成员变量静态成员变量,成员方法可以分为普通成员方法静态成员方法

注意:

  1. 一般一个文件当中只定义一个类
  2. main方法所在的类一般要使用public修饰
  3. public修饰的类必须要和文件名相同
  4. 类名一般采用大驼峰定义。即组成类名的每个单词或单词简写,使其单词的首字母大写,例:ClassName,NormalOperation等等

3. 类的实例化

前面说过,对象是实例化的类。
在Java中,通过new关键字+类名来实例化一个类,通过类名+对象名称(自定义)来接收一个实例化的对象。
例如:Dog dog = new Dog();
注意:

  1. new 关键字用于创建一个对象的实例.
  2. 使用 . 来访问对象中的属性和方法.
  3. 同一个类可以创建对个实例.

4. 类和对象的说明

  1. 类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员。
  2. 类是一种自定义的类型,可以用来定义变量。
  3. 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量。
  4. 打个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间。
  5. 类定义的变量属于引用数据类型,变量本身不含包整个对象,它存储的是指向对象的引用(地址)。如下图:

JAVA方法的五要素 及基本作用_JAVA方法的五要素 及基本作用_05

5. 对象的初始化和使用

5.1 对象的使用

对象成员使用的使用可以分为静态和非静态成员的使用。

  1. 静态成员(static修饰的变量或方法)

静态成员变量和静态成员方法的使用方式很简单,直接用 “类名”+“.”+“静态成员变量(方法)”即可,不需要实例化出一个对象。

  1. 普通成员

使用前必须实例化一个对象,然后用“对象名”+“.”+“普通成员变量(方法)”对成员进行使用。
注意事项:
对于静态成员既可以用“类名.静态成员变量(方法)”,也可以用“实例化对象的对象名.静态成员变量(方法)”的方式对成员进行使用,但一般更推荐用“类名.静态成员变量(方法)”的方式。

5.2 对象的初始化 !!!

5.2.1 构造方法

构造方法的作用是什么?
帮助类中定义的成员变量进行初始化。

构造方法的特点是什么?

  1. 名字必须与类名相同
  2. 没有返回值类型,设置为void也不行
  3. 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
  4. 构造方法可以重载(根据自己的需求提供不同参数的构造方法)

构造方法的语法格式:

public 类名(参数列表) {
初始化代码
}

例:

class Test1 {
    public int n;
    public boolean a;

    //无参构造方法
    public Test1() {
        n = 1;
        a = true;
    }

    //带一个参数的构造方法
    public Test1(int number) {
        n = number;
    }

    //带两个参数的构造方法
    public Test1(int number, boolean bool) {
        n = number;
        a = bool;
    }
}

注意事项:
若一个类没有不带参数的构造方法,且类中有带参数的构造方法,应在实例化对象的时候,在类的参数列表中添加对应参数对成员变量进行初始化。例:(假设上图代码中没有不带参数的构造方法)
Test1 test = new Test1(8); // 或者 Test1 test = new Test1(8, false);

5.2.2 未初始化的变量的使用?

大家是否有一个疑问,在Java中,规定了一个变量必须先进行初始化才能够使用,那么为什么在一个类中,只定义了变量,没有构造方法,且变量未初始化却能够被实例化的对象使用呢?(代码与运行结果如下)

class Test1 {
    public int n;
    public static boolean a;
}
public class Test {


    public static void main(String[] args) {

        Test1 test = new Test1();
        System.out.println("n: " + test.n);
        System.out.println("a: " + Test1.a);
    }

}

程序运行结果:
n: 0
a: false

原因:

①static修饰的静态变量如果没有进行初始化,则为默认值。

②定义一个类时,如果没有对类中定义的普通变量进行初始化,且定义的类中没有包含构造方法,那么编译器会自动提供一个默认的无参构造方法,在实例化一个对象的同时为普通成员变量设置一个默认值。(如下图)

JAVA方法的五要素 及基本作用_java_06

5.3 this引用 !!!

5.3.1 为什么要有this引用?

了解this引用之前我想让大家先看看这样一段代码:(以下为什么有toString方法暂且先不管,只需要知道它的功能是打印一个对象中成员变量的信息就行了)

class Animal {
    public String name;
    public int age;

    public void setAnimal(String n, int a) {
        name = n;
        age = a;
    }

    @Override
    public String toString() {
        return "Animal{" +
        "name='" + name + '\'' +
        ", age=" + age +
        '}';
    }
}

public class Main {

    public static void main(String[] args) {
        Animal animal1 = new Animal();
        Animal animal2 = new Animal();
        animal1.setAnimal("十七",5);
        animal2.setAnimal("阿布",2);
        System.out.println(animal1);
        System.out.println(animal2);
    }
}

以上代码看上去都顺其自然,但细想之下,大家是否会产生这样两个疑问:

  1. 假如给成员变量初始化的方法的参数名与成员变量名一样,那函数体中到底是谁给谁赋值?成员变量给成员变量?参数给参数?参数给成员变量?成员变量参数? (代码如下)
public void setAnimal(String name, int age) {
        name = name;
        age = age;
    }
  1. 同上述代码一样,假如两个对象都调用setAnimal方法为其成员变量初始化,但是这两个方法中没有任何有关对象的说明,在进入方法体后,setAnimal方法如何知道初始化的是那个对象的数据呢

—>因此,this引用的存在完美解决了这两个问题。

5.3.2 什么是this引用?

this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

上面两个问题的解答—>
第2个问题:了解了this的概念,上面第二个问题基本已经解决了,原因很简单,在调用对象的成员方法时,因为this引用指向当前对象,所以使用的方法进行的操作也针对当前对象。
第1个问题:当成员变量初始化的方法的参数名与成员变量名一样时,初始化的结果不会达到我们的预期,成员变量的值都会被赋上默认值,因此,我们通常需要通过this引用来使用变量,再为其赋值。(代码如下)

public void setAnimal(String name, int age) {
    this.name = name;
    this.age = age;
}
5.3.3 this引用的特性
  1. this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
  2. this只能在"成员方法"中使用
  3. 在"成员方法"中,this只能引用当前对象,不能再引用其他对象
  4. this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法对象的引用传递给该成员方法,this负责来接收 (代码验证结果如下图)
class Animal {
    public String name;
    public int age;

    public void setAnimal(Animal this, String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Animal{" +
        "name='" + name + '\'' +
        ", age=" + age +
        '}';
    }
}

public class Main {

    public static void main(String[] args) {
        Animal animal1 = new Animal();
        Animal animal2 = new Animal();
        animal1.setAnimal("十七",5);
        animal2.setAnimal("阿布",2);
        System.out.println(animal1);
        System.out.println(animal2);
    }
}

程序运行结果:
Animal{name=‘十七’, age=5}
Animal{name=‘阿布’, age=2}


以上就是本篇文章的全部内容了,如果这篇文章对你有些许帮助,你的点赞、收藏和评论就是对我最大的支持。
另外,文章的不足之处,也希望你可以给我一点小小的建议,我会努力检查并改进。