0

0

Java中构造器内创建对象的正确访问与管理实践

心靈之曲

心靈之曲

发布时间:2025-11-07 16:15:01

|

704人浏览过

|

来源于php中文网

原创

Java中构造器内创建对象的正确访问与管理实践

本文详细探讨了在java中,当一个类(如`bus`)的构造器内创建另一个对象(如`trip`)时,如何在外部类(如`interface`的`main`方法)中正确访问该对象。核心问题在于变量作用域的理解和实例成员的正确引用。教程将通过实例代码演示如何将局部变量提升为类成员变量,并利用getter方法实现封装和安全访问,同时提供处理多对象场景的设计建议,以提升代码的可维护性和扩展性。

理解Java中的变量作用域

在Java中,变量的作用域决定了其可访问的范围。当我们在一个方法的内部(包括构造器)声明一个变量时,该变量被称为局部变量。局部变量只在该方法或代码块内部有效,一旦方法执行完毕,局部变量就会被销毁,无法从外部访问。

原始代码中的Bus类存在的问题就在于此:

public class Bus
{
    // ... 其他成员变量
    // private Trip trip1; // 缺少这一行,导致 trip1 成为局部变量

    public Bus(int tripNumber)
    {
        this.tripNumber = tripNumber;

        if (tripNumber==1)
        {
            // 在构造器内部声明的 trip1 是局部变量
            Trip trip1 = new Trip(this, tripNumber); 
        }
    }
    // ...
}

在上述代码中,Trip trip1 = new Trip(this, tripNumber); 语句将trip1声明为Bus构造器内部的一个局部变量。这意味着trip1只在Bus构造器的if (tripNumber==1)代码块中存在。一旦构造器执行完毕,trip1就超出了作用域,无法再被Bus类的其他方法或外部类访问。

修正方法:将局部变量提升为实例变量

立即学习Java免费学习笔记(深入)”;

要使Trip对象能够在Bus类的生命周期内持续存在并被外部访问,我们需要将其声明为Bus类的实例变量(或称成员变量)。实例变量属于类的每一个对象,并在对象创建时被初始化,直到对象被垃圾回收。

public class Bus
{
    // ... 其他成员变量
    private Trip trip; // 将 trip 声明为实例变量

    public Bus(int tripNumber)
    {
        this.tripNumber = tripNumber;

        if (tripNumber==1)
        {
            this.model = "Setra";
            this.type = "2+2";
            this.age = 8;
            this.capacity = 40;
            this.remainingCapacity = 23;

            // 为实例变量 trip 赋值
            this.trip = new Trip(this, tripNumber); 
        }
    }
    // ...
}

通过将Trip trip;声明在类级别,trip现在是Bus对象的一个属性。当Bus对象被创建时,trip变量也随之存在,并可以在Bus对象的生命周期内被访问。

正确访问实例成员

解决了Bus类内部Trip对象的可见性问题后,下一步是解决如何在Interface(主类)中正确访问它。原始的Interface类试图通过Trip.trip1.toString();来访问trip1,这存在两个问题:

  1. trip1不是Trip类的静态成员:Trip.trip1的语法暗示trip1是Trip类的一个静态成员。然而,我们希望访问的是Bus对象(bus1)所拥有的Trip实例。
  2. 直接暴露内部对象不符合封装原则:即使trip1是Bus的公共成员,直接通过bus1.trip1访问也不推荐。

引入 Getter 方法:封装与访问控制

面向对象编程中,为了实现封装性,我们通常将实例变量声明为private,并通过公共的getter方法来提供对这些变量的受控访问。这不仅保护了对象的内部状态,还提供了未来修改内部实现的灵活性,而无需更改外部调用代码。

首先,在Bus类中添加一个getTrip()方法:

public class Bus
{
    // ... 其他成员变量
    private Trip trip; // 实例变量

    public Bus(int tripNumber)
    {
        // ... 构造器逻辑
        if (tripNumber==1)
        {
            // ... 赋值其他属性
            this.trip = new Trip(this, tripNumber); 
        }
    }

    // 为 trip 实例变量提供公共的 getter 方法
    public Trip getTrip() {
        return this.trip;
    }

    public String toString()
    {
        return ("\n\tBus Information:\n\t\tBus: " + this.model + "\n\t\tType: " + this.type + "\n\t\tAge: " + this.age + "\n\t\tCapacity" + this.capacity + "\n\t\tRemainingCapacity" + this.remainingCapacity);
    }
}

然后,在Interface类中,通过Bus对象的实例来调用getTrip()方法,获取Trip对象,再对其进行操作:

public class Interface
{
    public static void main(String args[])
    {       
        Bus bus1 = new Bus(1);

        // 通过 bus1 实例的 getTrip() 方法获取 Trip 对象
        if (bus1.getTrip() != null) { // 检查是否成功创建了 Trip 对象
            System.out.println(bus1.getTrip().toString());
        } else {
            System.out.println("Trip object not created for bus1.");
        }
    }
}

通过这种方式,我们不仅正确地访问了Trip对象,还遵循了面向对象的封装原则。

AITDK
AITDK

免费AI SEO工具,SEO的AI生成器

下载

完整的修正代码示例

以下是经过修正和优化的完整代码示例:

Bus.java

public class Bus
{
    private int tripNumber;
    private String model;
    private String type;
    private int age;
    private int capacity;
    private int remainingCapacity;
    private boolean[][] seats;
    private Trip trip; // 将 trip 声明为实例变量

    public Bus(int tripNumber)
    {
        this.tripNumber = tripNumber;

        if (tripNumber==1)
        {
            this.model = "Setra";
            this.type = "2+2";
            this.age = 8;
            this.capacity = 40;
            this.remainingCapacity = 23;

            this.trip = new Trip(this, tripNumber); // 为实例变量 trip 赋值
        }
        // 如果 tripNumber 不是1,trip 将保持为 null,这是需要注意的。
        // 可以考虑在构造器末尾添加一个默认的 trip 赋值或者抛出异常。
    }

    // 提供对 trip 实例的公共访问方法
    public Trip getTrip() {
        return this.trip;
    }

    public String toString()
    {
        return ("\n\tBus Information:\n\t\tBus: " + this.model + "\n\t\tType: " + this.type + "\n\t\tAge: " + this.age + "\n\t\tCapacity: " + this.capacity + "\n\t\tRemainingCapacity: " + this.remainingCapacity);
    }
}

Trip.java

public class Trip
{
    private int tripNumber;
    private String date;
    private String origin;
    private String destination;
    private String departureTime;
    private String arrivalTime;
    private Bus assignedBus;

    public Trip(Bus bus, int tripNumber)
    {
        if (tripNumber==1) // 这里的条件可能需要更灵活,或者从 Bus 构造器传递所有必要参数
        {
            this.tripNumber = tripNumber; // 应该使用传入的 tripNumber
            this.assignedBus = bus;
            this.date = "27/11/2022";
            this.origin = "Ankara";
            this.destination = "Istanbul";
            this.departureTime = "00:15";
            this.arrivalTime = "06:30";
        }
        // 同样,如果 tripNumber 不是1,Trip 对象可能不会被完全初始化
    }

    public String toString()
    {
        // 检查 assignedBus 是否为 null,以避免 NullPointerException
        String busInfo = (this.assignedBus != null) ? this.assignedBus.toString() : "\n\t\tNo assigned bus information.";
        return tripNumber + ") Trip Information: \n\tDate: " + this.date + "\n\tFrom: " + this.origin + " to " + this.destination + "\n\tTrip time: " + this.departureTime + " to " + this.arrivalTime + busInfo;
    }
}

Interface.java

public class Interface
{
    public static void main(String args[])
    {       
        Bus bus1 = new Bus(1); // 创建一个 tripNumber 为 1 的 Bus 对象

        // 通过 Bus 实例的 getter 方法获取 Trip 对象
        Trip tripForBus1 = bus1.getTrip();

        if (tripForBus1 != null) {
            System.out.println(tripForBus1.toString());
        } else {
            System.out.println("No trip assigned to bus1 for the given trip number.");
        }

        // 示例:如果创建的 Bus 没有对应的 Trip (例如 tripNumber 不是1)
        Bus bus2 = new Bus(2); 
        Trip tripForBus2 = bus2.getTrip();
        if (tripForBus2 != null) {
            System.out.println(tripForBus2.toString());
        } else {
            System.out.println("No trip assigned to bus2 for the given trip number.");
        }
    }
}

最佳实践与进阶考量

  1. 封装原则:始终将实例变量声明为private,并通过公共的getter(和setter,如果需要修改)方法来访问它们。这不仅保护了数据,还提高了代码的模块化和可维护性。

  2. 构造器的职责:构造器应主要负责初始化对象的状态。避免在构造器中执行复杂的业务逻辑,特别是那些可能失败或耗时的操作。如果对象创建逻辑复杂,可以考虑使用工厂模式。

  3. 处理多对象关联:当前设计中,一辆Bus只能关联一个Trip对象(通过private Trip trip;)。在实际应用中,一辆巴士可能执行多趟行程,或者需要管理历史行程。在这种情况下,应该使用集合类型(如List<Trip>或Map<Integer, Trip>)来存储多个Trip对象:

    public class Bus {
        private List<Trip> trips; // 一辆巴士可以有多趟行程
    
        public Bus(int initialCapacity) {
            this.trips = new ArrayList<>(); // 初始化行程列表
            // ... 其他初始化
        }
    
        public void addTrip(Trip trip) {
            this.trips.add(trip);
        }
    
        public List<Trip> getTrips() {
            return Collections.unmodifiableList(this.trips); // 返回不可修改的列表,保护内部状态
        }
        // ...
    }

    这样,在Bus构造器中可以创建并添加多个Trip对象,或者在后续通过addTrip方法动态添加。

  4. 条件初始化:在Bus和Trip的构造器中,都存在if (tripNumber == 1)这样的条件判断。这使得只有特定tripNumber的实例才会被完全初始化,而其他情况下的对象可能处于不完整或null的状态。这可能导致运行时出现NullPointerException。

    • 改进策略
      • 确保构造器始终创建一个有效的对象,或者在无法创建时抛出异常。
      • 如果tripNumber不为1时不需要创建Trip,则getTrip()方法返回null是合理的,但调用方必须进行null检查。
      • 更好的做法是,Bus构造器不直接创建Trip,而是接收一个Trip对象作为参数,或者有一个单独的方法来分配Trip。
  5. Null 安全:在Interface类中调用bus1.getTrip()后,务必检查返回的Trip对象是否为null,以避免潜在的NullPointerException。同样,在Trip的toString()方法中,也应检查assignedBus是否为null。

总结

正确访问在构造器中创建的对象是Java面向对象编程中的一个基本但重要的概念。通过理解变量作用域(局部变量与实例变量的区别)、将相关对象声明为实例变量,并遵循封装原则使用getter方法,我们可以构建出结构清晰、可维护性高且健壮的Java应用程序。此外,对于复杂的对象关联,应考虑使用集合类型来管理,并时刻注意代码的健壮性和Null安全。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

254

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1089

2024.03.01

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

847

2023.08.22

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

58

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

63

2025.11.27

go中interface用法
go中interface用法

本专题整合了go语言中int相关内容,阅读专题下面的文章了解更多详细内容。

78

2025.09.10

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

77

2025.09.05

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

40

2025.11.16

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.4万人学习

C# 教程
C# 教程

共94课时 | 11.3万人学习

Java 教程
Java 教程

共578课时 | 81.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号