课时8:构造方法与匿名对象
摘要:本此课程主要围绕Java中的构造方法与匿名对象展开讨论。详细阐述了构造方法出现的原因、定义要求、使用方式、重载特性,以及与setter方法的区别;同时介绍了匿名对象的概念、使用场景,并通过程序示例进行内存分析,帮助读者深入理解这两个重要的Java概念。
1. 构造方法的引入
2. 构造方法的定义与使用
3. 构造方法与默认构造方法
4. 构造方法的重载
5. 构造方法与setter方法的区别
6. 匿名对象
01、 构造方法的引入
在Java程序中,通常我们在使用对象时,需经历两个步骤:先声明并实例化对象,此时对象中的属性为对应数据类型的默认值;接着通过一系列setter方法为对象属性设置内容。
若对象属性较多,如假设有8个属性,就需要调用8次setter方法,这种方式较为繁琐。为解决对象初始化的问题,Java提供了构造方法,其主要目的是实现实例化对象中的属性初始化处理。
02、 构造方法的定义与使用
2.1 定义要求
1.方法名称:构造方法的名称必须与类名称保持一致。
2.返回值类型:构造方法不允许设置任何返回值类型,即没有返回值定义。
3.自动调用:构造方法在使用关键字`new`实例化对象的时候自动调用。
示例代码
以`Person`类为例,定义有参构造方法:方法名称与类名称相同,并且无返回值定义
//有参构造方法 public Person(String n,in ta){ name=n; age=a; } 在代码中使用构造方法实例化对象: Person per=newPerson("张三",18);
通过上述代码可以看出,构造方法为对象的属性进行了初始化。
下面针对当前的对象实例化格式与之前的对象实例化格式做一个比较:
之前的对象实例化格式:①person ②per=③new④person();
当前的对象实例化格式:①person ②per=③new④Person(“张三”.18);
“①person“:主要是定义对象的所属类型,类型决定了你可以调用的方法。
“②per“:实例化对象的名称,所有的操作通过对象来进行访问。
“③new”:开辟一块新的堆内存空间;
“④Person(“张三”.18)“:调用有参构造。” ④Person()“:调用无参构造。
03、 构造方法与默认构造方法
在Java程序中,为保证程序结构的完整性,所有的类都会提供构造方法。若类中没有定义任何构造方法,编译器会默认提供一个无参的、什么都不做的构造方法。这个默认构造方法在程序编译时自动创建,通过反编译工具可以看到。
但当类中明确定义了构造方法时,默认构造方法将不会被自动创建。
例如,在已经定义了有参构造方法的`Person`类中,若尝试使用无参构造方法实例化对象:
Person per=newPerson();//
会报错,提示无法找到匹配的构造器
这是因为此时类中只有有参构造方法,不存在默认的无参构造方法。结论:一个类至少存在有一个构造方法,永恒存在。
构造方法不允许设置返回值类型的原因
构造方法不允许设置返回值类型,这可能会让部分开发者感到疑惑。从编译器的角度来看,编译器是根据代码结构来进行编译和执行处理的。构造方法和普通方法在结构上,如果构造方法使用`void`定义,其结构就与普通方法完全相同,编译器会将其误认为是普通方法。
而构造方法是在对象实例化的时候调用,普通方法是在对象实例化产生之后调用,两者有着本质区别,所以构造方法不能设置返回值类型。
04、 构造方法的重载
构造方法作为一种方法,具有重载的特点。在进行构造方法重载时,只需要考虑参数的类型及个数即可。
例如,对`Person`类进行构造方法重载:
4.1 无参构造方法
Public Person(){ Public Person(string n){ name=n;执行
假如
Public Person(){ Public Person(string n){ name=“无名氏“; age=-1; }
4.2 有参构造方法
publicPerson(String n,int a){ name=n; age=a; } }
在定义多个构造方法时,建议按照参数个数升序或降序排列,如先定义无参构造方法,再定义单参构造方法,最后定义多参构造方法,这样代码结构更清晰。虽然不按此顺序定义代码本身不会出错,但会影响代码的可读性和维护性。
05、 构造方法与setter方法的区别
构造方法和setter方法都可以进行数据设置,但它们有着不同的用途。构造方法是在对象实例化的时候为属性设置初始化内容;而setter方法除了具有设置数据的功能之外,还具有修改数据的功能。
在使用时:
Person per=new Person("张三",10); person.setAge(18); per.tell();//进行方法的调用
通过上述代码可以清晰地看到两者的区别。
经过了分析之后可以发现,利用构造方法可以传递属性数据,于是现在进一步分析对象的产生格式:
定义对象的名称:类名称 对象名称
实例化对象:对象名称=new类名称()
如果这个时候只是通过实例化对象来进行类的操作也是可以的。而这种形式的对象由于没有名字就称为匿名对象
06、 匿名对象
在Java中,当我们仅通过实例化对象来进行类的操作,且这个对象没有名字时,就称其为匿名对象。
匿名对象使用一次之后,由于没有任何引用指向它,就将成为垃圾,会被垃圾回收器(GC)回收与释放。在实际开发中,使用有名对象还是匿名对象取决于具体需求。如果某个对象只需要使用一次,并且不需要在后续代码中再次引用,就可以考虑使用匿名对象。
(1) 构造方法与匿名对象的内存分析示例
下面通过一个示例程序来分析构造方法与匿名对象在内存中的操作:
classMessage{ private String title; public message (String t){ title=t; } Public String get Title(){ return title; } public void setTitle(string t) title=t; } } class Person private String name; private int age; public Person(message,int a){ name=msg.getTitle; age=a; } Public message getinfo(){ Return new message(name+“;“+age); } Public void tell(){ Systyem.out.println(“姓名:“+name+”、年龄+age); } } public class JavaDemo{//主类 public static void main(String args[]){ Message msg=new message(“mldn”) person per=new person(new message(“msg,20”)) msg=per.getinfo() System.out.println(msg.getTitle()); } }
通过此程序我们进行一个简短的内存分析
(2) 内存分析
咱们以一段代码为例来进行内存分析。当代码中出现“messagemsg”时,就表明必然存在一个堆栈。代码里有个msg,它指向的空间有个title,内容是“MLdn”。
接下来,person per=newperson这行代码,清晰地表明msg会接收自身title数据的引用。只要出现关键字new,就意味着要开辟新空间。在这个例子中,新开辟空间的内容通过name=mldn可知,name和title是一样的,同时年龄被设为20。
再往下,调用per.getinfo方法,这里出现了return关键字,这使得代码逻辑变得有趣。看到关键字new,就要知道它是用来开辟新空间的,这里创建的是一个匿名对象,其内容是“MLdn:20”。
这个匿名对象创建后会返回给msg,但msg原本就有引用,所以它会抛弃原本的引用,转而指向新的引用,这就产生了一个垃圾问题,原本msg指向的旧空间会成为垃圾空间。
这段程序本身没有实际意义,主要是通过构造方法展示了方法可以传递任意数据类型,包括基本数据类型和引用数据类型,像字符串就是一种特殊的引用数据类型。