第五章 面向对象(中)

目录

一、面向对象三大特征之二:继承性

二、方法的重写【尤其是抽象类和接口】

三、四种访问权限修饰符

四、关键字:super

五、子类对象实例化过程

六、面向对象三大特征之三:多态性

1.多态:

2.向下转型

3.instanceof操作符

七、Object类的使用

1.equals()与==

2.toString() 

八、包装类的使用

九、Debug的使用

十、单元测试类


一、面向对象三大特征之二:继承性

* 一、继承性的好处:
 * ① 减少了代码的冗余,提高了代码的复用性
 * ② 便于功能的扩展
 * ③ 为之后【多态性的使用,提供了前提
 * 
 * 二、继承性的格式: 
 *    class A extends B{}
 *    A:子类、派生类、subclass
 *    B:父类、超类、基类、superclass
 *    
 *    2.1体现:一旦【子类A继承父类B以后,子类A中就【获取】了父类B中声明的【所有的属性和方法】。在堆中,子类的对象也有父类的结构】
 *    【构造器不能叫做获取,叫做子类调用父类构造器
 *    【构造器不能理解为从父类复制粘贴到子类,因为构造器要与类同名】
 *    【特别的,父类中声明为private的属性或方法,子类继承父类以后,仍然认为【获取了】父类中私有的结构。
 *    只有因为封装性的影响,使得子类【不能直接调用】父类的结构而已。】


 *    2.2 子类继承父类以后,还可以声明自己特有的属性或方法:实现功能的拓展。
 * 
 * 三、Java中关于继承性的规定:
 *    1.一个类可以被多个子类继承。
 *    2.Java中类的单继承性:一个类只能有一个父类【类单继承,接口多继承】
 *    3.子父类是相对的概念。
 *    4.子类直接继承的父类,称为:【直接父类】。间接继承的父类称为:【间接父类】
 *    5.子类继承父类以后,就【获取了直接父类以及所有间接父类中声明的属性和方法】
 *     
 * 四、 1. 【如果我们没有显式的声明一个类的父类的话,则此类继承于java.lang.Object类
 *    2. 【所有的java类(除java.lang.Object类之外)都直接或间接的继承于java.lang.Object类】
 *    3. 意味着,【所有的java类具有java.lang.Object类声明的功能。】
 *    【光标放在类上,ctrl+t,看类的继承关系】

 /**
 * 【bug调试方法】
 * 1.打印一些输出语句,看变量的值 
 * 2.debug
 */

/*
 * Eclipse中的快捷键: 
 * 1.【补全代码的声明:alt + /】
 * 2.【快速修复: ctrl + 1】  
 * 3.【批量导包:ctrl + shift + o】
 * 4.使用单行注释:ctrl + /
 * 5.使用多行注释: ctrl + shift + /   
 * 6.取消多行注释:ctrl + shift + \
 * 7.复制指定行的代码:ctrl + alt + down 或 ctrl + alt + up
 * 8.删除指定行的代码:ctrl + d
 * 9.上下移动代码:alt + up  或 alt + down
 * 10.切换到下一行代码空位:shift + enter
 * 11.切换到上一行代码空位:ctrl + shift + enter
 * 12.如何查看源码:ctrl + 选中指定的结构   或  ctrl + shift + t
 * 13.退回到前一个编辑的页面:alt + left 
 * 14.进入到下一个编辑的页面(针对于上面那条来说的):alt + right
 * 15.光标选中指定的类,查看继承树结构:ctrl + t
 * 16.复制代码: ctrl + c
 * 17.撤销: ctrl + z
 * 18.反撤销: ctrl + y
 * 19.剪切:ctrl + x 
 * 20.粘贴:ctrl + v
 * 21.保存: ctrl + s
 * 22.全选:ctrl + a
 * 23.格式化代码: ctrl + shift + f
 * 24.选中数行,整体往后移动:tab
 * 25.选中数行,整体往前移动:shift + tab
 * 26.在当前类中,显示类结构,并支持搜索指定的方法、属性等:ctrl + o
 * 27.批量修改指定的变量名、方法名、类名等:alt + shift + r
 * 28.选中的结构的大小写的切换:变成大写: ctrl + shift + x
 * 29.选中的结构的大小写的切换:变成小写:ctrl + shift + y
 * 30.调出生成getter/setter/构造器等结构: alt + shift + s
 * 31.显示当前选择资源(工程 or 文件)的属性:alt + enter
 * 32.快速查找:参照选中的Word快速定位到下一个 :ctrl + k
 * 
 * 33.关闭当前窗口:ctrl + w
 * 34.关闭所有的窗口:ctrl + shift + w
 * 35.查看指定的结构使用过的地方:ctrl + alt + g
 * 36.查找与替换:ctrl + f
 * 37.最大化当前的View:ctrl + m
 * 38.直接定位到当前行的首位:home
 * 39.直接定位到当前行的末位:end
 */
 

二、方法的重写【尤其是抽象类和接口】

 * 1.重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作
 * 
 * 2.应用:重写以后,当创建子类对象以后,【通过子类对象调用子父类中的同名同参数的方法时,实际执行的是子类重写父类的方法。】
 * 
 * 3. 重写的规定:
 *             方法的声明: 权限修饰符  返回值类型  方法名(形参列表) throws 异常的类型{
 *                         //方法体
 *                     }
 *             约定俗称:子类中的叫重写的方法,父类中的叫被重写的方法
 *      ① 子类重写的方法的方法名和形参列表与父类被重写的【方法的方法名和形参列表相同】
 *      ② 子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
 *          >特殊情况:【子类不能重写父类中声明为private权限的方法
 *      ③ 【返回值类型:】
 *          >父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
 *          >父类被重写的方法的返回值类型是(引用)A类型,则子类重写的方法的返回值类型可以是A类或A类的子类
 *          >父类被重写的方法的返回值类型是【基本数据类型】(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(必须也是double)
 *      【因为基本数据类型,没有子类父类关系,那就只能是一样的】
 *        ④ 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型(具体放到异常处理时候讲)【异常也有子父类关系】
 *【返回值类型和抛出的异常要么相同,要么是子类】
 *【开发过程中,直接复制粘贴要重写的方法,然后修改方法体。或者打父类方法名的一部分,alt+/,就可以。被重写的方法,行号前有绿色小三角
 *    **********************************************************************
 *        子类和父类中的同名同参数的方法要么都声明为非static的(考虑重写)【只有非static的才能被重写】,要么都声明为static的(不是重写)【不可被重写,静态不可被覆盖,随着类的加载而加载】。


 *             方法的声明: 权限修饰符  【其他修饰符static】 返回值类型  方法名(形参列表) throws 异常的类型{
 *                         //方法体
 *                     }
 *
 * 面试题:区分方法的重载与重写
 * 【构造器可以重载不可以重写
 * 重写的前提是继承
 * 重载不表现为多态性,在编译期就确定了
 * 重写编译父类,运行子类
 * 】

三、四种访问权限修饰符

在一个类中使用别的类的属性和方法等成员,必须要先造对象,考虑类的成员的权限大小,然后导包 

/*
 * 体会4种不同的权限修饰
 */
public class Order {
	
	private int orderPrivate;
	int orderDefault;
	protected int orderProtected;
	public int orderPublic;
	
	private void methodPrivate(){
		orderPrivate = 1;
		orderDefault = 2;
		orderProtected = 3;
		orderPublic = 4;
	}
	void methodDefault(){
		orderPrivate = 1;
		orderDefault = 2;
		orderProtected = 3;
		orderPublic = 4;
	}
	protected void methodProtected(){
		orderPrivate = 1;
		orderDefault = 2;
		orderProtected = 3;
		orderPublic = 4;
	}
	
	public void methodPublic(){
		orderPrivate = 1;
		orderDefault = 2;
		orderProtected = 3;
		orderPublic = 4;
	}
}

import com.atguigu.java2.Order;//【不同包中的类,要导包】

public class SubOrder extends Order {//【SubOrder和Order不同包,但SubOrder是Order的子类】
	//【因为是子类,是继承关系,属性方法可以直接拿来用。方法中可以调属性和方法】
	
//	orderProtected = 1;//【这个位置是定义本类的成员变量属性,只有方法才能调方法和属性】
	public void method(){
		orderProtected = 1;
		orderPublic = 2;
		
		methodProtected();
		methodPublic();
		
		//在不同包的子类中,不能调用Order类中声明为private和缺省权限的属性、方法
//		orderDefault = 3;
//		orderPrivate = 4;
//		
//		methodDefault();
//		methodPrivate();
	}
	
}

四、关键字:super

* 【1.super理解为:父类的
 * 2.super可以用来调用:属性、方法、构造器】

 * 3.super的使用:调用属性和方法
 * 
 *   3.1 我们可以在子类的方法或构造器中。通过使用"super.属性"或"super.方法"的方式,显式的调用
 *   父类中声明的属性或方法。但是,通常情况下,我们习惯省略"super."
 *   3.2 特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的
 *   使用"super.属性"的方式,表明调用的是父类中声明的属性。
 *   3.3 特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的
 *   使用"super.方法"的方式,表明调用的是父类中被重写的方法。
 * 
 * 4.super调用构造器


 *      4.1  我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
 *   4.2 "super(形参列表)"的使用,必须声明在子类构造器的首行!
 *   4.3 【我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二选一【因为this、super都得首行,有一个是首行另一个肯定就不是了】,不能同时出现。】
 *   【this(形参)调用本类中的其他重载构造器,super(形参)调用父类中的指定构造器
 *   4.4 【在构造器的首行,没有显式的声明"this(形参列表)"或"super(形参列表)",则默认调用的是父类中空参的构造器:super()
 *   4.5 在类的多个构造器中,至少有一个类的构造器中使用了"super(形参列表)",调用父类中的构造器
 *   【一个类有n个构造器,最多n-1个使用this,没用的那个使用super】
 *   
 *   【this(形参列表):调本类重载的其他构造器
 *   super(形参列表):调父类指定的构造器】

public class Person {
	String name;
	int age;
	int id = 1001;//身份证号
	
	public Person(){
		System.out.println("我无处不在!");//【验证Student类默认调用super()】
	}
	
}
public class Student extends Person{
	
	String major;
	int id = 1002;//学号
	
	public Student(){
		super();
	}
	public Student(String major){
		super();
		this.major = major;
	}
	
	public Student(String name,int age,String major){
//		this.name = name;
//		this.age = age;
		super(name,age);
		this.major = major;
	}
	
	
	public void study(){
		System.out.println("学生:学习知识");
		this.eat();
		super.eat();
		walk();//【对于子类没有重写的方法写this,super都行。区别是:this先在本类找,找不到再去父类(直接和间接)】
	}
	
	public void show(){
		System.out.println("name = " + name + ", age = " + age);
		
		System.out.println("id = " + id);//1002【默认调当前类的,id前面默认有this.】
		System.out.println("id = " + this.id);//1002【this.先在本类找,找不到再去父类找。super.直接去父类找】
		System.out.println("id = " + super.id);//1001【子父类同名同类型属性】
	}
}

五、子类对象实例化过程

* 1. 从结果上来看:(继承性)
 *         子类继承父类以后,就获取了父类中声明的属性或方法。
 *      创建子类的对象,在堆空间中,就会加载所有父类【直接父类、间接父类】中声明的属性。
 * 
 * 2. 从过程上来看
 *         当我们通过子类的构造器创建子类对象时,【我们一定会直接或间接的调用其父类的构造器,进而调用父类的父类的构造器,...
 *    直到调用了java.lang.Object类中空参的构造器为止。】正因为加载过所有的父类的结构,所以才可以看到内存中有父类中的结构,子类对象才可以考虑进行调用。
 *    
 * 明确:虽然创建子类对象时,调用了父类的构造器,但是自始至终就创建过一个对象,即为new的子类对象。

 

六、面向对象三大特征之三:多态性

1.多态:

 

多态=向上转型

public class PersonTest {
	
	
	public static void main(String[] args) {
		
		Person p1 = new Person();
		p1.eat();
		
		Man man = new Man();
		man.eat();
		man.age = 25;
		man.earnMoney();
		
		//*************************************************
		System.out.println("*******************");
		//子类对象的多态性【左边是父类的变量,右边是new出来的子类对象】:
		//父类的引用【引用:p2】指向子类的对象【子类的对象:new Man()】
		Person p2 = new Man();
//		Person p3 = new Woman();
		//【多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法 ---虚拟方法调用】
		p2.eat();//【ctrl点eat,进入了父类,此时是编译,还没运行。执行的时候是Man()里的】
		p2.walk();
		
//		p2.earnMoney();【不能调子类特有的方法】
		
		System.out.println(p2.id);//1001【对于属性不存在多态性】
		
	}
}

* 1.理解多态性:可以理解为【一个事物的多种形态】。
 * 2.何为多态性:
 *   【对象的多态性】:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
 *   
 * 3. 多态的使用:虚拟方法调用
 *   有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
 *   总结:编译,看左边;运行,看右边。
 *   
 * 4.【多态性的使用前提:  ① 类的继承关系【子父类】  ② 方法的重写
 * 
 * 5.【对象的多态性,只适用于方法(编译,看左边;运行,看右边。),不适用于属性(编译和运行都看左边)】

 * 6.多态的使用举例:(1)形参是父类,子类对象作为实参(2)虚拟方法调用

import java.sql.Connection;


//多态性的使用举例一:【多态性:类new一个它的子类。声明一个类型,用子类的对象赋值】
//【equals(Object obj)】
public class AnimalTest {
	
	public static void main(String[] args) {
		
		AnimalTest test = new AnimalTest();
		test.func(new Dog());
		
		
		test.func(new Cat());
	}
	
	public void func(Animal animal){//Animal animal = new Dog();【多态的使用举例】
		animal.eat();
		animal.shout();
		
		if(animal instanceof Dog){
			Dog d = (Dog)animal;
			d.watchDoor();
		}
	}
	
	//【多态的使用举例1】【如果没有多态性,代码通用性很低,只能这样传参Animal animal=new Animal(),
	//就得造很多重载的方法。】
	//【多态的使用举例2】【抽象类、接口(后面讲)】
	//【抽象类、接口都不能造对象,不能造对象就无法落地。要使用抽象类和接口,就必须使用它们子类的对象,体现了多态性】
	//【类是单继承,接口是多继承】
//	public void func(Dog dog){
//		dog.eat();
//		dog.shout();
//	}
//	public void func(Cat cat){
//		cat.eat();
//		cat.shout();
//	}
}


class Animal{
	
	
	public void eat(){
		System.out.println("动物:进食");
	}
	
	public void shout(){
		System.out.println("动物:叫");
	}
	
	
}

class Dog extends Animal{
	public void eat(){
		System.out.println("狗吃骨头");
	}
	
	public void shout(){
		System.out.println("汪!汪!汪!");
	}
	
	public void watchDoor(){
		System.out.println("看门");
	}
}
class Cat extends Animal{
	public void eat(){
		System.out.println("猫吃鱼");
	}
	
	public void shout(){
		System.out.println("喵!喵!喵!");
	}
}

//举例二:

class Order{
	
	public void method(Object obj){//【形参是Object类,因为多态,这个方法通用性就很好】
		
	}
}

//举例三:
class Driver{
	
	public void doData(Connection conn){//conn = new MySQlConnection(); / conn = new OracleConnection();
		//规范的步骤去操作数据
//		conn.method1();
//		conn.method2();
//		conn.method3();
		
	}
	
}

 

//        if(salary == 0){
//            System.out.println("no job");
//        }else{
//            System.out.println("job");
//        }
        String jobInfo = (salary == 0) ? "no job" : "job";

if-else和三元运算符的转换

【讲到反射和JDBC,就知道为什么要有空参构造器和get、set方法】

2.向下转型

多态=向上转型

为什么要向下转型?因为多态导致父类的引用无法调用子类的特有属性。向下转型后,就可以调子类特有属性了

【比如id】 

public class PersonTest {
	public static void main(String[] args) {
		
		Person p1 = new Person();
		p1.eat();
		
		Man man = new Man();
		man.eat();
		man.age = 25;
		man.earnMoney();
		
		//*************************************************
		System.out.println("*******************");
		//对象的多态性:父类的引用指向子类的对象
		Person p2 = new Man();
//		Person p3 = new Woman();
		//多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法 ---虚拟方法调用
		p2.eat();
		p2.walk();
		
		
//		p2.earnMoney();【编译(代码)时,不能通过父类的引用,调用子类特有的方法】
		
		System.out.println(p2.id);//1001
		
		System.out.println("****************************");
		//【//不能调用子类所特有的方法、属性:编译时,p2是Person类型。Person类中根本没定义earnMoney()】
		p2.name = "Tom";
//		p2.earnMoney();
//		p2.isSmoking = true;【isSmoking是子类特有的属性,p2调不了】
		//【有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致
		//编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。】
		
		//【Man m1 = p2;不能这么写。赋值符号要么左右类型一样,要么基本数据类型自动类型提升】
		//【Person p2 = new Man();子的赋给父的,可行
		//Man m1 = p2;这是父的赋给子的,所以不行】
		
		//【如何才能调用子类特有的属性和方法?】【那就要求编译器看到的p2不是Person类型的,那就要声明成Man类型的】	
		//【向下转型:使用强制类型转换符。】
		Man m1 = (Man)p2;//【把Person强转为Man类型,编译器就识别p2为Man类型了】
		m1.earnMoney();
		m1.isSmoking = true;
		
		//使用强转时,可能出现ClassCastException的异常。
//		Woman w1 = (Woman)p2;【Person p2 = new Man();因为p2是new Man()出来的。p2指向的空间只有Person的结构和Man的结构】
//		w1.goShopping();

3.instanceof操作符

 

/*
         * 【instanceof关键字的使用】
         * 
         * a instanceof A:判断对象a是否是类A的实例。如果是,返回true;如果不是,返回false。
         * 
         * 
         *  使用情境:为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前,先
         *  进行instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。
         *  
         *  如果 a instanceof A返回true,则 a instanceof B也返回true.【反之不成立,Person可行,不代表Person的子类Woman可行】
         *  其中,类B是类A的父类。
         *  
         *  【判断了x是A的实例后,就可以往A类的父类找了】
         */

		if(p2 instanceof Woman){
			Woman w1 = (Woman)p2;
			w1.goShopping();
			System.out.println("******Woman******");
		}
		
		if(p2 instanceof Man){//【Man m1 = (Man)p2;new的时候是什么,instanceof的判断一定是true】
			Man m2 = (Man)p2;
			m2.earnMoney();
			System.out.println("******Man******");
		}
		
		if(p2 instanceof Person){//【Person是Man的父类】
			System.out.println("******Person******");
		}
		if(p2 instanceof Object){//【Object是Person和Man的父类】
			//【x instanceof Object都是对的,因为任何一个类的对象都可以是Object的实例,多态性】
			System.out.println("******Object******");
		}
		
//		if(p2 instanceof String){
//			
//		}
		
		
		
		//【能转的前提:new的是类的子类,才能向下转,因为子类里有super,就有了父类的东西】
		//练习:【这种题的做法是先想instanceof的判断,行了就找父类】
		//问题一:编译时通过,运行时不通过
		//举例一:
//		Person p3 = new Woman();
//		Man m3 = (Man)p3;//【因为要判断p3是不是Man的实例,显然不是】
		//举例二:
//		Person p4 = new Person();//【【Person里根本没加载Man,就不能转】】
//		Man m4 = (Man)p4;

		
		//问题二:编译通过,运行时也通过
//		Object obj = new Woman();【Woman里加载了Object类和Person类的东西,因为构造器里的super,所以可以强转为Person】
		//【obj是Woman的实例,Woman的直接父类是Person,间接父类是Object】
//		Person p = (Person)obj;
		
		//问题三:编译不通过
		
		
//		Man m5 = new Woman();
		
//		String str = new Date();
		
		//【骗编译器】
//		Object o = new Date();【先向上转型(多态)】
//		String str1 = (String)o;【再向下转型】

七、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类只声明了一个空参的构造器【子类实例化过程,所有类造对象,最终都会调这个空参构造器。因为super】
 * 
 * 面试题:
 * final、finally、finalize的区别?【关键字,关键字(异常),方法名】
 * 
 */

1.equals()与==

 * 面试题: == 和 equals() 区别
 * 
 * 一、回顾 == 的使用:
 * == :运算符
 * 1. 可以使用在基本数据类型变量和引用数据类型变量中
 * 2. 如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。【(不一定类型要相同)】
 *    如果比较的是引用数据类型变量:比较两个对象的地址值是否相同.【即两个引用是否指向同一个对象实体】
 *    【补充: 引用数据变量在== 符号使用时,必须保证符号左右两边的变量类型一致。】
 * 
 * 二、equals()方法的使用:
 * 1. 是一个方法,而非运算符
 * 2. 只能适用于引用数据类型。【因为方法是类成员,通过对象调用,类是引用类型。】【java面向对象目前没有基本数据类型,所以引入包装类带它们玩】
 * 3. 【Object类中equals()的定义:】
 *    public boolean equals(Object obj) {
            return (this == obj);
      }
 *    说明:Object类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体
 * 
 * 4. 像String、Date、File【io】、包装类等都重写了Object类中的equals()方法。重写以后,比较的不是
 *    两个引用的地址是否相同,而是比较两个对象的"实体内容"是否相同。
 *    
 * 5. 通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同。那么,我们
 *    就需要对Object类中的equals()进行重写.
 *    重写的原则:比较两个对象的实体内容是否相同.
 *    
 *    【重写equals()对后面重写集合compare()有用】

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//【基本数据类型存在类型提升,由int->double】
		
		boolean b = true;
//		System.out.println(i == b);//【基本数据类型运算时不带布尔型玩。编译报错了。】
		
		char c = 10;//【这个10是数字10】
/*		'A'		65
		'a'		97
		()		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
		//【boolean java.lang.Object.equals(Object obj)
		//重写了Customer类中的equals()方法】
		System.out.println(str1.equals(str2));//true
		//【boolean java.lang.String.equals(Object anObject),String类重写了equals()】
		
		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) {【1.引用地址是否相同】
//            return true;
//        }
//		
//		if(obj instanceof Customer){//【2.是不是同一数据类型。这句话可以理解成obj是不是Customer的实例】
//			Customer cust = (Customer)obj;【是,就把obj转成Customer类】
//			//比较两个对象的每个属性是否都相同
			if(this.age == cust.age && this.name.equals(cust.name)){【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 + "]";
	}
}

 

2.toString() 

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

八、包装类的使用

 * 包装类的使用:
 * 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);//【并不是Object obj = num1;】
		
		//自动装箱:基本数据类型 --->包装类
		int num2 = 10;
		Integer in1 = num2;//自动装箱【为什么int基本数据类型变量,可以赋值给一个类呢?】
		//【本来是Integer in1 = new Integer(num2);】
		
		boolean b1 = true;
		Boolean b2 = b1;//自动装箱
		
		//自动拆箱:包装类--->基本数据类型
		System.out.println(in1.toString());
		
		int num3 = in1;//自动拆箱【本来是int num3 = in1.intValue();】
		
	}
	
	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;//【isFemale是包装类,是个类。默认初始化值是null】
}

九、Debug的使用

/*
 * 没有异常提示,结果却和预期不同
 * 【如何调试程序:】
 * 绿箭头后面没有断点就终止程序,后面有断点就直接执行到断点处;红方是终止;虫子是开始debug
 * 1. System.out.println().打印相关变量,看中间环节变量如何变化
 * 2. Eclipse - Debug调试
 * (1)设置断点(在变量赋值打断点),双击。
 * run as是main(){}从头到尾,和断点无关。debug as和断点有关
 * (2)debug as
 *     step over(f6),一行代码一行代码往下走,到了这一行,这一行还没执行。过了才执行了
 *  step into(f5),进去看方法里做了什么事
 *  step return(f7),从方法里出来
 */

十、单元测试类

* Java中的JUnit单元测试【只想测一块代码,不想测全部代码。main是测试全部代码,test是测试部分代码】
 * 
 * 步骤:
 * 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.如果执行结果出现异常:红条

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值