写在前面
Hello大家好, 我是【麟-小白】,一位软件工程专业的学生,喜好计算机知识。希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误或不足之处,请多多指正!谢谢大家!!!
如果小哥哥小姐姐们对我的文章感兴趣,请不要吝啬你们的小手,多多点赞加关注呀!❤❤❤ 爱你们!!!
目录
【往期回顾】
一文带你深入理解【Java基础】· 面向对象编程(中)②子类对象实例化和多态
一文带你深入理解【Java基础】· 面向对象编程(中)①继承、方法的重写、权限修饰符和super
一文带你深入理解【Java基础】· 面向对象编程(上)②重载、封装、构造器、this、package和import
一文带你深入理解【Java基础】· 面向对象编程(上)①面向对象的理解、类和对象、对象的创建使用和属性
【习题总结】
1. Object类的使用
1.1 Object类的介绍
Object 类是所有 Java 类的根父类
- 如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类
public class Person {...}等价于:public class Person extends Object {...}//例: method(Object obj){…} //可以接收任何类作为其参数 Person o = new Person(); method(o);
1.2 Object类中的主要结构
……
1.3 ==操作符和equals方法
= = :
- 基本类型比较值:只要两个变量的值相等,即为true。
int a=5; if(a==6){…}
- 引用类型比较引用(是否指向同一个对象):只有指向同一个对象时,==才返回true。
Person p1=new Person();Person p2=new Person();if (p1==p2){…}
- 用“==”进行比较时,符号两边的数据类型必须兼容(可自动转换的基本数据类型除外),否则编译出错
equals():
- 所有类都继承了Object,也就获得了equals()方法。还可以重写。
- 只能比较引用类型,其作用与“==”相同,比较是否指向同一个对象。
- 格式:obj1.equals(obj2)
- 特例:当用equals()方法进行比较时,对类File、String、Date及包装类(Wrapper Class)来说,是比较类型及内容而不考虑引用的是否是同一个对象;
- 原因:在这些类中重写了Object类的equals()方法。
- 当自定义使用equals()时,可以重写。用于比较两个对象的“内容”是否都相等
重写equals()方法的原则:
- 对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。
- 自反性:x.equals(x)必须返回是“true”。
- 传递性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。
- 一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。
- 任何情况下,x.equals(null),永远返回是“false”;x.equals(和x不同类型的对象)永远返回是“false”
1.4 ==和equals的区别
- == 既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型就是比较内存地址
- equals的话,它是属于java.lang.Object类里面的方法,如果该方法没有被重写过默认也是==;我们可以看到String等类的equals方法是被重写过的,而且String类在日常开发中用的比较多,久而久之,形成了equals是比较值的错误观点。
- 具体要看自定义类里有没有重写Object的equals方法来判断。
- 通常情况下,重写equals方法,会比较类中的相应属性是否都相等。
1.5 Object类代码演示
/* * java.lang.Object类 * 1.Object类是所有Java类的根父类 * 2.如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类 * 3.Object类中的功能(属性、方法)就具有通用性。 * 属性:无 * 方法:equals() / toString() / getClass() /hashCode() / clone() / finalize() * wait() 、 notify()、notifyAll() * * 4. Object类只声明了一个空参的构造器 * */ public class ObjectTest { public static void main(String[] args) { Order order = new Order(); System.out.println(order.getClass().getSuperclass()); // class java.lang.Object } }
Object类的clone()的使用:
//Object类的clone()的使用 public class CloneTest { public static void main(String[] args) { Animal a1 = new Animal("花花"); try { Animal a2 = (Animal) a1.clone(); System.out.println("原始对象:" + a1);// 原始对象:Animal [name=花花] a2.setName("毛毛"); System.out.println("clone之后的对象:" + a2);// clone之后的对象:Animal [name=毛毛] } catch (CloneNotSupportedException e) { e.printStackTrace(); } } } class Animal implements Cloneable { private String name; public Animal() { super(); } public Animal(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Animal [name=" + name + "]"; } @Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return super.clone(); } }
Object类的finalize方法的使用:
/* 垃圾回收机制关键点 垃圾回收机制只回收JVM堆内存里的对象空间。 对其他物理连接,比如数据库连接、输入流输出流、Socket连接无能为力 现在的JVM有多种垃圾回收实现算法,表现各异。 垃圾回收发生具有不可预知性,程序无法精确控制垃圾回收机制执行。 可以将对象的引用变量设置为null,暗示垃圾回收机制可以回收该对象。 程序员可以通过System.gc()或者Runtime.getRuntime().gc()来通知系统进行垃圾回收,会有 一些效果,但是系统是否进行垃圾回收依然不确定。 垃圾回收机制回收任何对象之前,总会先调用它的finalize方法(如果覆盖该方法,让一 个新的引用变量重新引用该对象,则会重新激活对象)。 永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用。 */ public class FinalizeTest { public static void main(String[] args) { Person p = new Person("Peter", 12); System.out.println(p); p = null;// 此时对象实体就是垃圾对象,等待被回收。但时间不确定。 System.gc();// 强制性释放空间 } } class Person { private String name; private int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } 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; } // 子类重写此方法,可在释放对象前进行某些操作 @Override protected void finalize() throws Throwable { System.out.println("对象被释放--->" + this); } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }
equals方法的使用:
import java.util.Date; /* * 面试题: == 和 equals() 区别 * * 一、回顾 == 的使用: * == :运算符 * 1. 可以使用在基本数据类型变量和引用数据类型变量中 * 2. 如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。(不一定类型要相同) * 如果比较的是引用数据类型变量:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体 * 补充: == 符号使用时,必须保证符号左右两边的变量类型一致。 * * 二、equals()方法的使用: * 1. 是一个方法,而非运算符 * 2. 只能适用于引用数据类型 * 3. Object类中equals()的定义: * public boolean equals(Object obj) { return (this == obj); } * 说明:Object类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体 * * 4. 像String、Date、File、包装类等都重写了Object类中的equals()方法。重写以后,比较的不是 * 两个引用的地址是否相同,而是比较两个对象的"实体内容"是否相同。 * * 5. 通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同。那么,我们 * 就需要对Object类中的equals()进行重写. * 重写的原则:比较两个对象的实体内容是否相同. */ public class EqualsTest { public static void main(String[] args) { // 基本数据类型 int i = 10; int j = 10; double d = 10.0; System.out.println(i == j);// true System.out.println(i == d);// true boolean b = true; // System.out.println(i == b); char c = 10; System.out.println(i == c);// true char c1 = 'A'; char c2 = 65; System.out.println(c1 == c2);// true // 引用类型: Customer cust1 = new Customer("Tom", 21); Customer cust2 = new Customer("Tom", 21); System.out.println(cust1 == cust2);// false String str1 = new String("atguigu"); String str2 = new String("atguigu"); System.out.println(str1 == str2);// false System.out.println("****************************"); System.out.println(cust1.equals(cust2));// false--->true System.out.println(str1.equals(str2));// true Date date1 = new Date(32432525324L); Date date2 = new Date(32432525324L); System.out.println(date1.equals(date2));// true } } public class Customer { private String name; private int age; 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 Customer() { super(); } public Customer(String name, int age) { super(); this.name = name; this.age = age; } //自动生成的equals() @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Customer other = (Customer) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } //重写的原则:比较两个对象的实体内容(即:name和age)是否相同 //手动实现equals()的重写 // @Override // public boolean equals(Object obj) { // System.out.println("Customer equals()...."); // if (this == obj) { // return true; // } // // if(obj instanceof Customer){ // Customer cust = (Customer)obj; // //比较两个对象的每个属性是否都相同 if(this.age == cust.age && this.name.equals(cust.name)){ return true; }else{ return false; } // // //或 // return this.age == cust.age && this.name.equals(cust.name); // }else{ // return false; // // } // // } //手动实现 // @Override // public String toString() { // return "Customer[name = " + name + ",age = " + age + "]"; // } //自动实现 @Override public String toString() { return "Customer [name=" + name + ", age=" + age + "]"; } }
1.6 toString()方法
- toString()方法在Object类中定义,其返回值是String类型,返回类名和它的引用地址。
- 在进行String与其它类型数据的连接操作时,自动调用toString()方法
- Date now=new Date();
- System.out.println(“now=”+now); 相当于
- System.out.println(“now=”+now.toString());
- 可以根据需要在用户自定义类型中重写toString()方法
- 如String 类重写了toString()方法,返回字符串的值。
- s1=“hello”;
- System.out.println(s1);//相当于System.out.println(s1.toString());
- 基本类型数据转换为String类型时,调用了对应包装类的toString()方法
- int a=10; System.out.println(“a=”+a);
/* * Object类中toString()的使用: * * 1. 当我们输出一个对象的引用时,实际上就是调用当前对象的toString() * * 2. Object类中toString()的定义: * public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } * * 3. 像String、Date、File、包装类等都重写了Object类中的toString()方法。 * 使得在调用对象的toString()时,返回"实体内容"信息 * * 4. 自定义类也可以重写toString()方法,当调用此方法时,返回对象的"实体内容" */ public class ToStringTest { public static void main(String[] args) { Customer cust1 = new Customer("Tom", 21); System.out.println(cust1.toString()); // com.atguigu.java1.Customer@15db9742-->Customer[name=Tom, age=21] System.out.println(cust1); // com.atguigu.java1.Customer@15db9742-->Customer[name=Tom, age=21] String str = new String("MM"); System.out.println(str);// MM Date date = new Date(4534534534543L); System.out.println(date.toString());// Mon Sep 11 08:55:34 GMT+08:00 2113 } } public class Customer { private String name; private int age; 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 Customer() { super(); } public Customer(String name, int age) { super(); this.name = name; this.age = age; } //自动生成的equals() @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Customer other = (Customer) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } //重写的原则:比较两个对象的实体内容(即:name和age)是否相同 //手动实现equals()的重写 // @Override // public boolean equals(Object obj) { // System.out.println("Customer equals()...."); // if (this == obj) { // return true; // } // // if(obj instanceof Customer){ // Customer cust = (Customer)obj; // //比较两个对象的每个属性是否都相同 if(this.age == cust.age && this.name.equals(cust.name)){ return true; }else{ return false; } // // //或 // return this.age == cust.age && this.name.equals(cust.name); // }else{ // return false; // // } // // } //手动实现 // @Override // public String toString() { // return "Customer[name = " + name + ",age = " + age + "]"; // } //自动实现 @Override public String toString() { return "Customer [name=" + name + ", age=" + age + "]"; } }
1.7 Java中的JUnit单元测试
步骤:
1.选中当前工程 - 右键选择:build path - add libraries - JUnit 4 - 下一步
2.创建Java类,进行单元测试。
此时的Java类要求:① 此类是public的 ②此类提供公共的无参的构造器
3.此类中声明单元测试方法。
此时的单元测试方法:方法的权限是public,没有返回值,没有形参
4.此单元测试方法上需要声明注解:@Test,并在单元测试类中导入:import org.junit.Test;
5.声明好单元测试方法以后,就可以在方法体内测试相关的代码。
6.写完代码以后,左键双击单元测试方法名,右键:run as - JUnit Test
说明:
1.如果执行结果没有任何异常:绿条
2.如果执行结果出现异常:红条/* * Java中的JUnit单元测试 * * 步骤: * 1.选中当前工程 - 右键选择:build path - add libraries - JUnit 4 - 下一步 * 2.创建Java类,进行单元测试。 * 此时的Java类要求:① 此类是public的 ②此类提供公共的无参的构造器 * 3.此类中声明单元测试方法。 * 此时的单元测试方法:方法的权限是public,没有返回值,没有形参 * * 4.此单元测试方法上需要声明注解:@Test,并在单元测试类中导入:import org.junit.Test; * * 5.声明好单元测试方法以后,就可以在方法体内测试相关的代码。 * 6.写完代码以后,左键双击单元测试方法名,右键:run as - JUnit Test * * 说明: * 1.如果执行结果没有任何异常:绿条 * 2.如果执行结果出现异常:红条 */ public class JUnitTest { int num = 10; @Test public void testEquals() { String s1 = "MM"; String s2 = "MM"; System.out.println(s1.equals(s2)); // ClassCastException的异常 // Object obj = new String("GG"); // Date date = (Date)obj; System.out.println(num); show(); } public void show() { num = 20; System.out.println("show()...."); } @Test public void testToString() { String s2 = "MM"; System.out.println(s2.toString()); } }
2. 包装类的使用
2.1 什么是包装类
- 针对八种基本数据类型定义相应的引用类型—包装类(封装类)
- 有了类的特点,就可以调用类中的方法,Java才是真正的面向对象
基本数据类型包装成包装类的实例 --- 装箱
- 通过包装类的构造器实现:
- int i = 500; Integer t = new Integer(i);
- 还可以通过字符串参数构造包装类对象:
- Float f = new Float(“4.56”);
- Long l = new Long(“asdf”); //NumberFormatException
获得包装类对象中包装的基本类型变量 --- 拆箱
- 调用包装类的.xxxValue()方法:
- boolean b = bObj.booleanValue();
- JDK1.5之后,支持自动装箱,自动拆箱。但类型必须匹配。
字符串转换成基本数据类型
- 通过包装类的构造器实现:
- int i = new Integer(“12”);
- 通过包装类的parseXxx(String s)静态方法:
- Float f = Float.parseFloat(“12.1”);
基本数据类型转换成字符串
- 调用字符串重载的valueOf()方法:
- String fstr = String.valueOf(2.34f);
- 更直接的方式:
- String intStr = 5 + “”
基本类型、包装类与 String 类间的转换:
2.2 包装类用法举例
int i = 500; Integer t = new Integer(i); //装箱:包装类使得一个基本数据类型的数据变成了类。 //有了类的特点,可以调用类中的方法。 String s = t.toString(); // s = “500“,t是类,有toString方法 String s1 = Integer.toString(314); // s1= “314“ 将数字转换成字符串。 String s2=“4.56”; double ds=Double.parseDouble(s2); //将字符串转换成数字
拆箱:将数字包装类中内容变为基本数据类型。
int j = t.intValue(); // j = 500,intValue取出包装类中的数据
包装类在实际开发中用的最多的在于字符串变为基本数据类型。
String str1 = "30" ; String str2 = "30.3" ; int x = Integer.parseInt(str1) ; // 将字符串变为int型 float f = Float.parseFloat(str2) ; // 将字符串变为int型
2.3 包装类代码演示
/* * 包装类的使用: * 1.java提供了8种基本数据类型对应的包装类,使得基本数据类型的变量具有类的特征 * * 2.掌握的:基本数据类型、包装类、String三者之间的相互转换 * */ public class WrapperTest { // String类型 --->基本数据类型、包装类:调用包装类的parseXxx(String s) @Test public void test5() { String str1 = "123"; // 错误的情况: // int num1 = (int)str1; // Integer in1 = (Integer)str1; // 可能会报NumberFormatException int num2 = Integer.parseInt(str1); System.out.println(num2 + 1); String str2 = "true1"; boolean b1 = Boolean.parseBoolean(str2); System.out.println(b1); } // 基本数据类型、包装类--->String类型:调用String重载的valueOf(Xxx xxx) @Test public void test4() { int num1 = 10; // 方式1:连接运算 String str1 = num1 + ""; // 方式2:调用String的valueOf(Xxx xxx) float f1 = 12.3f; String str2 = String.valueOf(f1);// "12.3" Double d1 = new Double(12.4); String str3 = String.valueOf(d1); System.out.println(str2); System.out.println(str3);// "12.4" } /* * JDK 5.0 新特性:自动装箱 与自动拆箱 */ @Test public void test3() { // int num1 = 10; // //基本数据类型-->包装类的对象 // method(num1); // 自动装箱:基本数据类型 --->包装类 int num2 = 10; Integer in1 = num2;// 自动装箱 boolean b1 = true; Boolean b2 = b1;// 自动装箱 // 自动拆箱:包装类--->基本数据类型 System.out.println(in1.toString()); int num3 = in1;// 自动拆箱 } public void method(Object obj) { System.out.println(obj); } // 包装类--->基本数据类型:调用包装类Xxx的xxxValue() @Test public void test2() { Integer in1 = new Integer(12); int i1 = in1.intValue(); System.out.println(i1 + 1); Float f1 = new Float(12.3); float f2 = f1.floatValue(); System.out.println(f2 + 1); } // 基本数据类型 --->包装类:调用包装类的构造器 @Test public void test1() { int num1 = 10; // System.out.println(num1.toString()); Integer in1 = new Integer(num1); System.out.println(in1.toString()); Integer in2 = new Integer("123"); System.out.println(in2.toString()); // 报异常 // Integer in3 = new Integer("123abc"); // System.out.println(in3.toString()); Float f1 = new Float(12.3f); Float f2 = new Float("12.3"); System.out.println(f1); System.out.println(f2); Boolean b1 = new Boolean(true); Boolean b2 = new Boolean("TrUe"); System.out.println(b2);// true Boolean b3 = new Boolean("true123"); System.out.println(b3);// false Order order = new Order(); System.out.println(order.isMale);// false System.out.println(order.isFemale);// null } } class Order { boolean isMale; Boolean isFemale; }
import org.junit.Test; /* * 关于包装类使用的面试题 */ public class InterviewTest { @Test public void test1() { Object o1 = true ? new Integer(1) : new Double(2.0); System.out.println(o1);// 1.0 } @Test public void test2() { Object o2; if (true) o2 = new Integer(1); else o2 = new Double(2.0); System.out.println(o2);// 1 } @Test public void test3() { Integer i = new Integer(1); Integer j = new Integer(1); System.out.println(i == j);// false // Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[], // 保存了从-128~127范围的整数。如果我们使用自动装箱的方式,给Integer赋值的范围在 // -128~127范围内时,可以直接使用数组中的元素,不用再去new了。目的:提高效率 Integer m = 1; Integer n = 1; System.out.println(m == n);// true Integer x = 128;// 相当于new了一个Integer对象 Integer y = 128;// 相当于new了一个Integer对象 System.out.println(x == y);// false } }
结语
本人会持续更新文章的哦!希望大家一键三连,你们的鼓励就是作者不断更新的动力