形成多态 前提条件: ? 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);
}
}
?
|