java面向对象-常用类的使用

43 阅读11分钟

常用类的使用

Object类的使用

万物的父类都是Object

package com.atguigu.java1;
/*
 * java.lang.Object类
 * 1.Object类是所有Java类的根父类
 * 2.如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类 
 * 3.Object类中的功能(属性、方法)就具有通用性。
 * 	属性:无
 *  方法:equals() / toString() / getClass() /hashCode() / clone() / finalize()
 *     wait() 、 notify()、notifyAll()
 * 
 * 4. Object类只声明了一个空参的构造器
 * 
 * 
 * 
 * 面试题:
 * final、finally、finalize的区别?
 * 
 */
public class ObjectTest {

	public static void main(String[] args) {
		
		Order order = new Order();
		System.out.println(order.getClass().getSuperclass());
		
	}
}

class Order{
	
}

clone()

package com.atguigu.java1;

//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);
			a2.setName("毛毛");
			System.out.println("clone之后的对象:" + a2);
		} 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();
	}
	
}

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()方法

equals()方法的使用:
  1. 是一个方法,而非运算符

  2. 只能适用于引用数据类型

  3. Object类中equals()源码的定义(因为父类是比较虚的,它不知道子类有什么属性):

public boolean equals(Object obj) {

return (this == obj);

}

说明:Object类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体

  1. 像String、Date、File、包装类等都重写了Object类中的equals()方法。

重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的"实体内容"是否相同。

  1. 通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同。那么,我们 就需要对Object类中的equals()进行重写.重写的原则:比较两个对象的实体内容是否相同.
package com.atguigu.java1;

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
		
		
	}
}

自己实现equals()

//重写的原则:比较两个对象的实体内容(即: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;
        return this.age == cust.age && this.name.equals(cust.name);
    }else{
        return false;
    }
}

练习

toString() 方法

输出语句去输出对象,会调用该对象的toString方法,默认会输出该对象的地址值

import java.util.Date;

/*
 * Object类中toString()的使用:
 * 
 * 1. 当我们输出一个对象的引用时,实际上就是调用当前对象的toString()
 * 
 * 2. Object类中toString()的定义:
 *   public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
     }
 * 
 * 3. 像StringDate、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
		
	}
}

为什么System.out.println(对象) ; 等同于 System.out.println( 对象.toString() ) ; ?

下面看一下,System.out.println(对象) ; 的源码

//这里会加锁,所以一般实战中输出日志不会用 System.out.println();
public void println(Object x) {
    String s = String.valueOf(x);
    synchronized (this) {
        print(s);
        newLine();
    }
}

//底层只是调用了 toString() 方法而已,所以要想输出该对象的内容,则需要重写toString方法
public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

包装类(Wrapper)的使用

父类是Number -> Object类

基本数据类型、包装类型 和 String类型 的转换图(重点,面试常考)

JDK5 之后就可以自动拆装箱了

import org.junit.Test;

/*
 * 包装类的使用:
 * 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);
		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 {

    /*
     * 解析:这个输出1.0的原因是
     * 1、首先肯定是进入new Integer(1),因为前面是赋值语句。
     * 2、然后,为什么不是输出地址值呢,因为这一个是多态,所以虽然是调用父类的方法,但是实际上是调用了子类重写后的方法。
     * 3、然后为什么不是1,而是1.0呢,因为三目运算符会把左右两边的类型提升已达统一,所以1变成了1.0。
     *
     */
	@Test
	public void test1() {
		Object o1 = true ? new Integer(1) : new Double(2.0);
		System.out.println(o1);// 1.0
        
	}

    //这一题就是1了,只考察了多态
	@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
	}

}

复习

Object类的使用

1.java.lang.Object类的说明:
  • 1.Object类是所Java类的根父类

  • 2.如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类

  • 3.Object类中的功能(属性、方法)就具通用性。

  • 属性:无

  • 方法:equals() / toString() / getClass() /hashCode() / clone() / finalize()

  • wait() 、 notify()、notifyAll()

    1. Object类只声明了一个空参的构造器

2.equals()方法

2.1 equals()的使用:

  1. 是一个方法,而非运算符
    1. 只能适用于引用数据类型
    1. Object类中equals()的定义:
  • public boolean equals(Object obj) {

return (this == obj);

}

  • 说明:Object类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体

    1. 像String、Date、File、包装类等都重写了Object类中的equals()方法。重写以后,比较的不是
  • 两个引用的地址是否相同,而是比较两个对象的"实体内容"是否相同。

    1. 通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同。那么,我们
  • 就需要对Object类中的equals()进行重写.

  • 重写的原则:比较两个对象的实体内容是否相同.

2.2 如何重写equals()

2.2.1 手动重写举例:

class User{

String name;

int age;

//重写其equals()方法

public boolean equals(Object obj){

if(obj == this){

return true;

}

if(obj instanceof User){

User u = (User)obj;

return this.age == u.age && this.name.equals(u.name);

}

return false;

}

}

2.2.2 开发中如何实现:自动生成的

2.3 回顾 == 运算符的使用:

  • == :运算符

    1. 可以使用在基本数据类型变量和引用数据类型变量中
    1. 如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。(不一定类型要相同)
  • 如果比较的是引用数据类型变量:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体

  • 补充: == 符号使用时,必须保证符号左右两边的变量类型一致。

3. toString()方法

3.1 toString()的使用:

  1. 当我们输出一个对象的引用时,实际上就是调用当前对象的toString()
    1. Object类中toString()的定义:
  • public String toString() {

return getClass().getName() + "@" + Integer.toHexString(hashCode());

}

    1. 像String、Date、File、包装类等都重写了Object类中的toString()方法。
  • 使得在调用对象的toString()时,返回"实体内容"信息

    1. 自定义类也可以重写toString()方法,当调用此方法时,返回对象的"实体内容"

3.2 如何重写toString()

举例:

//自动实现

@Override

public String toString() {

return "Customer [name=" + name + ", age=" + age + "]";

}

4.面试题:

① final、finally、finalize的区别?

② == 和 equals() 区别

单元测试方法

  • 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.如果执行结果出现异常:红条

包装类的使用

1.为什么要有包装类(或封装类)

为了使基本数据类型的变量具有类的特征,引入包装类。

2.基本数据类型与对应的包装类:

3.需要掌握的类型间的转换:(基本数据类型、包装类、String)

简易版:

基本数据类型<--->包装类:JDK 5.0 新特性:自动装箱 与自动拆箱

基本数据类型、包装类--->String:调用String重载的valueOf(Xxx xxx)

String--->基本数据类型、包装类:调用包装类的parseXxx(String s)

注意:转换时,可能会报NumberFormatException

应用场景举例:

① Vector类中关于添加元素,只定义了形参为Object类型的方法:

v.addElement(Object obj); //基本数据类型 --->包装类 --->使用多态