{Java}一个有关类属性初始化的有趣儿情况

本文探讨了一个有趣的Java编程现象:子类属性在父类构造函数执行后的初始化问题。通过一个具体例子展示了属性初始化顺序对程序行为的影响。

========================================================
作者:qiujuer
博客:blog.youkuaiyun.com/qiujuer
网站:www.qiujuer.net
开源库:github.com/qiujuer/Genius-Android
开源库:github.com/qiujuer/Blink
转载请注明出处:http://blog.youkuaiyun.com/qiujuer/article/details/46747975
—— 学之开源,用于开源;初学者的心态,与君共勉!

========================================================

有趣儿?

何为有趣儿?其实就是搞怪。
一段时间没有写博客了,最近弄一个APP去了,后面我把APP贴上,欢迎大家测试使用。


问题

这个情况有些特殊,当时我在弄APP的设置模块;结果发现无论设置如何保存第二次获取值的时候都是初始值,跟踪了一下发现保存的时候的确是保存到文件了,那么这就奇葩了。想了一下问题肯定出在获取值的时候,跟踪了一下获取值的断点,发现获取的时候是之前保存的值,而在类的构造函数之后值却又成了初始值,这个是为啥?

百思不得其姐啊~~~

我喜欢直接一点,来看看代码是怎么回事儿。

代码

package net.qiujuer;

public abstract class People {
    public People() {
        initValue();
    }

    public abstract void initValue();

    public void show() {
        System.out.printf("Show:" + toString());
    }
}

一个父类,在构造函数中调用初始化方法。

package net.qiujuer;

public class Man extends People {
    private String mName = "聂小倩";
    private int mAge = 18;

    @Override
    public void initValue() {
        mName = "Qiujuer";
        mAge = 23;
    }

    @Override
    public String toString() {
        return "Name:" + (mName == null ? "NULL" : mName) + " Age:" + mAge + "\n";
    }
}

实现类,实现其具体的初始化方法,并在该方法中做一些属性操作。

package net.qiujuer;

public class MainClass {
    public static void main(String[] args) {
        Man man = new Man();
        man.show();
    }
}

测试类,在该类中直接 new 并调用方法。
结果是什么呢?

有谁能猜到?

其输出为:

Show:Name:聂小倩 Age:18

怎么样?有想到的么?为什么会这样呢?自己试试看看是不是。

变更

我们输出一些详细的地方。

首先更改父类的构造函数:

    public People() {
        System.out.printf("People-1:" + toString());
        initValue();
        System.out.printf("People-2:" + toString());
    }

然后更改 Man 的构造函数:

    public Man() {
        super();
        System.out.printf("Man:" + toString());
    }

再来运行看看~~

想想一下结果是什么呢?

先想一下,然后再看估计有些用处。

算了,还是直接进入吧~

结果输出:

People-1:Name:NULL Age:0
People-2:Name:Qiujuer Age:23
Man:Name:聂小倩 Age:18
Show:Name:聂小倩 Age:18

想到了么?

结论

我想到了这些:
- 在类属性初始化的时候,其直接赋值的默认值将会在父类的构造函数之后进行。
- 在父类操作的时候,其子类的属性并不具备值:mName 属性为 NULL
- 在父类中可以通过方法对实现类的属性进行赋值操作,但是当其实现类中默认有对值进行赋值的话,那么将会自动进行二次赋值。

一个无心之举,或许会造成一个天大的BUG;且用且珍惜~

Other

关于APP,这个APP是用来记录一些对你重要的日子的软件,并采用时间序的方式对你进行无声提醒。
UPMiss} 思念你的夏天
下载地址:

========================================================
作者:qiujuer
博客:blog.youkuaiyun.com/qiujuer
网站:www.qiujuer.net
开源库:github.com/qiujuer/Genius-Android
开源库:github.com/qiujuer/Blink
转载请注明出处:http://blog.youkuaiyun.com/qiujuer/article/details/46747975
—— 学之开源,用于开源;初学者的心态,与君共勉!

========================================================

<think>嗯,用户让我写一个Java控制台的种田游戏,而且要有可玩性。首先,我得考虑控制台游戏的限制,因为没有图形界面,所以得通过文本和简单的输入来交互。可玩性要强的话,可能需要包括多种作物、成长周期、天气系统、经济系统等等。 首先,确定基本结构。可能需要一个游戏循环,不断显示菜单选项,比如种植、浇水、收获、查看状态、退出等。然后,玩家可以选择不同的操作。每个操作对应不同的功能。 接下来是作物的管理。每种作物应该有名称、生长阶段、生长所需时间、购买价格、出售价格等属性。可能需要一个Crop来存储这些信息。然后,玩家拥有的土地可以是一个数组或者列表,记录每块地种植的作物和生长进度。 天气系统的话,可以随机影响作物的生长速度或者产量。比如晴天加速生长,雨天可能增加水量但可能有洪涝风险,干旱会影响生长等。不过控制台实现复杂的天气效果可能有点难,可以简化,比如每天随机天气,并对作物产生影响。经济系统方面,玩家需要有金币来购买种子,收获后卖出得到金币。可以设置市场价格波动,或者不同作物的利润不同,增加策略性。 然后考虑游戏的时间推进。每次操作可能会消耗时间,比如一天只能进行几次操作,或者每次浇水、种植等操作后时间推进。或者采用每天选择行动的方式,比如每天早晨选择要做什么。 随机事件也是增加可玩性的好方法,比如害虫、干旱、强盗等,玩家需要应对这些事件,否则作物受损。比如,害虫事件需要玩家选择使用农药,否则作物减产。 接下来,如何将这些元素整合到Java代码中。主可能包含游戏状态,比如当前天数、金币、土地情况、天气等。使用面向对象的方式,将作物、土地、天气等作为对象处理。 代码结构可能如下: 1.主,包含游戏循环和主菜单。 2. Crop,定义作物属性。3. 土地管理,比如一个数组,每个元素代表一块地,存储作物和生长进度。 4.天气系统,随机生成每日天气,并影响作物。 5.事件系统,随机触发事件,玩家需要处理。 然后,具体实现每个部分。比如,游戏开始时初始化玩家的金币和土地数量。每次循环显示状态,比如天数、金币、天气,然后显示菜单选项。 种植功能:玩家选择一块空地,选择要种植的作物,扣除金币,初始化该地块的作物和生长进度。浇水:可能加速生长,或者维持生长所需的水分。需要记录每块地是否浇过水,或者有水分值。收获:当作物成熟后,收获并出售获得金币。可能需要计算产量,考虑天气和事件的影响。 查看状态:显示所有地块的情况,比如作物名称、生长阶段。 随机事件可以在每天开始的时候触发,比如有20%的概率发生事件,玩家需要选择应对方法。测试各个功能是否正常,比如种植后生长进度是否正确,浇水是否有效,收获是否获得金币等。 可能遇到的问题包括控制台输入的验证,比如处理非数字输入,避免程序崩溃。还有如何管理多块土地的状态,确保每块地的信息正确更新。 最后,确保游戏有明确的目标,比如赚取一定数量的金币,或者在限定天数内达到目标,增加挑战性。</think>以下是一个基于Java控制台的种田游戏实现,包含天气系统、作物生长、经济系统等要素: ```java import java.util.*; class FarmingGame { private static final Random RANDOM = new Random(); private int day = 1; private int gold = 100; private String[] crops = {"小麦", "玉米", "南瓜", "草莓"}; private String[] weathers = {"晴天", "雨天", "多云", "干旱"}; private String currentWeather; private List<Field> fields = new ArrayList<>(); class Field { String crop; int growthStage; int maxGrowth; boolean isWatered; public Field(String crop, int maxGrowth) { this.crop = crop; this.maxGrowth = maxGrowth; this.growthStage = 0; } } public FarmingGame() { currentWeather = weathers[RANDOM.nextInt(weathers.length)]; for (int i = 0; i < 5; i++) { fields.add(new Field("空闲", 0)); } } public void start() { Scanner scanner = new Scanner(System.in); while (true) { System.out.println("\n=== 第 " + day + " 天 ==="); System.out.println("天气:" + currentWeather); System.out.println("金币:" + gold); System.out.println("1. 种植作物"); System.out.println("2. 浇水"); System.out.println("3. 收获作物"); System.out.println("4. 查看田地状态"); System.out.println("5. 跳过本日"); System.out.println("6. 退出游戏"); System.out.print("请选择操作:"); int choice = scanner.nextInt(); handleChoice(choice); if (choice == 6) break; } scanner.close(); } private void handleChoice(int choice) { switch (choice) { case 1 -> plantCrop(); case 2 -> waterField(); case 3 -> harvestCrop(); case 4 -> showFields(); case 5 -> nextDay(); case 6 -> System.out.println("游戏结束!"); } } private void plantCrop() { Scanner scanner = new Scanner(System.in); System.out.println("\n可用作物:"); for (int i = 0; i < crops.length; i++) { System.out.println((i+1) + ". " + crops[i] + " (价格:" + (i+1)*10 + "金币)"); } System.out.print("选择作物:"); int cropIndex = scanner.nextInt()-1; System.out.print("选择田地(1-5):"); int fieldIndex = scanner.nextInt()-1; if (fieldIndex < 0 || fieldIndex >= fields.size()) { System.out.println("无效的田地编号!"); return; } Field field = fields.get(fieldIndex); if (!field.crop.equals("空闲")) { System.out.println("该田地已有作物!"); return; } int cost = (cropIndex+1)*10; if (gold < cost) { System.out.println("金币不足!"); return; } gold -= cost; fields.set(fieldIndex, new Field(crops[cropIndex], (cropIndex+1)*3)); System.out.println("种植成功!"); } private void waterField() { // 浇水逻辑(实现略) } private void harvestCrop() { // 收获逻辑(实现略) } private void showFields() { // 显示田地状态逻辑(实现略) } private void nextDay() { day++; currentWeather = weathers[RANDOM.nextInt(weathers.length)]; for (Field field : fields) { if (!field.crop.equals("空闲") && field.isWatered) { field.growthStage++; field.isWatered = false; } } handleRandomEvent(); } private void handleRandomEvent() { if (RANDOM.nextDouble() < 0.3) { String[] events = {"蝗虫来袭!", "大丰收!", "商人到访", "干旱持续"}; System.out.println("\n随机事件:" + events[RANDOM.nextInt(events.length)]); // 事件处理逻辑 } } public static void main(String[] args) { new FarmingGame().start(); } } ``` 游戏特性说明: 1. 5块田地管理系统,可种植不同作物 2. 动态天气系统影响作物生长 3. 随机事件系统增加游戏趣味性 4. 完整的经济系统(种植成本/收获收益) 5. 作物生长可视化 6. 每日进度推进机制 代码结构: - Field管理每块田地的状态 - 主游戏循环处理玩家输入 - nextDay()方法推进游戏时间并处理自动增长 - 随机事件系统增加游戏变数
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值