Java笔记014 您所在的位置:网站首页 java实现debug断点 Java笔记014

Java笔记014

2024-07-09 18:57| 来源: 网络整理| 查看: 265

目录

Object类详解

equals方法

== 和 equals 的对比

如何重写equals方法

练习题

hashCode方法

小结:

toString方法

基本介绍

重写toString方法

finalize方法

断点调试(debug)

一个实际需求

断点调试介绍

断点调试的快捷键

断点调试应用案例

案例1:看变量的变化情况

案例2:看一下数组越界的异常

案例3:演示如何追源码,看看java设计者是怎么实现的。(提高编程思想)

案例4:演示如何直接执行到下一个断点F9 resume

 断点调试练习

1、使用断点调试的方法,追踪下一个对象创建的过程。

2、我们使用断点调试,查看动态绑定机制的如何工作

项目-零钱通

项目开发流程说明

项目需求说明

项目的界面

项目代码实现

项目代码实现改进

Object类详解 equals方法

== 和 equals 的对比

1、==:既可以判断基本类型,又可以判断引用类型

2、==:如果判断基本类型,判断的是值是否相等。示例:int i=10; double d=10.0;

3、==:如果判断引用类型,判断的是地址是否相等,即判定是不是同一个对象【案例说明】

4、equals:是Object类中的方法,只能判断引用类型,如何看Jdk源码,看演示

5、默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等。 比如:Integer,String【看String 和 Integer 的 equals 源代码】

package com.object; public class Equals { public static void main(String[] args) { A a = new A(); A b = a; A c = b; System.out.println(a == c);//true System.out.println(b == c);//true B bObj = a; System.out.println(bObj == c);//true int num1 = 10; double num2 = 10.0; System.out.println(num1 == num2);//基本数据类型,判断值是否相等 //equals方法,源码怎么查看 //把光标放在equals方法,直接输入ctrl+b // 看Jdk的源码 Object类的 equals方法 // public boolean equals(Object anObject) { // if (this == anObject) {//如果是同一个对象 // return true;//返回true // } // if (anObject instanceof String) {//判断类型 // String anotherString = (String)anObject;//向下转型 // int n = value.length; // if (n == anotherString.value.length) {//如果长度相同 // char v1[] = value; // char v2[] = anotherString.value; // int i = 0; // while (n-- != 0) {//然后一个一个的比较字符 // if (v1[i] != v2[i]) // return false; // i++; // } // return true;//如果两个字符串的所有字符都相等,则返回true // } // } // return false;//如果比较的不是字符串,则直接返回false // } "hello".equals("abc"); //看Object类的 equals //即Object 的equals 方法默认就是比较对象地址是否相同 //也就是判断两个对象是不是同一个对象 // public boolean equals(Object obj) { // return (this == obj); // } //从源码可以看到 Integer 也重写了Object类的equals方法 //变成了判断两个值是否相同 // public boolean equals(Object obj) { // if (obj instanceof Integer) { // return value == ((Integer)obj).intValue(); // } // return false; // } Integer integer1 = new Integer(1000); Integer integer2 = new Integer(1000); System.out.println(integer1 == integer2);//false System.out.println(integer1.equals(integer2));//true String str1 = new String("甲柒"); String str2 = new String("甲柒"); System.out.println(str1 == str2);//false System.out.println(str1.equals(str2));//true } } class B { } class A extends B { } 如何重写equals方法

应用实例: 判断两个Person对象的内容是否相等,如果两个Person对象的各个属性值都一样,则返回true,反之false。

package com.object; public class EqualsExercise { public static void main(String[] args) { Person person1 = new Person("jack", 10, '男'); Person person2 = new Person("jack", 10, '男'); Person person3 = new Person("tom", 20, '男'); Person person4 = new Person("tom", 29, '男'); System.out.println(person1.equals(person2));//true System.out.println(person3.equals(person4));//false } } //判断两个Person对象的内容是否相等, //如果两个Person对象的各个属性值都一样,则返回true,反之false。 class Person { private String name; private int age; private char gender; //重写Object 的 equals方法 public Person(String name, int age, char gender) { this.name = name; this.age = age; this.gender = gender; } @Override public boolean equals(Object obj) { //判断如果比较的两个对象是同一个对象,则直接返回true if (this == obj) { return true; } //类型判断 if (obj instanceof Person) {//是Person,才比较 //进行 向下转型,因为需要得到obj的 各个属性 Person p = (Person) obj; return this.name.equals(p.name) && this.age == p.age && this.gender == gender; } //如果不是Person,则直接返回false return false; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public char getGender() { return gender; } public void setGender(char gender) { this.gender = gender; } } 练习题

1、

package com.object; public class EqualsExercise { public static void main(String[] args) { Person p1 = new Person(); p1.name = "甲柒"; Person p2 = new Person(); p2.name = "甲柒"; System.out.println(p1 == p2);//false System.out.println(p1.name.equals(p2.name));//true System.out.println(p1.equals(p2));//false String s1 = new String("abc"); String s2 = new String("abc"); System.out.println(s1.equals(s2));//true System.out.println(s1 == s2);//false } } class Person { public String name; }

运行结果

2、

package com.object; public class EqualsExercise { public static void main(String[] args) { int it = 65; float fl = 65.0f; System.out.println("65和65.0f是否相等?" + (it == fl));//true char ch1 = 'A'; char ch2 = 12; System.out.println("65和'A'是否相等?" + (it == ch1));//true System.out.println("12和ch2是否相等?" + (12 == ch2));//true String str1 = new String("hello"); String str2 = new String("hello"); System.out.println("str1和str2是否相等?" + (str1 == str2));//false System.out.println("str1是否equals str2?" + (str1.equals(str2)));//true // System.out.println("hello" == new java.sql.Date());//编译错误 } }

运行结果

hashCode方法

小结:

1、提高具有哈希结构的容器的效率!

2、两个引用,如果指向的是同一个对象,则哈希值肯定是一样的!

3、两个引用,如果指向的是不同对象,则哈希值是不一样的

4、哈希值主要根据地址号来的!,不能完全将哈希值等价于地址。

5、案例演示 [测试:A obj1 = new A();A obj2 = new AO);Aobj3 = obj1]

6、后面在集合,中hashCode如果需要的话,也会重写

package com.object; public class HashCode { public static void main(String[] args) { AA aa1 = new AA(); AA aa2 = new AA(); AA aa3 = aa1; System.out.println("aa1.hashCode()=" + aa1.hashCode()); System.out.println("aa2.hashCode()=" + aa2.hashCode()); System.out.println("aa3.hashCode()=" + aa3.hashCode()); } } class AA { }

运行结果

toString方法 基本介绍

默认返回:全类名+@+哈希值的十六进制,【查看Object 的toString方法】 子类往往重写toString方法,用于返回对象的属性信息

重写toString方法

打印对象或拼接对象时,都会自动调用该对象的toString形式 案例演示:Monster [name, job, sal] 案例:ToString.java

当直接输出一个对象时,toString方法会被默认的调用 比如:System.out.println(monster);就会默认调用monster.toString(0)

package com.object; public class ToString { public static void main(String[] args) { //Object的toString() 源码 //(1)getClass().getName()类的全类名(包名+类名) //(2)Integer.toHexString(hashCode())将对象的hashCode值转成16进制字符串 // public String toString() { // return getClass().getName() + "@" + Integer.toHexString(hashCode()); // } Monster monster = new Monster("小妖怪", "巡山的", 1000); System.out.println(monster.toString() + " hashcode=" + monster.hashCode()); System.out.println("==当直接输出一个对象时,toString方法会被默认的调用=="); System.out.println(monster);//等价monster.toString() } } class Monster { private String name; private String job; private double sal; public Monster(String name, String job, double sal) { this.name = name; this.job = job; this.sal = sal; } //重写toString方法,输出对象的属性 //使用快捷键即可alt+insert -> toString @Override public String toString() {//重写后,一般是把对象的属性值输出,当然程序员也可以自己定制 return "Monster{" + "name='" + name + '\'' + ", job='" + job + '\'' + ", sal=" + sal + '}'; } }

运行结果

finalize方法

1、当对象被回收时,系统自动调用该对象的finalize方法。子类可以重写该方法,做一些释放资源的操作【演示】

2、什么时候被回收:当某个对象没有任何引用时,则jvm就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用finalize方法。

3、垃圾回收机制的调用,是由系统来决定(即有自己的GC算法),也可以通过System.gc() 主动触发垃圾回收机制,测试:Car [name]

提示:在实际开发中,几乎不会运用finalize,所以更多就是为了应付面试

package com.object; //演示Finalize public class Finalize { public static void main(String[] args) { Car car = new Car("兰博基尼"); car = null; //这时 car对象就是一个垃圾,垃圾回收器就会回收(销毁)对象, //在销毁对象前,会调用该对象的finalize方法 //,程序员就可以在finalize中,写自己的业务逻辑代码(比如释放资源:数据库连接,或者打开文件...) //,如果程序员不重写 finalize,那么就会调用0bject类的 finalize,即默认处理 //,如果程序员重写了finalize,就可以实现自己的逻辑 System.gc();//主动调用垃圾回收器 System.out.println("程序退出了..."); } } class Car { private String name; public Car(String name) { this.name = name; } //重写finalize @Override protected void finalize() throws Throwable { System.out.println("销毁 汽车" + name); System.out.println("释放了某些资源"); } }

运行结果

断点调试(debug) 一个实际需求

1、在开发中:新手程序员在查找错误时,这时老程序员就会温馨提示,可以用断点调试, 一步一步的看源码执行的过程,从而发现错误所在。

2、重要提示:在断点调试过程中,是运行状态,是以对象的运行类型来执行的 A extends B; Bb = new A0); b.xx();

断点调试介绍

1、断点调试是指在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后你可以一步一步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下。进行分析从而找到这个Bug

2、断点调试是程序员必须掌握的技能。

3、断点调试也能帮助我们查看java底层源代码的执行过程,提高程序员的Java水平。

断点调试的快捷键

F7:(跳入)

F8:(跳过)

shift+F8:(跳出)

F9:(resume,执行到下一个断点)

F7:跳入方法内

F8:逐行执行代码

shift+F8:跳出方

断点调试应用案例 案例1:看变量的变化情况 package com.debug; public class Debug { public static void main(String[] args) { //演示逐行执行代码 int sum = 0; for (int i = 0; i < 5; i++) { sum += i; System.out.println("i=" + i); System.out.println("sum=" + sum); } System.out.println("退出for..."); } }

 

案例2:看一下数组越界的异常 package com.debug; public class Debug { public static void main(String[] args) { int[] arr = {1, 10, -1}; for (int i = 0; i Debug Arrays.sort(arr); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } } }

 

 

案例4:演示如何直接执行到下一个断点F9 resume

小技巧:断点可以在debug过程中,动态的下断点

package com.debug; import java.util.Arrays; //演示执行到下一个断点,同时支持动态的下断点. public class Debug { public static void main(String[] args) { int[] arr = {1, -1, 10, -20, 100}; //看Arrays.sort方法底层实现 ->Debug Arrays.sort(arr); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } System.out.println("hello world~~~100"); System.out.println("hello world~~~200"); System.out.println("hello world~~~300"); System.out.println("hello world~~~400"); System.out.println("hello world~~~500"); System.out.println("hello world~~~600"); System.out.println("hello world~~~700"); System.out.println("hello world~~~800"); } }

 断点调试练习 1、使用断点调试的方法,追踪下一个对象创建的过程。

Person [name, age, 构造器..]

package com.debug; //debug对象创建的过程,加深对调试的理解 public class DebugExercise { public static void main(String[] args) { Person jack = new Person("jack", 20); System.out.println(jack); } } class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }

2、我们使用断点调试,查看动态绑定机制的如何工作 package com.dynamic; public class DynamicBinding { public static void main(String[] args) { //a 的编译类型 A,运行类型 B A a = new B();//向上转型 System.out.println(a.sum());//40 -> 30 System.out.println(a.sum1());//30 -> 20 } } class A {//父类 public int i = 10; //动态绑定机制: public int sum() {//父类sum() return getI() + 10;//20 + 10 } public int sum1() {//父类sum1() return i + 10;//10 + 10 } public int getI() {//父类getI() return i; } } class B extends A {//子类 public int i = 20; // public int sum() { // return i + 20; // } public int getI() {//子类getI() return i; } // public int sum1() { // return i + 10; // } }

项目-零钱通 项目开发流程说明 项目需求说明

使用Java开发零钱通项目,可以完成收益入账,消费,查看明细,退出系统等功能.

项目的界面

化繁为简 1、先完成显示菜单,并可以选择 2、完成零钱通明细 3、完成收益入账 4、消费 5、退出  

项目代码实现

编写文件 SmallChangeSys.java 完成基本功能(过程编程)

提示:先使用过程编程,后面改成OOP版本,体会OOP编程带来的好处

package com.smallchange; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; public class SmallChangeSys { //化繁为简 //1.先完成显示菜单,并可以选择菜单,给出对应提示 //2.完成零钱通明细 //3.完成收益入账 //4.消费 //5.退出 public static void main(String[] args) { //定义相关变量 boolean loop = true; Scanner scanner = new Scanner(System.in); String key = ""; //2.完成零钱通明细 //思路 //(1)可以把收益入账和消费,保存到数组 //(2)可以使用对象 //(3)简单的话可以使用String拼接 String details = "=============零钱通明细============="; //3.完成收益入账 完成功能驱动程序员增加新的变化和代码 //思路,定义新的变量 double money = 0; double balance = 0; Date date = null;// date是java.util.Date 类型,表示日期 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//可以用于日期格式化 //4.消费 //定义新变量,保存消费原因 String note = ""; do { System.out.println(); System.out.println("=============零钱通菜单============="); System.out.println("\t\t\t1 零钱通明细"); System.out.println("\t\t\t2 收益入账"); System.out.println("\t\t\t3 消费"); System.out.println("\t\t\t4 退 出"); System.out.println("请选择(1-4):"); key = scanner.next(); //使用switch分支结构 switch (key) { case "1": System.out.print(details); break; case "2": System.out.print("收益入账金额:"); money = scanner.nextDouble(); //money 的值范围应该校验 balance += money; //拼接收益入账信息到 details date = new Date();//获取当前时间 // System.out.println(sdf.format(date)); details += "\n收益入账\t+" + money + "\t" + sdf.format(date) + "\t余额:" + balance; break; case "3": System.out.print("消费金额:"); money = scanner.nextDouble(); //money 的值范围应该校验 System.out.print("消费说明:"); note = scanner.next(); balance -= money; //拼接消费信息信息到 details date = new Date();//获取当前时间 // System.out.println(sdf.format(date)); details += "\n" + note + "\t-" + money + "\t" + sdf.format(date) + "\t余额:" + balance; break; case "4": System.out.println("4 退 出"); loop = false; break; default: System.out.println("选择有误,请重新选择"); } } while (loop); System.out.println("============退出零钱通项目============"); } }

运行结果

项目代码实现改进

1、用户输入4退出时,给出提示"你确定要退出吗? y/n",必须输入正确的y/n,否则 循环输入指令,直到输入y或者n。

2、在收益入账和消费时,判断金额是否合理,并给出相应的提示。

package com.smallchange; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; public class SmallChangeSys { //化繁为简 //1.先完成显示菜单,并可以选择菜单,给出对应提示 //2.完成零钱通明细 //3.完成收益入账 //4.消费 //5.退出 //6.用户输入4退出时,给出提示"你确定要退出吗? y/n",必须输入正确的y/n,否则 //循环输入指令,直到输入y或者n。 //7.在收益入账和消费时,判断金额是否合理,并给出相应的提示。 public static void main(String[] args) { //定义相关变量 boolean loop = true; Scanner scanner = new Scanner(System.in); String key = ""; //2.完成零钱通明细 //思路 //(1)可以把收益入账和消费,保存到数组 //(2)可以使用对象 //(3)简单的话可以使用String拼接 String details = "=============零钱通明细============="; //3.完成收益入账 完成功能驱动程序员增加新的变化和代码 //思路,定义新的变量 double money = 0; double balance = 0; Date date = null;// date是java.util.Date 类型,表示日期 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//可以用于日期格式化 //4.消费 //定义新变量,保存消费原因 String note = ""; do { System.out.println(); System.out.println("=============零钱通菜单============="); System.out.println("\t\t\t1 零钱通明细"); System.out.println("\t\t\t2 收益入账"); System.out.println("\t\t\t3 消费"); System.out.println("\t\t\t4 退 出"); System.out.println("请选择(1-4):"); key = scanner.next(); //使用switch分支结构 switch (key) { case "1": System.out.print(details); break; case "2": System.out.print("收益入账金额:"); money = scanner.nextDouble(); //money 的值范围应该校验 //思路 //找出不正确的金额条件,然后给出提示,就直接break if (money


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有