文章目录
类的成员之三:
构造器(constructor),又叫
构造方法(和一般的方法不一样)
类的成员,前面还有属性和方法,还没有来得及更,先往后走,有空我再更。学到这里的应该都知道吧~
一、介绍
(1)理解和作用
【构造器的理解】
我们new完对象时,所有成员变量都是默认值,如果我们需要赋别的值,需要挨个为它们再赋值,太麻烦了。
我们能不能在new对象时,直接为当前对象的某个或所有成员变量直接赋值呢? 可以,Java给我们提供了 构造器
(Constructor) ,也称为 构造方法
。
构造器非常常用,一个类里面一定会有构造器。
即使是抽象类(这个类不能造对象),也有构造器。
constructor :n. 建设者、建造者
construct:v. 建设、建造、创造
construction: n. 建设、建造 CCB
【构造器的作用】
作用1:搭配new关键字,创建类的对象
作用2:在创建对象的同时,可以给对象的相关属性赋值
new对象,并在new对象的时候为实例变量赋值。
举例:Person p = new Person(“Peter”,15) ;
解释:如同我们规定每个“人”一出生就必须先洗澡,我们就可以在“人”的构造器中加入完成“洗澡”的程序 代码,于是每个“人”一出生就会自动完成“洗澡”,程序就不必再在每个人刚出生时一个一个地告诉他们 要“洗澡”了。
(2) 构造器的语法格式
[修饰符] class 类名{
[修饰符] 构造器名(){
// 实例初始化代码
}
[修饰符] 构造器名(参数列表){
// 实例初始化代码
}
}
说明:
- 构造器名必须与它所在的类名必须相同。
- 它没有返回值,所以不需要返回值类型,也不需要void。
- 构造器的修饰符只能是权限修饰符,不能被其他任何修饰。比如,不能被static、final、 synchronized、abstract、native修饰,不能有return语句返回值。
【举例】
之前用过的Scanner:
Scanner scan =new Scanner(System.in);
Scanner()就是一个构造器,构造器里面有形参,这里传入了一个实参System.in。
二、举例剖析
💀举例
(1)构造器在哪
比如现在创建一个类【Person.java】:
package yuyi.exer02;
/** * ClassName: Person * Package: yuyi.exer02 * Description: * * @Author 雨翼轻尘 * @Create 2023/10/23 0023 8:43 */
public class Person {
//属性(先不考虑权限的问题)
String name;
int age;
//方法
public void eat(){
System.out.println("人吃饭");
}
public void sleep(int hour){
System.out.println("每天睡眠"+hour+"小时");
}
}
再创建一个测试类【PersonTest.java】:
package yuyi.exer02;
public class PersonTest {
public static void main(String[] args) {
//创建类的对象
Person p1=new Person(); //类型 变量名 =new 具体对象
//通过对象来调属性、调方法
p1.eat();
}
}
其实Person()
就是构造器:
点击这个位置,创建新的字节码文件:(反编译)
在out文件夹下,找到相应目录,可以看到被隐藏的构造器:(记得点左上角刷新一下)
(2)权限问题
若将Person类的修饰符Public去掉:
再看一下字节码文件:
可以看到,默认生成的构造器的权限与类声明的权限一致。
(3)声明构造器
构造器声明的格式:权限修饰符 类名(形参列表){}
①隐藏的构造器
上面可以看到,隐藏的构造器是这样的:
//构造器
public Person(){
}
如图:
若在Person构造器里面加上输出语句:
//构造器
public Person(){
System.out.println("我是构造器");
}
可以在测试类里面运行出来:
②显示的构造器
我们可以显示的声明其他构造器。
package yuyi.exer02;
public class Person {
//属性(先不考虑权限的问题)
String name;
int age;
//默认构造器
/*public Person(){ System.out.println("我是构造器"); }*/
//声明其他构造器
public Person(int a){
//参数一般考虑对类中属性赋值
age=a; //通过这个构造器,造对象的同时把属性age赋值
}
}
同样可以在测试类里面创造对象,但此时会看到一个报错:
报错内容:
一旦类中显示声明了构造器,则系统不再提供默认的空参的构造器。
若此时还想用这个空参的构造器,需要自行定义:
显示构造之后,可以在测试类里面赋值并输出:
public class PersonTest {
public static void main(String[] args) {
//创建类的对象
Person p2=new Person(1);
System.out.println(p2.age);
}
}
输出结果:
(4)声明多个构造器
在一个类中可以声明多个构造器,比如再声明一个,对name属性进行初始化:
public Person(String n){
name=n;
}
或者对name属性和age属性同时给初始化:
public Person(String n,int a){
name=n;
age=a;
}
这些构造器构成重载。
再比如String:(API)
(5)构造器重点总结说明
构造器声明的格式:
权限修饰符 类名(形参列表){}
4种权限都能用来修饰构造器。
没有返回值类型,直接写构造器的名字。
小括号里面是形参列表。
大括号里面是构造器体。
创建类以后,在没有显示提供任何构造器的情况下,系统会默认提供一个空参的构造器,且构造器的权限与类声明的权限相同。
一旦类中显示声明了构造器,则系统不再提供默认的空参的构造器。
一个类中可以声明多个构造器,彼此之间构成重载。
三、练习
(1)练习1
🌋题目描述
(1)定义Student类,有4个属性:
String name;
int age;
String school;
String major;
(2)定义Student类的3个构造器:
- 第一个构造器Student(String n, int a)设置类的name和age属性;
- 第二个构造器Student(String n, int a, String s)设置类的name, age 和school属性;
- 第三个构造器Student(String n, int a, String s, String m)设置类的name, age ,school和major属性;
(3)在main方法中分别调用不同的构造器创建的对象,并输出其属性值。
🤺代码
package anli;
public class Student {
//属性
String name;
int age;
String school;
String major;
//构造器
public Student(String n, int a){
name=n;
age=a;
}
public Student(String n, int a, String s){
name=n;
age=a;
school=s;
}
public Student(String n, int a, String s, String m){
name=n;
age=a;
school=s;
major=m;
}
}
class StudentTest{
public static void main(String[] args) {
Student one=new Student("张三",19);
Student two=new Student("李四",20,"哈佛");
Student three=new Student("王强",22,"北大","硕士");
System.out.println("name="+one.name+",age="+one.age);
System.out.println("name="+two.name+",age="+two.age+",school="+two.school);
System.out.println("name="+three.name+",age="+three.age+",school="+three.school+",major="+three.major);
}
}
⚡输出结果
👻注意
①构造器没有初始化的属性,默认值是null:(String类型举例)
②小技巧
在调用构造器的时候,因为有很多重载,所以参数不同,可以点击小括号,将光标放在小括号内,按Ctrl+P
就可以显示各个参数:
③可以在Student方法内定义一个方法,方便输出。
public class Student{
//...
public String getInfo(){
return "name= "+name+",age= "+age+",school= "+school+",major= "+major;
}
}
在测试类里面调用:
class StudentTest{
public static void main(String[] args) {
Student four=new Student("黎明",45,"海淀大学","医科");
System.out.println(four.getInfo());
//构造器的作用:搭配new创建对象、通过参数的方式给创建的对象的相关属性赋值
}
}
输出结果:
(2)练习2
🌋题目描述
编写两个类,TriAngle和TriAngleTest,其中TriAngle类中声明私有的底边长base和高height,
同时声明公共方法访问私有变量。此外,提供类必要的构造器。另一个类中使用这些公共方法,计算三角形的面积。
angle:角
angel:天使
🤺代码
【TriAngle.java】
package anli;
/** * ClassName: TriAngle * Package: anli * Description: * * @Author 雨翼轻尘 * @Create 2023/10/23 0023 11:16 */
public class TriAngle {
//①属性
private double base; //底边长
private double height; //高
//②方法
//1.1设置底边长
public void setBase(double a){
base=a;
}
//1.2获得底边长
public double getBase(){
return base;
}
//2.1设置高
public void setHeight(double b){
height=b;
}
//2.2获得高
public double getHeight(){
return height;
}
//求面积的方法
public double findArea(){
//不需要形参,调用方法直接使用底边长和高即可
return base * height /2;
}
//③构造器
//习惯上给一个类提供构造器的时候,会先写一个空参构造器
public TriAngle(){
}
public TriAngle(double b,double h ){
base=b;
height=h;
}
}
【TriAngleTest.java】
package anli;
/** * ClassName: TriAngleTest * Package: anli * Description: * * @Author 雨翼轻尘 * @Create 2023/10/23 0023 11:17 */
public class TriAngleTest {
public static void main(String[] args) {
//创建TriAngle实例1
TriAngle t1=new TriAngle();
//属性被私有化了,要通过调用方法来设置属性
t1.setBase(3.4);
t1.setHeight(2.3);
System.out.println("面积为:"+t1.findArea());
//创建TriAngle实例2
TriAngle t2=new TriAngle(2.4,4.5); //通过构造器给属性赋值
//输出看一下是否真的赋值了
System.out.println("底边长为:"+t2.getBase());
System.out.println("高为:"+t2.getHeight());
System.out.println("面积为:"+t2.findArea());
}
}
记得看注释哦~
get、set不会写的看一下这一篇:Java面向对象(基础)– 类的成员之三:构造器(Constructor)
⚡输出结果
(3)练习3
🌋题目描述
1、写一个名为Account的类模拟账户。该类的属性和方法如下图所示。
该类包括的属性:账号id,余额balance,年利率annualInterestRate;
包含的构造器:自定义
包含的方法:访问器方法(getter和setter方法),取款方法withdraw(),存款方法deposit()。
提示:在提款方法withdraw中,需要判断用户余额是否能够满足提款数额的要求,如果不能,应给出提示。
2、创建Customer类。
a. 声明三个私有对象属性:firstName、lastName和account。
b. 声明一个公有构造器,这个构造器带有两个代表对象属性的参数(f和l)
c. 声明两个公有存取器来访问该对象属性,方法getFirstName和getLastName返回相应的属性。
d. 声明setAccount 方法来对account属性赋值。
e. 声明getAccount 方法以获取account属性。
3、写一个测试程序。
(1)创建一个Customer ,名字叫 Jane Smith, 他有一个账号为1000,余额为2000元,年利率为 1.23% 的账户。
(2)对Jane Smith操作。
存入 100 元,再取出960元。再取出2000元。
打印出Jane Smith 的基本信息:
成功存入 :100.0
成功取出:960.0
余额不足,取款失败
Customer [Smith, Jane] has a account: id is 1000, annualInterestRate is 1.23%, balance is 1140.0
🤺代码
【Account.java】
package anli;
/** * ClassName: Account * Package: anli * Description: * 该类包括的属性:账号id,余额balance,年利率annualInterestRate; * 包含的构造器:自定义 * 包含的方法:访问器方法(getter和setter方法),取款方法withdraw(),存款方法deposit()。 * * 提示:在提款方法withdraw中,需要判断用户余额是否能够满足提款数额的要求,如果不能,应给出提示。 * @Author 雨翼轻尘 * @Create 2023/10/23 0023 11:59 */
public class Account {
//属性
private int id; //账号
private double balance; //余额
private double annualInterestRate; //年利率
//构造器
public Account(){
}
public Account(int i,double b,double a){
id=i;
balance=b;
annualInterestRate=a;
}
//方法
//1.1设置账号
public void setId(int i){
id=i;
}
//1.2获得账号
public int getId(){
return id;
}
//2.1设置余额
public void setBalance(double b){
balance=b;
}
//2.2获得余额
public double getBalance(){
return balance;
}
//3.1设置年利率
public void setAnnualInterestRate(double a){
annualInterestRate=a;
}
//3.2获得年利率
public double getAnnualInterestRate(){
return annualInterestRate;
}
//取钱
public void withdraw(double amount){
if(amount<=balance && amount> 0){
//说明余额够
balance-=amount;
System.out.println("成功取出:"+amount);
}else{
System.out.println("余额不足,取款失败~");
}
}
//存钱
public void deposit(double amount){
if(amount>=0){
//充入的钱是正数
balance+=amount;
System.out.println("成功存入: "+amount);
}
}
}
【Customer.java】
package anli;
/** * ClassName: Customer * Package: anli * Description: * a. 声明三个私有对象属性:firstName、lastName和account。 * b. 声明一个公有构造器,这个构造器带有两个代表对象属性的参数(f和l) * c. 声明两个公有存取器来访问该对象属性,方法getFirstName和getLastName返回相应的属性。 * d. 声明setAccount 方法来对account属性赋值。 * e. 声明getAccount 方法以获取account属性。 * @Author 雨翼轻尘 * @Create 2023/10/23 0023 12:37 */
public class Customer {
//属性
private String firstName;
private String lastName;
private Account account; //account是自定义类属性
//在一个类(Customer)里面可以声明另外一个类(Account)的成员变量,
// 另外这个类可以是系统提供现成的(比如String),也可以是自定义类(Account)
//构造器
//在创建对象的时候,并没有给account赋值,此时account是NULL,可以在下面的方法中对account属性赋值
public Customer(String f,String l){
firstName=f;
lastName=l;
}
//方法
//1.针对姓名只有get方法(相当于给名字属性私有化之后,并没有提供set方法,就是一旦设置好之后就不允许再改变了)
public String getFirstName(){
return firstName;
}
public String getLastName(){
return lastName;
}
//2.针对account提供get和set方法
public void setAccount(Account a){
account=a;
}
public Account getAccount(){
return account;
}
}
【CustomerTest.java】
package yuyi.exer01.exe01.test2;
import anli.Account;
import anli.Customer;
/** * ClassName: CustomerTest * Package: yuyi.exer01.exe01.test2 * Description: *(1)创建一个Customer ,名字叫 Jane Smith, 他有一个账号为1000,余额为2000元,年利率为 1.23% 的账户。 *(2)对Jane Smith操作。 * 存入 100 元,再取出960元。再取出2000元。 * 打印出Jane Smith 的基本信息: * * 成功存入 :100.0 * 成功取出:960.0 * 余额不足,取款失败 * Customer [Smith, Jane] has a account: id is 1000, annualInterestRate is 1.23%, balance is 1140.0 * * @Author 雨翼轻尘 * @Create 2023/10/23 0023 16:24 */
public class CustomerTest {
public static void main(String[] args) {
//1.创建Customer实例
Customer customer=new Customer("Jane","Smith"); //通过构造器对类中的属性赋值
//2.创建账户
Account account=new Account(1000,2000,0.0123);
//3.客户与账户建立联系
customer.setAccount(account);
//4.针对于客户的账户进行取钱、存钱的操作
//方法一
/*不要直接通过account进行操作,就好像银行在操作一样,现在要体现自己操作 account.deposit(100);//存钱 account.withdraw(960);//取钱 account.withdraw(2000);//取钱*/
//方法二
//先通过客户找到账户,拿着账户再去存钱
customer.getAccount().deposit(100); //存钱100
customer.getAccount().withdraw(960); //取钱960
customer.getAccount().withdraw(2000); //取钱2000
//5.输出客户信息
System.out.println("Customer ["+customer.getLastName()+", "+customer.getFirstName()+"] has a account: " +
"id is "+customer.getAccount().getId()+
", annualInterestRate is "+ customer.getAccount().getAnnualInterestRate()*100+
"%, balance is "+ customer.getAccount().getBalance());
}
}
⚡输出结果
👻注意
①重要代码分析
②补充知识点
//1.创建Customer实例
Customer customer=new Customer("Jane","Smith"); //通过构造器对类中的属性赋值
//2.创建账户
Account account=new Account(1000,2000,0.0123); //创建了一个账户,账户的名字叫account
//3.客户与账户建立联系
customer.setAccount(account); //账户的名字account(变量)赋值给customer的setAccount属性
上面代码的第2个和第3个可以合并起来:
customer.setAccount(new Account(1000,2000,0.0123));
//在堆空间创造了一个对象new Account(1000,2000,0.0123),这个对象没有名字,叫做匿名对象
匿名对象:创建的对象没有名字。
【举例】
在main方法里面,取1000块钱:
//关于匿名对象
new Account(1001,2000,0.0123).withdraw(1000); //取钱
输出结果:
若想看一下刚才创建的对象它的账户余额,这样调用是不可行的:
System.out.println(new Account(1001, 2000, 0.0123).getBalance());//不可行,这里又会创建一个新的对象
输出结果:
上面造的匿名对象Account…,下面输出的时候还想拿到那个对象,是不行的。
匿名对象只能用一次,后边就找不到了。
在java里面调用一个对象或一个值,都是通过变量名来调用的。
之前我们都是将对象赋值给一个具体的对象,比如:
Account account=new Account(1000,2000,0.0123);
若想拿到这个对象,直接拿变量名account来操作就可以了。
匿名的话就只能调用一次啦。
那匿名对象咋用嘞?
开发当中,通常就是这样使用:
当造好的对象被赋值给了一个变量,紧接着又调用了这个变量,这个变量后边也没有用,就可以这样使用。
1.匿名对象往往只能被调用一次。
2.通常匿名对象作为实参传递给方法的形参。
小Tips:
customer.setAccount(new Account(1000,2000,0.0123));
其实,在setAccount
方法里面,针对a是可以多次调用的:
所谓的匿名对象传进setAccount内之后就有名了,在setAccount方法里面可以多次调用。
【注】纯手敲难免有误,欢迎各位读者指正,感兴趣的欢迎关注专栏:http://t.csdnimg.cn/XEkfM,后续会持续更新,关注博主不迷路~
今天的文章java类中构造方法_Java面向对象基础「建议收藏」分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/80073.html