查看原文
其他

方法参数与对象构造

树莓蛋黄派 Java规途 2023-07-04
  • 方法参数

  • 对象构造

    • 重载

    • 默认字段初始化

    • 无参数构造器

    • 显式字段初始化

    • 参数名

    • 调用另一个构造器

    • 初始化块

    • 对象析构与finalize方法


自定义类与时间类

类初识

数组与大数

输入输出与流程

字符串详解变量+运算=?

Java基本程序设计结构——数据类型


方法参数与对象构造

方法参数

一般来说,将数值传递给方法(函数)的形式一共有两种:按值调用、按引用调用

按值调用:表示方法接受的是调用者提供的值。

按引用调用:表示方法接收的是调用者提供的变量地址。

需要注意的是:方法可以「修改」按引用传递的变量的值,而无法修改按值传递的变量的值。

言归正传,Java语言总是按值调用的。即:方法所得到的是所有参数值的一个副本,也就是说方法不能修改传递给它的任何参数变量的内容。

来看个例子:假定一个方法将一个参数值扩大三倍。

public static void tripleValue(double x){
    x=3*x;
}
double percent=10;
tripleValue(percent);

从方法体中可以看出,该方法将参数扩大了三倍。但其实percent还是10。

来看看执行过程:

  1. 方法调用后,X成功将percent复制了一份,此时X=10
  2. 进入方法中,X进行了重新的赋值运算。但此时X的值为30,而percent仍然为10。
  3. 方法结束后,X不再使用了。

相信学过程序设计的人都知道,常见的程序中不仅仅有值,还有引用。

上面说到,对于值类型的数据,我们在Java中修改它显然没有持久的效果。那么对象引用呢?

来看个例子:我们将某个公司的员工的工资提高,来看看效果。

public static void  tripleValue(Employee x){
    x.raiseSalary(200);
}
public void raiseSalary(double x){
    Salary+=Salary*x
}
var harry=new Employee();
tripleValue(harry);

执行过程大概是这样的:

  1. X初始化为harry值的一个副本,这里是一个「对象引用」
  2. raiseSalary方法应用于X这个对象引用,与此同时X与harry同时引用那个Employee对象的工资提高了。
  3. 方法结束时,X不再使用,对象变量harry还在引用那个工资提高了的员工对象。

大致可以这么解释:原来的对象变量和副本都「引用了同一个对象」

下面来总结一下方法参数的有关内容

  • 方法不能修改基本数据类型的参数(即数值型和布尔型)。
  • 方法可以改变对象参数的状态。(改变引用对象的属性)
  • 方法不能让一个对象参数引用一个新对象。

对象构造

前面已经简单了解了简单的构造器,可以对象的初始状态。很幸运,Java提供了多种编写构造器的机制,下面一一介绍这些机制。

重载

有些类含有多种构造器,比如StringBuilder

var messages =new StringBuilder()var message =new StringBUilder(“To do :\n”)

这两种方式都是正确的,这种方式叫做方法的「重载」

如果某个类的多个方法出现了相同的名字,不同的方法参数,这便出现了方法的重载。

当然Java中允许重载多种方法,不仅仅只有构造器方法。

方法签名

方法名以及参数类型便叫做方法的「签名」。需要注意的是:返回类型并不是方法签名的一部分

也就是说不存在两个名字相同,参数类型相同却有不同返回值类型的方法。

默认字段初始化

如果在构造器中没有显式地为字段设置初始值,那么就会被自动地赋值为默认值。

数值类型为0,布尔值为false、对象引用为null

与此同时,字段与局部变量有着一个很明显的区别。

方法中的局部变量必须明确地初始化,但在类中,没有初始化类中的字段,将会自动初始化为默认值(0、false、null)

但是如果依赖于默认值将很大程度上影响程序的可读性,这也不是一种好的编程习惯。

无参数构造器

其实很多类都会在没有编写构造器之时,自动提供一个默认的无参构造器。

由无参构造器创建对象时,对象的状态会被设置为适当的默认值。

public Employee(){
    name=“”;
    salary=0
 hireDay=LOcalDate.now();   
}

当然如果类中有了含有方法参数的构造器方法,但是没有书写无参的构造器方法,此时如果构造无参的对象,编译器将会报错。

因为当自己编写构造器时会覆盖自动提供的默认构造器。

这里需要注意的是:当且仅当类中没有其他任何构造器时,你才会得到一个默认无参构造器。

建议在编写类时顺带写一个无参数的构造器方法,避免后期出现的错误。

显式字段初始化

通过重载类的构造器方法,可以采用多种形式设置类的实例字段的初始状态。

可以在类定义中直接为任何字段赋值

class Employee{
    private String name=“ ”;
        ```````
}

在执行构造器之前完成了对于名字的赋值操作,这种方法并不通用,毕竟谁都不希望该类的所有构造器将实例字段都设置为同一个值。

同时初始值不一定都是常量值,下面来看个例子:

class Employee{
    private static int nextId;
    private int id =assignId();
        ````
     public static int assignId(){
        int r=nextId;
        nextId++;
        return r;
    }
        ``````
}

这段程序中的初始值显然不是一个常量值。

参数名

我们在编写构造器方法时通常会在参数命名上犯难,一般来说,我们喜欢用单个字母作为参数名

public Employee(String n,int s){
    name=n;
    salary=s;
}

这样做有一个很明显的缺点,只有阅读代码之后才能够了解到它表示的含义。

也有很多人会采用在参数变量名之前加个前缀。

但更多时候我们还是倾向于采用与实例字段同名的参数名,当然直接使用与实例变量相同的参数名显然是行不通的。这时候我们需要在实例字段之前加this关键字,指示该字段是属于该类对象的实例字段。

如果不加this字段来访问实例字段,参数名会直接覆盖类中的实例字段。

public Employee(String name,int salary){
    this.name=name;
    this.salary=salary;
}

调用另一个构造器

上面我们了解到了this关键字能帮助我们访问类中的实例字段,当然它还有另一个用途:调用同一个类的另一个构造器

当然对于格式上也有要求,this(```)必须出现在构造器的第一行。

第一

下面来看个例子

public Employee(double s){
    //calls Employee(String ,double)
    this("Employee #"+nextId,s);
    nextId++;
}

初始化块

前面已经总结了两种初始化实例字段的方式:

  1. 在构造器中设置值
  2. 在声明中设置值

其实,还有第三种,称为「初始化块」

在一个类的声明中,可以包含任意多个代码块,只要对象被构造,代码块会被立即执行

来看个例子:

public Employee{
    private int id;
    private String name;
    private double salary;
    
    {
        id =nextId;
        nextId++;
    }
    public Employee(String name,double salary){
        this.name =name;
        this.salary=salary;
    }
    public Employee(){
        name="";
        salary=0;
    }
    ````
}

在这个例子中,无论使用哪个构造器构造对象,id字段都会在对象初始化块中初始化。并且最先运行对象初始化块。

并且执行顺序有一定的规律:一般是先执行初始化块,再执行构造器方法,最后执行普通方法,如果有静态初始化块出现,优先执行静态初始化块

对象析构与finalize方法

首先必须要声明,Java是不支持析构器方法的,因为Java有着自己的垃圾回收器

其次,如果对象使用了内存之外的资源,当这些资源不再使用时,将其回收和利用显得格外重要。

如果一个资源使用完毕之后需要立即关闭,那么close方法可以完成必要的清理工作。可以在对象使用完之后调用这个方法

需要注意的是:在Java中不要使用finalize方法来完成清理,因为这个方法已经废弃使用了。

以上就是关于方法参数与对象构造的有关知识。

<<< 左右滑动见更多 >>>


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存