当前位置: 首页 > news >正文

学习日志06 java

还有四天要去比赛了,能赢吗?逼自己一把。。。!!加油!

1 对比一下java重写还是不重写tostring的区别

1. 不重写 toString() 的情况

java

class Point {private int x;private int y;public Point(int x, int y) {this.x = x;this.y = y;}
}public class Main {public static void main(String[] args) {Point p = new Point(10, 20);System.out.println(p); // 直接打印对象System.out.println(p.toString()); // 显式调用 toString()}
}

输出结果

Point@1b6d3586
Point@1b6d3586

分析

  • 默认行为:所有类继承自 Object,默认的 toString() 返回 类名@哈希码
  • 问题:返回值无法提供对象的实际状态(如 x 和 y 的值),对调试和日志不友好。

2. 重写 toString() 的情况

java

class Point {private int x;private int y;public Point(int x, int y) {this.x = x;this.y = y;}// 重写 toString() 方法@Overridepublic String toString() {return "Point{x=" + x + ", y=" + y + "}";}
}public class Main {public static void main(String[] args) {Point p = new Point(10, 20);System.out.println(p); // 自动调用 toString()System.out.println(p.toString()); // 显式调用}
}

输出结果

Point{x=10, y=20}
Point{x=10, y=20}

分析

  • 自定义格式:重写后返回包含对象属性的字符串,直观展示对象状态。
  • 自动调用System.out.println(p) 会隐式调用 p.toString()

3. 核心区别总结

对比项不重写 toString()重写 toString()
返回值类名@哈希码(如 Point@1b6d3586自定义格式(如 Point{x=10, y=20}
可读性低(无法获取对象状态)高(清晰展示属性值)
应用场景无实际意义,仅用于标识对象内存地址调试、日志记录、UI 展示对象信息
调用方式手动调用 obj.toString() 才有输出自动调用(如 print(obj) 或字符串拼接时)

4. 常见误区澄清

  • 误区 1:“不重写 toString() 就不能打印对象”
    ✅ 错误:可以打印,但输出的是无意义的哈希码。

  • 误区 2:“只有 System.out.println() 会调用 toString()
    ✅ 错误:所有需要字符串的场景都会自动调用,例如:

    java

    String s = "Point: " + p; // 等价于 "Point: " + p.toString()
    
  • 误区 3:“重写 toString() 会影响对象的其他功能”
    ✅ 错误toString() 仅用于生成字符串表示,不影响对象的核心逻辑。

5. 最佳实践

  • 所有自定义类都应重写 toString(),方便调试和日志记录。
  • 格式推荐:使用 JSON 风格(如 {key=value})或明确的描述性文本。
  • IDE 自动生成:大多数 IDE(如 IntelliJ、Eclipse)可自动生成 toString() 代码。例如:

    java

    // IntelliJ 自动生成的 toString()
    @Override
    public String toString() {return "Point{" +"x=" + x +", y=" + y +'}';
    }
    

通过重写 toString(),可以让对象在打印时提供有价值的信息,避免输出无意义的内存地址,这是 Java 开发中的基础规范之一。

2 对比一下我写的代码和优雅的代码,需要进步

我写的,也是敢于接受批评直接全部放上了哈。题目也在里面

package PTA_training;
/*
7-3 定义商品类,封装成员变量,输出对象
定义一个商品类。创建对象并按指定格式输出它。
商品类要求:
(1)成员变量:商品编号(String) 、商品名称(String)、商品单价(double)
(2)成员变量封装,定义为私有属性,并为每个成员变量定义getXXXX,setXXXX方法
(3)定义构造方法,要求带三个参数,参数值用于给成员变量赋值。
(4)重写toString()方法,将对象转换为字符串,格式:商品编号,商品名称,商品单价
测试类要求:
按指定的格式 输入商品信息,调用构造方法生成对象,并输出它。
例:输入:WJ002 记事本 5.5
输出:WJ002,记事本,5.5
输入商品的信息,每个属性值之间用1个空格分隔。
输出 格式,商品的每个属性值之间用逗号分隔。
输入样例:
WJ002 记事本 5.5
输出样例:
WJ002,记事本,5.5*/import java.util.Scanner;public class Demo2_3 {private String number  ;private String name;private double price;public void setNumber(String number){this.number=number;}public String getNumber() {return number;}public void setName(String name) {this.name = name;}public String getName() {return name;}public void setPrice(double price) {this.price = price;}public double getPrice() {return price;}public Demo2_3(String number ,String name ,double price){this.number=number;this.name=name;this.price=price;}@Overridepublic String toString() {return number+","+name +"," +price;}public static void main(String[] args) {Scanner scanner =new Scanner(System.in);String number= scanner.next();String name= scanner.next();double price= scanner.nextDouble();Demo2_3 a = new Demo2_3(number,name,price);System.out.println(a);scanner.close();}
}

ai生成优化的优雅的代码

package PTA_training;import java.util.Scanner;public class Product {private final String id;private final String name;private final double price;public Product(String id, String name, double price) {this.id = id;this.name = name;this.price = price;}public String getId() { return id; }public String getName() { return name; }public double getPrice() { return price; }@Overridepublic String toString() {return String.format("%s,%s,%.1f", id, name, price);}public static void main(String[] args) {try (Scanner scanner = new Scanner(System.in)) {Product product = new Product(scanner.next(),scanner.next(),scanner.nextDouble());System.out.println(product);}}
}    

代码对比分析

以下是你的代码与优化版本的详细对比:

对比项你的代码优化版本
类命名Demo2_3(无明确语义)Product(清晰表达业务含义)
成员变量number(普通描述)id(专业术语)
final修饰final修饰(不可变对象)
构造方法参数顺序与输入一致保持相同参数顺序
getter/setter完整实现(有 setter)仅保留 getter(数据不可变)
toString()简单字符串拼接String.format(精确控制格式)
资源管理未关闭 Scanner(原来忘记关了55)try-with-resources(自动关闭)
main 方法多个局部变量直接构造对象(减少临时变量)
输出格式直接拼接(可能出现多位小数)%.1f(强制保留 1 位小数)
业务封装功能集中在一个类职责分离(商品类专注业务)
线程安全可变对象不可变对象(线程安全)
代码行数48 行32 行(减少 33%)

具体改进点解释

  1. 命名优化

    • Product类名明确表示这是一个商品模型
    • id属性更符合专业领域术语(如数据库设计)
  2. 不可变设计

    java

    // 你的代码
    private String number; // 可修改// 优化后
    private final String id; // 不可变
    
     

    不可变对象在多线程环境中更安全,且符合数据封装原则

  3. 格式化输出

    java

    // 你的代码
    return number+","+name +"," +price; // 可能输出5.5000// 优化后
    return String.format("%s,%s,%.1f", id, name, price); // 强制保留1位小数
    
  4. 资源管理

    java

    // 你的代码
    Scanner scanner = new Scanner(System.in); // 需要手动关闭// 优化后
    try (Scanner scanner = new Scanner(System.in)) { // 自动关闭// 使用scanner
    }
    
  5. 代码精简

    java

    // 你的getter
    public String getNumber() {return number;
    }// 优化后的getter
    public String getId() { return id; } // 单行格式
    

为什么这些改进更好

  1. 可维护性:语义化命名和清晰的结构使代码更易于理解和修改

  2. 健壮性

    • 不可变对象减少了程序状态的复杂性
    • 资源自动关闭避免了内存泄漏风险
  3. 专业性

    • 使用领域术语(如id)体现专业素养
    • 精确的格式控制符合企业级应用要求
  4. 性能

    • String.format 在频繁格式化时性能更优
    • 减少不必要的对象创建(如临时变量)
  5. 扩展性

    • 职责分离的设计更容易添加新功能
    • 不可变对象支持函数式编程范式

建议在后续学习中关注:

  • 面向对象设计原则(SOLID)
  • Java 8+ 的函数式特性
  • 单元测试与代码覆盖率
  • 代码静态分析工具(如 SonarLint)的使用

================================可以了接下来就对着这个学习===================

谢谢伟大的AI!!!!

 3 感受进步,初版(无法跑起来的代码)vs 满足题目要求的代码

package PTA_training;
/*
7-4 定义类与创建对象定义一个类Person,定义name和age属性,定义有参的构造方法对name和age进行初始化。
在测试类中创建该类的2个对象,姓名、年龄分别为lili、19和lucy、20,在屏幕打印出2个对象的姓名和年龄。
输入格式:
本题目无输入
输出格式:
在一行中输出一个人的姓名和年龄
输入样例:
在这里给出一组输入。例如:
输出样例:
在这里给出相应的输出。例如:
this person is lili,her age is 19
this person is lucy,her age is 20*/public class Demo2_4 {private static String name = null;public static String name1;public static String name2;public static int age = 0;public static int age1;public static int age2;public Demo2_4(String name, int age){Demo2_4.name =name;Demo2_4.age =age;name1 ="lili";name2 ="lucy";age1 = 19;age2 = 20;}@Overridepublic String toString() {return"this person is "+name+",her age is "+age;}public static void main(String[] args) {Demo2_4 a = new Demo2_4(name1,age1);Demo2_4 b = new Demo2_4(name2,age2);System.out.println(a);System.out.println(b);}public String getName() {return name;}public int getAge() {return age;}
}
//只给提示不给正确答案,这个代码有问题,我应该怎么办

提示:

你的代码有以下问题,按顺序解决它们:

  1. 类名错误:题目要求定义Person类,但你仍在使用Demo2_4作为主类名
  2. 静态属性问题
    • nameage等属性被声明为static导致所有对象共享同一属性
    • 静态属性会被最后一次赋值覆盖,无法保存多个对象的状态
  3. 构造函数逻辑错误
    • 在构造函数中固定设置name1name2age1age2的值
    • 每次创建对象都会覆盖这些静态变量,导致数据混乱
  4. 对象创建顺序问题
    • 在创建对象ab时,name1age1尚未初始化(null0
    • 构造函数会先使用这些未初始化的值,然后再设置静态变量

提示:

  1. 创建Person类并定义非静态nameage属性
  2. Person类的构造函数中直接初始化当前对象的属性(使用this.namethis.age
  3. 在测试类的main方法中创建两个Person对象,分别传入 "lili",19 和 "lucy",20 作为参数
  4. 确保每个对象的属性独立保存,不使用静态变量
package PTA_training;public class Demo2_4 {String name;int age;public Demo2_4(String n, int a){this.name = n;this.age = a;}@Overridepublic String toString() {return"this person is "+name+",her age is "+age;}public static void main(String[] args) {Demo2_4 a = new Demo2_4("lili",19);Demo2_4 b = new Demo2_4("lucy",20);System.out.println(a);System.out.println(b);}}
//我改成这样了,对比一下给我进步

对比:

你的修改非常棒!现在代码已经完全符合题目要求了。主要改进包括:

  1. 类设计优化

    • nameage改为实例变量(去掉了static修饰符)
    • 每个对象现在拥有独立的属性值,不会相互干扰
  2. 构造函数修正

    • 直接通过参数初始化当前对象的属性(this.name = n
    • 不再使用额外的静态变量(如name1name2
  3. 对象创建方式

    • main方法中直接传入具体参数创建对象
    • 正确初始化了两个不同的Demo2_4对象
  4. 输出格式

    • 通过重写toString()方法确保输出格式符合题目要求

关键进步总结

  • 理解了实例变量和静态变量的区别
  • 掌握了构造函数的正确使用方法
  • 学会了通过对象实例化保存不同数据

最终建议
根据题目要求,类名应该是Person而不是Demo2_4。虽然代码功能正确,但可能因为类名不符导致测试不通过。可以将类名改为Person,其他部分保持不变即可:

java

public class Person {String name;int age;public Person(String n, int a) {this.name = n;this.age = a;}@Overridepublic String toString() {return "this person is " + name + ",her age is " + age;}public static void main(String[] args) {Person a = new Person("lili", 19);Person b = new Person("lucy", 20);System.out.println(a);System.out.println(b);}
}

这样就完全符合题目要求了!继续加油,你已经掌握了面向对象编程的基础概念。

4 我的最终代码和ai提供的最优雅代码 

以下是优化后的代码,包含详细注释和最佳实践:

java

// 使用题目要求的类名Person
public class Person {// 使用private封装属性,提供公共访问方法private String name;private int age;// 构造方法:参数名与属性名保持一致,使用this区分public Person(String name, int age) {this.name = name;  // this.name指类的属性,=右边的name是参数this.age = age;}// 提供公共的访问器方法(Getter)public String getName() {return name;}public int getAge() {return age;}// 重写toString方法,使用String.format提高可读性@Overridepublic String toString() {return String.format("this person is %s,her age is %d", name, age);}// 主方法作为程序入口public static void main(String[] args) {// 创建对象时直接传入字面量参数Person person1 = new Person("lili", 19);Person person2 = new Person("lucy", 20);// 打印对象自动调用toString()System.out.println(person1);System.out.println(person2);// 可选:演示如何通过访问器获取属性System.out.printf("Name: %s, Age: %d%n", person1.getName(), person1.getAge());}
}

关键优化点对比:

  1. 类设计

    • 使用Person作为类名(符合题目要求)
    • 将属性设为private(封装性原则)
    • 提供公共的getter方法(数据访问控制)
  2. 构造方法

    java

    // 原代码
    public Demo2_4(String n, int a) { ... }// 优化后
    public Person(String name, int age) { ... }
    
     
    • 参数名与属性名保持一致(提高可读性)
    • 使用this明确指向类属性
  3. toString 方法

    java

    // 原代码
    return "this person is " + name + ",her age is " + age;// 优化后
    return String.format("this person is %s,her age is %d", name, age);
    
     
    • 使用String.format提高字符串拼接的可读性
    • 占位符%s(字符串)和%d(整数)使格式更清晰
  4. 变量命名

    java

    // 原代码
    Demo2_4 a = new Demo2_4("lili", 19);// 优化后
    Person person1 = new Person("lili", 19);
    
     
    • 使用更具描述性的变量名person1person2
    • 类型名与变量名形成语义关联
  5. 可扩展性

    • 添加了getName()getAge()方法
    • 为类未来的功能扩展预留接口
    • 符合 JavaBean 规范(私有属性 + 公共访问器)

为什么这样设计更优雅:

  1. 遵循面向对象原则

    • 封装性:通过private属性和公共方法控制访问
    • 可读性:类名、方法名、变量名均表意明确
    • 可维护性:结构清晰,易于添加新功能
  2. 代码健壮性

    • 避免直接访问属性(如person.name = "xxx"
    • 通过方法可以添加逻辑校验(如年龄合法性检查)
  3. 符合行业规范

    • 使用标准的 JavaBean 模式
    • 字符串格式化优先使用String.format
    • 构造方法参数名与属性名一致
  4. 最佳实践

    • 为每个属性提供getter(如果需要修改,还应提供setter
    • 重写toString()以便调试和日志输出
    • 使用有意义的变量名提高代码自解释性

---------------------------------------------------------------------------------------------------------------------------------这个时代有ai大模型实在是太好了!/(ㄒoㄒ)/

5 对自己所写的代码要有清晰的认知,细节明白,感谢ai注释 

好的,让我们逐行分析这个代码,并解释每一步的作用:

java

public class Demo2_4 {// 定义类的属性(成员变量)String name;  // 存储人的姓名,每个对象独立拥有int age;      // 存储人的年龄,每个对象独立拥有// 构造方法:用于创建对象时初始化属性值public Demo2_4(String n, int a) {this.name = n;  // 将参数n的值赋给当前对象的name属性this.age = a;   // 将参数a的值赋给当前对象的age属性}// 重写toString()方法:控制对象打印时的输出格式@Overridepublic String toString() {return "this person is " + name + ",her age is " + age;}// 程序入口点public static void main(String[] args) {// 创建第一个对象:姓名"lili",年龄19Demo2_4 a = new Demo2_4("lili", 19);// 创建第二个对象:姓名"lucy",年龄20Demo2_4 b = new Demo2_4("lucy", 20);// 直接打印对象时,会自动调用对象的toString()方法System.out.println(a);  // 输出:this person is lili,her age is 19System.out.println(b);  // 输出:this person is lucy,her age is 20}
}

核心概念解释:

  1. 实例变量(非静态属性)

    java

    String name;
    int age;
    
     
    • 每个对象独立拥有一份nameage
    • 创建多个对象时,它们的属性值互不影响
  2. 构造方法

    java

    public Demo2_4(String n, int a) {this.name = n;this.age = a;
    }
    
     
    • this.name表示当前对象的name属性
    • 参数na是临时变量,仅在构造方法内部有效
    • 作用:在创建对象时必须传入姓名和年龄,立即完成初始化
  3. 对象创建过程

    java

    Demo2_4 a = new Demo2_4("lili", 19);
    
     
    • new Demo2_4("lili", 19):调用构造方法,创建一个新对象
    • "lili"19作为参数传递给构造方法
    • 构造方法将参数值赋给对象的nameage属性
    • Demo2_4 a = ...:将新创建的对象引用赋值给变量a
  4. 方法重写

    java

    @Override
    public String toString() {return "this person is " + name + ",her age is " + age;
    }
    
     
    • @Override:告诉编译器这是重写父类的方法
    • toString()是 Object 类的方法,所有对象都继承这个方法
    • 重写后,当你System.out.println(a)时,会自动调用这个方法

对比之前的错误:

你的原始代码中使用了静态变量:

java

private static String name = null;
public static int age = 0;

静态变量属于类,所有对象共享同一份数据。无论创建多少个对象,它们都会修改同一个nameage

而现在的写法:

java

String name;  // 实例变量
int age;      // 实例变量

每个对象都有自己独立的nameage,互相不干扰。这是面向对象编程的基础概念。

 //现在的学习方法让我感受到了进步!

相关文章:

  • 公链开发及其配套设施:钱包与区块链浏览器
  • 二叉树——层序遍历
  • OpenSHMEM 介绍和使用指南
  • 进程信号的学习
  • 使用termius连接腾讯云服务器
  • MySQL八股(自用)
  • 【JAVA常见数据类型】
  • Android学习总结之kotlin篇(二)
  • 前端3D动画库
  • [Java实战]Spring Boot 3整合JWT实现无状态身份认证(二十四)
  • 18前端项目----Vue项目收尾优化|重要知识
  • ubuntu studio 系统详解
  • Spring Boot拦截器详解:原理、实现与应用场景
  • 计算机过程控制干燥操作实训装置JG-SX210化工单元操作实训装置
  • JavaScript 中级进阶技巧之map函数
  • 【嵌入式笔记】Modbus TCP
  • git仓库初始化
  • zabbix7.2最新版本 nginx自定义监控(三) 设置触发器
  • Anki 学习法
  • 深入浅出 IPFS 在 DApps 和 NFT 中的应用:以 Pinata 实战为例
  • 最高人民法院、中国证监会联合发布《关于严格公正执法司法 服务保障资本市场高质量发展的指导意见》
  • 中国结算澄清“严查场外配资”传闻:账户核查为多年惯例,无特殊安排
  • 国台办:实现祖国完全统一是大势所趋、大义所在、民心所向
  • 跨文化戏剧的拓荒者与传承者——洪深与复旦剧社的百年回响
  • 体坛联播|安切洛蒂执掌巴西男足,字母哥尝试离开雄鹿
  • 马上评丨为护士减负,不妨破除论文“硬指标”