一文带你深入理解【Java基础】· 面向对象编程(中)③Object类和包装类的使用

写在前面


        Hello大家好, 我是【麟-小白】,一位软件工程专业的学生,喜好计算机知识。希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误不足之处,请多多指正!谢谢大家!!!

        如果小哥哥小姐姐们对我的文章感兴趣,请不要吝啬你们的小手,多多点赞加关注呀!❤❤❤ 爱你们!!!


目录

写在前面

1. Object类的使用

1.1 Object类的介绍

1.2 Object类中的主要结构

1.3 ==操作符和equals方法

1.4 ==和equals的区别

1.5 Object类代码演示

1.6 toString()方法

1.7 Java中的JUnit单元测试

 2. 包装类的使用

2.1 什么是包装类

2.2 包装类用法举例

2.3 包装类代码演示

结语


【往期回顾】

一文带你深入理解【Java基础】· 面向对象编程(中)②子类对象实例化和多态

一文带你深入理解【Java基础】· 面向对象编程(中)①继承、方法的重写、权限修饰符和super

一文带你深入理解【Java基础】· 面向对象编程(上)②重载、封装、构造器、this、package和import

一文带你深入理解【Java基础】· 面向对象编程(上)①面向对象的理解、类和对象、对象的创建使用和属性


【习题总结】

【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()方法进行比较时,对类FileStringDate及包装类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”,只要xy内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。
  • 任何情况下,x.equals(null),永远返回是“false”;x.equals(x不同类型的对象)永远返回是“false

1.4 ==和equals的区别

  • == 既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型就是比较内存地址
  • equals的话,它是属于java.lang.Object类里面的方法,如果该方法没有被重写过默认也==;我们可以看到String等类的equals方法是被重写过的,而且String类在日常开发中用的比较多,久而久之,形成了equals是比较值的错误观点。
  • 具体要看自定义类里有没有重写Objectequals方法来判断。
  • 通常情况下,重写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
	}

}


结语


本人会持续更新文章的哦!希望大家一键三连,你们的鼓励就是作者不断更新的动力

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

麟-小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值