《JAVA编程思想》学习备忘(第155页:Initialization & Cleanup)-3

本文探讨了Java中如何在一个类的多个构造器之间进行调用以避免代码重复,通过具体示例解释了使用this关键字调用不同构造器的方法及限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 续《JAVA编程思想》学习备忘(第155页:Initialization & Cleanup)-2
Calling constructors from constructors
When you write several constuctors for a class,there are times when you'd like to call one constructor from another to avoid duplicating code.You can make such a call by using the this keyword.
Normally,when you say this,it is in the sense of"this object"or"the current object,"and by itself it produces the reference to the current object.In a constructor,the this keyword takes on a different meaning when you give it an argument list.It makes an explicit call to the constructor that matches that argument list.Thus you have a straightforward way to call other constructors:
实例:
import static staticPrint.Print.print;
public class Flower{
    int petalCount = 0;
    String s = "initial value";
    Flower(int petals){
        petalCount = petals;
        print("Constructor w/ int arg only, petalCount = " + petalCount);
    }
    Flower(String ss){
        print("Constructor w/ String arg only, s = " + ss);
        s = ss;
    }
    Flower(String s, int petals){
        this(petals);
// !  this(s); // Can't call two!
        this.s = s; // Another use of "this"
        print("String & int args");
    }
    Flower(){
        this("hi",47);
        print("default constructor (no args)");
    }
    void printPetalCount(){
// ! this(11); // not inside non-constructor!
        print("petalCount = " + petalCount + " s = " + s);
    }
    public static void main(String[] args){
        Flower x = new Flower();
        x.printPetalCount();
    }
}
以上输出:
Constructor w/ int arg only, petalCount = 47
String & int args
default constructor (no args)
petalCount = 47 s = hi
注意程序轨迹:在 main 方法中实例化类的对象名为 x ,调用默认构造方法 Flower() ,在进入默认无参构造方法 Flower() 后,用关键字 this 传两个参数:"hi", 47 以调用双参构造方法 Flower(String s, int petals),进入双参构造方法Flower(String s, int petals)后,又用关键字 this 传整形参 petals (注意,此时 petals 的值为 47), 以调用单参构造方法 Flower(int petals),进入单参构造方法 Flower(int petals)后,首先给petalCount 付值 47,然后打印出第1条语句,至此 Flower(int petals)内程序全部执行完毕,宣告双参构造方法Flower(String s, int petals)中执行完了第一行this(petals)的调用,接下来用传过来的字符串参数 "hi",将字符串 s 的初始值 "initial value" 覆盖掉,接下来打印出第二条语句,至此 Flower(String s, int petals)内程序全部执行完毕,同理也宣告了默认构造方法 Flower() 中 this("hi", 47) 调用程序执行完毕,接下来程序执行下一行打印码输出了第3条语句,至此,类 Flower 的对象 x 实例化完结,程序该执行下一行代码了:对象 x 调用方法 printPetalCount() 。程序进入 printPetalCount() 中那条打印代码输出最后一条语句,可以看到 petalCount 已被付值为 47 ,字符串 s 已被付值为 hi 。
The constructor Flower(String s,int petals)shows that,while you can call one constructor using this,you cannot call two.In addition,the constructor call must be the first thing you do,or you'll get a compiler error message.
This example also shows another way you'll see this used.Since the name of the argument s and the name of the member data s are the same,there's an ambiguity.You can resolve it using this.s,to say that you're referring to the member data.You'll often see this form used in Java code,and it's used in numerous places in this book.
In printPetalCount() you can see that the compiler won't let you call a constructor from inside any method other than a constructor.
(待续)
 
你遇到的错误信息如下: ``` error: invalid initialization of non-const reference of type 'std::__cxx11::string&' from an rvalue of type 'std::__cxx11::string' ``` 这是 C++ 编译器在尝试将一个 **临时对象(rvalue)** 绑定到一个 **非常量左值引用(non-const lvalue reference)** 时发生的编译错误。 --- ## 🔍 错误原因分析 ### 示例代码(导致错误): ```cpp void func(string& s) { cout << s << endl; } int main() { func("hello"); // ❌ 编译错误:临时对象不能绑定到非 const 引用 } ``` ### 解释: - `"hello"` 是一个字符串字面量(`const char*`),它会被隐式转换为一个 `std::string` 的**临时对象(rvalue)**。 - 函数 `func(string& s)` 接受的是一个**非常量左值引用**。 - 在 C++ 中,**不能将临时对象绑定到非常量左值引用上**,因为临时对象是只读的,而函数可能修改这个引用的内容,这是不允许的。 --- ## ✅ 正确解决方法 ### 方法一:将函数参数改为常量引用(推荐) 如果你不需要修改传入的字符串内容,应使用 `const string&`: ```cpp void func(const string& s) { cout << s << endl; } int main() { func("hello"); // ✅ 正确:临时对象可以绑定到 const 引用 } ``` > ✅ 这是最常用、最安全的做法。 --- ### 方法二:使用显式构造 + 左值(适合需要修改的情况) 如果你确实需要修改传入的字符串,你应该传递一个左值: ```cpp void func(string& s) { s += " world"; } int main() { string s = "hello"; func(s); // ✅ 正确:s 是左值 cout << s << endl; // 输出 hello world } ``` --- ### 方法三:使用右值引用(C++11 及以上) 如果你希望专门处理临时对象(如移动语义场景),可以使用右值引用: ```cpp void func(string&& s) { cout << s << " (rvalue)" << endl; } int main() { func("hello"); // ✅ 正确:绑定到右值引用 } ``` > 注意:这种方式适用于高级用途,比如资源管理或性能优化。 --- ## 🧪 常见出错场景汇总 | 场景 | 是否报错 | 原因 | |------|----------|------| | `func("hello")`,其中 `func(string&)` | ❌ 报错 | 临时对象不能绑定到非 const 引用 | | `func("hello")`,其中 `func(const string&)` | ✅ 正确 | 允许绑定到 const 引用 | | `func(string("abc"))`,其中 `func(string&)` | ❌ 报错 | 同样是一个临时对象 | | `func(s + "abc")`,其中 `func(string&)` | ❌ 报错 | 表达式结果是临时对象 | --- ## ✅ 总结处理流程: | 操作 | 描述 | |------|------| | ❌ 使用 `string&` 接收临时对象 | 导致编译错误 | | ✅ 使用 `const string&` 接收临时对象 | 安全、标准做法 | | ✅ 使用左值变量传递 | 需要修改内容时使用 | | ✅ 使用右值引用 `string&&` | 高级用途,如移动语义 | --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值