背景与动机
Java 是典型的面向对象语言。基础语法解决“语句怎么写”,类与对象解决“数据和行为如何组织”。
可以先这样理解:
- 类是模板,描述一类事物有哪些属性和行为。
- 对象是类创建出来的具体实例。
核心原理拆解
1. 类定义对象的结构
class User { String name; int age;
void sayHello() { System.out.println("hello, " + name); }}这里 name 和 age 是字段,sayHello 是方法。
2. 使用 new 创建对象
User user = new User();user.name = "Tom";user.age = 18;user.sayHello();new User() 会创建一个 User 对象,变量 user 保存对这个对象的引用。

2.1 从内存角度理解 new 做了什么
如果把上面的代码再往底层一点看,可以先建立一个简化理解:
- 栈:放方法调用过程中的局部变量和引用
- 堆:放真正创建出来的对象实例
- 方法区:放类的元信息、方法字节码、静态变量、常量等

可以把它和这段代码对应起来:
User user = new User();user.name = "Tom";user.age = 18;这里发生的事情可以按顺序理解为:
main()执行时,会有自己的栈帧。- 局部变量
user存在当前方法的栈帧里。 new User()在堆中创建一个真正的User对象。- 栈里的
user保存的不是整个对象本身,而是指向堆中对象的引用。 User这个类的结构信息,比如字段、方法、字节码等,可以先理解为放在方法区中。
这也是为什么我们常说:
- 基本类型局部变量经常直接放在栈帧里
- 对象一般创建在堆里
- 变量名拿到的很多时候只是“对象引用”
3. Java 创建对象不只有一种方式

日常开发里最常见的是 new,但严格来说,Java 创建对象常见有这些方式:
- 用
new调用构造方法创建对象 - 通过工厂方法返回对象
- 通过反射、
clone、反序列化等特殊机制创建对象
User u1 = new User("Tom", 18); // 最常见User u2 = User.of("Jerry", 20); // 工厂方法其中最值得先掌握的是前两种:
new:最直接,适合正常创建对象- 工厂方法:适合把创建规则收进类内部,比如缓存对象、隐藏实现细节、统一参数校验
反射、clone、反序列化都属于更进阶或特定场景下的对象创建方式,这里先知道它们存在即可,展开理解可以放到后续更具体的类库主题里。
4. 构造方法用于初始化对象
构造方法名称必须和类名一致,并且没有返回值类型:
class User { String name; int age;
User(String name, int age) { this.name = name; this.age = age; }}创建对象时会调用构造方法:
User user = new User("Tom", 18);构造参数的意义,不只是“把值传进去”,更重要的是让对象在创建时就具备一份完整、合法的初始状态。比如用户对象必须有名字和年龄,就可以要求调用方在 new User(...) 时一次性传入。
5. 无参构造、带参构造和重载构造
一个类可以有多个构造方法,只要参数列表不同,就叫构造方法重载:
class User { String name; int age;
User() { this("anonymous", 0); }
User(String name) { this(name, 0); }
User(String name, int age) { this.name = name; this.age = age; }}这样做的好处是:
- 调用方可以按自己已有的数据量选择不同构造方法
- 真正的初始化逻辑集中在一个主构造方法里,避免重复赋值代码
这里的 this("anonymous", 0) 和 this(name, 0) 不是访问字段,而是在当前构造方法里继续调用同类的另一个构造方法,这种写法叫构造方法链。
6. 什么时候类不能直接实例化
并不是所有类都能直接 new:
abstract class不能直接实例化,因为抽象类本身通常只提供公共结构或部分实现interface不能直接实例化,因为接口只描述能力约定,不提供完整对象- 构造方法是
private的类,不能在类外直接new
例如下面这些写法都不行:
abstract class Animal {}
interface Flyable {}
// Animal animal = new Animal(); // 编译失败// Flyable flyable = new Flyable(); // 编译失败private 构造方法常见于工具类、单例模式或不希望外部随便创建对象的场景。
7. this 表示当前对象
当参数名和字段名相同时,常用 this 区分:
this.name = name;左边的 this.name 是当前对象字段,右边的 name 是构造方法参数。
在构造方法里,this(...) 还可以调用当前类的其他构造方法;而 this.name 这种写法表示访问当前对象字段。两者都叫 this,但含义不一样,要结合上下文看。
最小可运行代码示例
public class ClassObjectDemo { public static void main(String[] args) { User user1 = new User(); User user2 = new User("Tom"); User user3 = new User("Jerry", 18);
user1.sayHello(); user2.sayHello(); user3.sayHello(); }}
class User { String name; int age;
User() { this("anonymous", 0); }
User(String name) { this(name, 0); }
User(String name, int age) { this.name = name; this.age = age; }
void sayHello() { System.out.println("hello, " + name + ", age=" + age); }}常见陷阱与错误示例
1. 构造方法写了返回值类型
错误示例:
void User(String name) { this.name = name;}这不是构造方法,而是一个普通方法。
2. 对象引用为 null 时调用方法
User user = null;user.sayHello();这会抛出 NullPointerException。调用对象方法前,要确认引用不是 null。
3. 写了带参构造后,以为默认无参构造还会自动存在
class User { User(String name) { }}
User user = new User(); // 编译失败如果类里已经手动声明了构造方法,编译器就不会再额外赠送默认无参构造。需要无参构造时,要自己写出来。
4. 试图直接实例化抽象类或接口
抽象类和接口都不能直接 new。它们的作用是定义抽象层、通用能力或约束,真正被实例化的通常是具体子类或实现类。
5. 字段直接公开导致状态随意修改
学习阶段可以先直接访问字段,但工程代码通常会配合封装,把字段设为 private,通过方法控制修改规则。
面试高频问题
1. 类和对象有什么区别
类是模板,描述属性和行为;对象是根据类创建出来的具体实例。
2. 构造方法有什么特点
构造方法名称和类名一致,没有返回值类型,创建对象时自动调用,通常用于初始化对象状态。
3. 为什么有些类不能实例化
因为它们不是“可直接创建的完整对象类型”。比如抽象类通常只提供公共骨架,接口只定义行为约定,private 构造方法则主动限制外部创建。
4. 无参构造和有参构造怎么选
如果对象创建时必须带上关键数据,优先提供有参构造;如果允许先创建、后赋值,或者需要给默认值,可以补无参构造。很多时候会同时提供多个重载构造方法。
5. Java 创建对象有哪些方式
最常见的是 new,此外还有工厂方法、反射、clone、反序列化等方式。入门和日常业务代码里,优先先掌握 new 和工厂方法。
6. final 代表什么
final 表示这个东西不能再被改写,具体是不能重新赋值、不能重写方法,还是不能继承类,要看它修饰的目标。
7. this 代表什么
this 代表当前对象,常用于访问当前对象字段、方法,或解决参数名和字段名冲突。
一句话总结
类定义结构和行为,对象承载具体状态;理解对象创建方式、构造方法、final 和 this,就抓住了“类与对象”这一章最核心的主线。