Java构造方法详解
问题
问题一:
构造对象,声明时,如StxStu s1 = StxStu(); ,前面的StxStu要和class 后面的类名称保持一致吗?
在 Java 中构造对象时,声明类型(等号左边的 StxStu)必须与类名(class StxStu)完全一致,包括大小写。这是 Java 的语法硬性要求。
以下是详细说明:
1. 基本语法规则
// 类定义
public class StxStu { // 类名是 StxStu
// 属性和方法...
}
// 正确构造方式
StxStu s1 = new StxStu(); // 前后 StxStu 必须完全一致
2. 常见错误示例
❌ 错误1:大小写不一致
java
Stxstu s1 = new StxStu(); // 编译错误:找不到符号 Stxstu
❌ 错误2:拼写不一致
java
StxStudent s1 = new StxStu(); // 编译错误:类型不兼容
❌ 错误3:缺少 new
关键字
java
StxStu s1 = StxStu(); // 编译错误:找不到符号 StxStu()
3. 特殊情况处理
(1) 使用父类/接口声明
class Animal {}
class Cat extends Animal {}
// 合法:用父类类型声明
Animal a = new Cat(); // 多态
(2) 使用 var
(Java 10+)
var s1 = new StxStu(); // 自动推断类型为 StxStu
(3) 构造方法重载
public class StxStu {
public StxStu() {} // 无参构造
public StxStu(String name) {} // 带参构造
}
// 根据参数选择不同构造方法
StxStu s1 = new StxStu();
StxStu s2 = new StxStu("张三");
4. 完整正确示例
// 定义类
public class StxStu {
private String name;
// 构造方法
public StxStu() {
this.name = "匿名";
}
public StxStu(String name) {
this.name = name;
}
public void sayHello() {
System.out.println("我是" + name);
}
}
// 使用类
public class Main {
public static void main(String[] args) {
// 正确构造对象
StxStu s1 = new StxStu(); // 前后类名一致
StxStu s2 = new StxStu("李四"); // 带参构造
s1.sayHello(); // 输出:我是匿名
s2.sayHello(); // 输出:我是李四
}
}
5. 关键记忆点
严格一致:声明类型、
new
后的类名、实际类定义三者必须完全一致大小写敏感:Java 是大小写敏感语言,
StxStu
≠stxstu
构造方法不是普通方法:不能直接写
StxStu()
,必须配合new
使用多态例外:当使用父类/接口声明时,右侧可以是子类实现(但子类名仍需正确)
提示:如果遇到类似错误,优先检查:
类名拼写和大小写
是否漏写
new
关键字类文件是否在正确路径(编译通过需要)
代码示例
public class Point {
double x,y;
public Point(double _x,double _y){
x = _x;
y = _y;
}
public double getDistance(Point p){
double d = Math.sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y));
return d;
}
public static void main(String[] args) {
Point p1 = new Point(3.0,4.0);
Point origin = new Point(.0,0.0);
System.out.println(origin.getDistance(p1));
}
}
问题二:
public Point(double _x,double _y){
x = _x;
y = _y;
}
这段代码是 Java 中的一个构造方法(Constructor),用于创建 Point
类的对象时初始化对象的属性。我来用简单易懂的方式解释:
构造方法的基本作用
对象出生时的"初始化":就像新生儿要登记姓名、出生时间一样,构造方法在对象创建时给它设置初始属性值
强制要求提供必要信息:这里要求创建
Point
对象时必须提供 x 和 y 坐标
逐行解析
java
public Point(double _x, double _y) { // 构造方法声明
x = _x; // 把传入的_x值赋给当前对象的x属性
y = _y; // 把传入的_y值赋给当前对象的y属性
}
实际使用示例
当这样创建对象时:
Point p = new Point(3.0, 4.0);
内存中的效果:
p → {
x: 3.0 // 来自第一个参数
y: 4.0 // 来自第二个参数
}
为什么参数名用 _x
和 _y
?
这是一种命名约定,目的是:
区分参数和属性:如果直接写
x = x;
会产生歧义更清晰的代码:一看就知道
_x
是参数,x
是成员变量
(也可以这样写,效果相同):
public Point(double x, double y) {
this.x = x; // this.x 表示当前对象的属性
this.y = y;
}
类比理解
把构造方法想象成点对象的出生证明办理处:
办理要求:必须提供横纵坐标(
_x
,_y
)办理过程:把提供的坐标登记到新对象的属性中(
x = _x
)产出结果:一个带有指定坐标的Point对象
如果没有构造方法会怎样?
Java会提供一个默认的无参构造方法,但这样创建的点对象坐标会是默认值0:
java
Point p = new Point(); // 如果没定义构造方法可以这样,但x,y都是0.0
// 但因为我们定义了构造方法,这样写会报错
关键点总结
构造方法特点:
方法名 = 类名
没有返回类型
在
new
时自动调用
这个构造方法的作用:
强制要求创建Point时必须提供坐标
把提供的坐标值赋给新对象的属性
参数命名的意义:
使用
_x
是为了避免与属性名x
冲突也可以使用
this.x = x
的写法
实际效果:
new Point(3.0, 4.0); // 创建的对象:{ x:3.0, y:4.0 }
这样设计的Point类,能确保每个点对象创建时都有明确的坐标位置。
问题三:
上面代码中的p1.中的“.”有什么作用
在 Java 中,p1.getDistance(origin)
里的点号(.)是一个非常重要的操作符,它的作用可以概括为:
点号(.)的三大核心作用
访问对象的成员
就像「的」字在中文里的作用
p1.getDistance
表示「p1 的 getDistance 方法」p1.x
表示「p1 的 x 属性」
连接对象和它的属性/方法
左侧是对象(
p1
)右侧是该对象的成员(
getDistance
方法)
触发方法调用
当后面跟的是方法时(如
getDistance()
),表示要执行这个方法
在代码中的具体解析
Point p1 = new Point(3.0, 4.0);
Point origin = new Point(0.0, 0.0);
System.out.println(p1.getDistance(origin));
p1
是一个Point
类的对象(实例)getDistance
是Point
类中定义的方法.
表示:「请调用 p1 这个点的 getDistance 方法」
类比现实世界理解
假设你有一部手机(对象):
手机.开机()
→ 调用手机的开机功能手机.电量
→ 查看手机的电池属性
你的 Point
类就像设计图,p1
是按这个设计图造出来的具体产品,.
就是操作这个产品的「按钮」
与其他语法的对比
特别注意事项
null 对象不能用 .
Point p2 = null; p2.getDistance(origin); // 抛出 NullPointerException
private 成员外部不能访问
System.out.println(p1.x); // 如果 x 是 private 的,这里会报错
链式调用(多个 . 连续使用)
String s = "Hello"; int length = s.toUpperCase().substring(1).length();
内存中的实际运作
栈内存 堆内存
p1 → Point对象 {
x: 3.0
y: 4.0
getDistance(): {...}
}
origin → Point对象 {
x: 0.0
y: 0.0
}
当执行 p1.getDistance(origin)
时:
Java 根据 p1 的引用找到堆中的 Point 对象
找到该对象的
getDistance
方法将
origin
作为参数传入执行
为什么需要点号?
没有点号的话,代码将无法表达:
哪个对象执行操作
具体操作是什么
就像如果没有「的」字:
「我书包」可能表示「我的书包」或「我是一个书包」
文章作者:Eila
版权声明:本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0 许可协议,转载请注明出处!