Java学习笔记——Object类、多态、final

Object类、多态

1. Object 类
2. 多态
3. 向上转型
4. 向下转型
5. final关键字

第一节: Object类

类Object是类层次结构的根类。每个类都使用Object作为超类。

1.1 equals()方法

指示其他某个对象是否与此对象“相等”。

/**
 * 学生类
 * @author wgy
 *
 */
public class Student extends Object{
    String stuNo;
    String stuName;
    int age;

    public void show() {
        System.out.println("学号:"+stuNo+" 姓名:"+stuName+" 年龄:"+age);
    }
}


public class Test {
    public static void main(String[] args) {
        Student zhangsan=new Student();
        zhangsan.stuNo="bj1805";
        zhangsan.stuName="xxx";
        zhangsan.age=20;

        Student lisi=new Student();
        lisi.stuNo="bj1805";
        lisi.stuName="xxx";
        lisi.age=20;

        boolean b=zhangsan.equals(lisi);
        boolean b2=zhangsan==lisi;
        System.out.println(b);
        System.out.println(b2);

    }
}





    String s1 = new String("abc");
    String s2 = new String("abc");
    System.out.println(s1==s2);//new表示在堆中开辟新的空间存储数据,双等号比较的是new出来的两块对内存
    System.out.println(s1.equals(s2));//String类中重写了equals方法,比较的是两个字符串内容是否相等

==操作符与equals方法的区别:

1 == 比较 基本类型比较的是数据 ,引用类型比较对象的引用(地址)

2 默认情况 Object中equals方法和==一样。

3 String类型重写了Object中的equals,所以String比较使用equals方法。

1.2 hashCode()方法

返回该对象的哈希码值(理解为对象的地址)。每一个对象的哈希码值唯一,

    Object obj1 = new Object();
    Object obj2 = new Object();
    Object obj3 = obj2;
    //obj2与obj3两个对象的哈希码值一样
    System.out.println(obj1.hashCode());
    System.out.println(obj2.hashCode());
    System.out.println(obj3.hashCode());

1.3 getClass()方法

返回此Object的运行时类。通过某个对象通过反射获取类。

    Object obj = new Object();
    Class cls = obj.getClass();//通过反射获取到了Object类

1.4 toString()方法

返回该对象的字符串表示。可以在自定义类中重写toString方法,以实现是对象转成指定格式的字符串。

public class Person{
    String name;
    public Person(String name){
        this.name = name;
    }
    //重写toString方法
    public String toString(){
        return "name="+name;
    }
}
public class DemoPerson{
    public static void main(String[]args){
        Person p = new Person("张三");
        System.out.println(p);//输出结果为:name=张三
    }
}

第二节: 多态

2.1 什么是多态

在生活中,一个事物有多种表现形态,对象的多种形态,方法的多样性,比如:某个音乐家有三个儿子,大儿子会唱美声,二儿子会唱流行,三儿子会摇滚。

程序中多态:同一个引用类型,使用不同的实例而执行不同操作 ,一句话理解:父类引用,子类对象。

2.2 案例引入:

需求:

1 编写一个宠物类 Pet 属性:id,name,health,love ;方法有print(),打印信息,要封装成员变量

2 两个子类狗狗和猫类,狗狗有品种(strain),猫类有爱好(hobby),重写父类print()方法

3 宠物饿了,需要主人给宠物喂食,狗狗吃狗粮、猫咪吃小鱼,吃完之后健康值狗狗增加3,猫咪增加5。

/*
宠物类
*/
package com.qf.day08;
public class Pet{
    private int id; //id 宠物编号
    private String name;// 宠物昵称
    private int health;// 健康值
    private int love;// 亲密度

    public void setId(int id){
        this.id=id;
    }
    public int getId(){
        return id;
    }
    public void setName(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
    public void setHealth(int health){
        this.health=health;
    }
    public int getHealth(){
        return health;
    }
    public void setLove(int love){
        this.love=love;
    }   
    public int getLove(){
        return love;
    }

    //方法
    public void print(){
        System.out.println("宠物id:"+this.id+",宠物昵称:"+this.name+",健康值:"+health+",亲密度:"+love);
    }
}

/*
dog类继承Pet类
*/
package com.qf.day08;
public class Dog extends Pet{
    private String strain;
    public void setStrain(String strain){
        this.strain=strain;
    }
    public String getStrain(){
        return strain;
    }

    public void print(){
        int id=getId();
        String name=getName();
        int health=getHealth();
        int love=getLove();
        System.out.println("狗狗id:"+id+" 昵称:"+name+" 健康值:"+health+" 亲密度:"+love+" 品种:"+strain);
    }

    public void eat(){
        String name=getName();
        System.out.println(name+"大口吃狗粮....");
        //增加健康值
        int health=getHealth();
        setHealth(health+3);
    }
}


/*
猫类
*/
package com.qf.day08;
public class Cat extends Pet{
    private String hobby;
    public void setHobby(String hobby){
        this.hobby=hobby;
    }
    public String getHobby(){
        return hobby;
    }

    public void print(){
        int id=getId();
        String name=getName();
        int health=getHealth();
        int love=getLove();
        System.out.println("猫咪id:"+id+" 昵称:"+name+" 健康值:"+health+" 亲密度:"+love+" 爱好:"+hobby);
    }

    public void eat(){
        String name=getName();
        System.out.println(name+"大口吃小鱼....");
        //增加健康值
        int health=getHealth();
        setHealth(health+5);
    }
}

/*
主人
*/
package com.qf.day08;
public class Master{
    private String name;    
    public void setName(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
    //喂食
    public void feed(Dog d){
        System.out.println(name+"要给狗狗喂食物...");
        d.eat();
        d.print();
    }
    public void feed(Cat c){
        System.out.println(name+"要给猫咪喂食物...");
        c.eat();
        c.print();
    }
}



package com.qf.day08;
public class TestPet{
    public static void main(String[] args){
        Dog afu=new Dog();
        afu.setId(120);
        afu.setName("阿福");
        afu.setHealth(85);
        afu.setLove(90);
        afu.setStrain("拉布拉多");
        afu.print();

        Cat amao=new Cat();
        amao.setId(119);
        amao.setName("阿猫");
        amao.setHealth(90);
        amao.setLove(70);
        amao.setHobby("爬树");
        amao.print();

        Master yuhuan=new Master();
        yuhuan.setName("玉环");
        yuhuan.feed(afu);
        yuhuan.feed(amao);
    }
}

思考:如果再领养XXX宠物,就需要给XXX喂食,怎么办?

这样频繁修改代码,代码可扩展性、可维护性差。使用多态优化。

2.3 多态实现步骤:

  • 1 编写父类、子类,子类重写父类方法
  • 2 运行时,使用父类变量,子类的对象

    /*
    public void feed(Dog d){
        System.out.println(name+"要给狗狗喂食物...");
        d.eat();
        d.print();
    }
    public void feed(Cat c){
        System.out.println(name+"要给猫咪喂食物...");
        c.eat();
        c.print();
    }*/
    
    public void feed(Pet p){
        String n=p.getName();
        System.out.println(name+"要给"+n+"喂食物...");
        p.eat();//调用子类重写的方法
        p.print();//调用子类重写的方法
    }
    

2.4 多态使用形式:

  • 1 使用父类作为方法形参实现多态
  • 2 使用父类作为方法返回值实现多态

上机练习1:使用多态实现领养宠物,使用父类作为方法返回值

//主人类中添加领养方法
//领养
    public Pet adopt(int type){
        if(type==1){
            Pet d=new Dog();
            d.setHealth(80);
            d.setLove(50);
            return  d;
        }else if(type==2){
            Pet c=new Cat();
            c.setHealth(80);
            c.setLove(50);
            return  c;
        }else{
            return null;
        }
    }


/*
 领养宠物
*/
package com.qf.day08;
import java.util.Scanner;
public class TestPet2{
    public static void main(String[] args){
        System.out.println("欢迎来到xxx宠物商店.....");
        System.out.println("请选择您要领养的宠物类型 1 狗狗  2 猫咪");
        Scanner input=new Scanner(System.in);
        int choice=input.nextInt();

        Master yuhuan=new Master();
        Pet p=yuhuan.adopt(choice);
        if(p!=null){
            System.out.println("领养成功");
            p.print();
        }else{
            System.out.println("领养失败");
        }

    }
}

2.5 向上转型,向下转型

向上转型:将子类的对象赋值给父类变量,自动转换

Pet pet = new Dog();

String str = "abc";
Object obj = str;

注意:
1 <父类型> <引用变量名> = new <子类型>();
2 此时通过父类引用变量调用的方法是子类覆盖或父类的方法  ,编译时看父类,运行时看子类
3 此时通过父类引用变量无法调用子类特有的属性和方法

向下转型:将父类的变量赋值给子类变量,强制转换

上机练习1:实现主人与宠物玩耍功能

//猫咪捉迷藏  猫类中
public void hideAndSeek(){
        String name=getName();
        System.out.println(name+"玩捉迷藏...");
        int health=getHealth();
        setHealth(health-5);
}

//接球 狗狗类
public void catchBall(){
    String name=getName();
    System.out.print(name+"玩接球游戏....");
    int health=getHealth();
    setHealth(health-3);
}

//和宠物玩耍
public void play(Pet pet){
        if(pet instanceof Dog){
            Dog d=(Dog)pet; 
            d.catchBall();
        }else if(pet instanceof Cat){
            Cat c=(Cat)pet;
            c.hideAndSeek();
        }

    }



Object obj = new String("abc");
String str = (String)obj;
Pet pet=new Dog();  // Pet pet=new Cat();
Dog d=(Dog)pet;

注意:
1 <子类型> <引用变量名> = (<子类型> )<父类型的引用变量>;
2 在向下转型的过程中,如果没有转换为真实子类类型,会出现类型转换异常

2.6 instanceof

对象向下转型时,存在一个问题:

若一个父类A的引用a,指向一个子类B的实例,将a赋值给另一个子类C引用时,会抛出java.lang.ClassCastException异常;

抛出异常后程序将不能继续向下执行,为了避免这个异常的抛出,我们可以通过instanceof关键字判断引用指向的实例是否可以进行强制转换成某个子类对象

已知Pet类有两个子类Dog和Cat:

public class Demo{
    public static void main(String[]args){
        Pet a = new Dog();
        check(a);
    }
    //设计一个方法,判断一个动物是猫还是狗
    public static void check(Pet a){
        if(a instanceof Dog){
            System.out.println("狗");
        }else if(a instanceof Cat){
            System.out.println("猫");
        }
    }
}

第三节:final关键字

final:最终的

在Java中声明类、属性和方法时,可以使用关键字final来修饰。

3.1 final修饰变量(成员变量或局部变量),则成为(符号)常量,只能赋值一次。重点

  • 修饰成员变量时,定义时同时给出初始值,或在构造方法中赋值
  • 修饰局部变量时,只能赋值一次

3.2 final修饰方法,则该方法不能被子类重写,能被继承

  final returnType methodName(paramList){

    …

  }

3.3 final修饰类,则类不能被继承

 final class finalClassName{

     …

 }

总结

1 Object 类 ,是所有的父类,默认继承Object

equals()方法:判断两个对象是否相等     this==obj;

    ==  : 基本类型比较的数据,引用类型比较的地址。

    equals()  默认 和== 一样,

hashCode()方法:返回对象的地址

getClass()方法:返回类对象

toString()方法:返回对象的字符串形式, com.qf.day10.Person@123142;  重写

2 多态:同一个引用类型,使用不同的实例,执行不同的操作, 父类引用,子类对象

实现多态的要素或条件:

1 子类继承父类,子类必须重写父类的方法

2 使用父类变量,子类对象 

多态表现形式:

1 使用父类作为方法的参数

2 使用父类作为方法的返回值

    向上转型和向下转型

向上转型:子类转成父类

向下转型:父类转成子类

instanceof: 判断变量是否是某种类型。

if(pet instanceof Dog){     

    Dog dog=(Dog)pet;

}

3 final 终止的

3.1 final 修饰变量   常量:只能赋值一次。

    修饰成员变量

    修饰局部变量

3.2 final 修饰方法  终止方法不能被重写,能被继承

3.3 final修饰类,终止类,不能被继承。

面试题

class A{  
    public String show(D obj){  
           return ("A and D");  
    }   
    public String show(A obj){  
           return ("A and A");  
    }   
}     
class B extends A{  
    public String show(B obj){  
           return ("B and B");  
    }  
    public String show(A obj){  
           return ("B and A");  
    }   
}    
class C extends B{}   
class D extends B{}  

问题:以下输出结果是什么?

A a1 = new A();

A a2 = new B();

B b = new B();

C c = new C();

D d = new D();

System.out.println(a1.show(b)); A and A

System.out.println(a1.show(c)); A and A

System.out.println(a1.show(d)); A and D

System.out.println(a2.show(b)); B and A

System.out.println(a2.show(c)); B and A

System.out.println(a2.show(d)); A and D

System.out.println(b.show(b)); B and B

System.out.println(b.show(c)); B and B

System.out.println(b.show(d)); A and D

猜你喜欢

转载自blog.csdn.net/lyf1997115/article/details/81535699