面向对象的特征之三:多态性
类:人
package com.atguigu2; public class Person { String name; int age; public void eat(){ System.out.println("人:吃"); } public void walk(){ System.out.println("人:走路"); } }
类:男人
package com.atguigu2; public class Man extends Person{ boolean isSmoking; public void earMoney(){ System.out.println("男人负责挣钱养家"); } public void eat(){ System.out.println("男人:吃"); } public void walk(){ System.out.println("男人:走路"); } }
类:女人
package com.atguigu2; public class Woman extends Person{ boolean isBeauty; public void goShopping(){ System.out.println("女人:购物"); } public void eat(){ System.out.println("女人:吃"); } public void walk(){ System.out.println("女人:走路"); } }
测试以及知识点说明
package com.atguigu; /* * 面向对象特征之三:多态性(Polymorphism) * * 1.理解多态性:可以理解为一个事物的多种形态。 * 2.何为多态性: * 对象的多态性,父类的引用指向子类的对象(或子类的对象赋给对象的引用) * * 3.多态的使用:虚拟方法调用 * 有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。 * 总结:编译看左边,运行看右边。 * * 4.多态性的使用前提:①类的继承关系②方法的重写 * * 5.对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边) * * ********************************************************* * * */ 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.earMoney(); //****************************** System.out.println("******************************"); //对象的多态性:父类的引用指向子类的对象 Person p2 = new Man(); // Person p3 = new Woman(); //多态的使用:当调用子父类同名同参数的方法时,实际执行的子类重写父类的方法---->虚拟方法调用 p2.eat(); p2.walk(); System.out.println("***********************************"); //不能调用子类所特有的方法,属性,编译时,p2是Person类型 p2.name = "Tom"; //p2.isSmoking = true; // p2.earnMoney(); //有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型 //导致编译时只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。 //如何才能调用子类特有的属性和方法? //向下转型:使用强制类型转换符 Man m1 = (Man)p2; m1.earMoney(); m1.isSmoking = true; //使用强转时可能出现ClassCastException的异常 //Woman w1 = (Woman)p2; //w1.goShopping(); /* * instanceof关键字的使用 * * a instanceof A:判断对象a是否为类A的实例。如果是,返回true,如果不是,返回false * * * * 使用情境:为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前 * 先进行instanceof的判断,一旦返回true,就进行向下转型,如果返回false,不进行向下转型。 * * 如果a instanceof A返回true,则a instanceof B也返回true。 * 其中,类B是类A的父类。 */ if(p2 instanceof Woman){ Woman w1 = (Woman)p2; w1.goShopping(); System.out.println("*******Woman**********"); } if(p2 instanceof Man){ Man m2 = (Man)p2; m2.earMoney(); System.out.println("*******Man**********"); } } }
1.若子类重写了父类的方法,就意味着子类里定义的方法彻底的覆盖了父类里的同名方法
系统将不可能把父类里的方法转移到子类中,编译看左,运行看右
2.对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量
这个实例变量依然不可能覆盖父类中定义的实例变量,编译运行都看左边
5.8 Object类的使用
package com.atguigu2; /* * 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{ }
==和equals()的区别
package com.atguigu2; 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); //引用类型: Customer cust1 = new Customer(21,"Tom"); Customer cust2 = new Customer(21,"Tom"); String str1 = new String("atguigu"); String str2 = new String("atguigu"); System.out.println(str1 == str2);//false System.out.println(cust1 == cust2);//false System.out.println("*******************************"); System.out.println(str1.equals(str2));//true System.out.println(cust1.equals(cust2));//false-->true Date date1 = new Date(1231242354235L); Date date2 = new Date(1231242354235L); System.out.println(date1.equals(date2)); } }
toString
package com.atguigu2; /* * Object类中的toString() * * 1.当我们输出一个对象的引用时,实际上就是调用当前对象的toString() * * 2.Object类中toString()的定义: * public String to String(){ * return getClass().getName() + "@" + Interger.toHexString(hashCode()); * * } * * 3.像String、Date、File、包装类等都重写了Object类中的toString()方法。 * 使得在调用对象的toString()时,返回实体内容信息(); * * 4.自定义类也可以重写toString()方法,当调用此方法时,返回对象的"实体内容" * */ public class ToStringTest { public static void main(String[] args) { Customer cust1 = new Customer(21,"Tom"); System.out.println(cust1.toString()); String str = new String("MM"); System.out.println(str);//MM } }
Java中的JUnit单元测试
package com.atguigu2; import org.junit.Test; /* * 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()....."); } }
5.8包装类的使用
package com.atguigu2; import org.junit.Test; /* * 包装类的使用: * 1.java提供了8种基本数据类型对应的包装类,使得基本数据类型的变量具有类的特征 * * 2.掌握的:基本数据类型,包装类,String三者之间的相互转换 */ public class WrapperTest { //String类型----->基本数据类型、包装类:调用包装类的parseXxx() @Test public void test5(){ String str1 = "123"; // int num1 = (int)str1; int num2 = Integer.parseInt(str1); System.out.println(num2); } //基本数据类型、包装类---->String类型:调用String重载的valueOf(Xxx xxx) @Test public void test4(){ int num1 = 10; //方式一 String str1 = num1 + ""; //方式二 float f1 = 12.3f; String str2 = String.valueOf(f1); System.out.println(str2); Double d1 = new Double(12.4); String str3 = String.valueOf(d1); System.out.println(str3); } /* * JDK5.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); } //包装类---->基本数据类型:调用包装类的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); } //基本数据类型---->包装类:调用包装类的构造器 @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()); } }