面向对象的特征之三:多态性

类:人

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());


    }
}