Java的构造器和隐式参数和显式参数

本文详细介绍了Java中的构造器概念及其使用方法,包括构造器的特点、如何通过构造器初始化类的实例域、构造器中的this关键字用法,以及与初始化相关的静态块和非静态块的概念。

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

1.构造器

      写一个java类,首先要先从构造器开始,构造器与类同名,在构造类的对象时会先从构造器开始。

      构造器总是伴随着new操作符的执行而被调用。

      构造器主要是用来初始化类的实例域。

      构造器的特点:

构造器与类同名。

每个类可以有1个或多个构造器。

构造器可以有0个或多个参数。

构造器没有返回值。

构造器总是伴随着new操作一起调用。

      如果在类中定义了一个final实例域,就意味着这个实例域只能被初始化一次,那么它必须在构造器中给予初始化。

      如果在多个构造器中都需要给类的一个实例域初始化成同一个数值,往往会在实例域处直接初始化。比如: private double salary = 100.0;

      构造器this方法:构造器可以有多个,如果在一个构造器中调用另一个构造器,要用this(...)方法。比如:

public class Abc
{
	private double salary;

	public Abc(){
		this(100.0);
	}
	public Abc(double aSalary){
		salary = aSalary;
	}
}


      如果类中没有写构造方法,那么java会提供一个隐含的默认的构造器,默认将类的实例域初始化为0、false或者null。如果在类中写了一个含参数的构造方法,就必须在类中同时也写一个不含参数的构造方法,否则java会提示出错。

      构造器是为了给类的实例域初始化,其实给实例域初始化还有其他的方法,比如在类中写一个静态块或者初始化块(也叫非静态块),有人认为非静态块是指构造函数,其实这是种错误的认识。

      静态块是这样写的:static{...},在一个类中只能有一个静态块,只能有一个公有类。它会在对象装载到系统的时候执行一次,然后销毁,它可以初始化静态变量。

      初始化块是这样的:{...},在一个类中可以有多个初始化块。它在每次构造对象的时候执行一次,它可以初始化实例域。

      如果你要搞清楚静态块和初始化块的执行顺序,请搞清楚以下内容逻辑(来自网络):

父类和子类中都要静态代码块,非静态代码块,构造方法时。

初始化子类对象时,调用的顺序是

调用顺序:父类静态,子类静态,父类非静态,父类构造,子类非静态,子类构造

2.显式参数和隐式参数

      显式参数,就是平时见到的在方法名括号中间的参数,就是所谓能看得见的参数。
      隐式参数,是在类的方法中调用了类的实例域。这个被调用的实例域就是隐式参数。在以下的这个类中调用了a.ariseSalary(100),就用到了隐式参数。比如:
public class Abc
{
	private double salary;
	public Abc(){
	}
	public void ariseSalary(double em){
		double employ = salary * em;
		salary += employ;
	}
}
Abc a = new Abc();
a.ariseSalary(100);
       在上面的类中,如果调用了这个方法salary是实例域,ariseSalary方法中的salary就是隐式参数。如果在隐式参数的前面加上this,隐式参数就更清晰: 
	public void ariseSalary(double em){
		double employ = this.salary * em;
		this.salary += employ;
	}
      推荐在隐式参数的前面加上this操作符。this操作符代表的是本类。
<think>好的,我现在需要帮助用户理解编程语言中函数定义的区别及用法。首先,我要确保自己准确掌握了这两个概念。函数定义通常是开发者直接写出函数的类型、参数返回类型,而可能是编译器或解释器自动推断类型,或者通过其他方生成函数,比如运算符重载或类型转换。 接下来,我需要回忆不同编程语言中的例子。比如,在C++中,explicit关键字用于构造函数,防止类型转换。而在Python中,函数的参数类型通常不需要声明,属于定义。Haskell这样的函数语言,类型推断也属于的范畴。 用户可能想知道两者的优缺点应用场景。定义的好处是明确,减少错误,但代码冗长;定义简洁,但可能带来歧义。需要举一些具体的例子,比如C++的构造函数加上explicit避免意外转换,或者Python使用类型注解逐渐支持类型声明。 还要考虑用户可能的疑惑点,比如转换的风险,比如JavaScript中的类型强制转换可能导致意想不到的结果。这时候需要强调定义在维护可读性上的优势。 另外,用户提到的引用是关于多态性的,可能与函数重载有关,但这里的问题更侧重于函数定义的方。需要确保回答紧扣主题,同时可能提到多态中的实现方,比如接口实现 vs 鸭子类型。 最后,生成相关问题时,要覆盖不同语言、优缺点比较、应用场景以及转换方法。比如,如何将转为,或者不同语言中的最佳实践。 需要检查是否有遗漏的重要点,比如动态类型语言静态类型语言在这方面的差异,或者现代编程语言的发展趋势,比如TypeScript为JavaScript添加类型。 总结结构:先定义,然后分点对比,接着用不同语言的例子说明,再讨论优缺点,最后注意事项应用场景。确保使用正确的中文术语,LaTeX格,引用标记,并生成相关问题。</think>### vs 函数定义 #### 1. 函数定义 **定义**:开发者直接声明函数的参数类型、返回值类型及具体实现,所有行为由代码明确指定。 **特点**: - 类型逻辑清晰,减少歧义 - 常用于静态类型语言(如C++、Java) - 需要手动处理类型转换 **示例**: - **C++**中使用`explicit`关键字防止构造函数调用: ```cpp class Box { public: explicit Box(int size) {} // 必须调用 }; Box b = 10; // 编译错误 Box b(10); // 正确 ``` - **Python**中通过类型注解声明类型(Python 3.6+): ```python def add(x: int, y: int) -> int: return x + y ``` #### 2. 函数定义 **定义**:编译器或解释器自动推断函数行为,开发者无需完整声明细节。 **特点**: - 代码简洁,开发效率高 - 常见于动态类型语言(如Python、JavaScript) - 可能引发意外类型转换 **示例**: - **JavaScript**中的类型自动转换: ```javascript function add(a, b) { return a + b; // 可能执行字符串拼接或数值加法 } add(2, "3"); // 返回"23"(转换) ``` - **Haskell**中的类型推断: ```haskell square x = x * x -- 编译器推断类型为Num a => a -> a ``` #### 3. 核心区别对比 | 特性 | 定义 | 定义 | |---------------------|-----------------------------------|-----------------------------------| | **类型声明** | 必须明确声明 | 可省略,由编译器推断 | | **代码安全性** | 高(减少运行时错误) | 低(依赖开发者经验) | | **适用场景** | 大型项目、团队协作 | 快速原型开发、脚本 | | **调试难度** | 较易(错误在编译期暴露) | 较难(错误可能在运行时出现) | #### 4. 使用注意事项 - **定义优先**:在需要维护性安全性的场景(如金融系统)中,声明类型接口[^1]。 - **定义适用场景**:快速开发时(如数据分析脚本),或语言本身强推定类型(如Haskell)。 - **风险案例**: ```python def multiply(a, b): return a * b multiply(3, "a") # 返回"aaa"(可能不符合预期) ``` #### 5. 跨语言实践 - **C#**:通过`var`关键字支持局部变量类型推断,但方法签名仍需声明。 - **Rust**:类型推断在块内有效,但函数参数返回类型必须声明。 - **TypeScript**:为JavaScript添加类型系统,编译时检查类型错误。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值