007—JAVA多态详细讲解(虚与非虚方法)

形成多态 前提条件:
  1.有继承关系 Chinese extends Programmer

  2.有方法重写

多态向上转型方法的引用问题
向上转型: 将子类对象赋值给父类的引用
   父类             子类对象
Programmer pro = new Chinese();

  编译看左边 运行看右边   等号 "="

  编译: javac 写完代码后
  运行: java  程序跑起来

注意:
    1.多态的向上转型 无法使用 子类自己独有的资源

public class Programmer {
    public void eat(){
        System.out.println("程序员吃饭......");
    }
    public void writeCode(){
        System.out.println("写代码.......");
    }

}
class Chinese extends Programmer{
    @Override
    public void eat() {
                    System.out.println("中国人 爱吃 饺子.....");
    }
        public void taiJi(){

            System.out.println("打太极......");
        }
}
public class Test {
    public static void main(String[] args) {

        int m = 10;
        double d = m;

        Programmer pro = new Chinese();
        pro.eat();
        pro.writeCode();
    }
}

多态在形参上的应用

public class Animal {
    public void play(){
        System.out.println("动物玩");
    }
    public void eat(){
        System.out.println("动物吃饭");
    }
}

class Cat extends Animal {
    @Override
    public void play() {
        System.out.println("小猫玩 老鼠......");
    }
    public void catchMouse(){
        System.out.println("小猫抓老鼠......");
    }
}

class Dog extends Animal {
    @Override
    public void play() {
        System.out.println("小狗玩球.....");
    }
    @Override
    public void eat() {
        System.out.println("小狗爱吃骨头.......");
    }
    public void lookHome(){
        System.out.println("小狗看家......");
    }
}
public static void main(String[] args) {
        Cat cat = new Cat();
        cat.play();
        Dog dog = new Dog();
        dog.play();
        showPlay(dog);

    }

    public static void showPlay(Animal animal){// = new Dog() 或  = new Cat()
        animal.play();

    }

多态的应用:应用在形参

                        父类类型做形参   接收任意子类对象

多态应用在数组:

                         父类类型作为数组类型  可以放入任意子类对象

多态    只和方法有关  与属性无关

public class Animal {
    String name = "Animal";
    public void play() {
        System.out.println("动物玩");
    }
}

class Cat extends Animal {
    String name = "Cat";

    @Override
    public void play() {
        System.out.println("小猫玩 老鼠......");
    }

    public void catchMouse() {
        System.out.println("小猫抓老鼠......");
    }
}

class Dog extends Animal {
    @Override
    public void play() {
        System.out.println("小狗 玩 球...........");
    }

    public void lookHome() {
        System.out.println("小狗看家......");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal a = new Cat();
        System.out.println(a.name);

    }
}

父类和子类都有name属性但是结果运行出来的是Animal

多态 只和方法有关 与属性无关

向下转型:在向上转型之后  想要使用子类自己独有的资源(方法和属性)

 小的数据类型  变量名 = (小的数据类型)大的数据类型的值;

  int m = 10;
  double d  = m;

  int m1 = (int)d;

注意:
    1.向下转型 有可能会发生 ClassCastException 类型转换异常

 当需要使用子类中独有的方法时需要向下转型,当需要使用子类的属性的时候需要向下转型;

虚方法与非虚方法

非虚方法:不能重写的方法

        (1)由invokestatic指令调用的static方法,这种方法在编译时确定在运行时不会改变。

         (2)由invokespecial指令调用的方法,这些方法包括私有方法,实例构造方法,这些方法也是在编译时已经确定,在运行时不会再改变的方法

           (3)由final关键字修饰的方法。虽然final方法是由invokevirtual指令进行调用的, 但是final修饰的方法不能够进行在子类中进行覆盖,所有final修饰的方法是不能够在运行期进行动态改变的。在java语言规范中明确规定final方法就是非虚方法。

虚方法: 能/可以重写的方法

静态分配:看形参最匹配
动态绑定: 执行重写后

案例一:

class MyClass{
	public void method(Father f) {
		System.out.println("father");
	}
	public void method(Son s) {
		System.out.println("son");
	}
	public void method(Daughter f) {
		System.out.println("daughter");
	}
}
class Father{
	
}
class Son extends Father{
	
}
class Daughter extends Father{
	
}

//静态分配   实参编译时类型 与形参最匹配
public class TestOverload {
	public static void main(String[] args) {
		Father f = new Father();
		Father s = new Son();
		Father d = new Daughter();
        
     MyClass my = new MyClass();
		my.method(f);//father
		my.method(s);//father  son
		my.method(d);//father daughter
	}
}

静态分配:看形参最匹配

动态绑定: 执行重写后

案例二:

class MyClass{
	public void method(Father f) {
		System.out.println("father");
	}
	public void method(Son s) {
		System.out.println("son");
	}
}
class Father{
	
}
class Son extends Father{
	
}
class Daughter extends Father{
	
}
public class TestOverload {
	public static void main(String[] args) {
		MyClass my = new MyClass();

		Father f = new Father();
		Son s = new Son();
		Daughter d = new Daughter();


		my.method(f);//father
		my.method(s);//son
		//父类类型做形参可以接受子类对象

		my.method(d);//father
	}
}

案例三:

class MyClass{
    public void method(Father f) {
        System.out.println("father");
    }
    public void method(Son s) {
        System.out.println("son");
    }
}
class MySub extends MyClass{
    public void method(Daughter d) {
        System.out.println("daughter");
    }
}
class Father{

}
class Son extends Father{

}
class Daughter extends Father{

}
public class TestOverload {
    public static void main(String[] args) {
        //多态向上转型
        MyClass my = new MySub();

        Father f = new Father();
        Son s = new Son();
        Daughter d = new Daughter();

        my.method(f);//father

        my.method(s);//son

        my.method(d);//father
    }
}

重写的时候形参列表必须一样

案例四

class MyClass{
	public void method(Father f) {
		System.out.println("father");
	}
	public void method(Son s) {
		System.out.println("son");
	}
}
class MySub extends MyClass{
	public void method(Father d) {//重写的
		System.out.println("sub--");
	}
	//新增的
    public void method(Daughter d) {
		System.out.println("daughter");
	}
}
class Father{
}
class Son extends Father{
}
class Daughter extends Father{
}
public class TestOverloadOverride {
    public static void main(String[] args) {
        //多态向上转型
        MyClass my = new MySub();
        //创建对象
        Father f = new Father();
        Son s = new Son();
        Daughter d = new Daughter();

        my.method(f);//sub  sub      sub
        my.method(s);//sub  son      son
        my.method(d);//father father sub
    }
}

native关键字

native:本地的原生的

修饰方法  本地方法
java 不是万能的 某些功能无法实现的 借助于 C/C++ 语言实现

本地方法没有方法体
  public native int hashCode();

虚拟机栈

本地方法栈:存储调用本地方法时的相关信息

final关键字

final修饰的类  不能有子类
      public final class Animal {}

final修饰的方法不能被重写
        public final void show(){}

final修饰的变量是常量

   final修饰的成员变量 必须有显示赋值的操作(要么直接赋值,要么在构造器中赋值),总之,必须有值。

final修饰的对象地址值不能改变

 Object类

1.如果一个类没有显示的继承另一个类那么此类必然继承 Object 类
2.数组的父亲也是Object
3.任何对象都可以与Object 写成多态的形式

getClass: 获取运行时类型

hashcode()

 hashCode():返回一个哈西码 散列值 哈西表:顺序表+链表组成

哈西码不同 对象肯定不同

哈西码相同同 对象不一定相同

为什么重写hashCode()? 如果两个对象的属性值完全一样 那么认为是同一个对象 如果是同一个对象 哈西码要相同 对hashCode()重写(否则不重写的情况下会导致永远调用的时native下的hashcode(),native的话只要new就会不一样)

 

 哈希表为了提高查询和存储的效率的,先用哈希值找到顺序表中的位置,在用equals比较在链表中的具体位置。

哈希表中存储的数据是无序唯一的

public class Person {

    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }



    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
public class Test {
    public static void main(String[] args) {
        Person p1 = new Person("张三", 20);

        System.out.println("p1.hashCode() = " + p1.hashCode());
        Person p2 = new Person("张三", 20);

        System.out.println("p2.hashCode() = " + p2.hashCode());


        System.out.println("Aa---->"+"Aa".hashCode());
        System.out.println("BB---->"+"BB".hashCode());
    }
}

equals方法

==:
    比较基本数据类型 比较的是值
    比较的是对象  比较的是地址值

equals:
    重写前:比较的是对象的地址值 this == obj

                public boolean equals(Object obj) {
                            return (this == obj);
                        }

    重写后: 比较属性值

public class Person {
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /*@Override
    public boolean equals(Object o){
        if (this == o){return true ; }
        if (o == null && this.getClass() != o.getClass()){
            return false;
        }
       Person person = (Person)o;
        return age == person.age && Objects.equals(name, person.name);
    }*/

    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }

    @Override
    public int hashCode(){
        return Objects.hash(name,age);
    }

}

 toString方法

输出对象时默认会调用对象的toString方法

全类名+@+16进制的哈希码

com.atguigu.object.tostring.Student@4554617c

public class Student {
    String name;
    int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
public class Test {
    public static void main(String[] args) {

        Student s1 = new Student("李白", 20);

        System.out.println(s1);

        String s = s1.toString();
        System.out.println(s);

    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值